# SearchArray
[![Python package](https://github.com/softwaredoug/searcharray/actions/workflows/test.yml/badge.svg)](https://github.com/softwaredoug/searcharray/actions/workflows/test.yml) | Discuss at [Relevance Slack](https://join.slack.com/t/relevancy/shared_invite/zt-2ccxvzn1w-2_50zf9xBOSv3n06Cu15jg)
SearchArray turns Pandas string columns into a term index. It alows efficient BM25 / TFIDF scoring of phrases and individual tokens.
Think Lucene, but as a Pandas column.
```python
from searcharray import SearchArray
import pandas as pd
df['title_indexed'] = SearchArray.index(df['title'])
np.sort(df['title_indexed'].array.score(['cat', 'in', 'the', 'hat'])) # Search w/ phrase
> BM25 scores:
> array([ 0. , 0. , 0. , ..., 15.84568033, 15.84568033, 15.84568033])
```
## Docs | Guide
SearchArray is documented in these notebooks:
[SearchArray Guide](https://colab.research.google.com/drive/1gmgVz53fDPTJakUHb6Mttevqry7gKHLM) | [SearchArray Offline Experiment](https://colab.research.google.com/drive/1w_Ajn5rHzcISKhdCuPhhVFav3zrvKWn1) | [About internals](https://softwaredoug.com/blog/2024/01/21/search-array-phrase-algorithm)
## Installation
```
pip install searcharray
```
## Features
* Search w/ terms by passing a string
* Search w/ a phrase by passing a list[str]
* Search w/ a [phrase w/ edit-distance](https://lucene.apache.org/core/9_6_0/core/org/apache/lucene/search/PhraseQuery.html) by passing slop=N.
* Access raw stats arrays in termfreqs / docfreqs methods on the array
* Bring your own tokenizer. Pass any (`def tokenize(value: str) -> List[str]`) when indexing.
* Memory map by passing `data_dir` to index for memory mapped index
* Accepts any python function to compute similarity. Here's [one similarity](https://github.com/softwaredoug/searcharray/blob/main/searcharray/similarity.py#L103)
* Scores the entire dataframe, allowing combination w/ other ranking attributes (recency, popularity, etc) or scores from other fields (ie boolean queries)
* Implement's Solr's [edismax query parser](https://github.com/softwaredoug/searcharray/blob/main/searcharray/solr.py) for efficient prototyping
## Motivation
To simplify lexical search in the Python data stack.
Many ML / AI practitioners reach for a vector search solution, then realize they need to sprinkle in some degree of BM25 / lexical search. Let's get traditional full-text search to behave like other parts of the data stack.
SearchArray creates a Pandas-centric way of creating and using a search index as just part of a Pandas array. In a sense, it builds a search engine in Pandas - to allow anyone to prototype ideas and perform reranking, without external systems.
You can see a full end-to-end search relevance experiment in this [colab notebook](https://colab.research.google.com/drive/1w_Ajn5rHzcISKhdCuPhhVFav3zrvKWn1?usp=sharing)
IE, let's take a dataframe that has a bunch of text, like movie title and overviews:
```
In[1]: df = pd.DataFrame({'title': titles, 'overview': overviews}, index=ids)
Out[1]:
title overview
374430 Black Mirror: White Christmas This feature-length special consists of three ...
19404 The Brave-Hearted Will Take the Bride Raj is a rich, carefree, happy-go-lucky second...
278 The Shawshank Redemption Framed in the 1940s for the double murder of h...
372058 Your Name. High schoolers Mitsuha and Taki are complete s...
238 The Godfather Spanning the years 1945 to 1955, a chronicle o...
... ... ...
65513 They Came Back The lives of the residents of a small French t...
65515 The Eleventh Hour An ex-Navy SEAL, Michael Adams, (Matthew Reese...
65521 Pyaar Ka Punchnama Outspoken and overly critical Nishant Agarwal ...
32767 Romero Romero is a compelling and deeply moving look ...
```
Index the text:
```
In[2]: df['title_indexed'] = SearchArray.index(df['title'])
df
Out[2]:
title overview title_indexed
374430 Black Mirror: White Christmas This feature-length special consists of three ... Terms({'Black', 'Mirror:', 'White'...
19404 The Brave-Hearted Will Take the Bride Raj is a rich, carefree, happy-go-lucky second... Terms({'The', 'Brave-Hearted', 'Wi...
278 The Shawshank Redemption Framed in the 1940s for the double murder of h... Terms({'The', 'Shawshank', 'Redemp...
372058 Your Name. High schoolers Mitsuha and Taki are complete s... Terms({'Your', 'Name.'}, {'Your': ...
238 The Godfather Spanning the years 1945 to 1955, a chronicle o... Terms({'The', 'Godfather'}, {'The'...
... ... ... ...
65513 They Came Back The lives of the residents of a small French t... Terms({'Back', 'They', 'Came'},...
65515 The Eleventh Hour An ex-Navy SEAL, Michael Adams, (Matthew Reese... Terms({'The', 'Hour', 'Eleventh': ...
65521 Pyaar Ka Punchnama Outspoken and overly critical Nishant Agarwal ... Terms({'Ka', 'Pyaar', 'Punchnama':...
32767 Romero Romero is a compelling and deeply moving look ... Terms({'Romero'})
65534 Poison Paul Braconnier and his wife Blandine only hav... Terms({'Poison'})```
```
(notice the dumb tokenization - no worries you can pass your own tokenizer).
Then search, getting top N with `Cat`
```
In[3]: np.sort(df['title_indexed'].array.score('Cat'))
Out[3]: array([ 0. , 0. , 0. , ..., 15.84568033,
15.84568033, 15.84568033])
In[4]: df['title_indexed'].score('Cat').argsort()
Out[4]:
array([0, 18561, 18560, ..., 15038, 19012, 4392])
```
And since its just pandas, we can, of course just retrieve the top matches
```
In[5]: df.iloc[top_n_cat[-10:]]
Out[5]:
title overview title_indexed
24106 The Black Cat American honeymooners in Hungary are trapped i... Terms({'Black': 1, 'The': 1, 'Cat': 1}, ...
12593 Fritz the Cat A hypocritical swinging college student cat ra... Terms({'Cat': 1, 'the': 1, 'Fritz': 1}, ...
39853 The Cat Concerto Tom enters from stage left in white tie and ta... Terms({'The': 1, 'Cat': 1, 'Concerto': 1...
75491 The Rabbi's Cat Based on the best-selling graphic novel by Joa... Terms({'The': 1, 'Cat': 1, "Rabbi's": 1}...
57353 Cat Run When a sexy, high-end escort holds the key evi... Terms({'Cat': 1, 'Run': 1}, {'Cat': [0],...
25508 Cat People Sketch artist Irena Dubrovna (Simon) and Ameri... Terms({'Cat': 1, 'People': 1}, {'Cat': [...
11694 Cat Ballou A woman seeking revenge for her murdered fathe... Terms({'Cat': 1, 'Ballou': 1}, {'Cat': [...
25078 Cat Soup The surreal black comedy follows Nyatta, an an... Terms({'Cat': 1, 'Soup': 1}, {'Cat': [0]...
35888 Cat Chaser A Miami hotel owner finds danger when be becom... Terms({'Cat': 1, 'Chaser': 1}, {'Cat': [...
6217 Cat People After years of separation, Irina (Nastassja Ki... Terms({'Cat': 1, 'People': 1}, {'Cat': [...
```
More use cases can be seen [in the colab notebook](https://colab.research.google.com/drive/1w_Ajn5rHzcISKhdCuPhhVFav3zrvKWn1)
## Goals
The overall goals are to recreate a lot of the lexical features (term / phrase search) of a search engine like Solr or Elasticsearch, but in a Pandas dataframe.
### Memory efficient and fast text index
We want the index to be as memory efficient and fast at searching as possible. We want using it to have a minimal overhead.
We want you to be able to work with a reasonable dataset (100X-1M docs) relatively efficiently for offline evaluation. And 1000s for fast reranking in a service.
### Experimentation, reranking, functionality over scalability
Instead of building for 'big data' our goal is to build for *small-data*. That is, focus on capabilities and expressiveness of Pandas, over limiting functionality in favor of scalability.
To this end, the applications of searcharray will tend to be focused on experimentation and top N candidate reranking. For experimentation, we want any ideas expressed in Pandas to have a somewhat clear path / "contract" in how they'd be implemented in a classical lexical search engine. For reranking, we want to load some top N results from a base system and be able to modify them.
### Make lexical search compatible with the data stack
We know in search, RAG, and other retrieval problems [hybrid search](https://www.pinecone.io/learn/hybrid-search-intro/) techniques dominate. Yet often its cast in terms of a giant, weird, big data lexical search engine that looks odd to most data scientists being joined with a vector database. We want lexical search to be more approachable to data scientists and ML engineers building these systems.
## Non-goals
### You need to bring your own tokenization
Python libraries [already do tokenization really well](https://github.com/snowballstem). Even exceeding what Lucene can do... giving you the ability to simulate and/or exceed the abilities of Lucene's tokenization.
In SearchArray, a tokenizer is a function takes a string and emits a series of tokens. IE dumb, default whitespace tokenization:
```python
def ws_tokenizer(string):
return string.split()
```
And you can pass any tokenizer that matches this signature to index:
```python
def ws_lowercase_tokenizer(string):
return string.lower().split()
df['title_indexed'] = SearchArray.index(df['title'], tokenizer=ws_lowercase_tokenizer)
```
Create your own using stemming libraries, or whatever Python functionality you want.
### Use Pandas instead of function queries
Solr has its [own unique function query syntax]()https://solr.apache.org/guide/7_7/function-queries.html. Elasticsearch has [Painless](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-painless.html).
Instead of recreating these, simply use Pandas on existing Pandas columns. Then later, if you need to implement this in Solr or Elasticsearch, attempt to recreate the functionality. Arguably what's in Solr / ES would be a subset of what you could do in Pandas.
```
# Calculate the number of hours into the past
df['hrs_into_past'] = (now - df['timestamp']).dt.total_seconds() / 3600
```
Then multiply by BM25 if you want:
```
df['score'] = df['title_indexed'].score('Cat') * df['hrs_into_past']
```
### Vector search
We focus on the lexical, ie "BM25-ish" and adjacent problems. There are other great tools for vector search out there.
## Need help?
Visit the [#searcharray channel on Relevance Slack](https://join.slack.com/t/relevancy/shared_invite/zt-2ccxvzn1w-2_50zf9xBOSv3n06Cu15jg)
## TODOs / Future Work / Known issues
* Always more efficient
* Support tokenizers with overlapping positions (ie synonyms, etc)
* Improve support for phrase slop
* Helper functions (like [this start at edismax](https://github.com/softwaredoug/searcharray/blob/main/searcharray/solr.py) that help recreate Solr / Elasticsearch lexical queries)
* Fuzzy search
* Efficient way to "slurp" some top N results from retrieval system into a dataframe
Raw data
{
"_id": null,
"home_page": "https://github.com/softwaredoug/searcharray",
"name": "searcharray",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.10",
"maintainer_email": null,
"keywords": "sample, setuptools, development search",
"author": "Doug Turnbull",
"author_email": "softwaredoug@gmail.com",
"download_url": null,
"platform": null,
"description": "# SearchArray \n\n[![Python package](https://github.com/softwaredoug/searcharray/actions/workflows/test.yml/badge.svg)](https://github.com/softwaredoug/searcharray/actions/workflows/test.yml) | Discuss at [Relevance Slack](https://join.slack.com/t/relevancy/shared_invite/zt-2ccxvzn1w-2_50zf9xBOSv3n06Cu15jg)\n\nSearchArray turns Pandas string columns into a term index. It alows efficient BM25 / TFIDF scoring of phrases and individual tokens.\n\nThink Lucene, but as a Pandas column.\n\n```python\nfrom searcharray import SearchArray\nimport pandas as pd\n\ndf['title_indexed'] = SearchArray.index(df['title'])\nnp.sort(df['title_indexed'].array.score(['cat', 'in', 'the', 'hat'])) # Search w/ phrase\n\n> BM25 scores:\n> array([ 0. , 0. , 0. , ..., 15.84568033, 15.84568033, 15.84568033])\n```\n\n## Docs | Guide\n\nSearchArray is documented in these notebooks:\n\n[SearchArray Guide](https://colab.research.google.com/drive/1gmgVz53fDPTJakUHb6Mttevqry7gKHLM) | [SearchArray Offline Experiment](https://colab.research.google.com/drive/1w_Ajn5rHzcISKhdCuPhhVFav3zrvKWn1) | [About internals](https://softwaredoug.com/blog/2024/01/21/search-array-phrase-algorithm)\n\n## Installation\n\n```\npip install searcharray\n```\n\n## Features\n\n* Search w/ terms by passing a string\n* Search w/ a phrase by passing a list[str]\n* Search w/ a [phrase w/ edit-distance](https://lucene.apache.org/core/9_6_0/core/org/apache/lucene/search/PhraseQuery.html) by passing slop=N.\n* Access raw stats arrays in termfreqs / docfreqs methods on the array\n* Bring your own tokenizer. Pass any (`def tokenize(value: str) -> List[str]`) when indexing.\n* Memory map by passing `data_dir` to index for memory mapped index\n* Accepts any python function to compute similarity. Here's [one similarity](https://github.com/softwaredoug/searcharray/blob/main/searcharray/similarity.py#L103)\n* Scores the entire dataframe, allowing combination w/ other ranking attributes (recency, popularity, etc) or scores from other fields (ie boolean queries)\n* Implement's Solr's [edismax query parser](https://github.com/softwaredoug/searcharray/blob/main/searcharray/solr.py) for efficient prototyping\n\n## Motivation\n\nTo simplify lexical search in the Python data stack.\n\nMany ML / AI practitioners reach for a vector search solution, then realize they need to sprinkle in some degree of BM25 / lexical search. Let's get traditional full-text search to behave like other parts of the data stack.\n\nSearchArray creates a Pandas-centric way of creating and using a search index as just part of a Pandas array. In a sense, it builds a search engine in Pandas - to allow anyone to prototype ideas and perform reranking, without external systems. \n\nYou can see a full end-to-end search relevance experiment in this [colab notebook](https://colab.research.google.com/drive/1w_Ajn5rHzcISKhdCuPhhVFav3zrvKWn1?usp=sharing)\n\nIE, let's take a dataframe that has a bunch of text, like movie title and overviews:\n\n```\nIn[1]: df = pd.DataFrame({'title': titles, 'overview': overviews}, index=ids)\nOut[1]:\n title overview\n374430 Black Mirror: White Christmas This feature-length special consists of three ...\n19404 The Brave-Hearted Will Take the Bride Raj is a rich, carefree, happy-go-lucky second...\n278 The Shawshank Redemption Framed in the 1940s for the double murder of h...\n372058 Your Name. High schoolers Mitsuha and Taki are complete s...\n238 The Godfather Spanning the years 1945 to 1955, a chronicle o...\n... ... ...\n65513 They Came Back The lives of the residents of a small French t...\n65515 The Eleventh Hour An ex-Navy SEAL, Michael Adams, (Matthew Reese...\n65521 Pyaar Ka Punchnama Outspoken and overly critical Nishant Agarwal ...\n32767 Romero Romero is a compelling and deeply moving look ...\n```\n\nIndex the text:\n\n```\nIn[2]: df['title_indexed'] = SearchArray.index(df['title'])\n df\n\nOut[2]:\n title overview title_indexed\n374430 Black Mirror: White Christmas This feature-length special consists of three ... Terms({'Black', 'Mirror:', 'White'...\n19404 The Brave-Hearted Will Take the Bride Raj is a rich, carefree, happy-go-lucky second... Terms({'The', 'Brave-Hearted', 'Wi...\n278 The Shawshank Redemption Framed in the 1940s for the double murder of h... Terms({'The', 'Shawshank', 'Redemp...\n372058 Your Name. High schoolers Mitsuha and Taki are complete s... Terms({'Your', 'Name.'}, {'Your': ...\n238 The Godfather Spanning the years 1945 to 1955, a chronicle o... Terms({'The', 'Godfather'}, {'The'...\n... ... ... ...\n65513 They Came Back The lives of the residents of a small French t... Terms({'Back', 'They', 'Came'},...\n65515 The Eleventh Hour An ex-Navy SEAL, Michael Adams, (Matthew Reese... Terms({'The', 'Hour', 'Eleventh': ...\n65521 Pyaar Ka Punchnama Outspoken and overly critical Nishant Agarwal ... Terms({'Ka', 'Pyaar', 'Punchnama':...\n32767 Romero Romero is a compelling and deeply moving look ... Terms({'Romero'})\n65534 Poison Paul Braconnier and his wife Blandine only hav... Terms({'Poison'})```\n```\n\n(notice the dumb tokenization - no worries you can pass your own tokenizer).\n\nThen search, getting top N with `Cat`\n\n```\nIn[3]: np.sort(df['title_indexed'].array.score('Cat'))\nOut[3]: array([ 0. , 0. , 0. , ..., 15.84568033,\n 15.84568033, 15.84568033])\n\nIn[4]: df['title_indexed'].score('Cat').argsort()\nOut[4]: \n\narray([0, 18561, 18560, ..., 15038, 19012, 4392])\n```\n\nAnd since its just pandas, we can, of course just retrieve the top matches\n\n```\nIn[5]: df.iloc[top_n_cat[-10:]]\nOut[5]:\n title overview title_indexed\n24106 The Black Cat American honeymooners in Hungary are trapped i... Terms({'Black': 1, 'The': 1, 'Cat': 1}, ...\n12593 Fritz the Cat A hypocritical swinging college student cat ra... Terms({'Cat': 1, 'the': 1, 'Fritz': 1}, ...\n39853 The Cat Concerto Tom enters from stage left in white tie and ta... Terms({'The': 1, 'Cat': 1, 'Concerto': 1...\n75491 The Rabbi's Cat Based on the best-selling graphic novel by Joa... Terms({'The': 1, 'Cat': 1, \"Rabbi's\": 1}...\n57353 Cat Run When a sexy, high-end escort holds the key evi... Terms({'Cat': 1, 'Run': 1}, {'Cat': [0],...\n25508 Cat People Sketch artist Irena Dubrovna (Simon) and Ameri... Terms({'Cat': 1, 'People': 1}, {'Cat': [...\n11694 Cat Ballou A woman seeking revenge for her murdered fathe... Terms({'Cat': 1, 'Ballou': 1}, {'Cat': [...\n25078 Cat Soup The surreal black comedy follows Nyatta, an an... Terms({'Cat': 1, 'Soup': 1}, {'Cat': [0]...\n35888 Cat Chaser A Miami hotel owner finds danger when be becom... Terms({'Cat': 1, 'Chaser': 1}, {'Cat': [...\n6217 Cat People After years of separation, Irina (Nastassja Ki... Terms({'Cat': 1, 'People': 1}, {'Cat': [...\n```\n\nMore use cases can be seen [in the colab notebook](https://colab.research.google.com/drive/1w_Ajn5rHzcISKhdCuPhhVFav3zrvKWn1)\n\n## Goals \n\nThe overall goals are to recreate a lot of the lexical features (term / phrase search) of a search engine like Solr or Elasticsearch, but in a Pandas dataframe. \n\n### Memory efficient and fast text index\n\nWe want the index to be as memory efficient and fast at searching as possible. We want using it to have a minimal overhead.\n\nWe want you to be able to work with a reasonable dataset (100X-1M docs) relatively efficiently for offline evaluation. And 1000s for fast reranking in a service.\n\n### Experimentation, reranking, functionality over scalability\n\nInstead of building for 'big data' our goal is to build for *small-data*. That is, focus on capabilities and expressiveness of Pandas, over limiting functionality in favor of scalability.\n\nTo this end, the applications of searcharray will tend to be focused on experimentation and top N candidate reranking. For experimentation, we want any ideas expressed in Pandas to have a somewhat clear path / \"contract\" in how they'd be implemented in a classical lexical search engine. For reranking, we want to load some top N results from a base system and be able to modify them.\n\n### Make lexical search compatible with the data stack\n\nWe know in search, RAG, and other retrieval problems [hybrid search](https://www.pinecone.io/learn/hybrid-search-intro/) techniques dominate. Yet often its cast in terms of a giant, weird, big data lexical search engine that looks odd to most data scientists being joined with a vector database. We want lexical search to be more approachable to data scientists and ML engineers building these systems.\n\n## Non-goals\n\n### You need to bring your own tokenization\n\nPython libraries [already do tokenization really well](https://github.com/snowballstem). Even exceeding what Lucene can do... giving you the ability to simulate and/or exceed the abilities of Lucene's tokenization.\n\nIn SearchArray, a tokenizer is a function takes a string and emits a series of tokens. IE dumb, default whitespace tokenization:\n\n```python\ndef ws_tokenizer(string):\n return string.split()\n```\n\nAnd you can pass any tokenizer that matches this signature to index:\n\n```python\ndef ws_lowercase_tokenizer(string):\n return string.lower().split()\n\ndf['title_indexed'] = SearchArray.index(df['title'], tokenizer=ws_lowercase_tokenizer)\n```\n\nCreate your own using stemming libraries, or whatever Python functionality you want.\n\n### Use Pandas instead of function queries\n\nSolr has its [own unique function query syntax]()https://solr.apache.org/guide/7_7/function-queries.html. Elasticsearch has [Painless](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-painless.html).\n\nInstead of recreating these, simply use Pandas on existing Pandas columns. Then later, if you need to implement this in Solr or Elasticsearch, attempt to recreate the functionality. Arguably what's in Solr / ES would be a subset of what you could do in Pandas.\n\n```\n# Calculate the number of hours into the past\ndf['hrs_into_past'] = (now - df['timestamp']).dt.total_seconds() / 3600\n```\n\nThen multiply by BM25 if you want:\n\n```\ndf['score'] = df['title_indexed'].score('Cat') * df['hrs_into_past']\n```\n\n### Vector search\n\nWe focus on the lexical, ie \"BM25-ish\" and adjacent problems. There are other great tools for vector search out there.\n\n## Need help?\n\nVisit the [#searcharray channel on Relevance Slack](https://join.slack.com/t/relevancy/shared_invite/zt-2ccxvzn1w-2_50zf9xBOSv3n06Cu15jg)\n\n## TODOs / Future Work / Known issues\n\n* Always more efficient\n* Support tokenizers with overlapping positions (ie synonyms, etc)\n* Improve support for phrase slop\n* Helper functions (like [this start at edismax](https://github.com/softwaredoug/searcharray/blob/main/searcharray/solr.py) that help recreate Solr / Elasticsearch lexical queries)\n* Fuzzy search\n* Efficient way to \"slurp\" some top N results from retrieval system into a dataframe\n",
"bugtrack_url": null,
"license": null,
"summary": "Searchable pandas text extension arrays for prototyping search",
"version": "0.0.72",
"project_urls": {
"Homepage": "https://github.com/softwaredoug/searcharray"
},
"split_keywords": [
"sample",
" setuptools",
" development search"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "192cb2de81e6a3e6755a8c2c7e0a39483b85efaa2f187ccb199c3dac8fa03598",
"md5": "8efa1fe361cc62588595be3e6ee9a5e7",
"sha256": "4849a87547e4ebd04584fe0aa5c0d960249a4f901f29f50980c3938c1c6aa765"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp310-cp310-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "8efa1fe361cc62588595be3e6ee9a5e7",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4,>=3.10",
"size": 674218,
"upload_time": "2024-10-27T22:05:33",
"upload_time_iso_8601": "2024-10-27T22:05:33.851417Z",
"url": "https://files.pythonhosted.org/packages/19/2c/b2de81e6a3e6755a8c2c7e0a39483b85efaa2f187ccb199c3dac8fa03598/searcharray-0.0.72-cp310-cp310-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7ac3206df50d2e4d44ebdfbab8724535f99449f242a78338ff7260b4b520ae11",
"md5": "a6b786a32e84b2267c9de92ad75c3916",
"sha256": "432b3a4d38793abd07002cd961549a19e5b2c65e209abae23a4d715000f5c374"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp310-cp310-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "a6b786a32e84b2267c9de92ad75c3916",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4,>=3.10",
"size": 634013,
"upload_time": "2024-10-27T22:05:56",
"upload_time_iso_8601": "2024-10-27T22:05:56.826361Z",
"url": "https://files.pythonhosted.org/packages/7a/c3/206df50d2e4d44ebdfbab8724535f99449f242a78338ff7260b4b520ae11/searcharray-0.0.72-cp310-cp310-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "540fc27b711175769b9e173ba0ab885c0c45f12744a075915b57fe175ecd2d8a",
"md5": "ce65162f0a32944b2aebe7adcd7a87de",
"sha256": "0b827cc956517f7e445587e2c7f2398d03dcc4cd8dbce5eb69758afd63c6e183"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "ce65162f0a32944b2aebe7adcd7a87de",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4,>=3.10",
"size": 3490470,
"upload_time": "2024-10-27T22:05:50",
"upload_time_iso_8601": "2024-10-27T22:05:50.518199Z",
"url": "https://files.pythonhosted.org/packages/54/0f/c27b711175769b9e173ba0ab885c0c45f12744a075915b57fe175ecd2d8a/searcharray-0.0.72-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "446dcb8f04378f7f0d0e50da1b502deced3168b8907096c924b1fd875f1eff70",
"md5": "d2bf9bf4ba9bc2c206bafd45d9959e77",
"sha256": "ee429977bfd3be4d96baf3d74a773d98688961f1de62790d1273b70600bf873a"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp310-cp310-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "d2bf9bf4ba9bc2c206bafd45d9959e77",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4,>=3.10",
"size": 3633409,
"upload_time": "2024-10-27T22:06:08",
"upload_time_iso_8601": "2024-10-27T22:06:08.223238Z",
"url": "https://files.pythonhosted.org/packages/44/6d/cb8f04378f7f0d0e50da1b502deced3168b8907096c924b1fd875f1eff70/searcharray-0.0.72-cp310-cp310-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c6e8e2aeb11de97b02693f99e2cf420e130daf6fa8652ec8ee1a5ae8d3a2a9eb",
"md5": "e9044a3962bbe48347092fe382520e94",
"sha256": "4c28df254501c7636bec995215ea9713e8cf6dc8749b0606e6e30ea548b3388d"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp311-cp311-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "e9044a3962bbe48347092fe382520e94",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4,>=3.10",
"size": 674329,
"upload_time": "2024-10-27T22:05:52",
"upload_time_iso_8601": "2024-10-27T22:05:52.683026Z",
"url": "https://files.pythonhosted.org/packages/c6/e8/e2aeb11de97b02693f99e2cf420e130daf6fa8652ec8ee1a5ae8d3a2a9eb/searcharray-0.0.72-cp311-cp311-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "741c1bd10377451469b7ba06691dc15412be6fcc5c61a08d74cf1a7d80c419f1",
"md5": "19272fc2d006f75d55d8e895b8718424",
"sha256": "3505e77a34bd831693c26feec587d0637e9ab1ae9f0489a29e062d2f3db62bc3"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp311-cp311-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "19272fc2d006f75d55d8e895b8718424",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4,>=3.10",
"size": 633326,
"upload_time": "2024-10-27T22:05:47",
"upload_time_iso_8601": "2024-10-27T22:05:47.601917Z",
"url": "https://files.pythonhosted.org/packages/74/1c/1bd10377451469b7ba06691dc15412be6fcc5c61a08d74cf1a7d80c419f1/searcharray-0.0.72-cp311-cp311-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "a92d5893fafa21ba726f00a034c30b34c12f122aa4352027ba2c9ca0726250c7",
"md5": "7ff42fc556648206814e1a8174478ea2",
"sha256": "8c17fbbf94e38290cc3d36e94432e32d3d45d6cafef3b6cb59de7c596c7125f3"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "7ff42fc556648206814e1a8174478ea2",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4,>=3.10",
"size": 3769007,
"upload_time": "2024-10-27T22:05:44",
"upload_time_iso_8601": "2024-10-27T22:05:44.131383Z",
"url": "https://files.pythonhosted.org/packages/a9/2d/5893fafa21ba726f00a034c30b34c12f122aa4352027ba2c9ca0726250c7/searcharray-0.0.72-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3eafedd5c64bd48c366d6564b8c42d73d4bccfa2d60611fca7c24c5cdbd40bc2",
"md5": "ef0867cafe48877c9dd8593f8ba84218",
"sha256": "0bbdb939a0172c2b8a75096cc15d1905bc1914b180dde422d24b89f5fe2061fd"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp311-cp311-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "ef0867cafe48877c9dd8593f8ba84218",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4,>=3.10",
"size": 3934491,
"upload_time": "2024-10-27T22:06:04",
"upload_time_iso_8601": "2024-10-27T22:06:04.675486Z",
"url": "https://files.pythonhosted.org/packages/3e/af/edd5c64bd48c366d6564b8c42d73d4bccfa2d60611fca7c24c5cdbd40bc2/searcharray-0.0.72-cp311-cp311-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9088b05e628db51392a6c630d98a1c058f37ee1fe559f0ceea40c08a8eb7514a",
"md5": "cc9715e394e314a6693b0d3779dfcc9c",
"sha256": "f5f19a2cc6ebf1823e82d22fb4f869848fd1e729966b4ae988eaf45c51ca76a5"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp312-cp312-macosx_10_13_x86_64.whl",
"has_sig": false,
"md5_digest": "cc9715e394e314a6693b0d3779dfcc9c",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": "<4,>=3.10",
"size": 681132,
"upload_time": "2024-10-27T22:06:11",
"upload_time_iso_8601": "2024-10-27T22:06:11.255245Z",
"url": "https://files.pythonhosted.org/packages/90/88/b05e628db51392a6c630d98a1c058f37ee1fe559f0ceea40c08a8eb7514a/searcharray-0.0.72-cp312-cp312-macosx_10_13_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "511d3b6750a30da76154ada9d3f65d4e1f48f8ed22dadbb0a395a196c77dc082",
"md5": "38674c8914a4660f4b28de7a7dfc34c5",
"sha256": "ad31b3d1560f54b5a7fab3dd28518eaa70ed982bb6e8a8c01b904b502c5de9df"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp312-cp312-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "38674c8914a4660f4b28de7a7dfc34c5",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": "<4,>=3.10",
"size": 640002,
"upload_time": "2024-10-27T22:05:35",
"upload_time_iso_8601": "2024-10-27T22:05:35.824125Z",
"url": "https://files.pythonhosted.org/packages/51/1d/3b6750a30da76154ada9d3f65d4e1f48f8ed22dadbb0a395a196c77dc082/searcharray-0.0.72-cp312-cp312-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "26e7c49b5d881ea5a617183ec7bc542c912dff96069eabf6c1259a9e4835f2c7",
"md5": "44bff71981192d1990f840a901e3350e",
"sha256": "6b3a5dd7a91fb08417488e2d58a9051621198ba8560d396d0e2a0c519aaa35dd"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "44bff71981192d1990f840a901e3350e",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": "<4,>=3.10",
"size": 3687129,
"upload_time": "2024-10-27T22:05:27",
"upload_time_iso_8601": "2024-10-27T22:05:27.055380Z",
"url": "https://files.pythonhosted.org/packages/26/e7/c49b5d881ea5a617183ec7bc542c912dff96069eabf6c1259a9e4835f2c7/searcharray-0.0.72-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "93f3fa7d25428b84e4effbb1209ac09a80853109121c11dada61ac036572b5db",
"md5": "e6b42616a4b299c316d8417942ac3496",
"sha256": "a56c2adc4eda5a20661b5fb23226b9a9b1b9ac8a0a45dd54b44c39173ab1bbd4"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp312-cp312-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "e6b42616a4b299c316d8417942ac3496",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": "<4,>=3.10",
"size": 3844920,
"upload_time": "2024-10-27T22:05:59",
"upload_time_iso_8601": "2024-10-27T22:05:59.905504Z",
"url": "https://files.pythonhosted.org/packages/93/f3/fa7d25428b84e4effbb1209ac09a80853109121c11dada61ac036572b5db/searcharray-0.0.72-cp312-cp312-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b77303acfe8ed7067857399659595ac2fe3f461d26ce2966f2a6074fbc57defd",
"md5": "b569599493ecb91d391bc92f7c3cd576",
"sha256": "f7d64af17f7c3c030934fc8ffd01f2603d94ee6c4325501402d60aba2ab8e0ef"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp313-cp313-macosx_10_13_x86_64.whl",
"has_sig": false,
"md5_digest": "b569599493ecb91d391bc92f7c3cd576",
"packagetype": "bdist_wheel",
"python_version": "cp313",
"requires_python": "<4,>=3.10",
"size": 671584,
"upload_time": "2024-10-27T22:05:29",
"upload_time_iso_8601": "2024-10-27T22:05:29.795424Z",
"url": "https://files.pythonhosted.org/packages/b7/73/03acfe8ed7067857399659595ac2fe3f461d26ce2966f2a6074fbc57defd/searcharray-0.0.72-cp313-cp313-macosx_10_13_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9a569fb785843a0f315e7689e15b13b51b3f04df924a8fc14f5c805157e8d11b",
"md5": "bfdaf19cd3f0740125dee4e9ed9fdacf",
"sha256": "68c0e2c66033072e71ad9b38f77c8d10ed58f61e21c7c96b21be60137a5b6bcb"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp313-cp313-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "bfdaf19cd3f0740125dee4e9ed9fdacf",
"packagetype": "bdist_wheel",
"python_version": "cp313",
"requires_python": "<4,>=3.10",
"size": 631301,
"upload_time": "2024-10-27T22:06:06",
"upload_time_iso_8601": "2024-10-27T22:06:06.288126Z",
"url": "https://files.pythonhosted.org/packages/9a/56/9fb785843a0f315e7689e15b13b51b3f04df924a8fc14f5c805157e8d11b/searcharray-0.0.72-cp313-cp313-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "09cd549ad2c46cd172507a41800ea63c36ac24add8dffc8d47da302a89efba16",
"md5": "269ccdaa9423cc6e19896fe241a9371f",
"sha256": "5b6320e116d42443245115ef5357afefcc31175b0332d9a77a14a1d194975c3b"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "269ccdaa9423cc6e19896fe241a9371f",
"packagetype": "bdist_wheel",
"python_version": "cp313",
"requires_python": "<4,>=3.10",
"size": 3659822,
"upload_time": "2024-10-27T22:05:40",
"upload_time_iso_8601": "2024-10-27T22:05:40.181519Z",
"url": "https://files.pythonhosted.org/packages/09/cd/549ad2c46cd172507a41800ea63c36ac24add8dffc8d47da302a89efba16/searcharray-0.0.72-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "abc51bda803db08841eb7d97dbb0a191f3782e4f7972316048a1c10bd0f89e2e",
"md5": "b8927e0abfc98a84c2c4a0db7ea74f56",
"sha256": "8a6a02eb6b5fc711e33de51775d745c118f7e5d0dc66b5b167092ab223b44bbb"
},
"downloads": -1,
"filename": "searcharray-0.0.72-cp313-cp313-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "b8927e0abfc98a84c2c4a0db7ea74f56",
"packagetype": "bdist_wheel",
"python_version": "cp313",
"requires_python": "<4,>=3.10",
"size": 3809767,
"upload_time": "2024-10-27T22:05:54",
"upload_time_iso_8601": "2024-10-27T22:05:54.986820Z",
"url": "https://files.pythonhosted.org/packages/ab/c5/1bda803db08841eb7d97dbb0a191f3782e4f7972316048a1c10bd0f89e2e/searcharray-0.0.72-cp313-cp313-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f2f1a8b251092999d9df9bee323729dc9a98383ed215c276879875015bbdd3e9",
"md5": "0a9993f4022a250576cbf998c2c5e246",
"sha256": "bc3a55a7ccd7687817156ebd8a5b2a3530fc974dde88fd4567d8fe3289dda3fd"
},
"downloads": -1,
"filename": "searcharray-0.0.72-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",
"has_sig": false,
"md5_digest": "0a9993f4022a250576cbf998c2c5e246",
"packagetype": "bdist_wheel",
"python_version": "pp310",
"requires_python": "<4,>=3.10",
"size": 559984,
"upload_time": "2024-10-27T22:05:58",
"upload_time_iso_8601": "2024-10-27T22:05:58.025412Z",
"url": "https://files.pythonhosted.org/packages/f2/f1/a8b251092999d9df9bee323729dc9a98383ed215c276879875015bbdd3e9/searcharray-0.0.72-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8a73fed0b4e30665517068769298cad7b1e3c0e38775ee8c797a12edb6a8700a",
"md5": "2e1af87361d845535d872baa9c986bcc",
"sha256": "a64efee116aeb2b5f5e9112f858808c457154c6528c2e1a832caecd300f133db"
},
"downloads": -1,
"filename": "searcharray-0.0.72-pp310-pypy310_pp73-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "2e1af87361d845535d872baa9c986bcc",
"packagetype": "bdist_wheel",
"python_version": "pp310",
"requires_python": "<4,>=3.10",
"size": 535206,
"upload_time": "2024-10-27T22:06:01",
"upload_time_iso_8601": "2024-10-27T22:06:01.344549Z",
"url": "https://files.pythonhosted.org/packages/8a/73/fed0b4e30665517068769298cad7b1e3c0e38775ee8c797a12edb6a8700a/searcharray-0.0.72-pp310-pypy310_pp73-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "99056e7c9531f1b3d58f382fa6143160ca914537eb605c9ac070c0f624ff98cd",
"md5": "8460558c6656efe06f74cbc8359271b5",
"sha256": "9914b2883431a8d734ec69befaeca15cd1fe26cfba15d471bb9acefaaa90684e"
},
"downloads": -1,
"filename": "searcharray-0.0.72-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "8460558c6656efe06f74cbc8359271b5",
"packagetype": "bdist_wheel",
"python_version": "pp310",
"requires_python": "<4,>=3.10",
"size": 675415,
"upload_time": "2024-10-27T22:05:45",
"upload_time_iso_8601": "2024-10-27T22:05:45.929221Z",
"url": "https://files.pythonhosted.org/packages/99/05/6e7c9531f1b3d58f382fa6143160ca914537eb605c9ac070c0f624ff98cd/searcharray-0.0.72-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-27 22:05:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "softwaredoug",
"github_project": "searcharray",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "appnope",
"specs": [
[
"==",
"0.1.3"
]
]
},
{
"name": "asttokens",
"specs": [
[
"==",
"2.4.1"
]
]
},
{
"name": "build",
"specs": [
[
"==",
"1.0.3"
]
]
},
{
"name": "certifi",
"specs": [
[
"==",
"2023.7.22"
]
]
},
{
"name": "charset-normalizer",
"specs": [
[
"==",
"3.3.2"
]
]
},
{
"name": "contourpy",
"specs": [
[
"==",
"1.3.0"
]
]
},
{
"name": "coverage",
"specs": [
[
"==",
"7.3.2"
]
]
},
{
"name": "cycler",
"specs": [
[
"==",
"0.12.1"
]
]
},
{
"name": "Cython",
"specs": [
[
"==",
"3.0.8"
]
]
},
{
"name": "cython-lint",
"specs": [
[
"==",
"0.16.2"
]
]
},
{
"name": "decorator",
"specs": [
[
"==",
"5.1.1"
]
]
},
{
"name": "docutils",
"specs": [
[
"==",
"0.20.1"
]
]
},
{
"name": "executing",
"specs": [
[
"==",
"2.0.1"
]
]
},
{
"name": "flake8",
"specs": [
[
"==",
"6.1.0"
]
]
},
{
"name": "flake8-print",
"specs": [
[
"==",
"5.0.0"
]
]
},
{
"name": "fonttools",
"specs": [
[
"==",
"4.46.0"
]
]
},
{
"name": "idna",
"specs": [
[
"==",
"3.4"
]
]
},
{
"name": "importlib-metadata",
"specs": [
[
"==",
"6.8.0"
]
]
},
{
"name": "iniconfig",
"specs": [
[
"==",
"2.0.0"
]
]
},
{
"name": "ipython",
"specs": [
[
"==",
"8.17.2"
]
]
},
{
"name": "jaraco.classes",
"specs": [
[
"==",
"3.3.0"
]
]
},
{
"name": "jedi",
"specs": [
[
"==",
"0.19.1"
]
]
},
{
"name": "Jinja2",
"specs": [
[
"==",
"3.1.3"
]
]
},
{
"name": "keyring",
"specs": [
[
"==",
"24.3.0"
]
]
},
{
"name": "kiwisolver",
"specs": [
[
"==",
"1.4.5"
]
]
},
{
"name": "linkify-it-py",
"specs": [
[
"==",
"2.0.3"
]
]
},
{
"name": "markdown-it-py",
"specs": [
[
"==",
"3.0.0"
]
]
},
{
"name": "MarkupSafe",
"specs": [
[
"==",
"2.1.5"
]
]
},
{
"name": "matplotlib",
"specs": [
[
"==",
"3.9.2"
]
]
},
{
"name": "matplotlib-inline",
"specs": [
[
"==",
"0.1.6"
]
]
},
{
"name": "mccabe",
"specs": [
[
"==",
"0.7.0"
]
]
},
{
"name": "mdit-py-plugins",
"specs": [
[
"==",
"0.4.0"
]
]
},
{
"name": "mdurl",
"specs": [
[
"==",
"0.1.2"
]
]
},
{
"name": "memray",
"specs": [
[
"==",
"1.11.0"
]
]
},
{
"name": "more-itertools",
"specs": [
[
"==",
"10.1.0"
]
]
},
{
"name": "mypy",
"specs": [
[
"==",
"1.8.0"
]
]
},
{
"name": "mypy-extensions",
"specs": [
[
"==",
"1.0.0"
]
]
},
{
"name": "nh3",
"specs": [
[
"==",
"0.2.14"
]
]
},
{
"name": "numpy",
"specs": [
[
">=",
"1.26.0"
]
]
},
{
"name": "packaging",
"specs": [
[
"==",
"23.2"
]
]
},
{
"name": "pandas",
"specs": [
[
"==",
"2.2.3"
]
]
},
{
"name": "pandas-stubs",
"specs": [
[
"==",
"2.1.4.231218"
]
]
},
{
"name": "parso",
"specs": [
[
"==",
"0.8.3"
]
]
},
{
"name": "pexpect",
"specs": [
[
"==",
"4.8.0"
]
]
},
{
"name": "Pillow",
"specs": [
[
"==",
"10.1.0"
]
]
},
{
"name": "pkginfo",
"specs": [
[
"==",
"1.9.6"
]
]
},
{
"name": "pluggy",
"specs": [
[
"==",
"1.3.0"
]
]
},
{
"name": "prompt-toolkit",
"specs": [
[
"==",
"3.0.39"
]
]
},
{
"name": "psutil",
"specs": [
[
"==",
"5.9.8"
]
]
},
{
"name": "ptyprocess",
"specs": [
[
"==",
"0.7.0"
]
]
},
{
"name": "pure-eval",
"specs": [
[
"==",
"0.2.2"
]
]
},
{
"name": "py-cpuinfo",
"specs": [
[
"==",
"9.0.0"
]
]
},
{
"name": "pycodestyle",
"specs": [
[
"==",
"2.11.1"
]
]
},
{
"name": "pyflakes",
"specs": [
[
"==",
"3.1.0"
]
]
},
{
"name": "pygal",
"specs": [
[
"==",
"3.0.4"
]
]
},
{
"name": "Pygments",
"specs": [
[
"==",
"2.16.1"
]
]
},
{
"name": "pyparsing",
"specs": [
[
"==",
"3.1.1"
]
]
},
{
"name": "pyproject_hooks",
"specs": [
[
"==",
"1.0.0"
]
]
},
{
"name": "pyroaring",
"specs": [
[
"==",
"0.4.4"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"7.4.3"
]
]
},
{
"name": "pytest-benchmark",
"specs": [
[
"==",
"4.0.0"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
"==",
"4.1.0"
]
]
},
{
"name": "pytest-memray",
"specs": [
[
"==",
"1.5.0"
]
]
},
{
"name": "python-dateutil",
"specs": [
[
"==",
"2.8.2"
]
]
},
{
"name": "pytz",
"specs": [
[
"==",
"2023.3.post1"
]
]
},
{
"name": "readme-renderer",
"specs": [
[
"==",
"42.0"
]
]
},
{
"name": "requests",
"specs": [
[
"==",
"2.31.0"
]
]
},
{
"name": "requests-toolbelt",
"specs": [
[
"==",
"1.0.0"
]
]
},
{
"name": "rfc3986",
"specs": [
[
"==",
"2.0.0"
]
]
},
{
"name": "rich",
"specs": [
[
"==",
"13.6.0"
]
]
},
{
"name": "scipy",
"specs": [
[
"==",
"1.14.1"
]
]
},
{
"name": "searcharray",
"specs": [
[
"==",
"0.0.1"
]
]
},
{
"name": "setuptools",
"specs": [
[
"==",
"75.2.0"
]
]
},
{
"name": "six",
"specs": [
[
"==",
"1.16.0"
]
]
},
{
"name": "snakeviz",
"specs": [
[
"==",
"2.2.0"
]
]
},
{
"name": "sortednp",
"specs": [
[
"==",
"0.4.1"
]
]
},
{
"name": "stack-data",
"specs": [
[
"==",
"0.6.3"
]
]
},
{
"name": "textual",
"specs": [
[
"==",
"0.50.1"
]
]
},
{
"name": "tokenize_rt",
"specs": [
[
"==",
"6.1.0"
]
]
},
{
"name": "tornado",
"specs": [
[
"==",
"6.4"
]
]
},
{
"name": "traitlets",
"specs": [
[
"==",
"5.13.0"
]
]
},
{
"name": "twine",
"specs": [
[
"==",
"4.0.2"
]
]
},
{
"name": "types-pytz",
"specs": [
[
"==",
"2023.3.1.1"
]
]
},
{
"name": "types-requests",
"specs": [
[
"==",
"2.31.0.10"
]
]
},
{
"name": "typing_extensions",
"specs": [
[
"==",
"4.9.0"
]
]
},
{
"name": "tzdata",
"specs": [
[
"==",
"2023.3"
]
]
},
{
"name": "uc-micro-py",
"specs": [
[
"==",
"1.0.3"
]
]
},
{
"name": "urllib3",
"specs": [
[
"==",
"2.1.0"
]
]
},
{
"name": "wcwidth",
"specs": [
[
"==",
"0.2.9"
]
]
},
{
"name": "zipp",
"specs": [
[
"==",
"3.17.0"
]
]
},
{
"name": "cython-lint",
"specs": []
}
],
"lcname": "searcharray"
}