Restore 0.1.5 version from stash

This commit is contained in:
liaibo
2025-12-08 19:56:24 +08:00
parent de189e938d
commit 8db3f4e32d
8578 changed files with 2703426 additions and 217 deletions
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2021-2024 Andrew Kane
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,554 @@
Metadata-Version: 2.1
Name: pgvector
Version: 0.3.5
Summary: pgvector support for Python
Author-email: Andrew Kane <andrew@ankane.org>
License: MIT
Project-URL: Homepage, https://github.com/pgvector/pgvector-python
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: numpy
# pgvector-python
[pgvector](https://github.com/pgvector/pgvector) support for Python
Supports [Django](https://github.com/django/django), [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy), [SQLModel](https://github.com/tiangolo/sqlmodel), [Psycopg 3](https://github.com/psycopg/psycopg), [Psycopg 2](https://github.com/psycopg/psycopg2), [asyncpg](https://github.com/MagicStack/asyncpg), and [Peewee](https://github.com/coleifer/peewee)
[![Build Status](https://github.com/pgvector/pgvector-python/actions/workflows/build.yml/badge.svg)](https://github.com/pgvector/pgvector-python/actions)
## Installation
Run:
```sh
pip install pgvector
```
And follow the instructions for your database library:
- [Django](#django)
- [SQLAlchemy](#sqlalchemy)
- [SQLModel](#sqlmodel)
- [Psycopg 3](#psycopg-3)
- [Psycopg 2](#psycopg-2)
- [asyncpg](#asyncpg)
- [Peewee](#peewee)
Or check out some examples:
- [Embeddings](https://github.com/pgvector/pgvector-python/blob/master/examples/openai/example.py) with OpenAI
- [Binary embeddings](https://github.com/pgvector/pgvector-python/blob/master/examples/cohere/example.py) with Cohere
- [Sentence embeddings](https://github.com/pgvector/pgvector-python/blob/master/examples/sentence_transformers/example.py) with SentenceTransformers
- [Hybrid search](https://github.com/pgvector/pgvector-python/blob/master/examples/hybrid_search/rrf.py) with SentenceTransformers (Reciprocal Rank Fusion)
- [Hybrid search](https://github.com/pgvector/pgvector-python/blob/master/examples/hybrid_search/cross_encoder.py) with SentenceTransformers (cross-encoder)
- [Sparse search](https://github.com/pgvector/pgvector-python/blob/master/examples/sparse_search/example.py) with Transformers
- [Late interaction search](https://github.com/pgvector/pgvector-python/blob/master/examples/colbert/exact.py) with ColBERT
- [Image search](https://github.com/pgvector/pgvector-python/blob/master/examples/image_search/example.py) with PyTorch
- [Image search](https://github.com/pgvector/pgvector-python/blob/master/examples/imagehash/example.py) with perceptual hashing
- [Morgan fingerprints](https://github.com/pgvector/pgvector-python/blob/master/examples/rdkit/example.py) with RDKit
- [Topic modeling](https://github.com/pgvector/pgvector-python/blob/master/examples/gensim/example.py) with Gensim
- [Implicit feedback recommendations](https://github.com/pgvector/pgvector-python/blob/master/examples/implicit/example.py) with Implicit
- [Explicit feedback recommendations](https://github.com/pgvector/pgvector-python/blob/master/examples/surprise/example.py) with Surprise
- [Recommendations](https://github.com/pgvector/pgvector-python/blob/master/examples/lightfm/example.py) with LightFM
- [Horizontal scaling](https://github.com/pgvector/pgvector-python/blob/master/examples/citus/example.py) with Citus
- [Bulk loading](https://github.com/pgvector/pgvector-python/blob/master/examples/loading/example.py) with `COPY`
## Django
Create a migration to enable the extension
```python
from pgvector.django import VectorExtension
class Migration(migrations.Migration):
operations = [
VectorExtension()
]
```
Add a vector field to your model
```python
from pgvector.django import VectorField
class Item(models.Model):
embedding = VectorField(dimensions=3)
```
Also supports `HalfVectorField`, `BitField`, and `SparseVectorField`
Insert a vector
```python
item = Item(embedding=[1, 2, 3])
item.save()
```
Get the nearest neighbors to a vector
```python
from pgvector.django import L2Distance
Item.objects.order_by(L2Distance('embedding', [3, 1, 2]))[:5]
```
Also supports `MaxInnerProduct`, `CosineDistance`, `L1Distance`, `HammingDistance`, and `JaccardDistance`
Get the distance
```python
Item.objects.annotate(distance=L2Distance('embedding', [3, 1, 2]))
```
Get items within a certain distance
```python
Item.objects.alias(distance=L2Distance('embedding', [3, 1, 2])).filter(distance__lt=5)
```
Average vectors
```python
from django.db.models import Avg
Item.objects.aggregate(Avg('embedding'))
```
Also supports `Sum`
Add an approximate index
```python
from pgvector.django import HnswIndex, IvfflatIndex
class Item(models.Model):
class Meta:
indexes = [
HnswIndex(
name='my_index',
fields=['embedding'],
m=16,
ef_construction=64,
opclasses=['vector_l2_ops']
),
# or
IvfflatIndex(
name='my_index',
fields=['embedding'],
lists=100,
opclasses=['vector_l2_ops']
)
]
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## SQLAlchemy
Enable the extension
```python
session.execute(text('CREATE EXTENSION IF NOT EXISTS vector'))
```
Add a vector column
```python
from pgvector.sqlalchemy import Vector
class Item(Base):
embedding = mapped_column(Vector(3))
```
Also supports `HALFVEC`, `BIT`, and `SPARSEVEC`
Insert a vector
```python
item = Item(embedding=[1, 2, 3])
session.add(item)
session.commit()
```
Get the nearest neighbors to a vector
```python
session.scalars(select(Item).order_by(Item.embedding.l2_distance([3, 1, 2])).limit(5))
```
Also supports `max_inner_product`, `cosine_distance`, `l1_distance`, `hamming_distance`, and `jaccard_distance`
Get the distance
```python
session.scalars(select(Item.embedding.l2_distance([3, 1, 2])))
```
Get items within a certain distance
```python
session.scalars(select(Item).filter(Item.embedding.l2_distance([3, 1, 2]) < 5))
```
Average vectors
```python
from pgvector.sqlalchemy import avg
session.scalars(select(func.avg(Item.embedding))).first()
```
Also supports `sum`
Add an approximate index
```python
index = Index(
'my_index',
Item.embedding,
postgresql_using='hnsw',
postgresql_with={'m': 16, 'ef_construction': 64},
postgresql_ops={'embedding': 'vector_l2_ops'}
)
# or
index = Index(
'my_index',
Item.embedding,
postgresql_using='ivfflat',
postgresql_with={'lists': 100},
postgresql_ops={'embedding': 'vector_l2_ops'}
)
index.create(engine)
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## SQLModel
Enable the extension
```python
session.exec(text('CREATE EXTENSION IF NOT EXISTS vector'))
```
Add a vector column
```python
from pgvector.sqlalchemy import Vector
from sqlalchemy import Column
class Item(SQLModel, table=True):
embedding: Any = Field(sa_column=Column(Vector(3)))
```
Also supports `HALFVEC`, `BIT`, and `SPARSEVEC`
Insert a vector
```python
item = Item(embedding=[1, 2, 3])
session.add(item)
session.commit()
```
Get the nearest neighbors to a vector
```python
session.exec(select(Item).order_by(Item.embedding.l2_distance([3, 1, 2])).limit(5))
```
Also supports `max_inner_product`, `cosine_distance`, `l1_distance`, `hamming_distance`, and `jaccard_distance`
Get the distance
```python
session.exec(select(Item.embedding.l2_distance([3, 1, 2])))
```
Get items within a certain distance
```python
session.exec(select(Item).filter(Item.embedding.l2_distance([3, 1, 2]) < 5))
```
Average vectors
```python
from pgvector.sqlalchemy import avg
session.exec(select(func.avg(Item.embedding))).first()
```
Also supports `sum`
Add an approximate index
```python
from sqlalchemy import Index
index = Index(
'my_index',
Item.embedding,
postgresql_using='hnsw',
postgresql_with={'m': 16, 'ef_construction': 64},
postgresql_ops={'embedding': 'vector_l2_ops'}
)
# or
index = Index(
'my_index',
Item.embedding,
postgresql_using='ivfflat',
postgresql_with={'lists': 100},
postgresql_ops={'embedding': 'vector_l2_ops'}
)
index.create(engine)
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## Psycopg 3
Enable the extension
```python
conn.execute('CREATE EXTENSION IF NOT EXISTS vector')
```
Register the vector type with your connection
```python
from pgvector.psycopg import register_vector
register_vector(conn)
```
For [async connections](https://www.psycopg.org/psycopg3/docs/advanced/async.html), use
```python
from pgvector.psycopg import register_vector_async
await register_vector_async(conn)
```
Create a table
```python
conn.execute('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))')
```
Insert a vector
```python
embedding = np.array([1, 2, 3])
conn.execute('INSERT INTO items (embedding) VALUES (%s)', (embedding,))
```
Get the nearest neighbors to a vector
```python
conn.execute('SELECT * FROM items ORDER BY embedding <-> %s LIMIT 5', (embedding,)).fetchall()
```
Add an approximate index
```python
conn.execute('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)')
# or
conn.execute('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)')
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## Psycopg 2
Enable the extension
```python
cur = conn.cursor()
cur.execute('CREATE EXTENSION IF NOT EXISTS vector')
```
Register the vector type with your connection or cursor
```python
from pgvector.psycopg2 import register_vector
register_vector(conn)
```
Create a table
```python
cur.execute('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))')
```
Insert a vector
```python
embedding = np.array([1, 2, 3])
cur.execute('INSERT INTO items (embedding) VALUES (%s)', (embedding,))
```
Get the nearest neighbors to a vector
```python
cur.execute('SELECT * FROM items ORDER BY embedding <-> %s LIMIT 5', (embedding,))
cur.fetchall()
```
Add an approximate index
```python
cur.execute('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)')
# or
cur.execute('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)')
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## asyncpg
Enable the extension
```python
await conn.execute('CREATE EXTENSION IF NOT EXISTS vector')
```
Register the vector type with your connection
```python
from pgvector.asyncpg import register_vector
await register_vector(conn)
```
or your pool
```python
async def init(conn):
await register_vector(conn)
pool = await asyncpg.create_pool(..., init=init)
```
Create a table
```python
await conn.execute('CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3))')
```
Insert a vector
```python
embedding = np.array([1, 2, 3])
await conn.execute('INSERT INTO items (embedding) VALUES ($1)', embedding)
```
Get the nearest neighbors to a vector
```python
await conn.fetch('SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5', embedding)
```
Add an approximate index
```python
await conn.execute('CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)')
# or
await conn.execute('CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)')
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## Peewee
Add a vector column
```python
from pgvector.peewee import VectorField
class Item(BaseModel):
embedding = VectorField(dimensions=3)
```
Also supports `HalfVectorField`, `FixedBitField`, and `SparseVectorField`
Insert a vector
```python
item = Item.create(embedding=[1, 2, 3])
```
Get the nearest neighbors to a vector
```python
Item.select().order_by(Item.embedding.l2_distance([3, 1, 2])).limit(5)
```
Also supports `max_inner_product`, `cosine_distance`, `l1_distance`, `hamming_distance`, and `jaccard_distance`
Get the distance
```python
Item.select(Item.embedding.l2_distance([3, 1, 2]).alias('distance'))
```
Get items within a certain distance
```python
Item.select().where(Item.embedding.l2_distance([3, 1, 2]) < 5)
```
Average vectors
```python
from peewee import fn
Item.select(fn.avg(Item.embedding).coerce(True)).scalar()
```
Also supports `sum`
Add an approximate index
```python
Item.add_index('embedding vector_l2_ops', using='hnsw')
```
Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance
## History
View the [changelog](https://github.com/pgvector/pgvector-python/blob/master/CHANGELOG.md)
## Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- [Report bugs](https://github.com/pgvector/pgvector-python/issues)
- Fix bugs and [submit pull requests](https://github.com/pgvector/pgvector-python/pulls)
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
```sh
git clone https://github.com/pgvector/pgvector-python.git
cd pgvector-python
pip install -r requirements.txt
createdb pgvector_python_test
pytest
```
To run an example:
```sh
cd examples/loading
pip install -r requirements.txt
createdb pgvector_example
python3 example.py
```
@@ -0,0 +1,81 @@
pgvector-0.3.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pgvector-0.3.5.dist-info/LICENSE.txt,sha256=kzzb1DKtBwp3Pn5-R7YEUm8uH1qHA-D2tjT67Bn_b6M,1083
pgvector-0.3.5.dist-info/METADATA,sha256=J5ZibepgmNk94dtOOYnO0ZiRyqhz7YSfvs1w98xoc6E,13231
pgvector-0.3.5.dist-info/RECORD,,
pgvector-0.3.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pgvector-0.3.5.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
pgvector-0.3.5.dist-info/top_level.txt,sha256=xGGaXFRcSRHEhn0HS1FN_UjCWr1G-WSPgxx4a0NJc0M,9
pgvector/asyncpg/__init__.py,sha256=nPEfolmn6hf2gmonE1sCne051hd28biWhlSRimDy0AI,180
pgvector/asyncpg/__pycache__/__init__.cpython-312.pyc,,
pgvector/asyncpg/__pycache__/register.cpython-312.pyc,,
pgvector/asyncpg/register.py,sha256=33xZD3SZjkDUFcEuVvVVQPZLEkpBVZZE2iZeWbLa1lc,835
pgvector/django/__init__.py,sha256=omSXhf85Nazw2e1h2HzgxphL-MNTZUg7A_hwQ6nXBCo,701
pgvector/django/__pycache__/__init__.cpython-312.pyc,,
pgvector/django/__pycache__/bit.cpython-312.pyc,,
pgvector/django/__pycache__/extensions.cpython-312.pyc,,
pgvector/django/__pycache__/functions.cpython-312.pyc,,
pgvector/django/__pycache__/halfvec.cpython-312.pyc,,
pgvector/django/__pycache__/indexes.cpython-312.pyc,,
pgvector/django/__pycache__/sparsevec.cpython-312.pyc,,
pgvector/django/__pycache__/vector.cpython-312.pyc,,
pgvector/django/bit.py,sha256=QjWHD4FhsveLQ8r3Q8SYDoe-zIYnhHR0W7HDLGx87Dc,935
pgvector/django/extensions.py,sha256=JAtn_FCIST0DWJtDPZAQ-MygbAkKEiL0ZsA2QbYITRo,158
pgvector/django/functions.py,sha256=QC6tiWErauN7EtbYqISiwJcpSGnxEW9qOhUBmwmGeoY,1364
pgvector/django/halfvec.py,sha256=XNr54sddUquK3yDOfJT8BJHbRrEGjN7bwAnRKi_rOgM,1825
pgvector/django/indexes.py,sha256=purT3nhq_CjHWUe-c3loCyK1XrWtZJ8pIq2wl975aSY,1440
pgvector/django/sparsevec.py,sha256=KJlGF_VAxSV1eSOHPzfT4uNhCGDMBqjjANJPq2E7osE,1675
pgvector/django/vector.py,sha256=xASXG7KGr65HsvsLYYrJfwv6azbDOdPcdmw9QLOHayA,2215
pgvector/peewee/__init__.py,sha256=tANx57_gHFXgJLnr7GhD5j_xhsCosZ4GWBpdG76FNnY,326
pgvector/peewee/__pycache__/__init__.cpython-312.pyc,,
pgvector/peewee/__pycache__/bit.cpython-312.pyc,,
pgvector/peewee/__pycache__/halfvec.cpython-312.pyc,,
pgvector/peewee/__pycache__/sparsevec.cpython-312.pyc,,
pgvector/peewee/__pycache__/vector.cpython-312.pyc,,
pgvector/peewee/bit.py,sha256=ZK6_RDDj46aAfYyxgXrwXYmHfPZpp5P5aA-CLt0M61Q,619
pgvector/peewee/halfvec.py,sha256=NY3Wz79QbkKJdmQ_ZrkAqayQutQaO3iR5JBZ00sbMAE,969
pgvector/peewee/sparsevec.py,sha256=SRDkw1_aWTVHOAXz3LYPMtDvIVlk5ByPcbDKkg1kR_0,981
pgvector/peewee/vector.py,sha256=HXPj77K70jU7Vk33TVQLkDrp3995a_wygXkjyszDzTM,948
pgvector/psycopg/__init__.py,sha256=ggPIFt-dlT9T4vCbzLfxReYqdUyFUx2n3J0p2kRZvek,248
pgvector/psycopg/__pycache__/__init__.cpython-312.pyc,,
pgvector/psycopg/__pycache__/bit.cpython-312.pyc,,
pgvector/psycopg/__pycache__/halfvec.cpython-312.pyc,,
pgvector/psycopg/__pycache__/register.cpython-312.pyc,,
pgvector/psycopg/__pycache__/sparsevec.cpython-312.pyc,,
pgvector/psycopg/__pycache__/vector.cpython-312.pyc,,
pgvector/psycopg/bit.py,sha256=ad9XneEmlCMEZi-1HN41mrTGogJmINtS7fy_I9Dbem8,712
pgvector/psycopg/halfvec.py,sha256=A_uVQhXzcDsiK41rB5gmxwqLp7Fjpw-YJYPTED5Va5M,1354
pgvector/psycopg/register.py,sha256=Ueuc9YKdhSI8Hd2JZIBrGHqp2i5sVW9DIKgS-Xo7Yyk,1107
pgvector/psycopg/sparsevec.py,sha256=jaOEpcMPknCONMDNmWkQDLcvttemS8aNZGwfbEqHxPQ,1390
pgvector/psycopg/vector.py,sha256=rUTcBJmyEtcideZ711H8kjVFfFRXLETmRMlGpOCALkA,1521
pgvector/psycopg2/__init__.py,sha256=ThM3WfiOQfXHv-EY1DbOUNLJkR2RsXmxQzJNoynT4dw,158
pgvector/psycopg2/__pycache__/__init__.cpython-312.pyc,,
pgvector/psycopg2/__pycache__/halfvec.cpython-312.pyc,,
pgvector/psycopg2/__pycache__/register.cpython-312.pyc,,
pgvector/psycopg2/__pycache__/sparsevec.cpython-312.pyc,,
pgvector/psycopg2/__pycache__/vector.cpython-312.pyc,,
pgvector/psycopg2/halfvec.py,sha256=7JCYfpgflVq-kg4abzPZStxqb4d7u19gd2_X0ZmdGz8,536
pgvector/psycopg2/register.py,sha256=BLGd6_xZgHGL6T8-lxDC03qkvUCI_HbpiYk46joLoRo,1107
pgvector/psycopg2/sparsevec.py,sha256=fsIyviFoLIOc1jlMi6R5xWc9NNoKXgNcUKOaOrKlx38,560
pgvector/psycopg2/vector.py,sha256=v3cwgISpStIS6zJqKcB78xqG0pQq4qCoa9Lbj1o8mCQ,535
pgvector/sqlalchemy/__init__.py,sha256=CDMSwvIt4mwpuuSMduq3IyvgEp6RLToQClkqOElFY7o,369
pgvector/sqlalchemy/__pycache__/__init__.cpython-312.pyc,,
pgvector/sqlalchemy/__pycache__/bit.cpython-312.pyc,,
pgvector/sqlalchemy/__pycache__/functions.cpython-312.pyc,,
pgvector/sqlalchemy/__pycache__/halfvec.cpython-312.pyc,,
pgvector/sqlalchemy/__pycache__/sparsevec.cpython-312.pyc,,
pgvector/sqlalchemy/__pycache__/vector.cpython-312.pyc,,
pgvector/sqlalchemy/bit.py,sha256=a-I24dwAR-Uc_vxj32MahDezjQVtUvIoMdPuYpztLIA,722
pgvector/sqlalchemy/functions.py,sha256=LCxFWiTH-pM4XE2R5QRUg3vJxsxB-LNCGkqCEU6JOfk,272
pgvector/sqlalchemy/halfvec.py,sha256=jlg3BuwvMrqSuDYJV0sjECEq_tq2n0IjgwtMz-grDak,1538
pgvector/sqlalchemy/sparsevec.py,sha256=SJPSs0G07Bo8JTzmlO3a0LsYimyYmONynlRQ5Nndxss,1556
pgvector/sqlalchemy/vector.py,sha256=dw7znnHjIQPblCzWD-uJmVY3HBGDOmw98uB1qkFBmTo,1517
pgvector/utils/__init__.py,sha256=2qAb4VM3LcsnWwhFvRosnI4QS0KJnTDrY0aoRSXXIcg,193
pgvector/utils/__pycache__/__init__.cpython-312.pyc,,
pgvector/utils/__pycache__/bit.cpython-312.pyc,,
pgvector/utils/__pycache__/halfvec.cpython-312.pyc,,
pgvector/utils/__pycache__/sparsevec.cpython-312.pyc,,
pgvector/utils/__pycache__/vector.cpython-312.pyc,,
pgvector/utils/bit.py,sha256=YMcmqSjdZEhxC4HhSpkCgyYG26WUjM2Qv8JjI2Wu_Ts,1711
pgvector/utils/halfvec.py,sha256=1yAmQ174UGFIWijfvegVWrr5sjltRAxMUMLmis-9BGc,2013
pgvector/utils/sparsevec.py,sha256=uo1YfKx35iYuBPC9V3dDHWoAin042q6klOWBgY_Cnhc,4622
pgvector/utils/vector.py,sha256=upyEMEEJF-o995GAk3UGhDPF9B0Ouv3zHWVZK54M4q8,2079
@@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: setuptools (75.1.0)
Root-Is-Purelib: true
Tag: py3-none-any