From 866270bb5abed981b39d37347306312e8d3876f0 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sun, 21 Jul 2024 15:01:13 +0200 Subject: [PATCH 01/44] added boilerplate for user management --- cognee/api/client.py | 71 +++++++++++++++++++ .../user_authentication/authentication_db.py | 36 ++++++++++ .../relational/user_authentication/schemas.py | 15 ++++ .../relational/user_authentication/users.py | 55 ++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 cognee/infrastructure/databases/relational/user_authentication/authentication_db.py create mode 100644 cognee/infrastructure/databases/relational/user_authentication/schemas.py create mode 100644 cognee/infrastructure/databases/relational/user_authentication/users.py diff --git a/cognee/api/client.py b/cognee/api/client.py index 196582b5d..2b2128d2d 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -43,6 +43,77 @@ app.add_middleware( allow_headers=["*"], ) +from contextlib import asynccontextmanager + +from fastapi import Depends, FastAPI + +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, create_db_and_tables +from cognee.infrastructure.databases.relational.user_authentication.schemas import UserCreate, UserRead, UserUpdate +from cognee.infrastructure.databases.relational.user_authentication.users import auth_backend, current_active_user, fastapi_users + +app.include_router( + fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"] +) +app.include_router( + fastapi_users.get_register_router(UserRead, UserCreate), + prefix="/auth", + tags=["auth"], +) +app.include_router( + fastapi_users.get_reset_password_router(), + prefix="/auth", + tags=["auth"], +) +app.include_router( + fastapi_users.get_verify_router(UserRead), + prefix="/auth", + tags=["auth"], +) +app.include_router( + fastapi_users.get_users_router(UserRead, UserUpdate), + prefix="/users", + tags=["users"], +) + + +@app.get("/authenticated-route") +async def authenticated_route(user: User = Depends(current_active_user)): + return {"message": f"Hello {user.email}!"} + +@asynccontextmanager +async def lifespan(app: FastAPI): + # Not needed if you setup a migration system like Alembic + await create_db_and_tables() + yield +app.include_router( + fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"] +) +app.include_router( + fastapi_users.get_register_router(UserRead, UserCreate), + prefix="/auth", + tags=["auth"], +) +app.include_router( + fastapi_users.get_reset_password_router(), + prefix="/auth", + tags=["auth"], +) +app.include_router( + fastapi_users.get_verify_router(UserRead), + prefix="/auth", + tags=["auth"], +) +app.include_router( + fastapi_users.get_users_router(UserRead, UserUpdate), + prefix="/users", + tags=["users"], +) + + +@app.get("/authenticated-route") +async def authenticated_route(user: User = Depends(current_active_user)): + return {"message": f"Hello {user.email}!"} + @app.get("/") async def root(): """ diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py new file mode 100644 index 000000000..63bc2e94a --- /dev/null +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -0,0 +1,36 @@ +from typing import AsyncGenerator + +from fastapi import Depends +from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine +from sqlalchemy.orm import DeclarativeBase + +DATABASE_URL = "sqlite+aiosqlite:///./test.db" + + +class Base(DeclarativeBase): + pass + + +class User(SQLAlchemyBaseUserTableUUID, Base): + pass + + + + +engine = create_async_engine(DATABASE_URL) +async_session_maker = async_sessionmaker(engine, expire_on_commit=False) + + +async def create_db_and_tables(): + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + + +async def get_async_session() -> AsyncGenerator[AsyncSession, None]: + async with async_session_maker() as session: + yield session + + +async def get_user_db(session: AsyncSession = Depends(get_async_session)): + yield SQLAlchemyUserDatabase(session, User) \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/schemas.py b/cognee/infrastructure/databases/relational/user_authentication/schemas.py new file mode 100644 index 000000000..d7156223f --- /dev/null +++ b/cognee/infrastructure/databases/relational/user_authentication/schemas.py @@ -0,0 +1,15 @@ +import uuid + +from fastapi_users import schemas + + +class UserRead(schemas.BaseUser[uuid.UUID]): + pass + + +class UserCreate(schemas.BaseUserCreate): + pass + + +class UserUpdate(schemas.BaseUserUpdate): + pass \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py new file mode 100644 index 000000000..3df38c4fe --- /dev/null +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -0,0 +1,55 @@ +import uuid +from typing import Optional + +from fastapi import Depends, Request +from fastapi_users import BaseUserManager, FastAPIUsers, UUIDIDMixin, models +from fastapi_users.authentication import ( + AuthenticationBackend, + BearerTransport, + JWTStrategy, +) +from fastapi_users.db import SQLAlchemyUserDatabase + +from app.db import User, get_user_db + +SECRET = "SECRET" + + +class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]): + reset_password_token_secret = SECRET + verification_token_secret = SECRET + + async def on_after_register(self, user: User, request: Optional[Request] = None): + print(f"User {user.id} has registered.") + + async def on_after_forgot_password( + self, user: User, token: str, request: Optional[Request] = None + ): + print(f"User {user.id} has forgot their password. Reset token: {token}") + + async def on_after_request_verify( + self, user: User, token: str, request: Optional[Request] = None + ): + print(f"Verification requested for user {user.id}. Verification token: {token}") + + +async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)): + yield UserManager(user_db) + + +bearer_transport = BearerTransport(tokenUrl="auth/jwt/login") + + +def get_jwt_strategy() -> JWTStrategy[models.UP, models.ID]: + return JWTStrategy(secret=SECRET, lifetime_seconds=3600) + + +auth_backend = AuthenticationBackend( + name="jwt", + transport=bearer_transport, + get_strategy=get_jwt_strategy, +) + +fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [auth_backend]) + +current_active_user = fastapi_users.current_user(active=True) \ No newline at end of file From 77e8c1b1d5db9dcce0882f45aa5d602bcf0deb9d Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sun, 21 Jul 2024 20:58:59 +0200 Subject: [PATCH 02/44] add sqlalchemy engine --- .../databases/relational/config.py | 5 +- .../relational/create_relational_engine.py | 37 +++++- .../sqlalchemy/SqlAlchemyAdapter.py | 125 ++++++++++++++++++ .../relational/sqlalchemy/__init__.py | 0 .../user_authentication/authentication_db.py | 7 +- 5 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py create mode 100644 cognee/infrastructure/databases/relational/sqlalchemy/__init__.py diff --git a/cognee/infrastructure/databases/relational/config.py b/cognee/infrastructure/databases/relational/config.py index f0ddfc01d..e76a15cd3 100644 --- a/cognee/infrastructure/databases/relational/config.py +++ b/cognee/infrastructure/databases/relational/config.py @@ -11,9 +11,11 @@ class RelationalConfig(BaseSettings): db_port: str = "5432" db_user: str = "cognee" db_password: str = "cognee" - database_engine: object = create_relational_engine(db_path, db_name) + db_provider: str = "duckdb" + database_engine: object = create_relational_engine(db_path, db_name, db_provider) db_file_path: str = os.path.join(db_path, db_name) + model_config = SettingsConfigDict(env_file = ".env", extra = "allow") def create_engine(self): @@ -29,6 +31,7 @@ class RelationalConfig(BaseSettings): "db_user": self.db_user, "db_password": self.db_password, "db_engine": self.database_engine, + "db_provider": self.db_provider, } @lru_cache diff --git a/cognee/infrastructure/databases/relational/create_relational_engine.py b/cognee/infrastructure/databases/relational/create_relational_engine.py index 416152f59..2d4d961e8 100644 --- a/cognee/infrastructure/databases/relational/create_relational_engine.py +++ b/cognee/infrastructure/databases/relational/create_relational_engine.py @@ -1,10 +1,33 @@ -from cognee.infrastructure.files.storage import LocalStorage -from cognee.infrastructure.databases.relational import DuckDBAdapter +from enum import Enum -def create_relational_engine(db_path: str, db_name: str): +from cognee.infrastructure.databases.relational.sqlalchemy.SqlAlchemyAdapter import SQLAlchemyAdapter +from cognee.infrastructure.files.storage import LocalStorage +from cognee.infrastructure.databases.relational import DuckDBAdapter, get_relationaldb_config + + +class DBProvider(Enum): + DUCKDB = "duckdb" + POSTGRES = "postgres" + + + +def create_relational_engine(db_path: str, db_name: str, db_provider:str): LocalStorage.ensure_directory_exists(db_path) - return DuckDBAdapter( - db_name = db_name, - db_path = db_path, - ) + llm_config = get_relationaldb_config() + + provider = DBProvider(llm_config.llm_provider) + + + if provider == DBProvider.DUCKDB: + + return DuckDBAdapter( + db_name = db_name, + db_path = db_path, + ) + elif provider == DBProvider.POSTGRES: + return SQLAlchemyAdapter( + db_name = db_name, + db_path = db_path, + db_type = db_provider, + ) \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py new file mode 100644 index 000000000..292eaea78 --- /dev/null +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -0,0 +1,125 @@ +import os +from sqlalchemy import create_engine, MetaData, Table, Column, String, Boolean, TIMESTAMP, text +from sqlalchemy.orm import sessionmaker + +class SQLAlchemyAdapter(): + def __init__(self, db_type: str, db_path: str, db_name: str): + self.db_location = os.path.abspath(os.path.join(db_path, db_name)) + self.engine = create_engine(f"{db_type}:///{self.db_location}") + self.Session = sessionmaker(bind=self.engine) + + def get_datasets(self): + with self.engine.connect() as connection: + result = connection.execute(text("SELECT DISTINCT schema_name FROM information_schema.tables;")) + tables = [row['schema_name'] for row in result] + return list( + filter( + lambda schema_name: not schema_name.endswith("staging") and schema_name != "cognee", + tables + ) + ) + + def get_files_metadata(self, dataset_name: str): + with self.engine.connect() as connection: + result = connection.execute(text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) + return [dict(row) for row in result] + + def create_table(self, schema_name: str, table_name: str, table_config: list[dict]): + fields_query_parts = [f"{item['name']} {item['type']}" for item in table_config] + with self.engine.connect() as connection: + connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema_name};")) + connection.execute(text(f"CREATE TABLE IF NOT EXISTS {schema_name}.{table_name} ({', '.join(fields_query_parts)});")) + + def delete_table(self, table_name: str): + with self.engine.connect() as connection: + connection.execute(text(f"DROP TABLE IF EXISTS {table_name};")) + + def insert_data(self, schema_name: str, table_name: str, data: list[dict]): + columns = ", ".join(data[0].keys()) + values = ", ".join([f"({', '.join([f':{key}' for key in row.keys()])})" for row in data]) + insert_query = text(f"INSERT INTO {schema_name}.{table_name} ({columns}) VALUES {values};") + with self.engine.connect() as connection: + connection.execute(insert_query, data) + + def get_data(self, table_name: str, filters: dict = None): + with self.engine.connect() as connection: + query = f"SELECT * FROM {table_name}" + if filters: + filter_conditions = " AND ".join([ + f"{key} IN ({', '.join([f':{key}{i}' for i in range(len(value))])})" if isinstance(value, list) + else f"{key} = :{key}" for key, value in filters.items() + ]) + query += f" WHERE {filter_conditions};" + query = text(query) + results = connection.execute(query, filters) + else: + query += ";" + query = text(query) + results = connection.execute(query) + return {result["data_id"]: result["status"] for result in results} + + def execute_query(self, query): + with self.engine.connect() as connection: + result = connection.execute(text(query)) + return [dict(row) for row in result] + + def load_cognify_data(self, data): + metadata = MetaData() + cognify_table = Table( + 'cognify', metadata, + Column('document_id', String), + Column('layer_id', String), + Column('created_at', TIMESTAMP, server_default=text('CURRENT_TIMESTAMP')), + Column('updated_at', TIMESTAMP, nullable=True, default=None), + Column('processed', Boolean, default=False), + Column('document_id_target', String, nullable=True) + ) + metadata.create_all(self.engine) + insert_query = cognify_table.insert().values(document_id=text(':document_id'), layer_id=text(':layer_id')) + with self.engine.connect() as connection: + connection.execute(insert_query, data) + + def fetch_cognify_data(self, excluded_document_id: str): + with self.engine.connect() as connection: + connection.execute(text(""" + CREATE TABLE IF NOT EXISTS cognify ( + document_id STRING, + layer_id STRING, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT NULL, + processed BOOLEAN DEFAULT FALSE, + document_id_target STRING NULL + ); + """)) + query = text(f""" + SELECT document_id, layer_id, created_at, updated_at, processed + FROM cognify + WHERE document_id != :excluded_document_id AND processed = FALSE; + """) + records = connection.execute(query, {'excluded_document_id': excluded_document_id}).fetchall() + if records: + document_ids = tuple(record['document_id'] for record in records) + update_query = text(f"UPDATE cognify SET processed = TRUE WHERE document_id IN :document_ids;") + connection.execute(update_query, {'document_ids': document_ids}) + return [dict(record) for record in records] + + def delete_cognify_data(self): + with self.engine.connect() as connection: + connection.execute(text(""" + CREATE TABLE IF NOT EXISTS cognify ( + document_id STRING, + layer_id STRING, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT NULL, + processed BOOLEAN DEFAULT FALSE, + document_id_target STRING NULL + ); + """)) + connection.execute(text("DELETE FROM cognify;")) + connection.execute(text("DROP TABLE cognify;")) + + def delete_database(self): + from cognee.infrastructure.files.storage import LocalStorage + LocalStorage.remove(self.db_location) + if LocalStorage.file_exists(self.db_location + ".wal"): + LocalStorage.remove(self.db_location + ".wal") diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/__init__.py b/cognee/infrastructure/databases/relational/sqlalchemy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py index 63bc2e94a..ef87a752c 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -5,6 +5,9 @@ from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase +from cognee.infrastructure.databases.relational import get_relationaldb_config +from cognee.infrastructure.databases.relational.create_relational_engine import create_relational_engine + DATABASE_URL = "sqlite+aiosqlite:///./test.db" @@ -17,8 +20,10 @@ class User(SQLAlchemyBaseUserTableUUID, Base): +llm_config = get_relationaldb_config() -engine = create_async_engine(DATABASE_URL) + +engine = create_relational_engine(llm_config.db_path, llm_config.db_name, llm_config.db_provider) async_session_maker = async_sessionmaker(engine, expire_on_commit=False) From e785b3011715355ed7dd19a9b76f1c2a9d831d12 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 22 Jul 2024 23:59:16 +0200 Subject: [PATCH 03/44] Initial functional user auth --- cognee/api/client.py | 13 +- .../databases/relational/config.py | 9 +- .../relational/create_relational_engine.py | 29 +- .../sqlalchemy/SqlAlchemyAdapter.py | 29 +- .../user_authentication/__init__.py | 0 .../user_authentication/authentication_db.py | 24 +- .../relational/user_authentication/users.py | 3 +- docker-compose.yml | 16 + poetry.lock | 328 ++++++++++++++---- pyproject.toml | 2 + 10 files changed, 354 insertions(+), 99 deletions(-) create mode 100644 cognee/infrastructure/databases/relational/user_authentication/__init__.py diff --git a/cognee/api/client.py b/cognee/api/client.py index 2b2128d2d..12fefab3c 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -26,8 +26,13 @@ if os.getenv("ENV") == "prod": traces_sample_rate = 1.0, profiles_sample_rate = 1.0, ) - -app = FastAPI(debug = os.getenv("ENV") != "prod") +from contextlib import asynccontextmanager +@asynccontextmanager +async def lifespan(app: FastAPI): + # Not needed if you setup a migration system like Alembic + await create_db_and_tables() + yield +app = FastAPI(debug = os.getenv("ENV") != "prod", lifespan=lifespan) origins = [ "http://frontend:3000", @@ -338,8 +343,8 @@ def start_api_server(host: str = "0.0.0.0", port: int = 8000): relational_config.create_engine() from cognee.modules.data.deletion import prune_system, prune_data - asyncio.run(prune_data()) - asyncio.run(prune_system(metadata = True)) + # asyncio.run(prune_data()) + # asyncio.run(prune_system(metadata = True)) uvicorn.run(app, host = host, port = port) except Exception as e: diff --git a/cognee/infrastructure/databases/relational/config.py b/cognee/infrastructure/databases/relational/config.py index e76a15cd3..746cce2ae 100644 --- a/cognee/infrastructure/databases/relational/config.py +++ b/cognee/infrastructure/databases/relational/config.py @@ -6,13 +6,13 @@ from .create_relational_engine import create_relational_engine class RelationalConfig(BaseSettings): db_path: str = os.path.join(get_absolute_path(".cognee_system"), "databases") - db_name: str = "cognee.db" + db_name: str = "cognee_db" db_host: str = "localhost" db_port: str = "5432" db_user: str = "cognee" db_password: str = "cognee" - db_provider: str = "duckdb" - database_engine: object = create_relational_engine(db_path, db_name, db_provider) + db_provider: str = "postgresql+asyncpg" + # database_engine: object = create_relational_engine(db_path, db_name, db_provider) db_file_path: str = os.path.join(db_path, db_name) @@ -20,7 +20,8 @@ class RelationalConfig(BaseSettings): def create_engine(self): self.db_file_path = os.path.join(self.db_path, self.db_name) - self.database_engine = create_relational_engine(self.db_path, self.db_name) + self.database_engine = create_relational_engine(self.db_path, self.db_name, self.db_provider, self.db_host, self.db_port, self.db_user, self.db_password) + return self.database_engine def to_dict(self) -> dict: return { diff --git a/cognee/infrastructure/databases/relational/create_relational_engine.py b/cognee/infrastructure/databases/relational/create_relational_engine.py index 2d4d961e8..5bbfa8ee3 100644 --- a/cognee/infrastructure/databases/relational/create_relational_engine.py +++ b/cognee/infrastructure/databases/relational/create_relational_engine.py @@ -2,32 +2,39 @@ from enum import Enum from cognee.infrastructure.databases.relational.sqlalchemy.SqlAlchemyAdapter import SQLAlchemyAdapter from cognee.infrastructure.files.storage import LocalStorage -from cognee.infrastructure.databases.relational import DuckDBAdapter, get_relationaldb_config +from cognee.infrastructure.databases.relational import DuckDBAdapter class DBProvider(Enum): DUCKDB = "duckdb" - POSTGRES = "postgres" + POSTGRES = "postgresql+asyncpg" - - -def create_relational_engine(db_path: str, db_name: str, db_provider:str): +def create_relational_engine(db_path: str, db_name: str, db_provider:str, db_host:str, db_port:str, db_user:str, db_password:str): LocalStorage.ensure_directory_exists(db_path) - llm_config = get_relationaldb_config() - - provider = DBProvider(llm_config.llm_provider) - + provider = DBProvider(db_provider) if provider == DBProvider.DUCKDB: - - return DuckDBAdapter( + # return DuckDBAdapter( + # db_name = db_name, + # db_path = db_path, + # ) + return SQLAlchemyAdapter( db_name = db_name, db_path = db_path, + db_type = db_provider, + db_host=db_host, + db_port=db_port, + db_user=db_user, + db_password=db_password ) elif provider == DBProvider.POSTGRES: return SQLAlchemyAdapter( db_name = db_name, db_path = db_path, db_type = db_provider, + db_host= db_host, + db_port= db_port, + db_user= db_user, + db_password= db_password ) \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index 292eaea78..18f7ec876 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -1,12 +1,35 @@ import os from sqlalchemy import create_engine, MetaData, Table, Column, String, Boolean, TIMESTAMP, text from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine class SQLAlchemyAdapter(): - def __init__(self, db_type: str, db_path: str, db_name: str): + def __init__(self, db_type: str, db_path: str, db_name: str, db_user:str, db_password:str, db_host:str, db_port:str): self.db_location = os.path.abspath(os.path.join(db_path, db_name)) - self.engine = create_engine(f"{db_type}:///{self.db_location}") - self.Session = sessionmaker(bind=self.engine) + # self.engine = create_engine(f"{db_type}:///{self.db_location}") + if db_type == "duckdb": + self.engine = create_engine(f"duckdb:///{self.db_location}") + self.Session = sessionmaker(bind=self.engine) + + else: + print("Name: ", db_name) + print("User: ", db_user) + print("Password: ", db_password) + print("Host: ", db_host) + print("Port: ", db_port) + self.engine = create_async_engine(f"postgresql+asyncpg://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}") + self.Session = sessionmaker(bind=self.engine, class_=AsyncSession, expire_on_commit=False) + + + async def get_async_session(self): + async_session_maker = self.Session + async with async_session_maker() as session: + yield session + + def get_session(self): + session_maker = self.Session + with session_maker() as session: + yield session def get_datasets(self): with self.engine.connect() as connection: diff --git a/cognee/infrastructure/databases/relational/user_authentication/__init__.py b/cognee/infrastructure/databases/relational/user_authentication/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py index ef87a752c..dad143ea4 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -1,15 +1,11 @@ -from typing import AsyncGenerator +from typing import AsyncGenerator, Generator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase +from sqlalchemy import create_engine from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine -from sqlalchemy.orm import DeclarativeBase - +from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session from cognee.infrastructure.databases.relational import get_relationaldb_config -from cognee.infrastructure.databases.relational.create_relational_engine import create_relational_engine - -DATABASE_URL = "sqlite+aiosqlite:///./test.db" - class Base(DeclarativeBase): pass @@ -19,23 +15,21 @@ class User(SQLAlchemyBaseUserTableUUID, Base): pass - -llm_config = get_relationaldb_config() +relational_config = get_relationaldb_config() -engine = create_relational_engine(llm_config.db_path, llm_config.db_name, llm_config.db_provider) -async_session_maker = async_sessionmaker(engine, expire_on_commit=False) +engine = relational_config.create_engine() +async_session_maker = async_sessionmaker(engine.engine, expire_on_commit=False) async def create_db_and_tables(): - async with engine.begin() as conn: + async with engine.engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) - async def get_async_session() -> AsyncGenerator[AsyncSession, None]: async with async_session_maker() as session: yield session - + # yield async_session_maker async def get_user_db(session: AsyncSession = Depends(get_async_session)): - yield SQLAlchemyUserDatabase(session, User) \ No newline at end of file + yield SQLAlchemyUserDatabase(session, User) diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py index 3df38c4fe..c4db189a1 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -10,7 +10,8 @@ from fastapi_users.authentication import ( ) from fastapi_users.db import SQLAlchemyUserDatabase -from app.db import User, get_user_db + +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db SECRET = "SECRET" diff --git a/docker-compose.yml b/docker-compose.yml index 21f6903b7..9dfd54cee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,8 +60,24 @@ services: - 3001:3000 networks: - cognee-network + postgres: + image: postgres:latest + container_name: postgres + environment: + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + networks: + - cognee-network networks: cognee-network: name: cognee-network +volumes: + postgres_data: + diff --git a/poetry.lock b/poetry.lock index 444922e52..66f207108 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiofiles" @@ -286,13 +286,13 @@ test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock [[package]] name = "astroid" -version = "3.2.3" +version = "3.2.4" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.8.0" files = [ - {file = "astroid-3.2.3-py3-none-any.whl", hash = "sha256:3eae9ea67c11c858cdd2c91337d2e816bd019ac897ca07d7b346ac10105fceb3"}, - {file = "astroid-3.2.3.tar.gz", hash = "sha256:7099b5a60985529d8d46858befa103b82d0d05a5a5e8b816b5303ed96075e1d9"}, + {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, + {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, ] [package.dependencies] @@ -356,6 +356,63 @@ files = [ {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, ] +[[package]] +name = "asyncpg" +version = "0.29.0" +description = "An asyncio PostgreSQL driver" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "asyncpg-0.29.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72fd0ef9f00aeed37179c62282a3d14262dbbafb74ec0ba16e1b1864d8a12169"}, + {file = "asyncpg-0.29.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52e8f8f9ff6e21f9b39ca9f8e3e33a5fcdceaf5667a8c5c32bee158e313be385"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e6823a7012be8b68301342ba33b4740e5a166f6bbda0aee32bc01638491a22"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:746e80d83ad5d5464cfbf94315eb6744222ab00aa4e522b704322fb182b83610"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ff8e8109cd6a46ff852a5e6bab8b0a047d7ea42fcb7ca5ae6eaae97d8eacf397"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97eb024685b1d7e72b1972863de527c11ff87960837919dac6e34754768098eb"}, + {file = "asyncpg-0.29.0-cp310-cp310-win32.whl", hash = "sha256:5bbb7f2cafd8d1fa3e65431833de2642f4b2124be61a449fa064e1a08d27e449"}, + {file = "asyncpg-0.29.0-cp310-cp310-win_amd64.whl", hash = "sha256:76c3ac6530904838a4b650b2880f8e7af938ee049e769ec2fba7cd66469d7772"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4900ee08e85af01adb207519bb4e14b1cae8fd21e0ccf80fac6aa60b6da37b4"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a65c1dcd820d5aea7c7d82a3fdcb70e096f8f70d1a8bf93eb458e49bfad036ac"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b52e46f165585fd6af4863f268566668407c76b2c72d366bb8b522fa66f1870"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc600ee8ef3dd38b8d67421359779f8ccec30b463e7aec7ed481c8346decf99f"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:039a261af4f38f949095e1e780bae84a25ffe3e370175193174eb08d3cecab23"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6feaf2d8f9138d190e5ec4390c1715c3e87b37715cd69b2c3dfca616134efd2b"}, + {file = "asyncpg-0.29.0-cp311-cp311-win32.whl", hash = "sha256:1e186427c88225ef730555f5fdda6c1812daa884064bfe6bc462fd3a71c4b675"}, + {file = "asyncpg-0.29.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfe73ffae35f518cfd6e4e5f5abb2618ceb5ef02a2365ce64f132601000587d3"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6011b0dc29886ab424dc042bf9eeb507670a3b40aece3439944006aafe023178"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b544ffc66b039d5ec5a7454667f855f7fec08e0dfaf5a5490dfafbb7abbd2cfb"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d84156d5fb530b06c493f9e7635aa18f518fa1d1395ef240d211cb563c4e2364"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54858bc25b49d1114178d65a88e48ad50cb2b6f3e475caa0f0c092d5f527c106"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bde17a1861cf10d5afce80a36fca736a86769ab3579532c03e45f83ba8a09c59"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a2ec1b9ff88d8773d3eb6d3784dc7e3fee7756a5317b67f923172a4748a175"}, + {file = "asyncpg-0.29.0-cp312-cp312-win32.whl", hash = "sha256:bb1292d9fad43112a85e98ecdc2e051602bce97c199920586be83254d9dafc02"}, + {file = "asyncpg-0.29.0-cp312-cp312-win_amd64.whl", hash = "sha256:2245be8ec5047a605e0b454c894e54bf2ec787ac04b1cb7e0d3c67aa1e32f0fe"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0009a300cae37b8c525e5b449233d59cd9868fd35431abc470a3e364d2b85cb9"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cad1324dbb33f3ca0cd2074d5114354ed3be2b94d48ddfd88af75ebda7c43cc"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:012d01df61e009015944ac7543d6ee30c2dc1eb2f6b10b62a3f598beb6531548"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000c996c53c04770798053e1730d34e30cb645ad95a63265aec82da9093d88e7"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e0bfe9c4d3429706cf70d3249089de14d6a01192d617e9093a8e941fea8ee775"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:642a36eb41b6313ffa328e8a5c5c2b5bea6ee138546c9c3cf1bffaad8ee36dd9"}, + {file = "asyncpg-0.29.0-cp38-cp38-win32.whl", hash = "sha256:a921372bbd0aa3a5822dd0409da61b4cd50df89ae85150149f8c119f23e8c408"}, + {file = "asyncpg-0.29.0-cp38-cp38-win_amd64.whl", hash = "sha256:103aad2b92d1506700cbf51cd8bb5441e7e72e87a7b3a2ca4e32c840f051a6a3"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5340dd515d7e52f4c11ada32171d87c05570479dc01dc66d03ee3e150fb695da"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e17b52c6cf83e170d3d865571ba574577ab8e533e7361a2b8ce6157d02c665d3"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f100d23f273555f4b19b74a96840aa27b85e99ba4b1f18d4ebff0734e78dc090"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48e7c58b516057126b363cec8ca02b804644fd012ef8e6c7e23386b7d5e6ce83"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9ea3f24eb4c49a615573724d88a48bd1b7821c890c2effe04f05382ed9e8810"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8d36c7f14a22ec9e928f15f92a48207546ffe68bc412f3be718eedccdf10dc5c"}, + {file = "asyncpg-0.29.0-cp39-cp39-win32.whl", hash = "sha256:797ab8123ebaed304a1fad4d7576d5376c3a006a4100380fb9d517f0b59c1ab2"}, + {file = "asyncpg-0.29.0-cp39-cp39-win_amd64.whl", hash = "sha256:cce08a178858b426ae1aa8409b5cc171def45d4293626e7aa6510696d46decd8"}, + {file = "asyncpg-0.29.0.tar.gz", hash = "sha256:d1c49e1f44fffafd9a55e1a9b101590859d881d639ea2922516f5d9c512d354e"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.3", markers = "python_version < \"3.12.0\""} + +[package.extras] +docs = ["Sphinx (>=5.3.0,<5.4.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["flake8 (>=6.1,<7.0)", "uvloop (>=0.15.3)"] + [[package]] name = "attrs" version = "23.2.0" @@ -425,6 +482,46 @@ files = [ {file = "backports_strenum-1.3.1.tar.gz", hash = "sha256:77c52407342898497714f0596e86188bb7084f89063226f4ba66863482f42414"}, ] +[[package]] +name = "bcrypt" +version = "4.1.2" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "bcrypt-4.1.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ac621c093edb28200728a9cca214d7e838529e557027ef0581685909acd28b5e"}, + {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea505c97a5c465ab8c3ba75c0805a102ce526695cd6818c6de3b1a38f6f60da1"}, + {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57fa9442758da926ed33a91644649d3e340a71e2d0a5a8de064fb621fd5a3326"}, + {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb3bd3321517916696233b5e0c67fd7d6281f0ef48e66812db35fc963a422a1c"}, + {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6cad43d8c63f34b26aef462b6f5e44fdcf9860b723d2453b5d391258c4c8e966"}, + {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:44290ccc827d3a24604f2c8bcd00d0da349e336e6503656cb8192133e27335e2"}, + {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:732b3920a08eacf12f93e6b04ea276c489f1c8fb49344f564cca2adb663b3e4c"}, + {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1c28973decf4e0e69cee78c68e30a523be441972c826703bb93099868a8ff5b5"}, + {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b8df79979c5bae07f1db22dcc49cc5bccf08a0380ca5c6f391cbb5790355c0b0"}, + {file = "bcrypt-4.1.2-cp37-abi3-win32.whl", hash = "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369"}, + {file = "bcrypt-4.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:9800ae5bd5077b13725e2e3934aa3c9c37e49d3ea3d06318010aa40f54c63551"}, + {file = "bcrypt-4.1.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:71b8be82bc46cedd61a9f4ccb6c1a493211d031415a34adde3669ee1b0afbb63"}, + {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e3c6642077b0c8092580c819c1684161262b2e30c4f45deb000c38947bf483"}, + {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387e7e1af9a4dd636b9505a465032f2f5cb8e61ba1120e79a0e1cd0b512f3dfc"}, + {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7"}, + {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2a298db2a8ab20056120b45e86c00a0a5eb50ec4075b6142db35f593b97cb3fb"}, + {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ba55e40de38a24e2d78d34c2d36d6e864f93e0d79d0b6ce915e4335aa81d01b1"}, + {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3566a88234e8de2ccae31968127b0ecccbb4cddb629da744165db72b58d88ca4"}, + {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b90e216dc36864ae7132cb151ffe95155a37a14e0de3a8f64b49655dd959ff9c"}, + {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:69057b9fc5093ea1ab00dd24ede891f3e5e65bee040395fb1e66ee196f9c9b4a"}, + {file = "bcrypt-4.1.2-cp39-abi3-win32.whl", hash = "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f"}, + {file = "bcrypt-4.1.2-cp39-abi3-win_amd64.whl", hash = "sha256:be3ab1071662f6065899fe08428e45c16aa36e28bc42921c4901a191fda6ee42"}, + {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d75fc8cd0ba23f97bae88a6ec04e9e5351ff3c6ad06f38fe32ba50cbd0d11946"}, + {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:a97e07e83e3262599434816f631cc4c7ca2aa8e9c072c1b1a7fec2ae809a1d2d"}, + {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e51c42750b7585cee7892c2614be0d14107fad9581d1738d954a262556dd1aab"}, + {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba4e4cc26610581a6329b3937e02d319f5ad4b85b074846bf4fef8a8cf51e7bb"}, + {file = "bcrypt-4.1.2.tar.gz", hash = "sha256:33313a1200a3ae90b75587ceac502b048b840fc69e7f7a0905b5f87fac7a1258"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + [[package]] name = "beautifulsoup4" version = "4.12.3" @@ -965,43 +1062,38 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.8" +version = "43.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, - {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, - {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, - {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, - {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, - {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, - {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, + {file = "cryptography-43.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47"}, + {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf"}, + {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55"}, + {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431"}, + {file = "cryptography-43.0.0-cp37-abi3-win32.whl", hash = "sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc"}, + {file = "cryptography-43.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778"}, + {file = "cryptography-43.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5"}, + {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f"}, + {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0"}, + {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b"}, + {file = "cryptography-43.0.0-cp39-abi3-win32.whl", hash = "sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf"}, + {file = "cryptography-43.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f"}, + {file = "cryptography-43.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069"}, + {file = "cryptography-43.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1"}, + {file = "cryptography-43.0.0.tar.gz", hash = "sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e"}, ] [package.dependencies] @@ -1014,7 +1106,7 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.0)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -1228,6 +1320,26 @@ snowflake = ["snowflake-connector-python (>=3.5.0)"] synapse = ["adlfs (>=2022.4.0)", "pyarrow (>=12.0.0)", "pyodbc (>=4.0.39)"] weaviate = ["weaviate-client (>=3.22)"] +[[package]] +name = "dnspython" +version = "2.6.1" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + [[package]] name = "docstring-parser" version = "0.16" @@ -1311,6 +1423,21 @@ duckdb = ">=0.5.0" packaging = ">=21" sqlalchemy = ">=1.3.22" +[[package]] +name = "email-validator" +version = "2.1.2" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.2-py3-none-any.whl", hash = "sha256:d89f6324e13b1e39889eab7f9ca2f91dc9aebb6fa50a6d8bd4329ab50f251115"}, + {file = "email_validator-2.1.2.tar.gz", hash = "sha256:14c0f3d343c4beda37400421b39fa411bbe33a75df20825df73ad53e06a9f04c"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + [[package]] name = "exceptiongroup" version = "1.2.2" @@ -1358,6 +1485,47 @@ typing-extensions = ">=4.8.0" [package.extras] all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +[[package]] +name = "fastapi-users" +version = "13.0.0" +description = "Ready-to-use and customizable users management for FastAPI" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi_users-13.0.0-py3-none-any.whl", hash = "sha256:e6246529e3080a5b50e5afeed1e996663b661f1dc791a1ac478925cb5bfc0fa0"}, + {file = "fastapi_users-13.0.0.tar.gz", hash = "sha256:b397c815b7051c8fd4b560fbeee707acd28e00bd3e8f25c292ad158a1e47e884"}, +] + +[package.dependencies] +email-validator = ">=1.1.0,<2.2" +fastapi = ">=0.65.2" +fastapi-users-db-sqlalchemy = {version = ">=6.0.0", optional = true, markers = "extra == \"sqlalchemy\""} +makefun = ">=1.11.2,<2.0.0" +pwdlib = {version = "0.2.0", extras = ["argon2", "bcrypt"]} +pyjwt = {version = "2.8.0", extras = ["crypto"]} +python-multipart = "0.0.9" + +[package.extras] +beanie = ["fastapi-users-db-beanie (>=3.0.0)"] +oauth = ["httpx-oauth (>=0.13)"] +redis = ["redis (>=4.3.3,<6.0.0)"] +sqlalchemy = ["fastapi-users-db-sqlalchemy (>=6.0.0)"] + +[[package]] +name = "fastapi-users-db-sqlalchemy" +version = "6.0.1" +description = "FastAPI Users database adapter for SQLAlchemy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi_users_db_sqlalchemy-6.0.1-py3-none-any.whl", hash = "sha256:d1050ec31eb75e8c4fa9abafa4addaf0baf5c97afeea2f0f910ea55e2451fcad"}, + {file = "fastapi_users_db_sqlalchemy-6.0.1.tar.gz", hash = "sha256:f0ef9fe3250453712d25c13170700c80fa205867ce7add7ef391c384ec27cbe1"}, +] + +[package.dependencies] +fastapi-users = ">=10.0.0" +sqlalchemy = {version = ">=2.0.0,<2.1.0", extras = ["asyncio"]} + [[package]] name = "fastembed" version = "0.2.7" @@ -2972,13 +3140,13 @@ tests = ["aiohttp", "boto3", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pyt [[package]] name = "langfuse" -version = "2.39.2" +version = "2.39.3" description = "A client library for accessing langfuse" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langfuse-2.39.2-py3-none-any.whl", hash = "sha256:ef2016704c0366026b93c6613e5ea8e0a2a0bfdbee1a887aa43fb08c6a255e10"}, - {file = "langfuse-2.39.2.tar.gz", hash = "sha256:bb1264722d4968309f3608af01186e0395bcd398a30792579a5f51d5fe1f4902"}, + {file = "langfuse-2.39.3-py3-none-any.whl", hash = "sha256:24b12cbb23f866b22706c1ea9631781f99fe37b0b15889d241198c4d1c07516b"}, + {file = "langfuse-2.39.3.tar.gz", hash = "sha256:4d2df8f9344572370703db103ddf97176df518699593254e6d6c2b8ca3bf2f12"}, ] [package.dependencies] @@ -4664,18 +4832,37 @@ files = [ [[package]] name = "pure-eval" -version = "0.2.2" +version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" files = [ - {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, - {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, + {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, + {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, ] [package.extras] tests = ["pytest"] +[[package]] +name = "pwdlib" +version = "0.2.0" +description = "Modern password hashing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pwdlib-0.2.0-py3-none-any.whl", hash = "sha256:be53812012ab66795a57ac9393a59716ae7c2b60841ed453eb1262017fdec144"}, + {file = "pwdlib-0.2.0.tar.gz", hash = "sha256:b1bdafc064310eb6d3d07144a210267063ab4f45ac73a97be948e6589f74e861"}, +] + +[package.dependencies] +argon2-cffi = {version = "23.1.0", optional = true, markers = "extra == \"argon2\""} +bcrypt = {version = "4.1.2", optional = true, markers = "extra == \"bcrypt\""} + +[package.extras] +argon2 = ["argon2-cffi (==23.1.0)"] +bcrypt = ["bcrypt (==4.1.2)"] + [[package]] name = "py" version = "1.11.0" @@ -4899,6 +5086,26 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pyjwt" +version = "2.8.0" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, +] + +[package.dependencies] +cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + [[package]] name = "pylance" version = "0.11.0" @@ -4927,17 +5134,17 @@ torch = ["torch"] [[package]] name = "pylint" -version = "3.2.5" +version = "3.2.6" description = "python code static checker" optional = false python-versions = ">=3.8.0" files = [ - {file = "pylint-3.2.5-py3-none-any.whl", hash = "sha256:32cd6c042b5004b8e857d727708720c54a676d1e22917cf1a2df9b4d4868abd6"}, - {file = "pylint-3.2.5.tar.gz", hash = "sha256:e9b7171e242dcc6ebd0aaa7540481d1a72860748a0a7816b8fe6cf6c80a6fe7e"}, + {file = "pylint-3.2.6-py3-none-any.whl", hash = "sha256:03c8e3baa1d9fb995b12c1dbe00aa6c4bcef210c2a2634374aedeb22fb4a8f8f"}, + {file = "pylint-3.2.6.tar.gz", hash = "sha256:a5d01678349454806cff6d886fb072294f56a58c4761278c97fb557d708e1eb3"}, ] [package.dependencies] -astroid = ">=3.2.2,<=3.3.0-dev0" +astroid = ">=3.2.4,<=3.3.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -4988,13 +5195,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pypdf" -version = "4.3.0" +version = "4.3.1" description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" optional = false python-versions = ">=3.6" files = [ - {file = "pypdf-4.3.0-py3-none-any.whl", hash = "sha256:eeea4d019b57c099d02a0e1692eaaab23341ae3f255c1dafa3c8566b4636496d"}, - {file = "pypdf-4.3.0.tar.gz", hash = "sha256:0d7a4c67fd03782f5a09d3f48c11c7a31e0bb9af78861a25229bb49259ed0504"}, + {file = "pypdf-4.3.1-py3-none-any.whl", hash = "sha256:64b31da97eda0771ef22edb1bfecd5deee4b72c3d1736b7df2689805076d6418"}, + {file = "pypdf-4.3.1.tar.gz", hash = "sha256:b2f37fe9a3030aa97ca86067a56ba3f9d3565f9a791b305c7355d8392c30d91b"}, ] [package.dependencies] @@ -5223,7 +5430,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6046,19 +6252,19 @@ tornado = ["tornado (>=6)"] [[package]] name = "setuptools" -version = "71.0.4" +version = "71.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-71.0.4-py3-none-any.whl", hash = "sha256:ed2feca703be3bdbd94e6bb17365d91c6935c6b2a8d0bb09b66a2c435ba0b1a5"}, - {file = "setuptools-71.0.4.tar.gz", hash = "sha256:48297e5d393a62b7cb2a10b8f76c63a73af933bd809c9e0d0d6352a1a0135dd8"}, + {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, + {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, ] [package.extras] core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" @@ -6281,7 +6487,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} +greenlet = {version = "!=0.4.17", optional = true, markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") or extra == \"asyncio\""} typing-extensions = ">=4.6.0" [package.extras] @@ -6862,13 +7068,13 @@ files = [ [[package]] name = "types-setuptools" -version = "70.3.0.20240710" +version = "71.0.0.20240722" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-70.3.0.20240710.tar.gz", hash = "sha256:842cbf399812d2b65042c9d6ff35113bbf282dee38794779aa1f94e597bafc35"}, - {file = "types_setuptools-70.3.0.20240710-py3-none-any.whl", hash = "sha256:bd0db2a4b9f2c49ac5564be4e0fb3125c4c46b1f73eafdcbceffa5b005cceca4"}, + {file = "types-setuptools-71.0.0.20240722.tar.gz", hash = "sha256:8f1fd5281945ed8f5a896f05dd50bc31917d6e2487ff9508f4bac522d13ad395"}, + {file = "types_setuptools-71.0.0.20240722-py3-none-any.whl", hash = "sha256:04a383bd1a2dcdb6a85397516ce2d7b46617d89f1d758f686d0d9069943d9811"}, ] [[package]] @@ -7350,4 +7556,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<3.12" -content-hash = "18134754d15827b8bf80691fa823aae83b8d5cc8a7461ae70f8328d33b5ddb2e" +content-hash = "e0776d8f9fb8fd682bef3b0c4111ca52540d901fc00a3c2ae809c94b7440c559" diff --git a/pyproject.toml b/pyproject.toml index ee26551f9..6ad360e76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,6 +69,8 @@ pydantic-settings = "^2.2.1" anthropic = "^0.26.1" pdfplumber = "^0.11.1" sentry-sdk = {extras = ["fastapi"], version = "^2.9.0"} +fastapi-users = { version = "*", extras = ["sqlalchemy"] } +asyncpg = "^0.29.0" From 14e1eba3634f5fad057b6e8dfa6fd5c989b44bba Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:43:08 +0200 Subject: [PATCH 04/44] Fixes for user flow with group management --- cognee/api/client.py | 4 +- cognee/infrastructure/data/models/Data.py | 4 +- cognee/infrastructure/data/models/Dataset.py | 4 +- .../infrastructure/data/models/DatasetData.py | 4 +- .../databases/relational/ModelBase.py | 8 +- .../databases/relational/__init__.py | 2 +- .../relational/sqlite/SqliteEngine.py | 4 +- .../user_authentication/authentication_db.py | 36 ++++- .../relational/user_authentication/routers.py | 28 ++++ .../relational/user_authentication/users.py | 21 ++- poetry.lock | 137 ++++++++---------- pyproject.toml | 2 +- 12 files changed, 160 insertions(+), 94 deletions(-) create mode 100644 cognee/infrastructure/databases/relational/user_authentication/routers.py diff --git a/cognee/api/client.py b/cognee/api/client.py index 12fefab3c..3b2e0c0a0 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -13,6 +13,8 @@ from fastapi.responses import JSONResponse, FileResponse from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel +from cognee.infrastructure.databases.relational.user_authentication.routers import permission_router + # Set up logging logging.basicConfig( level=logging.INFO, # Set the logging level (e.g., DEBUG, INFO, WARNING, ERROR, CRITICAL) @@ -80,7 +82,7 @@ app.include_router( tags=["users"], ) - +app.include_router(permission_router, prefix="/manage", tags=["management"]) @app.get("/authenticated-route") async def authenticated_route(user: User = Depends(current_active_user)): return {"message": f"Hello {user.email}!"} diff --git a/cognee/infrastructure/data/models/Data.py b/cognee/infrastructure/data/models/Data.py index 906958430..da389e154 100644 --- a/cognee/infrastructure/data/models/Data.py +++ b/cognee/infrastructure/data/models/Data.py @@ -2,10 +2,10 @@ from typing import List from datetime import datetime, timezone from sqlalchemy.orm import relationship, MappedColumn, Mapped from sqlalchemy import Column, String, DateTime, UUID, Text, JSON -from cognee.infrastructure.databases.relational import ModelBase +from cognee.infrastructure.databases.relational import Base from .DatasetData import DatasetData -class Data(ModelBase): +class Data(Base): __tablename__ = "data" id = Column(UUID, primary_key = True) diff --git a/cognee/infrastructure/data/models/Dataset.py b/cognee/infrastructure/data/models/Dataset.py index 5c7e55304..918cd5b28 100644 --- a/cognee/infrastructure/data/models/Dataset.py +++ b/cognee/infrastructure/data/models/Dataset.py @@ -2,10 +2,10 @@ from typing import List from datetime import datetime, timezone from sqlalchemy.orm import relationship, Mapped from sqlalchemy import Column, Text, DateTime, UUID -from cognee.infrastructure.databases.relational import ModelBase +from cognee.infrastructure.databases.relational import Base from .DatasetData import DatasetData -class Dataset(ModelBase): +class Dataset(Base): __tablename__ = "dataset" id = Column(UUID, primary_key = True) diff --git a/cognee/infrastructure/data/models/DatasetData.py b/cognee/infrastructure/data/models/DatasetData.py index 286142d89..552642686 100644 --- a/cognee/infrastructure/data/models/DatasetData.py +++ b/cognee/infrastructure/data/models/DatasetData.py @@ -1,9 +1,9 @@ from uuid import uuid4 from datetime import datetime, timezone from sqlalchemy import Column, DateTime, UUID, ForeignKey -from cognee.infrastructure.databases.relational import ModelBase +from cognee.infrastructure.databases.relational import Base -class DatasetData(ModelBase): +class DatasetData(Base): __tablename__ = "dataset_data" id = Column(UUID, primary_key = True, default = uuid4()) diff --git a/cognee/infrastructure/databases/relational/ModelBase.py b/cognee/infrastructure/databases/relational/ModelBase.py index 3ae4eeff4..6e60c638f 100644 --- a/cognee/infrastructure/databases/relational/ModelBase.py +++ b/cognee/infrastructure/databases/relational/ModelBase.py @@ -1,3 +1,7 @@ -from sqlalchemy.orm import declarative_base -ModelBase = declarative_base() +from sqlalchemy.orm import DeclarativeBase + + +class Base(DeclarativeBase): + pass + diff --git a/cognee/infrastructure/databases/relational/__init__.py b/cognee/infrastructure/databases/relational/__init__.py index 277553c82..214559ccb 100644 --- a/cognee/infrastructure/databases/relational/__init__.py +++ b/cognee/infrastructure/databases/relational/__init__.py @@ -1,4 +1,4 @@ -from .ModelBase import ModelBase +from .ModelBase import Base from .DatabaseEngine import DatabaseEngine from .sqlite.SqliteEngine import SqliteEngine from .duckdb.DuckDBAdapter import DuckDBAdapter diff --git a/cognee/infrastructure/databases/relational/sqlite/SqliteEngine.py b/cognee/infrastructure/databases/relational/sqlite/SqliteEngine.py index 126be6437..c636b1fd3 100644 --- a/cognee/infrastructure/databases/relational/sqlite/SqliteEngine.py +++ b/cognee/infrastructure/databases/relational/sqlite/SqliteEngine.py @@ -6,7 +6,7 @@ from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, Asyn from sqlalchemy.future import select from cognee.infrastructure.files.storage.LocalStorage import LocalStorage from ..DatabaseEngine import DatabaseEngine -from ..ModelBase import ModelBase +from ..ModelBase import Base from ..utils import with_rollback class SqliteEngine(DatabaseEngine): @@ -60,7 +60,7 @@ class SqliteEngine(DatabaseEngine): async def create_tables(self): async with self.engine.begin() as connection: - return await connection.run_sync(ModelBase.metadata.create_all) + return await connection.run_sync(Base.metadata.create_all) async def create(self, data): async with with_rollback(self.session_maker()) as session: diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py index dad143ea4..d517453c6 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -2,17 +2,43 @@ from typing import AsyncGenerator, Generator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase -from sqlalchemy import create_engine +from sqlalchemy import create_engine, UUID from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session -from cognee.infrastructure.databases.relational import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relationaldb_config, Base +from sqlalchemy import Column, String, ForeignKey, Table, Integer + + +from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session, relationship + +# Association table for many-to-many relationship between users and groups +user_group = Table('user_group', Base.metadata, + Column('user_id', UUID, ForeignKey('users.id')), + Column('group_id', UUID, ForeignKey('groups.id'))) + +# Association table for many-to-many relationship between groups and permissions +group_permission = Table('group_permission', Base.metadata, + Column('group_id', UUID, ForeignKey('groups.id')), + Column('permission_id', UUID, ForeignKey('permissions.id'))) -class Base(DeclarativeBase): - pass class User(SQLAlchemyBaseUserTableUUID, Base): - pass + __tablename__ = 'users' + groups = relationship('Group', secondary=user_group, back_populates='users') + +class Group(Base): + __tablename__ = 'groups' + id = Column(UUID, primary_key=True, index=True) + name = Column(String, unique=True, index=True) + users = relationship('User', secondary=user_group, back_populates='groups') + permissions = relationship('Permission', secondary=group_permission, back_populates='groups') + +class Permission(Base): + __tablename__ = 'permissions' + id = Column(UUID, primary_key=True, index=True) + name = Column(String, unique=True, index=True) + groups = relationship('Group', secondary=group_permission, back_populates='permissions') relational_config = get_relationaldb_config() diff --git a/cognee/infrastructure/databases/relational/user_authentication/routers.py b/cognee/infrastructure/databases/relational/user_authentication/routers.py new file mode 100644 index 000000000..42843db6f --- /dev/null +++ b/cognee/infrastructure/databases/relational/user_authentication/routers.py @@ -0,0 +1,28 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import get_user_db, User, Group, Permission + +permission_router = APIRouter() + +@permission_router.post("/groups/{group_id}/permissions") +async def assign_permission_to_group(group_id: int, permission: str, db: Session = Depends(get_user_db)): + group = db.query(Group).filter(Group.id == group_id).first() + if not group: + raise HTTPException(status_code=404, detail="Group not found") + perm = db.query(Permission).filter(Permission.name == permission).first() + if not perm: + perm = Permission(name=permission) + db.add(perm) + group.permissions.append(perm) + db.commit() + return {"msg": "Permission added to group"} + +@permission_router.post("/users/{user_id}/groups") +async def add_user_to_group(user_id: int, group_id: int, db: Session = Depends(get_user_db)): + user = db.query(User).filter(User.id == user_id).first() + group = db.query(Group).filter(Group.id == group_id).first() + if not user or not group: + raise HTTPException(status_code=404, detail="User or group not found") + user.groups.append(group) + db.commit() + return {"msg": "User added to group"} \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py index c4db189a1..685cff7fb 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -9,8 +9,8 @@ from fastapi_users.authentication import ( JWTStrategy, ) from fastapi_users.db import SQLAlchemyUserDatabase - - +from fastapi import Depends, HTTPException, status +from sqlalchemy.orm import Session from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db SECRET = "SECRET" @@ -53,4 +53,19 @@ auth_backend = AuthenticationBackend( fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [auth_backend]) -current_active_user = fastapi_users.current_user(active=True) \ No newline at end of file +current_active_user = fastapi_users.current_user(active=True) + + +async def get_user_permissions(user: User, session: Session): + permissions = set() + for group in user.groups: + permissions.update(permission.name for permission in group.permissions) + return permissions + +def has_permission(permission: str): + async def permission_checker(user: User = Depends(current_active_user), session: Session = Depends(get_user_db)): + user_permissions = await get_user_permissions(user, session) + if permission not in user_permissions: + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions") + return True + return Depends(permission_checker) \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 66f207108..d952b574a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -609,17 +609,17 @@ css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "boto3" -version = "1.34.145" +version = "1.34.146" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.145-py3-none-any.whl", hash = "sha256:69d5afb7a017d07dd6bdfb680d2912d5d369b3fafa0a45161207d9f393b14d7e"}, - {file = "boto3-1.34.145.tar.gz", hash = "sha256:ac770fb53dde1743aec56bd8e56b7ee2e2f5ad42a37825968ec4ff8428822640"}, + {file = "boto3-1.34.146-py3-none-any.whl", hash = "sha256:7ec568fb19bce82a70be51f08fddac1ef927ca3fb0896cbb34303a012ba228d8"}, + {file = "boto3-1.34.146.tar.gz", hash = "sha256:5686fe2a6d1aa1de8a88e9589cdcc33361640d3d7a13da718a30717248886124"}, ] [package.dependencies] -botocore = ">=1.34.145,<1.35.0" +botocore = ">=1.34.146,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -628,13 +628,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.145" +version = "1.34.146" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.145-py3-none-any.whl", hash = "sha256:2e72e262de02adcb0264ac2bac159a28f55dbba8d9e52aa0308773a42950dff5"}, - {file = "botocore-1.34.145.tar.gz", hash = "sha256:edf0fb4c02186ae29b76263ac5fda18b0a085d334a310551c9984407cf1079e6"}, + {file = "botocore-1.34.146-py3-none-any.whl", hash = "sha256:3fd4782362bd29c192704ebf859c5c8c5189ad05719e391eefe23088434427ae"}, + {file = "botocore-1.34.146.tar.gz", hash = "sha256:849cb8e54e042443aeabcd7822b5f2b76cb5cfe33fe3a71f91c7c069748a869c"}, ] [package.dependencies] @@ -3544,13 +3544,13 @@ pygments = ">2.12.0" [[package]] name = "mkdocs-material" -version = "9.5.29" +version = "9.5.30" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.29-py3-none-any.whl", hash = "sha256:afc1f508e2662ded95f0a35a329e8a5acd73ee88ca07ba73836eb6fcdae5d8b4"}, - {file = "mkdocs_material-9.5.29.tar.gz", hash = "sha256:3e977598ec15a4ddad5c4dfc9e08edab6023edb51e88f0729bd27be77e3d322a"}, + {file = "mkdocs_material-9.5.30-py3-none-any.whl", hash = "sha256:fc070689c5250a180e9b9d79d8491ef9a3a7acb240db0728728d6c31eeb131d4"}, + {file = "mkdocs_material-9.5.30.tar.gz", hash = "sha256:3fd417dd42d679e3ba08b9e2d72cd8b8af142cc4a3969676ad6b00993dd182ec"}, ] [package.dependencies] @@ -5742,13 +5742,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requirements-parser" -version = "0.9.0" +version = "0.10.0" description = "This is a small Python module for parsing Pip requirement files." optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "requirements_parser-0.9.0-py3-none-any.whl", hash = "sha256:40298fd2bb423798fc52ca4550adf1944d75c998fd2316b5b6959842dbc70a32"}, - {file = "requirements_parser-0.9.0.tar.gz", hash = "sha256:588f587ab76732d59df4c64bd81f1b4a4f1aaaa9b3eb7ad4f5890685446f03e8"}, + {file = "requirements_parser-0.10.0-py3-none-any.whl", hash = "sha256:3c165f679f2c69fc8b4910a8cd86cea1f2c125d8624eb272e90db86dfddff064"}, + {file = "requirements_parser-0.10.0.tar.gz", hash = "sha256:8eebcb5abc2ec300b5d4ff7777354564cab495af524336438d72688672d49dc6"}, ] [package.dependencies] @@ -6430,70 +6430,61 @@ files = [ [[package]] name = "sqlalchemy" -version = "2.0.31" +version = "2.0.21" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2a213c1b699d3f5768a7272de720387ae0122f1becf0901ed6eaa1abd1baf6c"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9fea3d0884e82d1e33226935dac990b967bef21315cbcc894605db3441347443"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ad7f221d8a69d32d197e5968d798217a4feebe30144986af71ada8c548e9fa"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2bee229715b6366f86a95d497c347c22ddffa2c7c96143b59a2aa5cc9eebbc"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cd5b94d4819c0c89280b7c6109c7b788a576084bf0a480ae17c227b0bc41e109"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:750900a471d39a7eeba57580b11983030517a1f512c2cb287d5ad0fcf3aebd58"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-win32.whl", hash = "sha256:7bd112be780928c7f493c1a192cd8c5fc2a2a7b52b790bc5a84203fb4381c6be"}, - {file = "SQLAlchemy-2.0.31-cp310-cp310-win_amd64.whl", hash = "sha256:5a48ac4d359f058474fadc2115f78a5cdac9988d4f99eae44917f36aa1476327"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f68470edd70c3ac3b6cd5c2a22a8daf18415203ca1b036aaeb9b0fb6f54e8298"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e2c38c2a4c5c634fe6c3c58a789712719fa1bf9b9d6ff5ebfce9a9e5b89c1ca"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd15026f77420eb2b324dcb93551ad9c5f22fab2c150c286ef1dc1160f110203"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2196208432deebdfe3b22185d46b08f00ac9d7b01284e168c212919891289396"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:352b2770097f41bff6029b280c0e03b217c2dcaddc40726f8f53ed58d8a85da4"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:56d51ae825d20d604583f82c9527d285e9e6d14f9a5516463d9705dab20c3740"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-win32.whl", hash = "sha256:6e2622844551945db81c26a02f27d94145b561f9d4b0c39ce7bfd2fda5776dac"}, - {file = "SQLAlchemy-2.0.31-cp311-cp311-win_amd64.whl", hash = "sha256:ccaf1b0c90435b6e430f5dd30a5aede4764942a695552eb3a4ab74ed63c5b8d3"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3b74570d99126992d4b0f91fb87c586a574a5872651185de8297c6f90055ae42"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f77c4f042ad493cb8595e2f503c7a4fe44cd7bd59c7582fd6d78d7e7b8ec52c"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1591329333daf94467e699e11015d9c944f44c94d2091f4ac493ced0119449"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74afabeeff415e35525bf7a4ecdab015f00e06456166a2eba7590e49f8db940e"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b9c01990d9015df2c6f818aa8f4297d42ee71c9502026bb074e713d496e26b67"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66f63278db425838b3c2b1c596654b31939427016ba030e951b292e32b99553e"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-win32.whl", hash = "sha256:0b0f658414ee4e4b8cbcd4a9bb0fd743c5eeb81fc858ca517217a8013d282c96"}, - {file = "SQLAlchemy-2.0.31-cp312-cp312-win_amd64.whl", hash = "sha256:fa4b1af3e619b5b0b435e333f3967612db06351217c58bfb50cee5f003db2a5a"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f43e93057cf52a227eda401251c72b6fbe4756f35fa6bfebb5d73b86881e59b0"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d337bf94052856d1b330d5fcad44582a30c532a2463776e1651bd3294ee7e58b"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c06fb43a51ccdff3b4006aafee9fcf15f63f23c580675f7734245ceb6b6a9e05"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:b6e22630e89f0e8c12332b2b4c282cb01cf4da0d26795b7eae16702a608e7ca1"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:79a40771363c5e9f3a77f0e28b3302801db08040928146e6808b5b7a40749c88"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-win32.whl", hash = "sha256:501ff052229cb79dd4c49c402f6cb03b5a40ae4771efc8bb2bfac9f6c3d3508f"}, - {file = "SQLAlchemy-2.0.31-cp37-cp37m-win_amd64.whl", hash = "sha256:597fec37c382a5442ffd471f66ce12d07d91b281fd474289356b1a0041bdf31d"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dc6d69f8829712a4fd799d2ac8d79bdeff651c2301b081fd5d3fe697bd5b4ab9"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:23b9fbb2f5dd9e630db70fbe47d963c7779e9c81830869bd7d137c2dc1ad05fb"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a21c97efcbb9f255d5c12a96ae14da873233597dfd00a3a0c4ce5b3e5e79704"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a6a9837589c42b16693cf7bf836f5d42218f44d198f9343dd71d3164ceeeac"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc251477eae03c20fae8db9c1c23ea2ebc47331bcd73927cdcaecd02af98d3c3"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2fd17e3bb8058359fa61248c52c7b09a97cf3c820e54207a50af529876451808"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-win32.whl", hash = "sha256:c76c81c52e1e08f12f4b6a07af2b96b9b15ea67ccdd40ae17019f1c373faa227"}, - {file = "SQLAlchemy-2.0.31-cp38-cp38-win_amd64.whl", hash = "sha256:4b600e9a212ed59355813becbcf282cfda5c93678e15c25a0ef896b354423238"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b6cf796d9fcc9b37011d3f9936189b3c8074a02a4ed0c0fbbc126772c31a6d4"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:78fe11dbe37d92667c2c6e74379f75746dc947ee505555a0197cfba9a6d4f1a4"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc47dc6185a83c8100b37acda27658fe4dbd33b7d5e7324111f6521008ab4fe"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a41514c1a779e2aa9a19f67aaadeb5cbddf0b2b508843fcd7bafdf4c6864005"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:afb6dde6c11ea4525318e279cd93c8734b795ac8bb5dda0eedd9ebaca7fa23f1"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3f9faef422cfbb8fd53716cd14ba95e2ef655400235c3dfad1b5f467ba179c8c"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-win32.whl", hash = "sha256:fc6b14e8602f59c6ba893980bea96571dd0ed83d8ebb9c4479d9ed5425d562e9"}, - {file = "SQLAlchemy-2.0.31-cp39-cp39-win_amd64.whl", hash = "sha256:3cb8a66b167b033ec72c3812ffc8441d4e9f5f78f5e31e54dcd4c90a4ca5bebc"}, - {file = "SQLAlchemy-2.0.31-py3-none-any.whl", hash = "sha256:69f3e3c08867a8e4856e92d7afb618b95cdee18e0bc1647b77599722c9a28911"}, - {file = "SQLAlchemy-2.0.31.tar.gz", hash = "sha256:b607489dd4a54de56984a0c7656247504bd5523d9d0ba799aef59d4add009484"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e7dc99b23e33c71d720c4ae37ebb095bebebbd31a24b7d99dfc4753d2803ede"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f0c4ee579acfe6c994637527c386d1c22eb60bc1c1d36d940d8477e482095d4"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7d57a7e140efe69ce2d7b057c3f9a595f98d0bbdfc23fd055efdfbaa46e3a5"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca38746eac23dd7c20bec9278d2058c7ad662b2f1576e4c3dbfcd7c00cc48fa"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3cf229704074bce31f7f47d12883afee3b0a02bb233a0ba45ddbfe542939cca4"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb87f763b5d04a82ae84ccff25554ffd903baafba6698e18ebaf32561f2fe4aa"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-win32.whl", hash = "sha256:89e274604abb1a7fd5c14867a412c9d49c08ccf6ce3e1e04fffc068b5b6499d4"}, + {file = "SQLAlchemy-2.0.21-cp310-cp310-win_amd64.whl", hash = "sha256:e36339a68126ffb708dc6d1948161cea2a9e85d7d7b0c54f6999853d70d44430"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf8eebccc66829010f06fbd2b80095d7872991bfe8415098b9fe47deaaa58063"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b977bfce15afa53d9cf6a632482d7968477625f030d86a109f7bdfe8ce3c064a"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff3dc2f60dbf82c9e599c2915db1526d65415be323464f84de8db3e361ba5b9"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44ac5c89b6896f4740e7091f4a0ff2e62881da80c239dd9408f84f75a293dae9"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:87bf91ebf15258c4701d71dcdd9c4ba39521fb6a37379ea68088ce8cd869b446"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, + {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8c323813963b2503e54d0944813cd479c10c636e3ee223bcbd7bd478bf53c178"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:419b1276b55925b5ac9b4c7044e999f1787c69761a3c9756dec6e5c225ceca01"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-win32.whl", hash = "sha256:4615623a490e46be85fbaa6335f35cf80e61df0783240afe7d4f544778c315a9"}, + {file = "SQLAlchemy-2.0.21-cp37-cp37m-win_amd64.whl", hash = "sha256:cca720d05389ab1a5877ff05af96551e58ba65e8dc65582d849ac83ddde3e231"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b4eae01faee9f2b17f08885e3f047153ae0416648f8e8c8bd9bc677c5ce64be9"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3eb7c03fe1cd3255811cd4e74db1ab8dca22074d50cd8937edf4ef62d758cdf4"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2d494b6a2a2d05fb99f01b84cc9af9f5f93bf3e1e5dbdafe4bed0c2823584c1"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b19ae41ef26c01a987e49e37c77b9ad060c59f94d3b3efdfdbf4f3daaca7b5fe"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fc6b15465fabccc94bf7e38777d665b6a4f95efd1725049d6184b3a39fd54880"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:014794b60d2021cc8ae0f91d4d0331fe92691ae5467a00841f7130fe877b678e"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-win32.whl", hash = "sha256:0268256a34806e5d1c8f7ee93277d7ea8cc8ae391f487213139018b6805aeaf6"}, + {file = "SQLAlchemy-2.0.21-cp38-cp38-win_amd64.whl", hash = "sha256:73c079e21d10ff2be54a4699f55865d4b275fd6c8bd5d90c5b1ef78ae0197301"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:785e2f2c1cb50d0a44e2cdeea5fd36b5bf2d79c481c10f3a88a8be4cfa2c4615"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c111cd40910ffcb615b33605fc8f8e22146aeb7933d06569ac90f219818345ef"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cba4e7369de663611ce7460a34be48e999e0bbb1feb9130070f0685e9a6b66"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a69067af86ec7f11a8e50ba85544657b1477aabf64fa447fd3736b5a0a4f67"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ccb99c3138c9bde118b51a289d90096a3791658da9aea1754667302ed6564f6e"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:513fd5b6513d37e985eb5b7ed89da5fd9e72354e3523980ef00d439bc549c9e9"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-win32.whl", hash = "sha256:f9fefd6298433b6e9188252f3bff53b9ff0443c8fde27298b8a2b19f6617eeb9"}, + {file = "SQLAlchemy-2.0.21-cp39-cp39-win_amd64.whl", hash = "sha256:2e617727fe4091cedb3e4409b39368f424934c7faa78171749f704b49b4bb4ce"}, + {file = "SQLAlchemy-2.0.21-py3-none-any.whl", hash = "sha256:ea7da25ee458d8f404b93eb073116156fd7d8c2a776d8311534851f28277b4ce"}, + {file = "SQLAlchemy-2.0.21.tar.gz", hash = "sha256:05b971ab1ac2994a14c56b35eaaa91f86ba080e9ad481b20d99d77f381bb6258"}, ] [package.dependencies] -greenlet = {version = "!=0.4.17", optional = true, markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") or extra == \"asyncio\""} -typing-extensions = ">=4.6.0" +greenlet = {version = "!=0.4.17", optional = true, markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\" or extra == \"asyncio\""} +typing-extensions = ">=4.2.0" [package.extras] aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] +aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] asyncio = ["greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] @@ -6503,7 +6494,7 @@ mssql-pyodbc = ["pyodbc"] mypy = ["mypy (>=0.910)"] mysql = ["mysqlclient (>=1.4.0)"] mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=8)"] +oracle = ["cx-oracle (>=7)"] oracle-oracledb = ["oracledb (>=1.0.1)"] postgresql = ["psycopg2 (>=2.7)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] @@ -6513,7 +6504,7 @@ postgresql-psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2cffi = ["psycopg2cffi"] postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3_binary"] +sqlcipher = ["sqlcipher3-binary"] [[package]] name = "squarify" @@ -7068,13 +7059,13 @@ files = [ [[package]] name = "types-setuptools" -version = "71.0.0.20240722" +version = "71.1.0.20240723" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-71.0.0.20240722.tar.gz", hash = "sha256:8f1fd5281945ed8f5a896f05dd50bc31917d6e2487ff9508f4bac522d13ad395"}, - {file = "types_setuptools-71.0.0.20240722-py3-none-any.whl", hash = "sha256:04a383bd1a2dcdb6a85397516ce2d7b46617d89f1d758f686d0d9069943d9811"}, + {file = "types-setuptools-71.1.0.20240723.tar.gz", hash = "sha256:8a9349038c7e22d88e6c5d9c6705b347b22930424114a452c1712899e85131ff"}, + {file = "types_setuptools-71.1.0.20240723-py3-none-any.whl", hash = "sha256:ac9fc263f59d1e02bca49cb7270a12c47ab80b3b911fb4d92f1fecf978bfe88a"}, ] [[package]] @@ -7556,4 +7547,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<3.12" -content-hash = "e0776d8f9fb8fd682bef3b0c4111ca52540d901fc00a3c2ae809c94b7440c559" +content-hash = "003bc600a702d9e31cbe73414f5db06c38bec29faa448fede74256efce786be2" diff --git a/pyproject.toml b/pyproject.toml index 6ad360e76..092328993 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ fastapi = "^0.109.2" uvicorn = "0.22.0" boto3 = "^1.26.125" gunicorn = "^20.1.0" -sqlalchemy = "^2.0.21" +sqlalchemy = "2.0.21" instructor = "1.3.5" networkx = "^3.2.1" debugpy = "^1.8.0" From 36e156e80a201ee6190677ce933e276c7dc27dda Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:12:37 +0200 Subject: [PATCH 05/44] Fixes to the model and adding the read info to the graph --- cognee/api/v1/cognify/cognify_v2.py | 24 +++++++++++++++++-- .../user_authentication/authentication_db.py | 2 +- .../data/processing/process_documents.py | 5 +++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index e10680f19..20e2624cb 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -1,8 +1,14 @@ import asyncio +import hashlib import logging +import uuid from typing import Union +from sqlalchemy.ext.asyncio import AsyncSession + from cognee.infrastructure.databases.graph import get_graph_config +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker +from cognee.infrastructure.databases.relational.user_authentication.users import get_user_permissions, fastapi_users from cognee.modules.cognify.config import get_cognify_config from cognee.infrastructure.databases.relational.config import get_relationaldb_config from cognee.modules.data.processing.document_types.AudioDocument import AudioDocument @@ -25,7 +31,21 @@ logger = logging.getLogger("cognify.v2") update_status_lock = asyncio.Lock() -async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None): +class PermissionDeniedException(Exception): + def __init__(self, message: str): + self.message = message + super().__init__(self.message) + +async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None, user_id:str="default_user"): + session: AsyncSession = async_session_maker() + user = await fastapi_users.get_user_manager.get(user_id) + user_permissions = await get_user_permissions(user, session) + hash_object = hashlib.sha256(user.encode()) + hashed_user_id = hash_object.hexdigest() + required_permission = "write" + if required_permission not in user_permissions: + raise PermissionDeniedException("Not enough permissions") + relational_config = get_relationaldb_config() db_engine = relational_config.database_engine create_task_status_table() @@ -60,7 +80,7 @@ async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = No root_node_id = "ROOT" tasks = [ - Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }, user_id = hashed_user_id, user_permissions=user_permissions), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type Task(establish_graph_topology, topology_model = KnowledgeGraph), # Set the graph topology for the document chunk data Task(expand_knowledge_graph, graph_model = KnowledgeGraph), # Generate knowledge graphs from the document chunks and attach it to chunk nodes Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py index d517453c6..ae4405a9b 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -31,7 +31,7 @@ class Group(Base): __tablename__ = 'groups' id = Column(UUID, primary_key=True, index=True) name = Column(String, unique=True, index=True) - users = relationship('User', secondary=user_group, back_populates='groups') + users = relationship('users', secondary=user_group, back_populates='groups') permissions = relationship('Permission', secondary=group_permission, back_populates='groups') class Permission(Base): diff --git a/cognee/modules/data/processing/process_documents.py b/cognee/modules/data/processing/process_documents.py index 1eb3bbd3e..8df8067b6 100644 --- a/cognee/modules/data/processing/process_documents.py +++ b/cognee/modules/data/processing/process_documents.py @@ -1,7 +1,7 @@ from cognee.infrastructure.databases.graph import get_graph_engine from .document_types import Document -async def process_documents(documents: list[Document], parent_node_id: str = None): +async def process_documents(documents: list[Document], parent_node_id: str = None, user:str=None, user_permissions:str=None): graph_engine = await get_graph_engine() nodes = [] @@ -16,6 +16,9 @@ async def process_documents(documents: list[Document], parent_node_id: str = Non document_node = document_nodes[document_index] if document_index in document_nodes else None if document_node is None: + document_dict = document.to_dict() + document_dict["user"] = user + document_dict["user_permissions"] = user_permissions nodes.append((str(document.id), document.to_dict())) if parent_node_id: From 3f5e665c45f214a81183309d9f751cbc6aa1ca1f Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:45:36 +0200 Subject: [PATCH 06/44] Update cognee/api/client.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/api/client.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/cognee/api/client.py b/cognee/api/client.py index 3b2e0c0a0..be164c30c 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -117,9 +117,6 @@ app.include_router( ) -@app.get("/authenticated-route") -async def authenticated_route(user: User = Depends(current_active_user)): - return {"message": f"Hello {user.email}!"} @app.get("/") async def root(): From e7b0e712b76d21cce4cd2d2ebc956cc175bad440 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:59:58 +0200 Subject: [PATCH 07/44] Fixes to translation services --- cognee/api/client.py | 3 --- .../relational/sqlalchemy/SqlAlchemyAdapter.py | 13 ++++--------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/cognee/api/client.py b/cognee/api/client.py index 3b2e0c0a0..3ed3efd07 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -83,9 +83,6 @@ app.include_router( ) app.include_router(permission_router, prefix="/manage", tags=["management"]) -@app.get("/authenticated-route") -async def authenticated_route(user: User = Depends(current_active_user)): - return {"message": f"Hello {user.email}!"} @asynccontextmanager async def lifespan(app: FastAPI): diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index 18f7ec876..dbdc44c40 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -9,25 +9,20 @@ class SQLAlchemyAdapter(): # self.engine = create_engine(f"{db_type}:///{self.db_location}") if db_type == "duckdb": self.engine = create_engine(f"duckdb:///{self.db_location}") - self.Session = sessionmaker(bind=self.engine) + self.sessionmaker = sessionmaker(bind=self.engine) else: - print("Name: ", db_name) - print("User: ", db_user) - print("Password: ", db_password) - print("Host: ", db_host) - print("Port: ", db_port) self.engine = create_async_engine(f"postgresql+asyncpg://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}") - self.Session = sessionmaker(bind=self.engine, class_=AsyncSession, expire_on_commit=False) + self.sessionmaker = sessionmaker(bind=self.engine, class_=AsyncSession, expire_on_commit=False) async def get_async_session(self): - async_session_maker = self.Session + async_session_maker = self.sessionmaker async with async_session_maker() as session: yield session def get_session(self): - session_maker = self.Session + session_maker = self.sessionmaker with session_maker() as session: yield session From 9616545de9f7da5900c7acea2ae2428c949c9d01 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:14:57 +0200 Subject: [PATCH 08/44] Exposed user management --- cognee/api/v1/authenticate_user/__init__.py | 1 + .../v1/authenticate_user/authenticate_user.py | 9 ++ cognee/api/v1/create_user/__init__.py | 1 + cognee/api/v1/create_user/create_user.py | 7 + cognee/api/v1/reset_user_password/__init__.py | 1 + cognee/api/v1/verify_user_token/__init__.py | 1 + .../v1/verify_user_token/verify_user_token.py | 8 ++ .../user_authentication/authentication_db.py | 122 +++++++++++++++++- 8 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 cognee/api/v1/authenticate_user/__init__.py create mode 100644 cognee/api/v1/authenticate_user/authenticate_user.py create mode 100644 cognee/api/v1/create_user/__init__.py create mode 100644 cognee/api/v1/create_user/create_user.py create mode 100644 cognee/api/v1/reset_user_password/__init__.py create mode 100644 cognee/api/v1/verify_user_token/__init__.py create mode 100644 cognee/api/v1/verify_user_token/verify_user_token.py diff --git a/cognee/api/v1/authenticate_user/__init__.py b/cognee/api/v1/authenticate_user/__init__.py new file mode 100644 index 000000000..67538a7e3 --- /dev/null +++ b/cognee/api/v1/authenticate_user/__init__.py @@ -0,0 +1 @@ +from .authenticate_user import authenticate_user diff --git a/cognee/api/v1/authenticate_user/authenticate_user.py b/cognee/api/v1/authenticate_user/authenticate_user.py new file mode 100644 index 000000000..d7dd5a22c --- /dev/null +++ b/cognee/api/v1/authenticate_user/authenticate_user.py @@ -0,0 +1,9 @@ +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import authenticate_user_method + + +async def authenticate_user(): + """ + This function is used to authenticate a user. + """ + output = await authenticate_user_method() + return output diff --git a/cognee/api/v1/create_user/__init__.py b/cognee/api/v1/create_user/__init__.py new file mode 100644 index 000000000..aad3147da --- /dev/null +++ b/cognee/api/v1/create_user/__init__.py @@ -0,0 +1 @@ +from .create_user import create_user diff --git a/cognee/api/v1/create_user/create_user.py b/cognee/api/v1/create_user/create_user.py new file mode 100644 index 000000000..41074751d --- /dev/null +++ b/cognee/api/v1/create_user/create_user.py @@ -0,0 +1,7 @@ +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import create_user_method + + + +async def create_user(email: str, password: str, is_superuser: bool = False): + output = await create_user_method(email=email, password=password, is_superuser=is_superuser) + return output \ No newline at end of file diff --git a/cognee/api/v1/reset_user_password/__init__.py b/cognee/api/v1/reset_user_password/__init__.py new file mode 100644 index 000000000..aad3147da --- /dev/null +++ b/cognee/api/v1/reset_user_password/__init__.py @@ -0,0 +1 @@ +from .create_user import create_user diff --git a/cognee/api/v1/verify_user_token/__init__.py b/cognee/api/v1/verify_user_token/__init__.py new file mode 100644 index 000000000..45fda4dba --- /dev/null +++ b/cognee/api/v1/verify_user_token/__init__.py @@ -0,0 +1 @@ +from .verify_user_token import verify_user_token diff --git a/cognee/api/v1/verify_user_token/verify_user_token.py b/cognee/api/v1/verify_user_token/verify_user_token.py new file mode 100644 index 000000000..bc1e9bcd9 --- /dev/null +++ b/cognee/api/v1/verify_user_token/verify_user_token.py @@ -0,0 +1,8 @@ +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import user_check_token + + + +async def verify_user_token(token: str): + + output = await user_check_token(token=token) + return output \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py index ae4405a9b..b83327ed7 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -1,4 +1,6 @@ -from typing import AsyncGenerator, Generator +import hashlib +import uuid +from typing import AsyncGenerator, Generator, Optional from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase @@ -7,10 +9,13 @@ from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_asyn from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session from cognee.infrastructure.databases.relational import get_relationaldb_config, Base from sqlalchemy import Column, String, ForeignKey, Table, Integer - - +from contextlib import asynccontextmanager +from fastapi_users.exceptions import UserAlreadyExists +from fastapi_users.authentication import JWTStrategy from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session, relationship - +from cognee.infrastructure.databases.relational.user_authentication.schemas import UserRead, UserCreate +from cognee.infrastructure.databases.relational.user_authentication.users import get_user_manager, get_jwt_strategy +from fastapi.security import OAuth2PasswordRequestForm # Association table for many-to-many relationship between users and groups user_group = Table('user_group', Base.metadata, Column('user_id', UUID, ForeignKey('users.id')), @@ -40,6 +45,17 @@ class Permission(Base): name = Column(String, unique=True, index=True) groups = relationship('Group', secondary=group_permission, back_populates='permissions') +class ACL(Base): + __tablename__ = 'acls' + id = Column(UUID, primary_key=True, index=True) + document_id = Column(UUID, ForeignKey('documents.id')) + user_id = Column(UUID, ForeignKey('users.id'), nullable=True) + group_id = Column(UUID, ForeignKey('groups.id'), nullable=True) + permission = Column(String) # 'read', 'write', 'execute' + document = relationship('dataset_data', back_populates='acls') + user = relationship('users', back_populates='acls') + group = relationship('groups', back_populates='acls') + relational_config = get_relationaldb_config() @@ -59,3 +75,101 @@ async def get_async_session() -> AsyncGenerator[AsyncSession, None]: async def get_user_db(session: AsyncSession = Depends(get_async_session)): yield SQLAlchemyUserDatabase(session, User) + + +async def hash_password(password: str) -> str: + return hashlib.sha256(password.encode()).hexdigest() + +# Define context managers for dependencies +get_async_session_context = asynccontextmanager(get_async_session) +get_user_db_context = asynccontextmanager(get_user_db) +get_user_manager_context = asynccontextmanager(get_user_manager) + +async def create_user_method(email: str, password: str, is_superuser: bool = False): + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + user = await user_manager.create( + UserCreate(email=email, password=password, is_superuser=is_superuser) + ) + print(f"User created: {user.email}") + except UserAlreadyExists: + print(f"User {email} already exists") + +async def authenticate_user_method(email: str, password: str) -> Optional[User]: + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + credentials = OAuth2PasswordRequestForm(username=email, password=password) + user = await user_manager.authenticate(credentials) + if user is None or not user.is_active: + return None + return user + except Exception as e: + print(f"Error during authentication: {e}") + return None + +async def reset_user_password_method(email: str, new_password: str) -> bool: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + user = await user_db.get_by_email(email) + if not user: + return False + user.hashed_password = await hash_password(new_password) + await user_db.update(user) + return True + +# async def generate_verification_token(email: str, tokens_db: dict) -> str: +# async with get_async_session_context() as session: +# async with get_user_db_context(session) as user_db: +# if not await user_db.get_by_email(email): +# raise ValueError("User does not exist") +# token = str(uuid.uuid4()) +# tokens_db[token] = email +# return token + +# async def verify_user_method(token: str, tokens_db: dict) -> bool: +# async with get_async_session_context() as session: +# async with get_user_db_context(session) as user_db: +# email = tokens_db.get(token) +# if not email or not await user_db.get_by_email(email): +# return False +# user = await user_db.get_by_email(email) +# user.is_verified = True +# await user_db.update(user) +# return True + + +async def user_create_token(user: User) -> Optional[str]: + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + if user is None: + return None + strategy = get_jwt_strategy() + token = await strategy.write_token(user) + if token is not None: + return token + else: + return None + except: + return None + +async def user_check_token(token: str) -> bool: + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + if token is None: + return False + strategy = get_jwt_strategy() + user = await strategy.read_token(token, user_manager) + if user is None or not user.is_active: + return False + else: + return True + except: + return False \ No newline at end of file From 218d322c75a4a62d17e23d841ace73ba0fe82c80 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sat, 27 Jul 2024 10:09:01 +0200 Subject: [PATCH 09/44] Fixes to the ACL model --- .../v1/authenticate_user/authenticate_user.py | 2 +- cognee/api/v1/cognify/cognify_v2.py | 20 +-- cognee/api/v1/create_user/create_user.py | 19 ++- .../v1/verify_user_token/verify_user_token.py | 2 +- .../infrastructure/data/models/DatasetData.py | 17 ++- .../user_authentication/authentication_db.py | 116 ++---------------- .../relational/user_authentication/users.py | 110 ++++++++++++++++- 7 files changed, 158 insertions(+), 128 deletions(-) diff --git a/cognee/api/v1/authenticate_user/authenticate_user.py b/cognee/api/v1/authenticate_user/authenticate_user.py index d7dd5a22c..7d493adfc 100644 --- a/cognee/api/v1/authenticate_user/authenticate_user.py +++ b/cognee/api/v1/authenticate_user/authenticate_user.py @@ -1,4 +1,4 @@ -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import authenticate_user_method +from cognee.infrastructure.databases.relational.user_authentication.users import authenticate_user_method async def authenticate_user(): diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 20e2624cb..ecb9fd7c4 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -7,8 +7,8 @@ from typing import Union from sqlalchemy.ext.asyncio import AsyncSession from cognee.infrastructure.databases.graph import get_graph_config -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker -from cognee.infrastructure.databases.relational.user_authentication.users import get_user_permissions, fastapi_users +# from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker +# from cognee.infrastructure.databases.relational.user_authentication.users import get_user_permissions, fastapi_users from cognee.modules.cognify.config import get_cognify_config from cognee.infrastructure.databases.relational.config import get_relationaldb_config from cognee.modules.data.processing.document_types.AudioDocument import AudioDocument @@ -37,14 +37,14 @@ class PermissionDeniedException(Exception): super().__init__(self.message) async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None, user_id:str="default_user"): - session: AsyncSession = async_session_maker() - user = await fastapi_users.get_user_manager.get(user_id) - user_permissions = await get_user_permissions(user, session) - hash_object = hashlib.sha256(user.encode()) - hashed_user_id = hash_object.hexdigest() - required_permission = "write" - if required_permission not in user_permissions: - raise PermissionDeniedException("Not enough permissions") + # session: AsyncSession = async_session_maker() + # user = await fastapi_users.get_user_manager.get(user_id) + # user_permissions = await get_user_permissions(user, session) + # hash_object = hashlib.sha256(user.encode()) + # hashed_user_id = hash_object.hexdigest() + # required_permission = "write" + # if required_permission not in user_permissions: + # raise PermissionDeniedException("Not enough permissions") relational_config = get_relationaldb_config() db_engine = relational_config.database_engine diff --git a/cognee/api/v1/create_user/create_user.py b/cognee/api/v1/create_user/create_user.py index 41074751d..3901aa593 100644 --- a/cognee/api/v1/create_user/create_user.py +++ b/cognee/api/v1/create_user/create_user.py @@ -1,7 +1,22 @@ -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import create_user_method +from cognee.infrastructure.databases.relational.user_authentication.users import create_user_method async def create_user(email: str, password: str, is_superuser: bool = False): output = await create_user_method(email=email, password=password, is_superuser=is_superuser) - return output \ No newline at end of file + return output + + +if __name__ == "__main__": + import asyncio + # Define an example user + example_email = "example@example.com" + example_password = "securepassword123" + example_is_superuser = False + + # Create an event loop and run the create_user function + loop = asyncio.get_event_loop() + result = loop.run_until_complete(create_user(example_email, example_password, example_is_superuser)) + + # Print the result + print(result) \ No newline at end of file diff --git a/cognee/api/v1/verify_user_token/verify_user_token.py b/cognee/api/v1/verify_user_token/verify_user_token.py index bc1e9bcd9..b5a0f2228 100644 --- a/cognee/api/v1/verify_user_token/verify_user_token.py +++ b/cognee/api/v1/verify_user_token/verify_user_token.py @@ -1,4 +1,4 @@ -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import user_check_token +from cognee.infrastructure.databases.relational.user_authentication.users import user_check_token diff --git a/cognee/infrastructure/data/models/DatasetData.py b/cognee/infrastructure/data/models/DatasetData.py index 552642686..9e586dcef 100644 --- a/cognee/infrastructure/data/models/DatasetData.py +++ b/cognee/infrastructure/data/models/DatasetData.py @@ -1,14 +1,19 @@ from uuid import uuid4 from datetime import datetime, timezone -from sqlalchemy import Column, DateTime, UUID, ForeignKey +from sqlalchemy import Column, DateTime, UUID, ForeignKey, PrimaryKeyConstraint, UniqueConstraint +from sqlalchemy.orm import relationship + from cognee.infrastructure.databases.relational import Base class DatasetData(Base): __tablename__ = "dataset_data" - id = Column(UUID, primary_key = True, default = uuid4()) + id = Column(UUID, primary_key=True, default=uuid4) + created_at = Column(DateTime, default=datetime.now(timezone.utc)) + dataset_id = Column(UUID, ForeignKey("dataset.id"), nullable=False) + data_id = Column(UUID, ForeignKey("data.id"), nullable=False) + __table_args__ = ( + UniqueConstraint('dataset_id', 'data_id', name='uix_dataset_data'), + ) - created_at = Column(DateTime, default = datetime.now(timezone.utc)) - - dataset_id = Column("dataset", UUID, ForeignKey("dataset.id"), primary_key = True) - data_id = Column("data", UUID, ForeignKey("data.id"), primary_key = True) + acls = relationship('ACL', back_populates='document') diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py index b83327ed7..bbc0a01f7 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py @@ -14,7 +14,7 @@ from fastapi_users.exceptions import UserAlreadyExists from fastapi_users.authentication import JWTStrategy from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session, relationship from cognee.infrastructure.databases.relational.user_authentication.schemas import UserRead, UserCreate -from cognee.infrastructure.databases.relational.user_authentication.users import get_user_manager, get_jwt_strategy +# from cognee.infrastructure.databases.relational.user_authentication.users import get_user_manager, get_jwt_strategy from fastapi.security import OAuth2PasswordRequestForm # Association table for many-to-many relationship between users and groups user_group = Table('user_group', Base.metadata, @@ -31,14 +31,15 @@ group_permission = Table('group_permission', Base.metadata, class User(SQLAlchemyBaseUserTableUUID, Base): __tablename__ = 'users' groups = relationship('Group', secondary=user_group, back_populates='users') + acls = relationship('ACL', back_populates='user') class Group(Base): __tablename__ = 'groups' - id = Column(UUID, primary_key=True, index=True) + id = Column(UUID, primary_key=True, index=True, default=uuid.uuid4) name = Column(String, unique=True, index=True) - users = relationship('users', secondary=user_group, back_populates='groups') + users = relationship('User', secondary=user_group, back_populates='groups') permissions = relationship('Permission', secondary=group_permission, back_populates='groups') - + acls = relationship('ACL', back_populates='group') class Permission(Base): __tablename__ = 'permissions' id = Column(UUID, primary_key=True, index=True) @@ -47,15 +48,14 @@ class Permission(Base): class ACL(Base): __tablename__ = 'acls' - id = Column(UUID, primary_key=True, index=True) - document_id = Column(UUID, ForeignKey('documents.id')) + id = Column(UUID, primary_key=True, index=True, default=uuid.uuid4) + document_id = Column(UUID, ForeignKey('dataset_data.id')) user_id = Column(UUID, ForeignKey('users.id'), nullable=True) group_id = Column(UUID, ForeignKey('groups.id'), nullable=True) permission = Column(String) # 'read', 'write', 'execute' - document = relationship('dataset_data', back_populates='acls') - user = relationship('users', back_populates='acls') - group = relationship('groups', back_populates='acls') - + document = relationship('DatasetData', back_populates='acls') + user = relationship('User', back_populates='acls') + group = relationship('Group', back_populates='acls') relational_config = get_relationaldb_config() @@ -77,99 +77,3 @@ async def get_user_db(session: AsyncSession = Depends(get_async_session)): yield SQLAlchemyUserDatabase(session, User) -async def hash_password(password: str) -> str: - return hashlib.sha256(password.encode()).hexdigest() - -# Define context managers for dependencies -get_async_session_context = asynccontextmanager(get_async_session) -get_user_db_context = asynccontextmanager(get_user_db) -get_user_manager_context = asynccontextmanager(get_user_manager) - -async def create_user_method(email: str, password: str, is_superuser: bool = False): - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - user = await user_manager.create( - UserCreate(email=email, password=password, is_superuser=is_superuser) - ) - print(f"User created: {user.email}") - except UserAlreadyExists: - print(f"User {email} already exists") - -async def authenticate_user_method(email: str, password: str) -> Optional[User]: - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - credentials = OAuth2PasswordRequestForm(username=email, password=password) - user = await user_manager.authenticate(credentials) - if user is None or not user.is_active: - return None - return user - except Exception as e: - print(f"Error during authentication: {e}") - return None - -async def reset_user_password_method(email: str, new_password: str) -> bool: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - user = await user_db.get_by_email(email) - if not user: - return False - user.hashed_password = await hash_password(new_password) - await user_db.update(user) - return True - -# async def generate_verification_token(email: str, tokens_db: dict) -> str: -# async with get_async_session_context() as session: -# async with get_user_db_context(session) as user_db: -# if not await user_db.get_by_email(email): -# raise ValueError("User does not exist") -# token = str(uuid.uuid4()) -# tokens_db[token] = email -# return token - -# async def verify_user_method(token: str, tokens_db: dict) -> bool: -# async with get_async_session_context() as session: -# async with get_user_db_context(session) as user_db: -# email = tokens_db.get(token) -# if not email or not await user_db.get_by_email(email): -# return False -# user = await user_db.get_by_email(email) -# user.is_verified = True -# await user_db.update(user) -# return True - - -async def user_create_token(user: User) -> Optional[str]: - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - if user is None: - return None - strategy = get_jwt_strategy() - token = await strategy.write_token(user) - if token is not None: - return token - else: - return None - except: - return None - -async def user_check_token(token: str) -> bool: - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - if token is None: - return False - strategy = get_jwt_strategy() - user = await strategy.read_token(token, user_manager) - if user is None or not user.is_active: - return False - else: - return True - except: - return False \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py index 685cff7fb..4f7e5dce7 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -1,3 +1,4 @@ +import hashlib import uuid from typing import Optional @@ -8,10 +9,16 @@ from fastapi_users.authentication import ( BearerTransport, JWTStrategy, ) +from fastapi_users.exceptions import UserAlreadyExists from fastapi_users.db import SQLAlchemyUserDatabase from fastapi import Depends, HTTPException, status from sqlalchemy.orm import Session -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db, \ + get_async_session +from fastapi.security import OAuth2PasswordRequestForm +from fastapi_users.authentication import JWTStrategy +from cognee.infrastructure.databases.relational.user_authentication.schemas import UserRead, UserCreate +from contextlib import asynccontextmanager SECRET = "SECRET" @@ -68,4 +75,103 @@ def has_permission(permission: str): if permission not in user_permissions: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions") return True - return Depends(permission_checker) \ No newline at end of file + return Depends(permission_checker) + + +async def hash_password(password: str) -> str: + return hashlib.sha256(password.encode()).hexdigest() + +# Define context managers for dependencies +get_async_session_context = asynccontextmanager(get_async_session) +get_user_db_context = asynccontextmanager(get_user_db) +get_user_manager_context = asynccontextmanager(get_user_manager) + +async def create_user_method(email: str, password: str, is_superuser: bool = False): + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + user = await user_manager.create( + UserCreate(email=email, password=password, is_superuser=is_superuser) + ) + print(f"User created: {user.email}") + except UserAlreadyExists: + print(f"User {email} already exists") + +async def authenticate_user_method(email: str, password: str) -> Optional[User]: + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + credentials = OAuth2PasswordRequestForm(username=email, password=password) + user = await user_manager.authenticate(credentials) + if user is None or not user.is_active: + return None + return user + except Exception as e: + print(f"Error during authentication: {e}") + return None + +async def reset_user_password_method(email: str, new_password: str) -> bool: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + user = await user_db.get_by_email(email) + if not user: + return False + user.hashed_password = await hash_password(new_password) + await user_db.update(user) + return True + +# async def generate_verification_token(email: str, tokens_db: dict) -> str: +# async with get_async_session_context() as session: +# async with get_user_db_context(session) as user_db: +# if not await user_db.get_by_email(email): +# raise ValueError("User does not exist") +# token = str(uuid.uuid4()) +# tokens_db[token] = email +# return token + +# async def verify_user_method(token: str, tokens_db: dict) -> bool: +# async with get_async_session_context() as session: +# async with get_user_db_context(session) as user_db: +# email = tokens_db.get(token) +# if not email or not await user_db.get_by_email(email): +# return False +# user = await user_db.get_by_email(email) +# user.is_verified = True +# await user_db.update(user) +# return True + + +async def user_create_token(user: User) -> Optional[str]: + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + if user is None: + return None + strategy = get_jwt_strategy() + token = await strategy.write_token(user) + if token is not None: + return token + else: + return None + except: + return None + +async def user_check_token(token: str) -> bool: + try: + async with get_async_session_context() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + if token is None: + return False + strategy = get_jwt_strategy() + user = await strategy.read_token(token, user_manager) + if user is None or not user.is_active: + return False + else: + return True + except: + return False + From b4d1a739bee31358e25b214fc9cfe7547de56d9c Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sat, 27 Jul 2024 12:45:15 +0200 Subject: [PATCH 10/44] Fixes to the ACL model --- cognee/api/v1/add/add.py | 13 +- cognee/api/v1/cognify/cognify_v2.py | 132 +++++++++--------- .../relational/user_authentication/users.py | 69 ++++++++- 3 files changed, 146 insertions(+), 68 deletions(-) diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index e5f120573..ce25288b7 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -3,7 +3,11 @@ from os import path import asyncio import dlt import duckdb +from fastapi_users import fastapi_users + import cognee.modules.ingestion as ingestion +from cognee.infrastructure.databases.relational.user_authentication.users import give_permission_document, \ + get_async_session_context, current_active_user, create_default_user from cognee.infrastructure.files.storage import LocalStorage from cognee.modules.ingestion import get_matched_datasets, save_data_to_file from cognee.shared.utils import send_telemetry @@ -48,7 +52,7 @@ async def add(data: Union[BinaryIO, List[BinaryIO], str, List[str]], dataset_nam return [] -async def add_files(file_paths: List[str], dataset_name: str): +async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "default_user"): base_config = get_base_config() data_directory_path = base_config.data_root_directory @@ -82,12 +86,17 @@ async def add_files(file_paths: List[str], dataset_name: str): ) @dlt.resource(standalone = True, merge_key = "id") - def data_resources(file_paths: str): + def data_resources(file_paths: str, user_id: str = user_id): for file_path in file_paths: with open(file_path.replace("file://", ""), mode = "rb") as file: classified_data = ingestion.classify(file) data_id = ingestion.identify(classified_data) + async with get_async_session_context() as session: + if user_id is None: + current_active_user = create_default_user() + + give_permission_document(current_active_user, data_id, "write", session= session) file_metadata = classified_data.get_metadata() diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index ecb9fd7c4..4d2c49440 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -4,9 +4,13 @@ import logging import uuid from typing import Union +from fastapi_users import fastapi_users from sqlalchemy.ext.asyncio import AsyncSession from cognee.infrastructure.databases.graph import get_graph_config +from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker +from cognee.infrastructure.databases.relational.user_authentication.users import has_permission_document, \ + get_user_permissions, get_async_session_context # from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker # from cognee.infrastructure.databases.relational.user_authentication.users import get_user_permissions, fastapi_users from cognee.modules.cognify.config import get_cognify_config @@ -37,14 +41,6 @@ class PermissionDeniedException(Exception): super().__init__(self.message) async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None, user_id:str="default_user"): - # session: AsyncSession = async_session_maker() - # user = await fastapi_users.get_user_manager.get(user_id) - # user_permissions = await get_user_permissions(user, session) - # hash_object = hashlib.sha256(user.encode()) - # hashed_user_id = hash_object.hexdigest() - # required_permission = "write" - # if required_permission not in user_permissions: - # raise PermissionDeniedException("Not enough permissions") relational_config = get_relationaldb_config() db_engine = relational_config.database_engine @@ -55,68 +51,78 @@ async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = No async def run_cognify_pipeline(dataset_name: str, files: list[dict]): - async with update_status_lock: - task_status = get_task_status([dataset_name]) - if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": - logger.info(f"Dataset {dataset_name} is being processed.") - return + for file in files: + file["id"] = str(uuid.uuid4()) + file["name"] = file["name"].replace(" ", "_") - update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") - try: - cognee_config = get_cognify_config() - graph_config = get_graph_config() - root_node_id = None + async with get_async_session_context() as session: - if graph_config.infer_graph_topology and graph_config.graph_topology_task: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - root_node_id = await topology_engine.add_graph_topology(files = files) - elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - await topology_engine.add_graph_topology(graph_config.topology_file_path) - elif not graph_config.graph_topology_task: - root_node_id = "ROOT" + out = await has_permission_document(user_id, file["id"], "write", session) - tasks = [ - Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }, user_id = hashed_user_id, user_permissions=user_permissions), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type - Task(establish_graph_topology, topology_model = KnowledgeGraph), # Set the graph topology for the document chunk data - Task(expand_knowledge_graph, graph_model = KnowledgeGraph), # Generate knowledge graphs from the document chunks and attach it to chunk nodes - Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks - Task( - save_data_chunks, - collection_name = "chunks", - ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) - run_tasks_parallel([ - Task( - summarize_text_chunks, - summarization_model = cognee_config.summarization_model, - collection_name = "chunk_summaries", - ), # Summarize the document chunks - Task( - classify_text_chunks, - classification_model = cognee_config.classification_model, - ), - ]), - Task(remove_obsolete_chunks), # Remove the obsolete document chunks. - ] - pipeline = run_tasks(tasks, [ - PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else - AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else - ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else - TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) - for file in files - ]) + async with update_status_lock: + task_status = get_task_status([dataset_name]) - async for result in pipeline: - print(result) + if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": + logger.info(f"Dataset {dataset_name} is being processed.") + return - update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") - except Exception as error: - update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") - raise error + update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") + try: + cognee_config = get_cognify_config() + graph_config = get_graph_config() + root_node_id = None + + if graph_config.infer_graph_topology and graph_config.graph_topology_task: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + root_node_id = await topology_engine.add_graph_topology(files = files) + elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + await topology_engine.add_graph_topology(graph_config.topology_file_path) + elif not graph_config.graph_topology_task: + root_node_id = "ROOT" + + tasks = [ + Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }, user_id = hashed_user_id, user_permissions=user_permissions), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(establish_graph_topology, topology_model = KnowledgeGraph), # Set the graph topology for the document chunk data + Task(expand_knowledge_graph, graph_model = KnowledgeGraph), # Generate knowledge graphs from the document chunks and attach it to chunk nodes + Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks + Task( + save_data_chunks, + collection_name = "chunks", + ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) + run_tasks_parallel([ + Task( + summarize_text_chunks, + summarization_model = cognee_config.summarization_model, + collection_name = "chunk_summaries", + ), # Summarize the document chunks + Task( + classify_text_chunks, + classification_model = cognee_config.classification_model, + ), + ]), + Task(remove_obsolete_chunks), # Remove the obsolete document chunks. + ] + + pipeline = run_tasks(tasks, [ + PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else + AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else + ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else + TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) + for file in files + ]) + + async for result in pipeline: + print(result) + + update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") + except Exception as error: + update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") + raise error existing_datasets = db_engine.get_datasets() diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py index 4f7e5dce7..cc2fe950a 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -12,9 +12,10 @@ from fastapi_users.authentication import ( from fastapi_users.exceptions import UserAlreadyExists from fastapi_users.db import SQLAlchemyUserDatabase from fastapi import Depends, HTTPException, status +from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db, \ - get_async_session + get_async_session, ACL from fastapi.security import OAuth2PasswordRequestForm from fastapi_users.authentication import JWTStrategy from cognee.infrastructure.databases.relational.user_authentication.schemas import UserRead, UserCreate @@ -86,13 +87,13 @@ get_async_session_context = asynccontextmanager(get_async_session) get_user_db_context = asynccontextmanager(get_user_db) get_user_manager_context = asynccontextmanager(get_user_manager) -async def create_user_method(email: str, password: str, is_superuser: bool = False): +async def create_user_method(email: str, password: str, is_superuser: bool = False, is_active: bool = True): try: async with get_async_session_context() as session: async with get_user_db_context(session) as user_db: async with get_user_manager_context(user_db) as user_manager: user = await user_manager.create( - UserCreate(email=email, password=password, is_superuser=is_superuser) + UserCreate(email=email, password=password, is_superuser=is_superuser, is_active=is_active) ) print(f"User created: {user.email}") except UserAlreadyExists: @@ -175,3 +176,65 @@ async def user_check_token(token: str) -> bool: except: return False +async def has_permission_document(user: User, document_id: str, permission: str, session: AsyncSession) -> bool: + # Check if the user has the specified permission for the document + acl_entry = await session.execute( + """ + SELECT 1 FROM acls + WHERE user_id = :user_id AND document_id = :document_id AND permission = :permission + """, + {'user_id': str(user.id), 'document_id': str(document_id), 'permission': permission} + ) + if acl_entry.scalar_one_or_none(): + return True + + # Check if any of the user's groups have the specified permission for the document + group_acl_entry = await session.execute( + """ + SELECT 1 FROM acls + JOIN user_group ON acls.group_id = user_group.group_id + WHERE user_group.user_id = :user_id AND acls.document_id = :document_id AND acls.permission = :permission + """, + {'user_id': str(user.id), 'document_id': str(document_id), 'permission': permission} + ) + if group_acl_entry.scalar_one_or_none(): + return True + + return False + +async def create_default_user(): + async with get_async_session_context() as session: + default_user_email = "default_user@example.com" + default_user_password = "default_password" + + user = await create_user_method( + email=default_user_email, + password=await hash_password(default_user_password), + is_superuser=True, + is_active=True) + session.add(user) + out = await session.commit() + await session.refresh(user) + return out.id + +async def give_permission_document(user: Optional[User], document_id: str, permission: str, + session: AsyncSession): + + acl_entry = ACL( + document_id=document_id, + user_id=user.id, + permission=permission + ) + session.add(acl_entry) + await session.commit() + + + if user.is_superuser: + permission = 'all_permissions' # Example permission, change as needed + acl_entry = ACL( + document_id=document_id, + user_id=user.id, + permission=permission + ) + session.add(acl_entry) + await session.commit() \ No newline at end of file From 7930586017614702e87b1f212d5014b904f7d8e0 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sat, 27 Jul 2024 12:48:03 +0200 Subject: [PATCH 11/44] Fixes to the ACL model --- cognee/api/v1/cognify/cognify_v2.py | 7 ++++--- .../databases/relational/user_authentication/users.py | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 4d2c49440..94ead86e7 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -10,7 +10,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from cognee.infrastructure.databases.graph import get_graph_config from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker from cognee.infrastructure.databases.relational.user_authentication.users import has_permission_document, \ - get_user_permissions, get_async_session_context + get_user_permissions, get_async_session_context, fast_api_users_init # from cognee.infrastructure.databases.relational.user_authentication.authentication_db import async_session_maker # from cognee.infrastructure.databases.relational.user_authentication.users import get_user_permissions, fastapi_users from cognee.modules.cognify.config import get_cognify_config @@ -40,7 +40,7 @@ class PermissionDeniedException(Exception): self.message = message super().__init__(self.message) -async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None, user_id:str="default_user"): +async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None): relational_config = get_relationaldb_config() db_engine = relational_config.database_engine @@ -57,8 +57,9 @@ async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = No file["name"] = file["name"].replace(" ", "_") async with get_async_session_context() as session: + active_user = await fast_api_users_init() - out = await has_permission_document(user_id, file["id"], "write", session) + out = await has_permission_document(active_user.current_user(active=True), file["id"], "write", session) async with update_status_lock: diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py index cc2fe950a..e48a4d9f4 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -61,6 +61,9 @@ auth_backend = AuthenticationBackend( fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [auth_backend]) +async def fast_api_users_init(): + return fastapi_users + current_active_user = fastapi_users.current_user(active=True) From 797e7baba3146378812c80cea9994d5382071865 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sat, 27 Jul 2024 15:27:00 +0200 Subject: [PATCH 12/44] Updates to searches --- cognee/api/v1/cognify/cognify_v2.py | 138 +++++++++--------- cognee/api/v1/search/search.py | 21 ++- .../relational/user_authentication/users.py | 11 +- 3 files changed, 99 insertions(+), 71 deletions(-) diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 94ead86e7..bcfd43273 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -61,91 +61,93 @@ async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = No out = await has_permission_document(active_user.current_user(active=True), file["id"], "write", session) + if out: - async with update_status_lock: - task_status = get_task_status([dataset_name]) - if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": - logger.info(f"Dataset {dataset_name} is being processed.") - return + async with update_status_lock: + task_status = get_task_status([dataset_name]) - update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") - try: - cognee_config = get_cognify_config() - graph_config = get_graph_config() - root_node_id = None + if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": + logger.info(f"Dataset {dataset_name} is being processed.") + return - if graph_config.infer_graph_topology and graph_config.graph_topology_task: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - root_node_id = await topology_engine.add_graph_topology(files = files) - elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - await topology_engine.add_graph_topology(graph_config.topology_file_path) - elif not graph_config.graph_topology_task: - root_node_id = "ROOT" + update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") + try: + cognee_config = get_cognify_config() + graph_config = get_graph_config() + root_node_id = None - tasks = [ - Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }, user_id = hashed_user_id, user_permissions=user_permissions), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type - Task(establish_graph_topology, topology_model = KnowledgeGraph), # Set the graph topology for the document chunk data - Task(expand_knowledge_graph, graph_model = KnowledgeGraph), # Generate knowledge graphs from the document chunks and attach it to chunk nodes - Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks - Task( - save_data_chunks, - collection_name = "chunks", - ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) - run_tasks_parallel([ + if graph_config.infer_graph_topology and graph_config.graph_topology_task: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + root_node_id = await topology_engine.add_graph_topology(files = files) + elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + await topology_engine.add_graph_topology(graph_config.topology_file_path) + elif not graph_config.graph_topology_task: + root_node_id = "ROOT" + + tasks = [ + Task(process_documents, parent_node_id = root_node_id, task_config = { "batch_size": 10 }, user_id = hashed_user_id, user_permissions=user_permissions), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(establish_graph_topology, topology_model = KnowledgeGraph), # Set the graph topology for the document chunk data + Task(expand_knowledge_graph, graph_model = KnowledgeGraph), # Generate knowledge graphs from the document chunks and attach it to chunk nodes + Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks Task( - summarize_text_chunks, - summarization_model = cognee_config.summarization_model, - collection_name = "chunk_summaries", - ), # Summarize the document chunks - Task( - classify_text_chunks, - classification_model = cognee_config.classification_model, - ), - ]), - Task(remove_obsolete_chunks), # Remove the obsolete document chunks. - ] + save_data_chunks, + collection_name = "chunks", + ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) + run_tasks_parallel([ + Task( + summarize_text_chunks, + summarization_model = cognee_config.summarization_model, + collection_name = "chunk_summaries", + ), # Summarize the document chunks + Task( + classify_text_chunks, + classification_model = cognee_config.classification_model, + ), + ]), + Task(remove_obsolete_chunks), # Remove the obsolete document chunks. + ] - pipeline = run_tasks(tasks, [ - PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else - AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else - ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else - TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) - for file in files - ]) + pipeline = run_tasks(tasks, [ + PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else + AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else + ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else + TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) + for file in files + ]) - async for result in pipeline: - print(result) + async for result in pipeline: + print(result) - update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") - except Exception as error: - update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") - raise error + update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") + except Exception as error: + update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") + raise error - existing_datasets = db_engine.get_datasets() + existing_datasets = db_engine.get_datasets() - awaitables = [] + awaitables = [] - # dataset_files = [] - # dataset_name = datasets.replace(".", "_").replace(" ", "_") + # dataset_files = [] + # dataset_name = datasets.replace(".", "_").replace(" ", "_") - # for added_dataset in existing_datasets: - # if dataset_name in added_dataset: - # dataset_files.append((added_dataset, db_engine.get_files_metadata(added_dataset))) + # for added_dataset in existing_datasets: + # if dataset_name in added_dataset: + # dataset_files.append((added_dataset, db_engine.get_files_metadata(added_dataset))) - for dataset in datasets: - if dataset in existing_datasets: - # for file_metadata in files: - # if root_node_id is None: - # root_node_id=file_metadata['id'] - awaitables.append(run_cognify_pipeline(dataset, db_engine.get_files_metadata(dataset))) + for dataset in datasets: + if dataset in existing_datasets: + # for file_metadata in files: + # if root_node_id is None: + # root_node_id=file_metadata['id'] + awaitables.append(run_cognify_pipeline(dataset, db_engine.get_files_metadata(dataset))) - return await asyncio.gather(*awaitables) + return await asyncio.gather(*awaitables) # diff --git a/cognee/api/v1/search/search.py b/cognee/api/v1/search/search.py index 8cec061b3..2d0bdeb75 100644 --- a/cognee/api/v1/search/search.py +++ b/cognee/api/v1/search/search.py @@ -4,6 +4,8 @@ from enum import Enum from typing import Dict, Any, Callable, List from pydantic import BaseModel, field_validator +from cognee.infrastructure.databases.relational.user_authentication.users import fast_api_users_init, \ + has_permission_document, get_async_session_context, get_document_ids_for_user from cognee.modules.search.graph import search_cypher from cognee.modules.search.graph.search_adjacent import search_adjacent from cognee.modules.search.vector.search_traverse import search_traverse @@ -41,8 +43,23 @@ class SearchParameters(BaseModel): async def search(search_type: str, params: Dict[str, Any]) -> List: - search_params = SearchParameters(search_type = search_type, params = params) - return await specific_search([search_params]) + active_user = await fast_api_users_init() + async with get_async_session_context() as session: + + extract_documents = await get_document_ids_for_user(active_user.current_user(active=True), session=session) + search_params = SearchParameters(search_type = search_type, params = params) + searches = await specific_search([search_params]) + + filtered_searches =[] + for document in searches: + for document_id in extract_documents: + if document_id in document: + filtered_searches.append(document) + + + return filtered_searches + + async def specific_search(query_params: List[SearchParameters]) -> List: diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py index e48a4d9f4..7435eaf5b 100644 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ b/cognee/infrastructure/databases/relational/user_authentication/users.py @@ -12,6 +12,7 @@ from fastapi_users.authentication import ( from fastapi_users.exceptions import UserAlreadyExists from fastapi_users.db import SQLAlchemyUserDatabase from fastapi import Depends, HTTPException, status +from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db, \ @@ -240,4 +241,12 @@ async def give_permission_document(user: Optional[User], document_id: str, permi permission=permission ) session.add(acl_entry) - await session.commit() \ No newline at end of file + await session.commit() + + +async def get_document_ids_for_user(user_id: uuid.UUID, session: AsyncSession) -> list[str]: + result = await session.execute( + select(ACL.document_id).filter_by(user_id=user_id) + ) + document_ids = [row[0] for row in result.fetchall()] + return document_ids \ No newline at end of file From 66749fadc20c1f5a64e6b909eec16dcfc354bd47 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Sat, 27 Jul 2024 16:18:08 +0200 Subject: [PATCH 13/44] Updates to functions --- cognee/api/v1/add/add.py | 6 +++--- .../v1/authenticate_user/authenticate_user.py | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index ce25288b7..cd488c708 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -86,7 +86,7 @@ async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "d ) @dlt.resource(standalone = True, merge_key = "id") - def data_resources(file_paths: str, user_id: str = user_id): + async def data_resources(file_paths: str, user_id: str = user_id): for file_path in file_paths: with open(file_path.replace("file://", ""), mode = "rb") as file: classified_data = ingestion.classify(file) @@ -94,9 +94,9 @@ async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "d data_id = ingestion.identify(classified_data) async with get_async_session_context() as session: if user_id is None: - current_active_user = create_default_user() + current_active_user = await create_default_user() - give_permission_document(current_active_user, data_id, "write", session= session) + await give_permission_document(current_active_user, data_id, "write", session= session) file_metadata = classified_data.get_metadata() diff --git a/cognee/api/v1/authenticate_user/authenticate_user.py b/cognee/api/v1/authenticate_user/authenticate_user.py index 7d493adfc..6761c65b8 100644 --- a/cognee/api/v1/authenticate_user/authenticate_user.py +++ b/cognee/api/v1/authenticate_user/authenticate_user.py @@ -1,9 +1,24 @@ from cognee.infrastructure.databases.relational.user_authentication.users import authenticate_user_method -async def authenticate_user(): +async def authenticate_user(email: str, password: str): """ This function is used to authenticate a user. """ - output = await authenticate_user_method() + output = await authenticate_user_method(email=email, password=password) return output + + +if __name__ == "__main__": + import asyncio + # Define an example user + example_email = "example@example.com" + example_password = "securepassword123" + example_is_superuser = False + + # Create an event loop and run the create_user function + loop = asyncio.get_event_loop() + result = loop.run_until_complete(authenticate_user(example_email, example_password)) + + # Print the result + print(result) From 401167bb0fe5cc11450979a043fcf80380503b5e Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Sun, 4 Aug 2024 22:23:28 +0200 Subject: [PATCH 14/44] fix: enable sqlalchemy adapter --- .pylintrc | 5 +- .../src/modules/datasets/cognifyDataset.ts | 2 +- .../src/modules/datasets/deleteDataset.ts | 2 +- .../src/modules/datasets/getDatasetData.ts | 2 +- .../exploration/getExplorationGraphUrl.ts | 2 +- .../modules/ingestion/DataView/DataView.tsx | 2 +- .../src/modules/ingestion/addData.ts | 2 +- .../src/modules/ingestion/useDatasets.ts | 4 +- .../ui/Partials/SettingsModal/Settings.tsx | 4 +- cognee/api/client.py | 109 +++----- cognee/api/v1/add/add.py | 51 ++-- cognee/api/v1/cognify/cognify.py | 13 +- cognee/api/v1/cognify/cognify_v2.py | 165 ++++++------ cognee/api/v1/config/config.py | 7 +- cognee/api/v1/create_user/create_user.py | 22 -- cognee/api/v1/datasets/datasets.py | 15 +- .../v1/permissions/get_permissions_router.py | 43 +++ cognee/api/v1/reset_user_password/__init__.py | 1 - cognee/api/v1/search/search.py | 29 +- .../api/v1/{create_user => users}/__init__.py | 0 cognee/api/v1/users/create_user.py | 12 + cognee/api/v1/users/routers/__init__.py | 5 + .../api/v1/users/routers/get_auth_router.py | 6 + .../v1/users/routers/get_register_router.py | 5 + .../routers/get_reset_password_router.py | 4 + .../api/v1/users/routers/get_users_router.py | 5 + .../api/v1/users/routers/get_verify_router.py | 5 + cognee/api/v1/verify_user_token/__init__.py | 1 - .../v1/verify_user_token/verify_user_token.py | 8 - .../infrastructure/data/models/DatasetData.py | 11 +- .../databases/relational/FakeAsyncSession.py | 29 ++ .../databases/relational/ModelBase.py | 3 - .../databases/relational/__init__.py | 4 +- .../databases/relational/config.py | 13 +- .../relational/create_db_and_tables.py | 9 + .../relational/create_relational_engine.py | 57 ++-- .../relational/duckdb/DuckDBAdapter.py | 13 +- .../relational/get_relational_engine.py | 8 + .../sqlalchemy/SqlAlchemyAdapter.py | 82 +++--- .../user_authentication/authentication_db.py | 79 ------ .../relational/user_authentication/routers.py | 28 -- .../relational/user_authentication/schemas.py | 15 -- .../relational/user_authentication/users.py | 252 ------------------ cognee/modules/data/deletion/prune_system.py | 7 +- .../knowledge_graph/expand_knowledge_graph.py | 10 +- cognee/modules/pipelines/models/Pipeline.py | 14 +- .../modules/pipelines/models/PipelineRun.py | 15 ++ .../modules/pipelines/models/PipelineTask.py | 8 +- cognee/modules/pipelines/models/Task.py | 14 +- .../pipelines/models/TaskStatus.py} | 0 .../modules/tasks/create_task_status_table.py | 5 +- cognee/modules/tasks/get_task_status.py | 5 +- cognee/modules/tasks/update_task_status.py | 5 +- cognee/modules/topology/topology.py | 10 +- cognee/modules/users/__init__.py | 1 + .../users/authentication/get_auth_backend.py | 24 ++ .../methods/authenticate_user.py | 21 ++ cognee/modules/users/get_fastapi_users.py | 15 ++ cognee/modules/users/get_user_db.py | 10 + cognee/modules/users/get_user_manager.py | 32 +++ cognee/modules/users/memory/__init__.py | 3 - .../users/memory/create_information_points.py | 23 -- .../users/memory/is_existing_memory.py | 6 - .../users/memory/register_memory_for_user.py | 4 - cognee/modules/users/methods/__init__.py | 3 + .../users/methods/create_default_user.py | 24 ++ cognee/modules/users/methods/create_user.py | 33 +++ .../modules/users/methods/get_default_user.py | 8 + cognee/modules/users/models/ACL.py | 25 ++ cognee/modules/users/models/ACLResources.py | 11 + cognee/modules/users/models/Group.py | 21 ++ cognee/modules/users/models/Permission.py | 23 ++ cognee/modules/users/models/Principal.py | 19 ++ cognee/modules/users/models/Resource.py | 18 ++ cognee/modules/users/models/User.py | 33 +++ cognee/modules/users/models/UserGroup.py | 11 + cognee/modules/users/models/__init__.py | 5 + .../users/permissions/methods/__init__.py | 3 + .../methods/check_permissions_on_documents.py | 32 +++ .../methods/get_document_ids_for_user.py | 24 ++ .../methods/give_permission_on_document.py | 38 +++ docker-compose.yml | 1 + poetry.lock | 116 +++++++- pyproject.toml | 2 +- 84 files changed, 1004 insertions(+), 812 deletions(-) delete mode 100644 cognee/api/v1/create_user/create_user.py create mode 100644 cognee/api/v1/permissions/get_permissions_router.py delete mode 100644 cognee/api/v1/reset_user_password/__init__.py rename cognee/api/v1/{create_user => users}/__init__.py (100%) create mode 100644 cognee/api/v1/users/create_user.py create mode 100644 cognee/api/v1/users/routers/__init__.py create mode 100644 cognee/api/v1/users/routers/get_auth_router.py create mode 100644 cognee/api/v1/users/routers/get_register_router.py create mode 100644 cognee/api/v1/users/routers/get_reset_password_router.py create mode 100644 cognee/api/v1/users/routers/get_users_router.py create mode 100644 cognee/api/v1/users/routers/get_verify_router.py delete mode 100644 cognee/api/v1/verify_user_token/__init__.py delete mode 100644 cognee/api/v1/verify_user_token/verify_user_token.py create mode 100644 cognee/infrastructure/databases/relational/FakeAsyncSession.py create mode 100644 cognee/infrastructure/databases/relational/create_db_and_tables.py create mode 100644 cognee/infrastructure/databases/relational/get_relational_engine.py delete mode 100644 cognee/infrastructure/databases/relational/user_authentication/authentication_db.py delete mode 100644 cognee/infrastructure/databases/relational/user_authentication/routers.py delete mode 100644 cognee/infrastructure/databases/relational/user_authentication/schemas.py delete mode 100644 cognee/infrastructure/databases/relational/user_authentication/users.py create mode 100644 cognee/modules/pipelines/models/PipelineRun.py rename cognee/{infrastructure/databases/relational/user_authentication/__init__.py => modules/pipelines/models/TaskStatus.py} (100%) create mode 100644 cognee/modules/users/authentication/get_auth_backend.py create mode 100644 cognee/modules/users/authentication/methods/authenticate_user.py create mode 100644 cognee/modules/users/get_fastapi_users.py create mode 100644 cognee/modules/users/get_user_db.py create mode 100644 cognee/modules/users/get_user_manager.py delete mode 100644 cognee/modules/users/memory/__init__.py delete mode 100644 cognee/modules/users/memory/create_information_points.py delete mode 100644 cognee/modules/users/memory/is_existing_memory.py delete mode 100644 cognee/modules/users/memory/register_memory_for_user.py create mode 100644 cognee/modules/users/methods/__init__.py create mode 100644 cognee/modules/users/methods/create_default_user.py create mode 100644 cognee/modules/users/methods/create_user.py create mode 100644 cognee/modules/users/methods/get_default_user.py create mode 100644 cognee/modules/users/models/ACL.py create mode 100644 cognee/modules/users/models/ACLResources.py create mode 100644 cognee/modules/users/models/Group.py create mode 100644 cognee/modules/users/models/Permission.py create mode 100644 cognee/modules/users/models/Principal.py create mode 100644 cognee/modules/users/models/Resource.py create mode 100644 cognee/modules/users/models/User.py create mode 100644 cognee/modules/users/models/UserGroup.py create mode 100644 cognee/modules/users/models/__init__.py create mode 100644 cognee/modules/users/permissions/methods/__init__.py create mode 100644 cognee/modules/users/permissions/methods/check_permissions_on_documents.py create mode 100644 cognee/modules/users/permissions/methods/get_document_ids_for_user.py create mode 100644 cognee/modules/users/permissions/methods/give_permission_on_document.py diff --git a/.pylintrc b/.pylintrc index 5dd663ba8..aba6f148c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -433,8 +433,9 @@ disable=raw-checker-failed, use-implicit-booleaness-not-comparison-to-zero, missing-module-docstring, missing-function-docstring, - missing-class-docstring - + missing-class-docstring, + relative-beyond-top-level + # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/cognee-frontend/src/modules/datasets/cognifyDataset.ts b/cognee-frontend/src/modules/datasets/cognifyDataset.ts index 424abd64f..ae7a8e827 100644 --- a/cognee-frontend/src/modules/datasets/cognifyDataset.ts +++ b/cognee-frontend/src/modules/datasets/cognifyDataset.ts @@ -1,5 +1,5 @@ export default function cognifyDataset(dataset: { id: string }) { - return fetch('http://0.0.0.0:8000/cognify', { + return fetch('http://127.0.0.1:8000/cognify', { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/cognee-frontend/src/modules/datasets/deleteDataset.ts b/cognee-frontend/src/modules/datasets/deleteDataset.ts index dfc686536..d449942e6 100644 --- a/cognee-frontend/src/modules/datasets/deleteDataset.ts +++ b/cognee-frontend/src/modules/datasets/deleteDataset.ts @@ -1,5 +1,5 @@ export default function deleteDataset(dataset: { id: string }) { - return fetch(`http://0.0.0.0:8000/datasets/${dataset.id}`, { + return fetch(`http://127.0.0.1:8000/datasets/${dataset.id}`, { method: 'DELETE', }) } diff --git a/cognee-frontend/src/modules/datasets/getDatasetData.ts b/cognee-frontend/src/modules/datasets/getDatasetData.ts index aa5138383..c2d480c54 100644 --- a/cognee-frontend/src/modules/datasets/getDatasetData.ts +++ b/cognee-frontend/src/modules/datasets/getDatasetData.ts @@ -1,4 +1,4 @@ export default function getDatasetData(dataset: { id: string }) { - return fetch(`http://0.0.0.0:8000/datasets/${dataset.id}/data`) + return fetch(`http://127.0.0.1:8000/datasets/${dataset.id}/data`) .then((response) => response.json()); } diff --git a/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts b/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts index aa83b1520..6af086d57 100644 --- a/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts +++ b/cognee-frontend/src/modules/exploration/getExplorationGraphUrl.ts @@ -1,5 +1,5 @@ export default function getExplorationGraphUrl(dataset: { id: string }) { - return fetch(`http://0.0.0.0:8000/datasets/${dataset.id}/graph`) + return fetch(`http://127.0.0.1:8000/datasets/${dataset.id}/graph`) .then(async (response) => { if (response.status !== 200) { throw new Error((await response.text()).replaceAll("\"", "")); diff --git a/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx b/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx index d9e66639e..288241e43 100644 --- a/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx +++ b/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx @@ -36,7 +36,7 @@ export default function DataView({ datasetId, data, onClose, onDataAdd }: DataVi const showRawData = useCallback((dataItem: Data) => { setSelectedData(dataItem); - fetch(`http://0.0.0.0:8000/datasets/${datasetId}/data/${dataItem.id}/raw`) + fetch(`http://127.0.0.1:8000/datasets/${datasetId}/data/${dataItem.id}/raw`) .then((response) => response.arrayBuffer()) .then(setRawData); diff --git a/cognee-frontend/src/modules/ingestion/addData.ts b/cognee-frontend/src/modules/ingestion/addData.ts index 3087f5e7d..b89160755 100644 --- a/cognee-frontend/src/modules/ingestion/addData.ts +++ b/cognee-frontend/src/modules/ingestion/addData.ts @@ -5,7 +5,7 @@ export default function addData(dataset: { id: string }, files: File[]) { }) formData.append('datasetId', dataset.id); - return fetch('http://0.0.0.0:8000/add', { + return fetch('http://127.0.0.1:8000/add', { method: 'POST', body: formData, }).then((response) => response.json()); diff --git a/cognee-frontend/src/modules/ingestion/useDatasets.ts b/cognee-frontend/src/modules/ingestion/useDatasets.ts index c76f51401..402b25a07 100644 --- a/cognee-frontend/src/modules/ingestion/useDatasets.ts +++ b/cognee-frontend/src/modules/ingestion/useDatasets.ts @@ -14,7 +14,7 @@ function useDatasets() { const statusTimeout = useRef(null); const fetchDatasetStatuses = useCallback((datasets: Dataset[]) => { - fetch(`http://0.0.0.0:8000/datasets/status?dataset=${datasets.map(d => d.id).join('&dataset=')}`) + fetch(`http://127.0.0.1:8000/datasets/status?dataset=${datasets.map(d => d.id).join('&dataset=')}`) .then((response) => response.json()) .then((statuses) => setDatasets( (datasets) => ( @@ -65,7 +65,7 @@ function useDatasets() { }, []); const fetchDatasets = useCallback(() => { - fetch('http://0.0.0.0:8000/datasets') + fetch('http://127.0.0.1:8000/datasets') .then((response) => response.json()) .then((datasets) => datasets.map((dataset: string) => ({ id: dataset, name: dataset }))) .then((datasets) => { diff --git a/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx b/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx index 134f2164c..05b7b30a5 100644 --- a/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx +++ b/cognee-frontend/src/ui/Partials/SettingsModal/Settings.tsx @@ -75,7 +75,7 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' startSaving(); - fetch('http://0.0.0.0:8000/settings', { + fetch('http://127.0.0.1:8000/settings', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -138,7 +138,7 @@ export default function Settings({ onDone = () => {}, submitButtonText = 'Save' useEffect(() => { const fetchConfig = async () => { - const response = await fetch('http://0.0.0.0:8000/settings'); + const response = await fetch('http://127.0.0.1:8000/settings'); const settings = await response.json(); if (!settings.llm.model) { diff --git a/cognee/api/client.py b/cognee/api/client.py index b9d8cd27f..50252319e 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -3,7 +3,6 @@ import os import aiohttp import uvicorn import json -import asyncio import logging import sentry_sdk from typing import Dict, Any, List, Union, Optional, Literal @@ -13,7 +12,7 @@ from fastapi.responses import JSONResponse, FileResponse from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel -from cognee.infrastructure.databases.relational.user_authentication.routers import permission_router +from cognee.infrastructure.databases.relational import create_db_and_tables # Set up logging logging.basicConfig( @@ -28,13 +27,16 @@ if os.getenv("ENV") == "prod": traces_sample_rate = 1.0, profiles_sample_rate = 1.0, ) + from contextlib import asynccontextmanager + @asynccontextmanager async def lifespan(app: FastAPI): # Not needed if you setup a migration system like Alembic await create_db_and_tables() yield -app = FastAPI(debug = os.getenv("ENV") != "prod", lifespan=lifespan) + +app = FastAPI(debug = os.getenv("ENV") != "prod", lifespan = lifespan) origins = [ "http://frontend:3000", @@ -50,70 +52,46 @@ app.add_middleware( allow_headers=["*"], ) -from contextlib import asynccontextmanager +from cognee.api.v1.users.routers import get_auth_router, get_register_router,\ + get_reset_password_router, get_verify_router, get_users_router -from fastapi import Depends, FastAPI - -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, create_db_and_tables -from cognee.infrastructure.databases.relational.user_authentication.schemas import UserCreate, UserRead, UserUpdate -from cognee.infrastructure.databases.relational.user_authentication.users import auth_backend, current_active_user, fastapi_users +from cognee.api.v1.permissions.get_permissions_router import get_permissions_router app.include_router( - fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"] -) -app.include_router( - fastapi_users.get_register_router(UserRead, UserCreate), - prefix="/auth", - tags=["auth"], -) -app.include_router( - fastapi_users.get_reset_password_router(), - prefix="/auth", - tags=["auth"], -) -app.include_router( - fastapi_users.get_verify_router(UserRead), - prefix="/auth", - tags=["auth"], -) -app.include_router( - fastapi_users.get_users_router(UserRead, UserUpdate), - prefix="/users", - tags=["users"], + get_auth_router(), + prefix = "/auth/jwt", + tags = ["auth"] ) -app.include_router(permission_router, prefix="/manage", tags=["management"]) - -@asynccontextmanager -async def lifespan(app: FastAPI): - # Not needed if you setup a migration system like Alembic - await create_db_and_tables() - yield app.include_router( - fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"] -) -app.include_router( - fastapi_users.get_register_router(UserRead, UserCreate), - prefix="/auth", - tags=["auth"], -) -app.include_router( - fastapi_users.get_reset_password_router(), - prefix="/auth", - tags=["auth"], -) -app.include_router( - fastapi_users.get_verify_router(UserRead), - prefix="/auth", - tags=["auth"], -) -app.include_router( - fastapi_users.get_users_router(UserRead, UserUpdate), - prefix="/users", - tags=["users"], + get_register_router(), + prefix = "/auth", + tags = ["auth"], ) +app.include_router( + get_reset_password_router(), + prefix = "/auth", + tags = ["auth"], +) +app.include_router( + get_verify_router(), + prefix = "/auth", + tags = ["auth"], +) + +app.include_router( + get_users_router(), + prefix = "/users", + tags = ["users"], +) + +app.include_router( + get_permissions_router(), + prefix = "/permissions", + tags = ["permissions"], +) @app.get("/") async def root(): @@ -135,7 +113,7 @@ class Payload(BaseModel): @app.get("/datasets", response_model=list) async def get_datasets(): from cognee.api.v1.datasets.datasets import datasets - return datasets.list_datasets() + return await datasets.list_datasets() @app.delete("/datasets/{dataset_id}", response_model=dict) async def delete_dataset(dataset_id: str): @@ -294,8 +272,8 @@ async def search(payload: SearchPayload): @app.get("/settings", response_model=dict) async def get_settings(): - from cognee.modules.settings import get_settings - return get_settings() + from cognee.modules.settings import get_settings as get_cognee_settings + return get_cognee_settings() class LLMConfig(BaseModel): provider: Union[Literal["openai"], Literal["ollama"], Literal["anthropic"]] @@ -334,13 +312,10 @@ def start_api_server(host: str = "0.0.0.0", port: int = 8000): try: logger.info("Starting server at %s:%s", host, port) - from cognee.infrastructure.databases.relational import get_relationaldb_config - relational_config = get_relationaldb_config() - relational_config.create_engine() - + import asyncio from cognee.modules.data.deletion import prune_system, prune_data - # asyncio.run(prune_data()) - # asyncio.run(prune_system(metadata = True)) + asyncio.run(prune_data()) + asyncio.run(prune_system(metadata = True)) uvicorn.run(app, host = host, port = port) except Exception as e: diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index cd488c708..8a4d90352 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -3,18 +3,20 @@ from os import path import asyncio import dlt import duckdb -from fastapi_users import fastapi_users import cognee.modules.ingestion as ingestion -from cognee.infrastructure.databases.relational.user_authentication.users import give_permission_document, \ - get_async_session_context, current_active_user, create_default_user from cognee.infrastructure.files.storage import LocalStorage from cognee.modules.ingestion import get_matched_datasets, save_data_to_file from cognee.shared.utils import send_telemetry from cognee.base_config import get_base_config -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_config, create_db_and_tables +from cognee.modules.users.methods import create_default_user +from cognee.modules.users.permissions.methods import give_permission_on_document +from cognee.modules.users.models import User + +async def add(data: Union[BinaryIO, List[BinaryIO], str, List[str]], dataset_name: str = "main_dataset", user: User = None): + await create_db_and_tables() -async def add(data: Union[BinaryIO, List[BinaryIO], str, List[str]], dataset_name: str = "main_dataset"): if isinstance(data, str): if "data://" in data: # data is a data directory path @@ -48,11 +50,11 @@ async def add(data: Union[BinaryIO, List[BinaryIO], str, List[str]], dataset_nam file_paths.append(save_data_to_file(data_item, dataset_name)) if len(file_paths) > 0: - return await add_files(file_paths, dataset_name) + return await add_files(file_paths, dataset_name, user) return [] -async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "default_user"): +async def add_files(file_paths: List[str], dataset_name: str, user): base_config = get_base_config() data_directory_path = base_config.data_root_directory @@ -73,12 +75,24 @@ async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "d else: processed_file_paths.append(file_path) - relational_config = get_relationaldb_config() - db = duckdb.connect(relational_config.db_file_path) + relational_config = get_relational_config() - destination = dlt.destinations.duckdb( - credentials = db, - ) + if relational_config.db_provider == "duckdb": + db = duckdb.connect(relational_config.db_file_path) + + destination = dlt.destinations.duckdb( + credentials = db, + ) + else: + destination = dlt.destinations.postgres( + credentials = { + "host": relational_config.db_host, + "port": relational_config.db_port, + "user": relational_config.db_user, + "password": relational_config.db_password, + "database": relational_config.db_name, + }, + ) pipeline = dlt.pipeline( pipeline_name = "file_load_from_filesystem", @@ -86,17 +100,18 @@ async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "d ) @dlt.resource(standalone = True, merge_key = "id") - async def data_resources(file_paths: str, user_id: str = user_id): + async def data_resources(file_paths: str, user: User): for file_path in file_paths: with open(file_path.replace("file://", ""), mode = "rb") as file: classified_data = ingestion.classify(file) data_id = ingestion.identify(classified_data) - async with get_async_session_context() as session: - if user_id is None: - current_active_user = await create_default_user() - await give_permission_document(current_active_user, data_id, "write", session= session) + if user is None: + user = await create_default_user() + + await give_permission_on_document(user, data_id, "read") + await give_permission_on_document(user, data_id, "write") file_metadata = classified_data.get_metadata() @@ -109,7 +124,7 @@ async def add_files(file_paths: List[str], dataset_name: str, user_id: str = "d } run_info = pipeline.run( - data_resources(processed_file_paths), + data_resources(processed_file_paths, user), table_name = "file_metadata", dataset_name = dataset_name.replace(" ", "_").replace(".", "_") if dataset_name is not None else "main_dataset", write_disposition = "merge", diff --git a/cognee/api/v1/cognify/cognify.py b/cognee/api/v1/cognify/cognify.py index 632d52c04..77f19f1ec 100644 --- a/cognee/api/v1/cognify/cognify.py +++ b/cognee/api/v1/cognify/cognify.py @@ -32,7 +32,7 @@ from cognee.shared.SourceCodeGraph import SourceCodeGraph from cognee.modules.tasks import get_task_status from cognee.infrastructure.data.chunking.config import get_chunk_config from cognee.modules.cognify.config import get_cognify_config -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine USER_ID = "default_user" @@ -49,11 +49,10 @@ async def cognify(datasets: Union[str, List[str]] = None): graph_client = await get_graph_engine() - relational_config = get_relationaldb_config() - db_engine = relational_config.database_engine + db_engine = get_relational_engine() if datasets is None or len(datasets) == 0: - datasets = db_engine.get_datasets() + datasets = await db_engine.get_datasets() awaitables = [] @@ -83,7 +82,7 @@ async def cognify(datasets: Union[str, List[str]] = None): graphs = await asyncio.gather(*awaitables) return graphs[0] - added_datasets = db_engine.get_datasets() + added_datasets = await db_engine.get_datasets() # datasets is a dataset name string dataset_files = [] @@ -167,7 +166,7 @@ async def cognify(datasets: Union[str, List[str]] = None): else: document_id = await add_document_node( graph_client, - parent_node_id = file_metadata['id'], + parent_node_id = file_metadata["id"], document_metadata = file_metadata, ) @@ -226,7 +225,7 @@ async def process_text(chunk_collection: str, chunk_id: str, input_text: str, fi if cognify_config.connect_documents is True: - db_engine = get_relationaldb_config().database_engine + db_engine = get_relational_engine() relevant_documents_to_connect = db_engine.fetch_cognify_data(excluded_document_id = document_id) list_of_nodes = [] diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 589c5331d..6b2502c46 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -1,13 +1,10 @@ import asyncio import logging -import uuid from typing import Union from cognee.infrastructure.databases.graph import get_graph_config -from cognee.infrastructure.databases.relational.user_authentication.users import has_permission_document, \ - get_async_session_context, fast_api_users_init from cognee.modules.cognify.config import get_cognify_config -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine from cognee.modules.data.processing.document_types.AudioDocument import AudioDocument from cognee.modules.data.processing.document_types.ImageDocument import ImageDocument from cognee.shared.data_models import KnowledgeGraph @@ -23,6 +20,9 @@ from cognee.modules.data.extraction.knowledge_graph.establish_graph_topology imp from cognee.modules.pipelines.tasks.Task import Task from cognee.modules.pipelines import run_tasks, run_tasks_parallel from cognee.modules.tasks import create_task_status_table, update_task_status, get_task_status +from cognee.modules.users.models import User +from cognee.modules.users.methods import get_default_user +from cognee.modules.users.permissions.methods import check_permissions_on_documents logger = logging.getLogger("cognify.v2") @@ -33,113 +33,98 @@ class PermissionDeniedException(Exception): self.message = message super().__init__(self.message) -async def cognify(datasets: Union[str, list[str]] = None, root_node_id: str = None): - - relational_config = get_relationaldb_config() - db_engine = relational_config.database_engine +async def cognify(datasets: Union[str, list[str]] = None, user: User = None): + db_engine = get_relational_engine() create_task_status_table() if datasets is None or len(datasets) == 0: - return await cognify(db_engine.get_datasets()) + return await cognify(await db_engine.get_datasets()) + if user is None: + user = await get_default_user() async def run_cognify_pipeline(dataset_name: str, files: list[dict]): + documents = [ + PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else + AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else + ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else + TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) + for file in files + ] - for file in files: - file["id"] = str(uuid.uuid4()) - file["name"] = file["name"].replace(" ", "_") + await check_permissions_on_documents(user, "read", [document.id for document in documents]) - async with get_async_session_context() as session: - active_user = await fast_api_users_init() + async with update_status_lock: + task_status = get_task_status([dataset_name]) - out = await has_permission_document(active_user.current_user(active=True), file["id"], "write", session) + if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": + logger.info(f"Dataset {dataset_name} is being processed.") + return - if out: - async with update_status_lock: - task_status = get_task_status([dataset_name]) + update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") + try: + cognee_config = get_cognify_config() + graph_config = get_graph_config() + root_node_id = None - if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": - logger.info(f"Dataset {dataset_name} is being processed.") - return + if graph_config.infer_graph_topology and graph_config.graph_topology_task: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + root_node_id = await topology_engine.add_graph_topology(files = files) + elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + await topology_engine.add_graph_topology(graph_config.topology_file_path) + elif not graph_config.graph_topology_task: + root_node_id = "ROOT" - update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") - try: - cognee_config = get_cognify_config() - graph_config = get_graph_config() - root_node_id = None + tasks = [ + Task(process_documents, parent_node_id = root_node_id), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(establish_graph_topology, topology_model = KnowledgeGraph, task_config = { "batch_size": 10 }), # Set the graph topology for the document chunk data + Task(expand_knowledge_graph, graph_model = KnowledgeGraph, collection_name = "entities"), # Generate knowledge graphs from the document chunks and attach it to chunk nodes + Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks + Task( + save_data_chunks, + collection_name = "chunks", + ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) + run_tasks_parallel([ + Task( + summarize_text_chunks, + summarization_model = cognee_config.summarization_model, + collection_name = "chunk_summaries", + ), # Summarize the document chunks + Task( + classify_text_chunks, + classification_model = cognee_config.classification_model, + ), + ]), + Task(remove_obsolete_chunks), # Remove the obsolete document chunks. + ] - if graph_config.infer_graph_topology and graph_config.graph_topology_task: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - root_node_id = await topology_engine.add_graph_topology(files = files) - elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - await topology_engine.add_graph_topology(graph_config.topology_file_path) - elif not graph_config.graph_topology_task: - root_node_id = "ROOT" + pipeline = run_tasks(tasks, documents) - tasks = [ - Task(process_documents, parent_node_id = root_node_id), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type - Task(establish_graph_topology, topology_model = KnowledgeGraph, task_config = { "batch_size": 10 }), # Set the graph topology for the document chunk data - Task(expand_knowledge_graph, graph_model = KnowledgeGraph, collection_name = "entities"), # Generate knowledge graphs from the document chunks and attach it to chunk nodes - Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks - Task( - save_data_chunks, - collection_name = "chunks", - ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) - run_tasks_parallel([ - Task( - summarize_text_chunks, - summarization_model = cognee_config.summarization_model, - collection_name = "chunk_summaries", - ), # Summarize the document chunks - Task( - classify_text_chunks, - classification_model = cognee_config.classification_model, - ), - ]), - Task(remove_obsolete_chunks), # Remove the obsolete document chunks. - ] + async for result in pipeline: + print(result) - pipeline = run_tasks(tasks, [ - PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else - AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else - ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else - TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) - for file in files - ]) - - async for result in pipeline: - print(result) - - update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") - except Exception as error: - update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") - raise error + update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") + except Exception as error: + update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") + raise error - existing_datasets = db_engine.get_datasets() + existing_datasets = await db_engine.get_datasets() + awaitables = [] - awaitables = [] + for dataset in datasets: + dataset_name = generate_dataset_name(dataset) + if dataset_name in existing_datasets: + awaitables.append(run_cognify_pipeline(dataset, db_engine.get_files_metadata(dataset_name))) - # dataset_files = [] - # dataset_name = datasets.replace(".", "_").replace(" ", "_") - - # for added_dataset in existing_datasets: - # if dataset_name in added_dataset: - # dataset_files.append((added_dataset, db_engine.get_files_metadata(added_dataset))) - - for dataset in datasets: - if dataset in existing_datasets: - # for file_metadata in files: - # if root_node_id is None: - # root_node_id=file_metadata['id'] - awaitables.append(run_cognify_pipeline(dataset, db_engine.get_files_metadata(dataset))) - - return await asyncio.gather(*awaitables) + return await asyncio.gather(*awaitables) +def generate_dataset_name(dataset_name: str) -> str: + return dataset_name.replace(".", "_").replace(" ", "_") # # if __name__ == "__main__": diff --git a/cognee/api/v1/config/config.py b/cognee/api/v1/config/config.py index b284c622f..2a9eb63d0 100644 --- a/cognee/api/v1/config/config.py +++ b/cognee/api/v1/config/config.py @@ -5,16 +5,17 @@ from cognee.modules.cognify.config import get_cognify_config from cognee.infrastructure.data.chunking.config import get_chunk_config from cognee.infrastructure.databases.vector import get_vectordb_config from cognee.infrastructure.databases.graph.config import get_graph_config -from cognee.infrastructure.databases.relational import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_config +from cognee.infrastructure.files.storage import LocalStorage class config(): @staticmethod def system_root_directory(system_root_directory: str): databases_directory_path = os.path.join(system_root_directory, "databases") - relational_config = get_relationaldb_config() + relational_config = get_relational_config() relational_config.db_path = databases_directory_path - relational_config.create_engine() + LocalStorage.ensure_directory_exists(databases_directory_path) graph_config = get_graph_config() graph_config.graph_file_path = os.path.join(databases_directory_path, "cognee.graph") diff --git a/cognee/api/v1/create_user/create_user.py b/cognee/api/v1/create_user/create_user.py deleted file mode 100644 index 3901aa593..000000000 --- a/cognee/api/v1/create_user/create_user.py +++ /dev/null @@ -1,22 +0,0 @@ -from cognee.infrastructure.databases.relational.user_authentication.users import create_user_method - - - -async def create_user(email: str, password: str, is_superuser: bool = False): - output = await create_user_method(email=email, password=password, is_superuser=is_superuser) - return output - - -if __name__ == "__main__": - import asyncio - # Define an example user - example_email = "example@example.com" - example_password = "securepassword123" - example_is_superuser = False - - # Create an event loop and run the create_user function - loop = asyncio.get_event_loop() - result = loop.run_until_complete(create_user(example_email, example_password, example_is_superuser)) - - # Print the result - print(result) \ No newline at end of file diff --git a/cognee/api/v1/datasets/datasets.py b/cognee/api/v1/datasets/datasets.py index 92ae14ce9..d46fd2413 100644 --- a/cognee/api/v1/datasets/datasets.py +++ b/cognee/api/v1/datasets/datasets.py @@ -1,14 +1,13 @@ from duckdb import CatalogException from cognee.modules.ingestion import discover_directory_datasets from cognee.modules.tasks import get_task_status -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine class datasets(): @staticmethod - def list_datasets(): - relational_config = get_relationaldb_config() - db = relational_config.database_engine - return db.get_datasets() + async def list_datasets(): + db = get_relational_engine() + return await db.get_datasets() @staticmethod def discover_datasets(directory_path: str): @@ -16,8 +15,7 @@ class datasets(): @staticmethod def list_data(dataset_name: str): - relational_config = get_relationaldb_config() - db = relational_config.database_engine + db = get_relational_engine() try: return db.get_files_metadata(dataset_name) except CatalogException: @@ -32,8 +30,7 @@ class datasets(): @staticmethod def delete_dataset(dataset_id: str): - relational_config = get_relationaldb_config() - db = relational_config.database_engine + db = get_relational_engine() try: return db.delete_table(dataset_id) except CatalogException: diff --git a/cognee/api/v1/permissions/get_permissions_router.py b/cognee/api/v1/permissions/get_permissions_router.py new file mode 100644 index 000000000..ab20fb1a2 --- /dev/null +++ b/cognee/api/v1/permissions/get_permissions_router.py @@ -0,0 +1,43 @@ +from fastapi import APIRouter, Depends, HTTPException +from fastapi.responses import JSONResponse +from sqlalchemy.orm import Session +from cognee.modules.users import get_user_db +from cognee.modules.users.models import User, Group, Permission + +def get_permissions_router() -> APIRouter: + permissions_router = APIRouter() + + @permissions_router.post("/groups/{group_id}/permissions") + async def give_permission_to_group(group_id: int, permission: str, db: Session = Depends(get_user_db)): + group = db.query(Group).filter(Group.id == group_id).first() + + if not group: + raise HTTPException(status_code = 404, detail = "Group not found") + + permission = db.query(Permission).filter(Permission.name == permission).first() + + if not permission: + permission = Permission(name = permission) + db.add(permission) + + group.permissions.append(permission) + + db.commit() + + return JSONResponse(status_code = 200, content = {"message": "Permission assigned to group"}) + + @permissions_router.post("/users/{user_id}/groups") + async def add_user_to_group(user_id: int, group_id: int, db: Session = Depends(get_user_db)): + user = db.query(User).filter(User.id == user_id).first() + group = db.query(Group).filter(Group.id == group_id).first() + + if not user or not group: + raise HTTPException(status_code = 404, detail = "User or group not found") + + user.groups.append(group) + + db.commit() + + return JSONResponse(status_code = 200, content = {"message": "User added to group"}) + + return permissions_router diff --git a/cognee/api/v1/reset_user_password/__init__.py b/cognee/api/v1/reset_user_password/__init__.py deleted file mode 100644 index aad3147da..000000000 --- a/cognee/api/v1/reset_user_password/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .create_user import create_user diff --git a/cognee/api/v1/search/search.py b/cognee/api/v1/search/search.py index b0c64f9ed..08c325576 100644 --- a/cognee/api/v1/search/search.py +++ b/cognee/api/v1/search/search.py @@ -4,14 +4,15 @@ from enum import Enum from typing import Dict, Any, Callable, List from pydantic import BaseModel, field_validator -from cognee.infrastructure.databases.relational.user_authentication.users import fast_api_users_init, \ - has_permission_document, get_async_session_context, get_document_ids_for_user from cognee.modules.search.graph import search_cypher from cognee.modules.search.graph.search_adjacent import search_adjacent from cognee.modules.search.vector.search_traverse import search_traverse from cognee.modules.search.graph.search_summary import search_summary from cognee.modules.search.graph.search_similarity import search_similarity from cognee.shared.utils import send_telemetry +from cognee.modules.users.permissions.methods import get_document_ids_for_user +from cognee.modules.users.methods import get_default_user +from cognee.modules.users.models import User class SearchType(Enum): ADJACENT = "ADJACENT" @@ -41,19 +42,19 @@ class SearchParameters(BaseModel): return value -async def search(search_type: str, params: Dict[str, Any]) -> List: - active_user = await fast_api_users_init() - async with get_async_session_context() as session: +async def search(search_type: str, params: Dict[str, Any], user: User = None) -> List: + if user is None: + user = await get_default_user() + + extract_documents = await get_document_ids_for_user(user.id) + search_params = SearchParameters(search_type = search_type, params = params) + searches = await specific_search([search_params]) - extract_documents = await get_document_ids_for_user(active_user.current_user(active=True), session=session) - search_params = SearchParameters(search_type = search_type, params = params) - searches = await specific_search([search_params]) - - filtered_searches =[] - for document in searches: - for document_id in extract_documents: - if document_id in document: - filtered_searches.append(document) + filtered_searches = [] + for document in searches: + for document_id in extract_documents: + if document_id in document: + filtered_searches.append(document) return filtered_searches diff --git a/cognee/api/v1/create_user/__init__.py b/cognee/api/v1/users/__init__.py similarity index 100% rename from cognee/api/v1/create_user/__init__.py rename to cognee/api/v1/users/__init__.py diff --git a/cognee/api/v1/users/create_user.py b/cognee/api/v1/users/create_user.py new file mode 100644 index 000000000..eba7a6e89 --- /dev/null +++ b/cognee/api/v1/users/create_user.py @@ -0,0 +1,12 @@ +from cognee.modules.users.methods import create_user as create_user_method + + +async def create_user(email: str, password: str, is_superuser: bool = False): + user = await create_user_method( + email = email, + password = password, + is_superuser = is_superuser, + is_verified = True, + ) + + return user diff --git a/cognee/api/v1/users/routers/__init__.py b/cognee/api/v1/users/routers/__init__.py new file mode 100644 index 000000000..482aac265 --- /dev/null +++ b/cognee/api/v1/users/routers/__init__.py @@ -0,0 +1,5 @@ +from .get_auth_router import get_auth_router +from .get_register_router import get_register_router +from .get_reset_password_router import get_reset_password_router +from .get_users_router import get_users_router +from .get_verify_router import get_verify_router diff --git a/cognee/api/v1/users/routers/get_auth_router.py b/cognee/api/v1/users/routers/get_auth_router.py new file mode 100644 index 000000000..8a65cde35 --- /dev/null +++ b/cognee/api/v1/users/routers/get_auth_router.py @@ -0,0 +1,6 @@ +from cognee.modules.users.get_fastapi_users import get_fastapi_users +from cognee.modules.users.authentication.get_auth_backend import get_auth_backend + +def get_auth_router(): + auth_backend = get_auth_backend() + return get_fastapi_users().get_auth_router(auth_backend) diff --git a/cognee/api/v1/users/routers/get_register_router.py b/cognee/api/v1/users/routers/get_register_router.py new file mode 100644 index 000000000..a1152c01c --- /dev/null +++ b/cognee/api/v1/users/routers/get_register_router.py @@ -0,0 +1,5 @@ +from cognee.modules.users.get_fastapi_users import get_fastapi_users +from cognee.modules.users.models.User import UserRead, UserCreate + +def get_register_router(): + return get_fastapi_users().get_register_router(UserRead, UserCreate) diff --git a/cognee/api/v1/users/routers/get_reset_password_router.py b/cognee/api/v1/users/routers/get_reset_password_router.py new file mode 100644 index 000000000..c058abe2a --- /dev/null +++ b/cognee/api/v1/users/routers/get_reset_password_router.py @@ -0,0 +1,4 @@ +from cognee.modules.users.get_fastapi_users import get_fastapi_users + +def get_reset_password_router(): + return get_fastapi_users().get_reset_password_router() diff --git a/cognee/api/v1/users/routers/get_users_router.py b/cognee/api/v1/users/routers/get_users_router.py new file mode 100644 index 000000000..b81be73b0 --- /dev/null +++ b/cognee/api/v1/users/routers/get_users_router.py @@ -0,0 +1,5 @@ +from cognee.modules.users.get_fastapi_users import get_fastapi_users +from cognee.modules.users.models.User import UserRead, UserUpdate + +def get_users_router(): + return get_fastapi_users().get_users_router(UserRead, UserUpdate) diff --git a/cognee/api/v1/users/routers/get_verify_router.py b/cognee/api/v1/users/routers/get_verify_router.py new file mode 100644 index 000000000..0c18b08c2 --- /dev/null +++ b/cognee/api/v1/users/routers/get_verify_router.py @@ -0,0 +1,5 @@ +from cognee.modules.users.get_fastapi_users import get_fastapi_users +from cognee.modules.users.models.User import UserRead + +def get_verify_router(): + return get_fastapi_users().get_verify_router(UserRead) diff --git a/cognee/api/v1/verify_user_token/__init__.py b/cognee/api/v1/verify_user_token/__init__.py deleted file mode 100644 index 45fda4dba..000000000 --- a/cognee/api/v1/verify_user_token/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .verify_user_token import verify_user_token diff --git a/cognee/api/v1/verify_user_token/verify_user_token.py b/cognee/api/v1/verify_user_token/verify_user_token.py deleted file mode 100644 index b5a0f2228..000000000 --- a/cognee/api/v1/verify_user_token/verify_user_token.py +++ /dev/null @@ -1,8 +0,0 @@ -from cognee.infrastructure.databases.relational.user_authentication.users import user_check_token - - - -async def verify_user_token(token: str): - - output = await user_check_token(token=token) - return output \ No newline at end of file diff --git a/cognee/infrastructure/data/models/DatasetData.py b/cognee/infrastructure/data/models/DatasetData.py index 9e586dcef..c84d890ae 100644 --- a/cognee/infrastructure/data/models/DatasetData.py +++ b/cognee/infrastructure/data/models/DatasetData.py @@ -1,19 +1,12 @@ from uuid import uuid4 from datetime import datetime, timezone -from sqlalchemy import Column, DateTime, UUID, ForeignKey, PrimaryKeyConstraint, UniqueConstraint -from sqlalchemy.orm import relationship - +from sqlalchemy import Column, DateTime, UUID, ForeignKey from cognee.infrastructure.databases.relational import Base class DatasetData(Base): __tablename__ = "dataset_data" id = Column(UUID, primary_key=True, default=uuid4) - created_at = Column(DateTime, default=datetime.now(timezone.utc)) + dataset_id = Column(UUID, ForeignKey("dataset.id"), nullable=False) data_id = Column(UUID, ForeignKey("data.id"), nullable=False) - __table_args__ = ( - UniqueConstraint('dataset_id', 'data_id', name='uix_dataset_data'), - ) - - acls = relationship('ACL', back_populates='document') diff --git a/cognee/infrastructure/databases/relational/FakeAsyncSession.py b/cognee/infrastructure/databases/relational/FakeAsyncSession.py new file mode 100644 index 000000000..cd7e4b6a3 --- /dev/null +++ b/cognee/infrastructure/databases/relational/FakeAsyncSession.py @@ -0,0 +1,29 @@ +import inspect +from typing import Any + +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import Session + +class FakeAsyncSession: + def __init__(self, session: Session): + self.session = session + + def run_sync(self, *args, **kwargs): + return self.execute(*args, **kwargs) + + def __getattr__(self, name: str) -> Any: + """ + If the method being called is async in AsyncSession, create a fake async version + for Session so callers can `await` as usual. Think `commit`, `refresh`, + `delete`, etc. + """ + async_session_attr = getattr(AsyncSession, name, None) + session_attr = getattr(self.session, name) + + if not inspect.iscoroutinefunction(async_session_attr): + return session_attr + + async def async_wrapper(*args, **kwargs): + return session_attr(*args, **kwargs) + + return async_wrapper diff --git a/cognee/infrastructure/databases/relational/ModelBase.py b/cognee/infrastructure/databases/relational/ModelBase.py index 6e60c638f..f75ec448b 100644 --- a/cognee/infrastructure/databases/relational/ModelBase.py +++ b/cognee/infrastructure/databases/relational/ModelBase.py @@ -1,7 +1,4 @@ - from sqlalchemy.orm import DeclarativeBase - class Base(DeclarativeBase): pass - diff --git a/cognee/infrastructure/databases/relational/__init__.py b/cognee/infrastructure/databases/relational/__init__.py index 214559ccb..61ff4ef85 100644 --- a/cognee/infrastructure/databases/relational/__init__.py +++ b/cognee/infrastructure/databases/relational/__init__.py @@ -2,4 +2,6 @@ from .ModelBase import Base from .DatabaseEngine import DatabaseEngine from .sqlite.SqliteEngine import SqliteEngine from .duckdb.DuckDBAdapter import DuckDBAdapter -from .config import get_relationaldb_config +from .config import get_relational_config +from .create_db_and_tables import create_db_and_tables +from .get_relational_engine import get_relational_engine diff --git a/cognee/infrastructure/databases/relational/config.py b/cognee/infrastructure/databases/relational/config.py index 746cce2ae..e5e4854e2 100644 --- a/cognee/infrastructure/databases/relational/config.py +++ b/cognee/infrastructure/databases/relational/config.py @@ -2,27 +2,21 @@ import os from functools import lru_cache from pydantic_settings import BaseSettings, SettingsConfigDict from cognee.root_dir import get_absolute_path -from .create_relational_engine import create_relational_engine class RelationalConfig(BaseSettings): db_path: str = os.path.join(get_absolute_path(".cognee_system"), "databases") db_name: str = "cognee_db" - db_host: str = "localhost" + db_host: str = "127.0.0.1" db_port: str = "5432" db_user: str = "cognee" db_password: str = "cognee" db_provider: str = "postgresql+asyncpg" - # database_engine: object = create_relational_engine(db_path, db_name, db_provider) + # db_provider: str = "duckdb" db_file_path: str = os.path.join(db_path, db_name) model_config = SettingsConfigDict(env_file = ".env", extra = "allow") - def create_engine(self): - self.db_file_path = os.path.join(self.db_path, self.db_name) - self.database_engine = create_relational_engine(self.db_path, self.db_name, self.db_provider, self.db_host, self.db_port, self.db_user, self.db_password) - return self.database_engine - def to_dict(self) -> dict: return { "db_path": self.db_path, @@ -31,10 +25,9 @@ class RelationalConfig(BaseSettings): "db_port": self.db_port, "db_user": self.db_user, "db_password": self.db_password, - "db_engine": self.database_engine, "db_provider": self.db_provider, } @lru_cache -def get_relationaldb_config(): +def get_relational_config(): return RelationalConfig() diff --git a/cognee/infrastructure/databases/relational/create_db_and_tables.py b/cognee/infrastructure/databases/relational/create_db_and_tables.py new file mode 100644 index 000000000..d6cf22f87 --- /dev/null +++ b/cognee/infrastructure/databases/relational/create_db_and_tables.py @@ -0,0 +1,9 @@ +from .ModelBase import Base +from .get_relational_engine import get_relational_engine + +async def create_db_and_tables(): + relational_engine = get_relational_engine() + + async with relational_engine.engine.begin() as connection: + if len(Base.metadata.tables.keys()) > 0: + await connection.run_sync(Base.metadata.create_all) diff --git a/cognee/infrastructure/databases/relational/create_relational_engine.py b/cognee/infrastructure/databases/relational/create_relational_engine.py index 5bbfa8ee3..713614eab 100644 --- a/cognee/infrastructure/databases/relational/create_relational_engine.py +++ b/cognee/infrastructure/databases/relational/create_relational_engine.py @@ -1,40 +1,21 @@ -from enum import Enum - -from cognee.infrastructure.databases.relational.sqlalchemy.SqlAlchemyAdapter import SQLAlchemyAdapter -from cognee.infrastructure.files.storage import LocalStorage -from cognee.infrastructure.databases.relational import DuckDBAdapter +from .sqlalchemy.SqlAlchemyAdapter import SQLAlchemyAdapter -class DBProvider(Enum): - DUCKDB = "duckdb" - POSTGRES = "postgresql+asyncpg" - -def create_relational_engine(db_path: str, db_name: str, db_provider:str, db_host:str, db_port:str, db_user:str, db_password:str): - LocalStorage.ensure_directory_exists(db_path) - - provider = DBProvider(db_provider) - - if provider == DBProvider.DUCKDB: - # return DuckDBAdapter( - # db_name = db_name, - # db_path = db_path, - # ) - return SQLAlchemyAdapter( - db_name = db_name, - db_path = db_path, - db_type = db_provider, - db_host=db_host, - db_port=db_port, - db_user=db_user, - db_password=db_password - ) - elif provider == DBProvider.POSTGRES: - return SQLAlchemyAdapter( - db_name = db_name, - db_path = db_path, - db_type = db_provider, - db_host= db_host, - db_port= db_port, - db_user= db_user, - db_password= db_password - ) \ No newline at end of file +def create_relational_engine( + db_path: str, + db_name: str, + db_provider: str, + db_host: str, + db_port: str, + db_user: str, + db_password: str, +): + return SQLAlchemyAdapter( + db_name = db_name, + db_path = db_path, + db_type = db_provider, + db_host = db_host, + db_port = db_port, + db_user = db_user, + db_password = db_password + ) diff --git a/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py b/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py index 1a0fbde3e..2695e04cc 100644 --- a/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py +++ b/cognee/infrastructure/databases/relational/duckdb/DuckDBAdapter.py @@ -79,7 +79,6 @@ class DuckDBAdapter(): connection.execute(""" CREATE TABLE IF NOT EXISTS cognify ( document_id STRING, - layer_id STRING, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, @@ -89,8 +88,8 @@ class DuckDBAdapter(): # Prepare the insert statement insert_query = """ - INSERT INTO cognify (document_id, layer_id) - VALUES (?, ?); + INSERT INTO cognify (document_id) + VALUES (?); """ # Insert each record into the "cognify" table @@ -98,7 +97,6 @@ class DuckDBAdapter(): with self.get_connection() as connection: connection.execute(insert_query, [ record.get("document_id"), - record.get("layer_id") ]) def fetch_cognify_data(self, excluded_document_id: str): @@ -106,7 +104,6 @@ class DuckDBAdapter(): create_table_sql = """ CREATE TABLE IF NOT EXISTS cognify ( document_id STRING, - layer_id STRING, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, @@ -118,7 +115,7 @@ class DuckDBAdapter(): connection.execute(create_table_sql) # SQL command to select data from the "cognify" table - select_data_sql = f"SELECT document_id, layer_id, created_at, updated_at, processed FROM cognify WHERE document_id != '{excluded_document_id}' AND processed = FALSE;" + select_data_sql = f"SELECT document_id, created_at, updated_at, processed FROM cognify WHERE document_id != '{excluded_document_id}' AND processed = FALSE;" with self.get_connection() as connection: # Execute the query and fetch the results @@ -144,7 +141,6 @@ class DuckDBAdapter(): create_table_sql = """ CREATE TABLE IF NOT EXISTS cognify ( document_id STRING, - layer_id STRING, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, @@ -166,7 +162,8 @@ class DuckDBAdapter(): def delete_database(self): from cognee.infrastructure.files.storage import LocalStorage - LocalStorage.remove(self.db_location) + if LocalStorage.file_exists(self.db_location): + LocalStorage.remove(self.db_location) if LocalStorage.file_exists(self.db_location + ".wal"): LocalStorage.remove(self.db_location + ".wal") diff --git a/cognee/infrastructure/databases/relational/get_relational_engine.py b/cognee/infrastructure/databases/relational/get_relational_engine.py new file mode 100644 index 000000000..6024c7bd0 --- /dev/null +++ b/cognee/infrastructure/databases/relational/get_relational_engine.py @@ -0,0 +1,8 @@ +from .config import get_relational_config +from .create_relational_engine import create_relational_engine + + +def get_relational_engine(): + relational_config = get_relational_config() + + return create_relational_engine(**relational_config.to_dict()) diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index dbdc44c40..e518dda38 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -1,22 +1,37 @@ import os +import asyncio +from typing import AsyncGenerator +from contextlib import asynccontextmanager from sqlalchemy import create_engine, MetaData, Table, Column, String, Boolean, TIMESTAMP, text from sqlalchemy.orm import sessionmaker -from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine +from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker +from cognee.infrastructure.files.storage import LocalStorage +from cognee.infrastructure.databases.relational.FakeAsyncSession import FakeAsyncSession + +def make_async_sessionmaker(sessionmaker): + @asynccontextmanager + async def async_session_maker(): + await asyncio.sleep(0.1) + yield FakeAsyncSession(sessionmaker()) + + return async_session_maker class SQLAlchemyAdapter(): - def __init__(self, db_type: str, db_path: str, db_name: str, db_user:str, db_password:str, db_host:str, db_port:str): + def __init__(self, db_type: str, db_path: str, db_name: str, db_user: str, db_password: str, db_host: str, db_port: str): self.db_location = os.path.abspath(os.path.join(db_path, db_name)) - # self.engine = create_engine(f"{db_type}:///{self.db_location}") - if db_type == "duckdb": - self.engine = create_engine(f"duckdb:///{self.db_location}") - self.sessionmaker = sessionmaker(bind=self.engine) + if db_type == "duckdb": + LocalStorage.ensure_directory_exists(db_path) + + self.engine = create_engine(f"duckdb:///{self.db_location}") + self.sessionmaker = make_async_sessionmaker(sessionmaker(bind = self.engine)) else: self.engine = create_async_engine(f"postgresql+asyncpg://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}") - self.sessionmaker = sessionmaker(bind=self.engine, class_=AsyncSession, expire_on_commit=False) + self.sessionmaker = async_sessionmaker(bind = self.engine, expire_on_commit = False) - async def get_async_session(self): + @asynccontextmanager + async def get_async_session(self) -> AsyncGenerator[AsyncSession, None]: async_session_maker = self.sessionmaker async with async_session_maker() as session: yield session @@ -26,10 +41,10 @@ class SQLAlchemyAdapter(): with session_maker() as session: yield session - def get_datasets(self): - with self.engine.connect() as connection: - result = connection.execute(text("SELECT DISTINCT schema_name FROM information_schema.tables;")) - tables = [row['schema_name'] for row in result] + async def get_datasets(self): + async with self.engine.connect() as connection: + result = await connection.execute(text("SELECT DISTINCT schema_name FROM information_schema.tables;")) + tables = [row["schema_name"] for row in result] return list( filter( lambda schema_name: not schema_name.endswith("staging") and schema_name != "cognee", @@ -83,17 +98,20 @@ class SQLAlchemyAdapter(): def load_cognify_data(self, data): metadata = MetaData() + cognify_table = Table( - 'cognify', metadata, - Column('document_id', String), - Column('layer_id', String), - Column('created_at', TIMESTAMP, server_default=text('CURRENT_TIMESTAMP')), - Column('updated_at', TIMESTAMP, nullable=True, default=None), - Column('processed', Boolean, default=False), - Column('document_id_target', String, nullable=True) + "cognify", + metadata, + Column("document_id", String), + Column("created_at", TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")), + Column("updated_at", TIMESTAMP, nullable=True, default=None), + Column("processed", Boolean, default=False), + Column("document_id_target", String, nullable=True) ) + metadata.create_all(self.engine) - insert_query = cognify_table.insert().values(document_id=text(':document_id'), layer_id=text(':layer_id')) + + insert_query = cognify_table.insert().values(document_id=text(":document_id")) with self.engine.connect() as connection: connection.execute(insert_query, data) @@ -102,23 +120,23 @@ class SQLAlchemyAdapter(): connection.execute(text(""" CREATE TABLE IF NOT EXISTS cognify ( document_id STRING, - layer_id STRING, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, document_id_target STRING NULL ); """)) - query = text(f""" - SELECT document_id, layer_id, created_at, updated_at, processed + query = text(""" + SELECT document_id, created_at, updated_at, processed FROM cognify WHERE document_id != :excluded_document_id AND processed = FALSE; """) - records = connection.execute(query, {'excluded_document_id': excluded_document_id}).fetchall() + records = connection.execute(query, {"excluded_document_id": excluded_document_id}).fetchall() + if records: - document_ids = tuple(record['document_id'] for record in records) - update_query = text(f"UPDATE cognify SET processed = TRUE WHERE document_id IN :document_ids;") - connection.execute(update_query, {'document_ids': document_ids}) + document_ids = tuple(record["document_id"] for record in records) + update_query = text("UPDATE cognify SET processed = TRUE WHERE document_id IN :document_ids;") + connection.execute(update_query, {"document_ids": document_ids}) return [dict(record) for record in records] def delete_cognify_data(self): @@ -126,7 +144,6 @@ class SQLAlchemyAdapter(): connection.execute(text(""" CREATE TABLE IF NOT EXISTS cognify ( document_id STRING, - layer_id STRING, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, @@ -136,8 +153,7 @@ class SQLAlchemyAdapter(): connection.execute(text("DELETE FROM cognify;")) connection.execute(text("DROP TABLE cognify;")) - def delete_database(self): - from cognee.infrastructure.files.storage import LocalStorage - LocalStorage.remove(self.db_location) - if LocalStorage.file_exists(self.db_location + ".wal"): - LocalStorage.remove(self.db_location + ".wal") + async def delete_database(self): + async with self.engine.begin() as connection: + from ..ModelBase import Base + await connection.run_sync(Base.metadata.drop_all) diff --git a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py b/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py deleted file mode 100644 index bbc0a01f7..000000000 --- a/cognee/infrastructure/databases/relational/user_authentication/authentication_db.py +++ /dev/null @@ -1,79 +0,0 @@ -import hashlib -import uuid -from typing import AsyncGenerator, Generator, Optional - -from fastapi import Depends -from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase -from sqlalchemy import create_engine, UUID -from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine -from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session -from cognee.infrastructure.databases.relational import get_relationaldb_config, Base -from sqlalchemy import Column, String, ForeignKey, Table, Integer -from contextlib import asynccontextmanager -from fastapi_users.exceptions import UserAlreadyExists -from fastapi_users.authentication import JWTStrategy -from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session, relationship -from cognee.infrastructure.databases.relational.user_authentication.schemas import UserRead, UserCreate -# from cognee.infrastructure.databases.relational.user_authentication.users import get_user_manager, get_jwt_strategy -from fastapi.security import OAuth2PasswordRequestForm -# Association table for many-to-many relationship between users and groups -user_group = Table('user_group', Base.metadata, - Column('user_id', UUID, ForeignKey('users.id')), - Column('group_id', UUID, ForeignKey('groups.id'))) - -# Association table for many-to-many relationship between groups and permissions -group_permission = Table('group_permission', Base.metadata, - Column('group_id', UUID, ForeignKey('groups.id')), - Column('permission_id', UUID, ForeignKey('permissions.id'))) - - - -class User(SQLAlchemyBaseUserTableUUID, Base): - __tablename__ = 'users' - groups = relationship('Group', secondary=user_group, back_populates='users') - acls = relationship('ACL', back_populates='user') - -class Group(Base): - __tablename__ = 'groups' - id = Column(UUID, primary_key=True, index=True, default=uuid.uuid4) - name = Column(String, unique=True, index=True) - users = relationship('User', secondary=user_group, back_populates='groups') - permissions = relationship('Permission', secondary=group_permission, back_populates='groups') - acls = relationship('ACL', back_populates='group') -class Permission(Base): - __tablename__ = 'permissions' - id = Column(UUID, primary_key=True, index=True) - name = Column(String, unique=True, index=True) - groups = relationship('Group', secondary=group_permission, back_populates='permissions') - -class ACL(Base): - __tablename__ = 'acls' - id = Column(UUID, primary_key=True, index=True, default=uuid.uuid4) - document_id = Column(UUID, ForeignKey('dataset_data.id')) - user_id = Column(UUID, ForeignKey('users.id'), nullable=True) - group_id = Column(UUID, ForeignKey('groups.id'), nullable=True) - permission = Column(String) # 'read', 'write', 'execute' - document = relationship('DatasetData', back_populates='acls') - user = relationship('User', back_populates='acls') - group = relationship('Group', back_populates='acls') - -relational_config = get_relationaldb_config() - - - -engine = relational_config.create_engine() -async_session_maker = async_sessionmaker(engine.engine, expire_on_commit=False) - -async def create_db_and_tables(): - async with engine.engine.begin() as conn: - await conn.run_sync(Base.metadata.create_all) - -async def get_async_session() -> AsyncGenerator[AsyncSession, None]: - async with async_session_maker() as session: - yield session - # yield async_session_maker - -async def get_user_db(session: AsyncSession = Depends(get_async_session)): - yield SQLAlchemyUserDatabase(session, User) - - diff --git a/cognee/infrastructure/databases/relational/user_authentication/routers.py b/cognee/infrastructure/databases/relational/user_authentication/routers.py deleted file mode 100644 index 42843db6f..000000000 --- a/cognee/infrastructure/databases/relational/user_authentication/routers.py +++ /dev/null @@ -1,28 +0,0 @@ -from fastapi import APIRouter, Depends, HTTPException -from sqlalchemy.orm import Session -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import get_user_db, User, Group, Permission - -permission_router = APIRouter() - -@permission_router.post("/groups/{group_id}/permissions") -async def assign_permission_to_group(group_id: int, permission: str, db: Session = Depends(get_user_db)): - group = db.query(Group).filter(Group.id == group_id).first() - if not group: - raise HTTPException(status_code=404, detail="Group not found") - perm = db.query(Permission).filter(Permission.name == permission).first() - if not perm: - perm = Permission(name=permission) - db.add(perm) - group.permissions.append(perm) - db.commit() - return {"msg": "Permission added to group"} - -@permission_router.post("/users/{user_id}/groups") -async def add_user_to_group(user_id: int, group_id: int, db: Session = Depends(get_user_db)): - user = db.query(User).filter(User.id == user_id).first() - group = db.query(Group).filter(Group.id == group_id).first() - if not user or not group: - raise HTTPException(status_code=404, detail="User or group not found") - user.groups.append(group) - db.commit() - return {"msg": "User added to group"} \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/schemas.py b/cognee/infrastructure/databases/relational/user_authentication/schemas.py deleted file mode 100644 index d7156223f..000000000 --- a/cognee/infrastructure/databases/relational/user_authentication/schemas.py +++ /dev/null @@ -1,15 +0,0 @@ -import uuid - -from fastapi_users import schemas - - -class UserRead(schemas.BaseUser[uuid.UUID]): - pass - - -class UserCreate(schemas.BaseUserCreate): - pass - - -class UserUpdate(schemas.BaseUserUpdate): - pass \ No newline at end of file diff --git a/cognee/infrastructure/databases/relational/user_authentication/users.py b/cognee/infrastructure/databases/relational/user_authentication/users.py deleted file mode 100644 index 7435eaf5b..000000000 --- a/cognee/infrastructure/databases/relational/user_authentication/users.py +++ /dev/null @@ -1,252 +0,0 @@ -import hashlib -import uuid -from typing import Optional - -from fastapi import Depends, Request -from fastapi_users import BaseUserManager, FastAPIUsers, UUIDIDMixin, models -from fastapi_users.authentication import ( - AuthenticationBackend, - BearerTransport, - JWTStrategy, -) -from fastapi_users.exceptions import UserAlreadyExists -from fastapi_users.db import SQLAlchemyUserDatabase -from fastapi import Depends, HTTPException, status -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.orm import Session -from cognee.infrastructure.databases.relational.user_authentication.authentication_db import User, get_user_db, \ - get_async_session, ACL -from fastapi.security import OAuth2PasswordRequestForm -from fastapi_users.authentication import JWTStrategy -from cognee.infrastructure.databases.relational.user_authentication.schemas import UserRead, UserCreate -from contextlib import asynccontextmanager - -SECRET = "SECRET" - - -class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]): - reset_password_token_secret = SECRET - verification_token_secret = SECRET - - async def on_after_register(self, user: User, request: Optional[Request] = None): - print(f"User {user.id} has registered.") - - async def on_after_forgot_password( - self, user: User, token: str, request: Optional[Request] = None - ): - print(f"User {user.id} has forgot their password. Reset token: {token}") - - async def on_after_request_verify( - self, user: User, token: str, request: Optional[Request] = None - ): - print(f"Verification requested for user {user.id}. Verification token: {token}") - - -async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)): - yield UserManager(user_db) - - -bearer_transport = BearerTransport(tokenUrl="auth/jwt/login") - - -def get_jwt_strategy() -> JWTStrategy[models.UP, models.ID]: - return JWTStrategy(secret=SECRET, lifetime_seconds=3600) - - -auth_backend = AuthenticationBackend( - name="jwt", - transport=bearer_transport, - get_strategy=get_jwt_strategy, -) - -fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [auth_backend]) - -async def fast_api_users_init(): - return fastapi_users - -current_active_user = fastapi_users.current_user(active=True) - - -async def get_user_permissions(user: User, session: Session): - permissions = set() - for group in user.groups: - permissions.update(permission.name for permission in group.permissions) - return permissions - -def has_permission(permission: str): - async def permission_checker(user: User = Depends(current_active_user), session: Session = Depends(get_user_db)): - user_permissions = await get_user_permissions(user, session) - if permission not in user_permissions: - raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions") - return True - return Depends(permission_checker) - - -async def hash_password(password: str) -> str: - return hashlib.sha256(password.encode()).hexdigest() - -# Define context managers for dependencies -get_async_session_context = asynccontextmanager(get_async_session) -get_user_db_context = asynccontextmanager(get_user_db) -get_user_manager_context = asynccontextmanager(get_user_manager) - -async def create_user_method(email: str, password: str, is_superuser: bool = False, is_active: bool = True): - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - user = await user_manager.create( - UserCreate(email=email, password=password, is_superuser=is_superuser, is_active=is_active) - ) - print(f"User created: {user.email}") - except UserAlreadyExists: - print(f"User {email} already exists") - -async def authenticate_user_method(email: str, password: str) -> Optional[User]: - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - credentials = OAuth2PasswordRequestForm(username=email, password=password) - user = await user_manager.authenticate(credentials) - if user is None or not user.is_active: - return None - return user - except Exception as e: - print(f"Error during authentication: {e}") - return None - -async def reset_user_password_method(email: str, new_password: str) -> bool: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - user = await user_db.get_by_email(email) - if not user: - return False - user.hashed_password = await hash_password(new_password) - await user_db.update(user) - return True - -# async def generate_verification_token(email: str, tokens_db: dict) -> str: -# async with get_async_session_context() as session: -# async with get_user_db_context(session) as user_db: -# if not await user_db.get_by_email(email): -# raise ValueError("User does not exist") -# token = str(uuid.uuid4()) -# tokens_db[token] = email -# return token - -# async def verify_user_method(token: str, tokens_db: dict) -> bool: -# async with get_async_session_context() as session: -# async with get_user_db_context(session) as user_db: -# email = tokens_db.get(token) -# if not email or not await user_db.get_by_email(email): -# return False -# user = await user_db.get_by_email(email) -# user.is_verified = True -# await user_db.update(user) -# return True - - -async def user_create_token(user: User) -> Optional[str]: - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - if user is None: - return None - strategy = get_jwt_strategy() - token = await strategy.write_token(user) - if token is not None: - return token - else: - return None - except: - return None - -async def user_check_token(token: str) -> bool: - try: - async with get_async_session_context() as session: - async with get_user_db_context(session) as user_db: - async with get_user_manager_context(user_db) as user_manager: - if token is None: - return False - strategy = get_jwt_strategy() - user = await strategy.read_token(token, user_manager) - if user is None or not user.is_active: - return False - else: - return True - except: - return False - -async def has_permission_document(user: User, document_id: str, permission: str, session: AsyncSession) -> bool: - # Check if the user has the specified permission for the document - acl_entry = await session.execute( - """ - SELECT 1 FROM acls - WHERE user_id = :user_id AND document_id = :document_id AND permission = :permission - """, - {'user_id': str(user.id), 'document_id': str(document_id), 'permission': permission} - ) - if acl_entry.scalar_one_or_none(): - return True - - # Check if any of the user's groups have the specified permission for the document - group_acl_entry = await session.execute( - """ - SELECT 1 FROM acls - JOIN user_group ON acls.group_id = user_group.group_id - WHERE user_group.user_id = :user_id AND acls.document_id = :document_id AND acls.permission = :permission - """, - {'user_id': str(user.id), 'document_id': str(document_id), 'permission': permission} - ) - if group_acl_entry.scalar_one_or_none(): - return True - - return False - -async def create_default_user(): - async with get_async_session_context() as session: - default_user_email = "default_user@example.com" - default_user_password = "default_password" - - user = await create_user_method( - email=default_user_email, - password=await hash_password(default_user_password), - is_superuser=True, - is_active=True) - session.add(user) - out = await session.commit() - await session.refresh(user) - return out.id - -async def give_permission_document(user: Optional[User], document_id: str, permission: str, - session: AsyncSession): - - acl_entry = ACL( - document_id=document_id, - user_id=user.id, - permission=permission - ) - session.add(acl_entry) - await session.commit() - - - if user.is_superuser: - permission = 'all_permissions' # Example permission, change as needed - acl_entry = ACL( - document_id=document_id, - user_id=user.id, - permission=permission - ) - session.add(acl_entry) - await session.commit() - - -async def get_document_ids_for_user(user_id: uuid.UUID, session: AsyncSession) -> list[str]: - result = await session.execute( - select(ACL.document_id).filter_by(user_id=user_id) - ) - document_ids = [row[0] for row in result.fetchall()] - return document_ids \ No newline at end of file diff --git a/cognee/modules/data/deletion/prune_system.py b/cognee/modules/data/deletion/prune_system.py index 70627bdc7..38c625558 100644 --- a/cognee/modules/data/deletion/prune_system.py +++ b/cognee/modules/data/deletion/prune_system.py @@ -1,6 +1,6 @@ from cognee.infrastructure.databases.vector import get_vector_engine from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine -from cognee.infrastructure.databases.relational import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine async def prune_system(graph = True, vector = True, metadata = False): if graph: @@ -12,6 +12,5 @@ async def prune_system(graph = True, vector = True, metadata = False): await vector_engine.prune() if metadata: - db_config = get_relationaldb_config() - db_engine = db_config.database_engine - db_engine.delete_database() + db_engine = get_relational_engine() + await db_engine.delete_database() diff --git a/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py b/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py index 3735b41b9..0a959df52 100644 --- a/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py +++ b/cognee/modules/data/extraction/knowledge_graph/expand_knowledge_graph.py @@ -1,7 +1,7 @@ import json import asyncio from uuid import uuid5, NAMESPACE_OID -from datetime import datetime +from datetime import datetime, timezone from typing import Type from pydantic import BaseModel from cognee.infrastructure.databases.graph import get_graph_engine @@ -91,8 +91,8 @@ async def expand_knowledge_graph(data_chunks: list[DocumentChunk], graph_model: name = node_name, type = node_name, description = node.description, - created_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - updated_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + created_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S"), + updated_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S"), ) graph_nodes.append(( @@ -145,8 +145,8 @@ async def expand_knowledge_graph(data_chunks: list[DocumentChunk], graph_model: name = type_node_name, type = type_node_id, description = type_node_name, - created_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - updated_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + created_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S"), + updated_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S"), ) graph_nodes.append((type_node_id, dict( diff --git a/cognee/modules/pipelines/models/Pipeline.py b/cognee/modules/pipelines/models/Pipeline.py index 7666b8bbf..8005844be 100644 --- a/cognee/modules/pipelines/models/Pipeline.py +++ b/cognee/modules/pipelines/models/Pipeline.py @@ -1,22 +1,22 @@ -from typing import List from uuid import uuid4 from datetime import datetime, timezone from sqlalchemy import Column, UUID, DateTime, String, Text from sqlalchemy.orm import relationship, Mapped -from cognee.infrastructure.databases.relational import ModelBase +from cognee.infrastructure.databases.relational import Base from .PipelineTask import PipelineTask -class Pipeline(ModelBase): +class Pipeline(Base): __tablename__ = "pipelines" - id = Column(UUID, primary_key = True, default = uuid4()) + id = Column(UUID, primary_key = True, default = uuid4) + name = Column(String) description = Column(Text, nullable = True) - created_at = Column(DateTime, default = datetime.now(timezone.utc)) - updated_at = Column(DateTime, onupdate = datetime.now(timezone.utc)) + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) - tasks = Mapped[List["Task"]] = relationship( + tasks = Mapped[list["Task"]] = relationship( secondary = PipelineTask.__tablename__, back_populates = "pipeline", ) diff --git a/cognee/modules/pipelines/models/PipelineRun.py b/cognee/modules/pipelines/models/PipelineRun.py new file mode 100644 index 000000000..bc5f890d9 --- /dev/null +++ b/cognee/modules/pipelines/models/PipelineRun.py @@ -0,0 +1,15 @@ +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy import Column, UUID, DateTime, String, JSON +from cognee.infrastructure.databases.relational import Base + +class PipelineRun(Base): + __tablename__ = "pipeline_runs" + + id = Column(UUID, primary_key = True, default = uuid4) + + dataset_name = Column(String) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + + run_info = Column(JSON) diff --git a/cognee/modules/pipelines/models/PipelineTask.py b/cognee/modules/pipelines/models/PipelineTask.py index 82b618368..0c70baddc 100644 --- a/cognee/modules/pipelines/models/PipelineTask.py +++ b/cognee/modules/pipelines/models/PipelineTask.py @@ -1,14 +1,14 @@ from uuid import uuid4 from datetime import datetime, timezone from sqlalchemy import Column, DateTime, UUID, ForeignKey -from cognee.infrastructure.databases.relational import ModelBase +from cognee.infrastructure.databases.relational import Base -class PipelineTask(ModelBase): +class PipelineTask(Base): __tablename__ = "pipeline_task" - id = Column(UUID, primary_key = True, default = uuid4()) + id = Column(UUID, primary_key = True, default = uuid4) - created_at = Column(DateTime, default = datetime.now(timezone.utc)) + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) pipeline_id = Column("pipeline", UUID, ForeignKey("pipeline.id"), primary_key = True) task_id = Column("task", UUID, ForeignKey("task.id"), primary_key = True) diff --git a/cognee/modules/pipelines/models/Task.py b/cognee/modules/pipelines/models/Task.py index 34a193dc7..c3ee89e41 100644 --- a/cognee/modules/pipelines/models/Task.py +++ b/cognee/modules/pipelines/models/Task.py @@ -1,24 +1,24 @@ from uuid import uuid4 -from typing import List from datetime import datetime, timezone from sqlalchemy.orm import relationship, Mapped from sqlalchemy import Column, String, DateTime, UUID, Text -from cognee.infrastructure.databases.relational import ModelBase +from cognee.infrastructure.databases.relational import Base from .PipelineTask import PipelineTask -class Task(ModelBase): +class Task(Base): __tablename__ = "tasks" - id = Column(UUID, primary_key = True, default = uuid4()) + id = Column(UUID, primary_key = True, default = uuid4) + name = Column(String) description = Column(Text, nullable = True) executable = Column(Text) - created_at = Column(DateTime, default = datetime.now(timezone.utc)) - updated_at = Column(DateTime, onupdate = datetime.now(timezone.utc)) + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) - datasets: Mapped[List["Pipeline"]] = relationship( + datasets: Mapped[list["Pipeline"]] = relationship( secondary = PipelineTask.__tablename__, back_populates = "task" ) diff --git a/cognee/infrastructure/databases/relational/user_authentication/__init__.py b/cognee/modules/pipelines/models/TaskStatus.py similarity index 100% rename from cognee/infrastructure/databases/relational/user_authentication/__init__.py rename to cognee/modules/pipelines/models/TaskStatus.py diff --git a/cognee/modules/tasks/create_task_status_table.py b/cognee/modules/tasks/create_task_status_table.py index f92709f06..42b6a0333 100644 --- a/cognee/modules/tasks/create_task_status_table.py +++ b/cognee/modules/tasks/create_task_status_table.py @@ -1,8 +1,7 @@ -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine def create_task_status_table(): - config = get_relationaldb_config() - db_engine = config.database_engine + db_engine = get_relational_engine() db_engine.create_table("cognee.cognee", "cognee_task_status", [ dict(name = "data_id", type = "STRING"), diff --git a/cognee/modules/tasks/get_task_status.py b/cognee/modules/tasks/get_task_status.py index 863ada164..17b796084 100644 --- a/cognee/modules/tasks/get_task_status.py +++ b/cognee/modules/tasks/get_task_status.py @@ -1,8 +1,7 @@ -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine def get_task_status(data_ids: [str]): - relational_config = get_relationaldb_config() - db_engine = relational_config.database_engine + db_engine = get_relational_engine() formatted_data_ids = ", ".join([f"'{data_id}'" for data_id in data_ids]) diff --git a/cognee/modules/tasks/update_task_status.py b/cognee/modules/tasks/update_task_status.py index 1efb3823e..0676a5a92 100644 --- a/cognee/modules/tasks/update_task_status.py +++ b/cognee/modules/tasks/update_task_status.py @@ -1,6 +1,5 @@ -from cognee.infrastructure.databases.relational.config import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine def update_task_status(data_id: str, status: str): - config = get_relationaldb_config() - db_engine = config.database_engine + db_engine = get_relational_engine() db_engine.insert_data("cognee.cognee", "cognee_task_status", [dict(data_id = data_id, status = status)]) diff --git a/cognee/modules/topology/topology.py b/cognee/modules/topology/topology.py index c733763c2..95ee510e5 100644 --- a/cognee/modules/topology/topology.py +++ b/cognee/modules/topology/topology.py @@ -14,7 +14,7 @@ from pydantic import BaseModel from cognee.infrastructure.data.chunking.config import get_chunk_config from cognee.infrastructure.data.chunking.get_chunking_engine import get_chunk_engine from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine -from cognee.infrastructure.databases.relational import get_relationaldb_config +from cognee.infrastructure.databases.relational import get_relational_engine from cognee.infrastructure.files.utils.extract_text_from_file import extract_text_from_file from cognee.infrastructure.files.utils.guess_file_type import guess_file_type, FileTypeException from cognee.modules.cognify.config import get_cognify_config @@ -162,11 +162,9 @@ async def main(): await add(f"data://{data_dir}", dataset_name="explanations") - relational_config = get_relationaldb_config() - db_engine = relational_config.database_engine + db_engine = get_relational_engine() - - datasets = db_engine.get_datasets() + datasets = await db_engine.get_datasets() dataset_files =[] for added_dataset in datasets: @@ -180,7 +178,7 @@ async def main(): file_path = "example_data.json" # or 'example_data.csv' # # # Adding graph topology - graph = await topology_engine.add_graph_topology(file_path, dataset_files=dataset_files) + graph = await topology_engine.add_graph_topology(file_path, files = dataset_files) print(graph) # Run the main function diff --git a/cognee/modules/users/__init__.py b/cognee/modules/users/__init__.py index e69de29bb..2fe7c570c 100644 --- a/cognee/modules/users/__init__.py +++ b/cognee/modules/users/__init__.py @@ -0,0 +1 @@ +from .get_user_db import get_user_db diff --git a/cognee/modules/users/authentication/get_auth_backend.py b/cognee/modules/users/authentication/get_auth_backend.py new file mode 100644 index 000000000..3e5017ffa --- /dev/null +++ b/cognee/modules/users/authentication/get_auth_backend.py @@ -0,0 +1,24 @@ +import os +from functools import lru_cache +from fastapi_users import models +from fastapi_users.authentication import ( + AuthenticationBackend, + BearerTransport, + JWTStrategy, +) + +@lru_cache +def get_auth_backend(): + bearer_transport = BearerTransport(tokenUrl = "auth/jwt/login") + + def get_jwt_strategy() -> JWTStrategy[models.UP, models.ID]: + secret = os.getenv("FASTAPI_USERS_JWT_SECRET", "super_secret") + return JWTStrategy(secret, lifetime_seconds = 3600) + + auth_backend = AuthenticationBackend( + name = "jwt", + transport = bearer_transport, + get_strategy = get_jwt_strategy, + ) + + return auth_backend diff --git a/cognee/modules/users/authentication/methods/authenticate_user.py b/cognee/modules/users/authentication/methods/authenticate_user.py new file mode 100644 index 000000000..5095092f4 --- /dev/null +++ b/cognee/modules/users/authentication/methods/authenticate_user.py @@ -0,0 +1,21 @@ +from fastapi.security import OAuth2PasswordRequestForm +from fastapi_users.exceptions import UserNotExists +from cognee.infrastructure.databases.relational import get_relational_engine +from ...get_user_manager import get_user_manager_context +from ...get_user_db import get_user_db_context + +async def authenticate_user(email: str, password: str): + try: + relational_engine = get_relational_engine() + + async with relational_engine.get_async_session() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + credentials = OAuth2PasswordRequestForm(username = email, password = password) + user = await user_manager.authenticate(credentials) + if user is None or not user.is_active: + return None + return user + except UserNotExists as error: + print(f"User {email} doesn't exist") + raise error diff --git a/cognee/modules/users/get_fastapi_users.py b/cognee/modules/users/get_fastapi_users.py new file mode 100644 index 000000000..81abe3551 --- /dev/null +++ b/cognee/modules/users/get_fastapi_users.py @@ -0,0 +1,15 @@ +import uuid +from functools import lru_cache +from fastapi_users import FastAPIUsers +from .authentication.get_auth_backend import get_auth_backend + +from .get_user_manager import get_user_manager +from .models.User import User + +@lru_cache +def get_fastapi_users(): + auth_backend = get_auth_backend() + + fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [auth_backend]) + + return fastapi_users diff --git a/cognee/modules/users/get_user_db.py b/cognee/modules/users/get_user_db.py new file mode 100644 index 000000000..fb99defef --- /dev/null +++ b/cognee/modules/users/get_user_db.py @@ -0,0 +1,10 @@ +# from fastapi import Depends +from fastapi_users.db import SQLAlchemyUserDatabase +# from cognee.infrastructure.databases.relational import get_relational_engine +from .models.User import User + +async def get_user_db(session): + yield SQLAlchemyUserDatabase(session, User) + +from contextlib import asynccontextmanager +get_user_db_context = asynccontextmanager(get_user_db) diff --git a/cognee/modules/users/get_user_manager.py b/cognee/modules/users/get_user_manager.py new file mode 100644 index 000000000..b9d69e947 --- /dev/null +++ b/cognee/modules/users/get_user_manager.py @@ -0,0 +1,32 @@ +import os +import uuid +from typing import Optional +from fastapi import Depends, Request +from fastapi_users import BaseUserManager, UUIDIDMixin +from fastapi_users.db import SQLAlchemyUserDatabase + +from .get_user_db import get_user_db +from .models import User + +class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]): + reset_password_token_secret = os.getenv("FASTAPI_USERS_RESET_PASSWORD_TOKEN_SECRET", "super_secret") + verification_token_secret = os.getenv("FASTAPI_USERS_VERIFICATION_TOKEN_SECRET", "super_secret") + + async def on_after_register(self, user: User, request: Optional[Request] = None): + print(f"User {user.id} has registered.") + + async def on_after_forgot_password( + self, user: User, token: str, request: Optional[Request] = None + ): + print(f"User {user.id} has forgot their password. Reset token: {token}") + + async def on_after_request_verify( + self, user: User, token: str, request: Optional[Request] = None + ): + print(f"Verification requested for user {user.id}. Verification token: {token}") + +async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)): + yield UserManager(user_db) + +from contextlib import asynccontextmanager +get_user_manager_context = asynccontextmanager(get_user_manager) diff --git a/cognee/modules/users/memory/__init__.py b/cognee/modules/users/memory/__init__.py deleted file mode 100644 index 736ec61f6..000000000 --- a/cognee/modules/users/memory/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .is_existing_memory import is_existing_memory -from .register_memory_for_user import register_memory_for_user -from .create_information_points import create_information_points diff --git a/cognee/modules/users/memory/create_information_points.py b/cognee/modules/users/memory/create_information_points.py deleted file mode 100644 index 748f70706..000000000 --- a/cognee/modules/users/memory/create_information_points.py +++ /dev/null @@ -1,23 +0,0 @@ -import uuid -from typing import List -from qdrant_client.models import PointStruct -from cognee.infrastructure.databases.vector.get_vector_database import get_vector_database -from cognee.infrastructure.llm.openai.openai_tools import async_get_embedding_with_backoff - -async def create_information_points(memory_name: str, payload: List[str]): - vector_db = get_vector_database() - - data_points = list() - for point in map(create_data_point, payload): - data_points.append(await point) - - return await vector_db.create_data_points(memory_name, data_points) - -async def create_data_point(data: str) -> PointStruct: - return PointStruct( - id = str(uuid.uuid4()), - vector = await async_get_embedding_with_backoff(data), - payload = { - "raw": data, - } - ) diff --git a/cognee/modules/users/memory/is_existing_memory.py b/cognee/modules/users/memory/is_existing_memory.py deleted file mode 100644 index 76b7fe34b..000000000 --- a/cognee/modules/users/memory/is_existing_memory.py +++ /dev/null @@ -1,6 +0,0 @@ -from cognee.infrastructure.databases.relational.get_database import get_database - -async def is_existing_memory(memory_name: str): - memory = await (get_database().get_memory_by_name(memory_name)) - - return memory is not None diff --git a/cognee/modules/users/memory/register_memory_for_user.py b/cognee/modules/users/memory/register_memory_for_user.py deleted file mode 100644 index e8bb29de7..000000000 --- a/cognee/modules/users/memory/register_memory_for_user.py +++ /dev/null @@ -1,4 +0,0 @@ -from cognee.infrastructure.databases.relational.get_database import get_database - -def register_memory_for_user(user_id: str, memory_name: str): - return get_database().add_memory(user_id, memory_name) diff --git a/cognee/modules/users/methods/__init__.py b/cognee/modules/users/methods/__init__.py new file mode 100644 index 000000000..bb962a227 --- /dev/null +++ b/cognee/modules/users/methods/__init__.py @@ -0,0 +1,3 @@ +from .create_user import create_user +from .get_default_user import get_default_user +from .create_default_user import create_default_user diff --git a/cognee/modules/users/methods/create_default_user.py b/cognee/modules/users/methods/create_default_user.py new file mode 100644 index 000000000..673756ed1 --- /dev/null +++ b/cognee/modules/users/methods/create_default_user.py @@ -0,0 +1,24 @@ +import hashlib +# from cognee.infrastructure.databases.relational import get_relational_engine +from .create_user import create_user + +async def create_default_user(): + default_user_email = "default_user@example.com" + default_user_password = "default_password" + + user = await create_user( + email = default_user_email, + password = await hash_password(default_user_password), + is_superuser = True, + is_active = True, + is_verified = True, + ) + + # db_engine = get_relational_engine() + # async with db_engine.get_async_session() as session: + # await session.refresh(user) + + return user + +async def hash_password(password: str) -> str: + return hashlib.sha256(password.encode()).hexdigest() diff --git a/cognee/modules/users/methods/create_user.py b/cognee/modules/users/methods/create_user.py new file mode 100644 index 000000000..f2886caae --- /dev/null +++ b/cognee/modules/users/methods/create_user.py @@ -0,0 +1,33 @@ +from fastapi_users.exceptions import UserAlreadyExists +from cognee.infrastructure.databases.relational import get_relational_engine +from ..get_user_manager import get_user_manager_context +from ..get_user_db import get_user_db_context +from ..models.User import UserCreate + +async def create_user( + email: str, + password: str, + is_superuser: bool = False, + is_active: bool = True, + is_verified: bool = False, +): + try: + relational_engine = get_relational_engine() + + async with relational_engine.get_async_session() as session: + async with get_user_db_context(session) as user_db: + async with get_user_manager_context(user_db) as user_manager: + user = await user_manager.create( + UserCreate( + email = email, + password = password, + is_superuser = is_superuser, + is_active = is_active, + is_verified = is_verified, + ) + ) + return user + print(f"User created: {user.email}") + except UserAlreadyExists as error: + print(f"User {email} already exists") + raise error diff --git a/cognee/modules/users/methods/get_default_user.py b/cognee/modules/users/methods/get_default_user.py new file mode 100644 index 000000000..011c06ec4 --- /dev/null +++ b/cognee/modules/users/methods/get_default_user.py @@ -0,0 +1,8 @@ +from cognee.modules.users.models import User +from cognee.infrastructure.databases.relational import get_relational_engine + +async def get_default_user() -> User: + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + return session.query(User).filter(User.email == "default_user@example.com").first() diff --git a/cognee/modules/users/models/ACL.py b/cognee/modules/users/models/ACL.py new file mode 100644 index 000000000..2bcffcc92 --- /dev/null +++ b/cognee/modules/users/models/ACL.py @@ -0,0 +1,25 @@ +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy.orm import relationship, Mapped +from sqlalchemy import Column, ForeignKey, DateTime, UUID +from cognee.infrastructure.databases.relational import Base +from .ACLResources import ACLResources + +class ACL(Base): + __tablename__ = "acls" + + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) + + principal_id = Column(UUID(as_uuid = True), ForeignKey("principals.id")) + permission_id = Column(UUID(as_uuid = True), ForeignKey("permissions.id")) + + principal = relationship("Principal") + permission = relationship("Permission") + resources: Mapped[list["Resource"]] = relationship( + "Resource", + secondary = ACLResources.__tablename__, + back_populates = "acls", + ) diff --git a/cognee/modules/users/models/ACLResources.py b/cognee/modules/users/models/ACLResources.py new file mode 100644 index 000000000..73d0a22fc --- /dev/null +++ b/cognee/modules/users/models/ACLResources.py @@ -0,0 +1,11 @@ +from datetime import datetime, timezone +from sqlalchemy import Column, ForeignKey, UUID, DateTime +from cognee.infrastructure.databases.relational import Base + +class ACLResources(Base): + __tablename__ = "acl_resources" + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + + acl_id = Column(UUID(as_uuid = True), ForeignKey("acls.id"), primary_key = True) + resource_id = Column(UUID(as_uuid = True), ForeignKey("resources.id"), primary_key = True) diff --git a/cognee/modules/users/models/Group.py b/cognee/modules/users/models/Group.py new file mode 100644 index 000000000..19b93443d --- /dev/null +++ b/cognee/modules/users/models/Group.py @@ -0,0 +1,21 @@ +from sqlalchemy.orm import relationship, Mapped +from sqlalchemy import Column, String, ForeignKey, UUID +from .Principal import Principal +from .UserGroup import UserGroup + +class Group(Principal): + __tablename__ = "groups" + + id = Column(UUID(as_uuid = True), ForeignKey("principals.id"), primary_key = True) + + name = Column(String, unique = True, nullable = False, index = True) + + users: Mapped[list["User"]] = relationship( + "User", + secondary = UserGroup.__tablename__, + back_populates = "groups", + ) + + __mapper_args__ = { + "polymorphic_identity": "group", + } diff --git a/cognee/modules/users/models/Permission.py b/cognee/modules/users/models/Permission.py new file mode 100644 index 000000000..41ed8b135 --- /dev/null +++ b/cognee/modules/users/models/Permission.py @@ -0,0 +1,23 @@ +from uuid import uuid4 +from datetime import datetime, timezone +# from sqlalchemy.orm import relationship, Mapped +from sqlalchemy import Column, DateTime, UUID, String +from cognee.infrastructure.databases.relational import Base + +class Permission(Base): + __tablename__ = "permissions" + + id = Column(UUID, primary_key = True, index = True, default = uuid4) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) + + name = Column(String, unique = True, nullable = False, index = True) + + # acls = relationship("ACL", back_populates = "permission") + + # groups: Mapped[list["Group"]] = relationship( + # "Group", + # secondary = "group_permissions", + # back_populates = "permissions", + # ) diff --git a/cognee/modules/users/models/Principal.py b/cognee/modules/users/models/Principal.py new file mode 100644 index 000000000..b5f14a428 --- /dev/null +++ b/cognee/modules/users/models/Principal.py @@ -0,0 +1,19 @@ +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy import Column, String, DateTime, UUID +from cognee.infrastructure.databases.relational import Base + +class Principal(Base): + __tablename__ = "principals" + + id = Column(UUID(as_uuid = True), primary_key = True, index = True, default = uuid4) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) + + type = Column(String, nullable = False) + + __mapper_args__ = { + "polymorphic_identity": "principal", + "polymorphic_on": "type", + } diff --git a/cognee/modules/users/models/Resource.py b/cognee/modules/users/models/Resource.py new file mode 100644 index 000000000..bc9e14023 --- /dev/null +++ b/cognee/modules/users/models/Resource.py @@ -0,0 +1,18 @@ +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy.orm import relationship +from sqlalchemy import Column, DateTime, UUID +from cognee.infrastructure.databases.relational import Base +from .ACLResources import ACLResources + +class Resource(Base): + __tablename__ = "resources" + + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) + + resource_id = Column(UUID(as_uuid = True), nullable = False) + + acls = relationship("ACL", secondary = ACLResources.__tablename__, back_populates = "resources") diff --git a/cognee/modules/users/models/User.py b/cognee/modules/users/models/User.py new file mode 100644 index 000000000..fba04e6a0 --- /dev/null +++ b/cognee/modules/users/models/User.py @@ -0,0 +1,33 @@ +from uuid import UUID as uuid_UUID +from sqlalchemy import ForeignKey, UUID, Column +from sqlalchemy.orm import relationship, Mapped +from fastapi_users.db import SQLAlchemyBaseUserTableUUID +from .Principal import Principal +from .UserGroup import UserGroup + +class User(SQLAlchemyBaseUserTableUUID, Principal): + __tablename__ = "users" + + id = Column(UUID(as_uuid = True), ForeignKey("principals.id"), primary_key = True) + + groups: Mapped[list["Group"]] = relationship( + secondary = UserGroup.__tablename__, + back_populates = "users", + ) + + __mapper_args__ = { + "polymorphic_identity": "user", + } + + +# Keep these schemas in sync with User model +from fastapi_users import schemas + +class UserRead(schemas.BaseUser[uuid_UUID]): + pass + +class UserCreate(schemas.BaseUserCreate): + pass + +class UserUpdate(schemas.BaseUserUpdate): + pass diff --git a/cognee/modules/users/models/UserGroup.py b/cognee/modules/users/models/UserGroup.py new file mode 100644 index 000000000..0bb6cf657 --- /dev/null +++ b/cognee/modules/users/models/UserGroup.py @@ -0,0 +1,11 @@ +from datetime import datetime, timezone +from sqlalchemy import Column, ForeignKey, DateTime, UUID +from cognee.infrastructure.databases.relational import Base + +class UserGroup(Base): + __tablename__ = "user_groups" + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + + user_id = Column(UUID(as_uuid = True), ForeignKey("users.id"), primary_key = True) + group_id = Column(UUID(as_uuid = True), ForeignKey("groups.id"), primary_key = True) diff --git a/cognee/modules/users/models/__init__.py b/cognee/modules/users/models/__init__.py new file mode 100644 index 000000000..7dc1bf8ca --- /dev/null +++ b/cognee/modules/users/models/__init__.py @@ -0,0 +1,5 @@ +from .User import User +from .Group import Group +from .Resource import Resource +from .Permission import Permission +from .ACL import ACL diff --git a/cognee/modules/users/permissions/methods/__init__.py b/cognee/modules/users/permissions/methods/__init__.py new file mode 100644 index 000000000..bc4c475dc --- /dev/null +++ b/cognee/modules/users/permissions/methods/__init__.py @@ -0,0 +1,3 @@ +from .check_permissions_on_documents import check_permissions_on_documents +from .give_permission_on_document import give_permission_on_document +from .get_document_ids_for_user import get_document_ids_for_user diff --git a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py new file mode 100644 index 000000000..4bc6f82c7 --- /dev/null +++ b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py @@ -0,0 +1,32 @@ +import logging +from cognee.infrastructure.databases.relational import get_relational_engine +from ...models.User import User +from ...models.ACL import ACL + +logger = logging.getLogger(__name__) + +async def check_permissions_on_documents( + user: User, + permission_type: str, + document_ids: list[str], +): + try: + relational_engine = get_relational_engine() + + async with relational_engine.get_async_session() as session: + user_group_ids = [group.id for group in user.groups] + + acls = session.query(ACL) \ + .filter(ACL.principal_id.in_([user.id, *user_group_ids])) \ + .filter(ACL.permission.name == permission_type) \ + .all() + + resource_ids = [resource.resource_id for resource in acl.resources for acl in acls] + + has_permissions = all([document_id in resource_ids for document_id in document_ids]) + + if not has_permissions: + raise Exception(f"User {user.username} does not have {permission_type} permission on documents") + except Exception as error: + logger.error("Error checking permissions on documents: %s", str(error)) + raise error diff --git a/cognee/modules/users/permissions/methods/get_document_ids_for_user.py b/cognee/modules/users/permissions/methods/get_document_ids_for_user.py new file mode 100644 index 000000000..31f031d75 --- /dev/null +++ b/cognee/modules/users/permissions/methods/get_document_ids_for_user.py @@ -0,0 +1,24 @@ +from uuid import UUID +from sqlalchemy import select +from cognee.infrastructure.databases.relational import get_relational_engine +from ...models import ACL + +async def get_document_ids_for_user(user_id: UUID) -> list[str]: + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + async with session.begin(): + result = await session.execute( + select(ACL.resources.resource_id) \ + .join(ACL.resources) \ + .filter_by( + ACL.principal_id == user_id, + ACL.permission.name == "read", + ) + ) + document_ids = [row[0] for row in result.fetchall()] + return document_ids + + + + diff --git a/cognee/modules/users/permissions/methods/give_permission_on_document.py b/cognee/modules/users/permissions/methods/give_permission_on_document.py new file mode 100644 index 000000000..f4dabfd6b --- /dev/null +++ b/cognee/modules/users/permissions/methods/give_permission_on_document.py @@ -0,0 +1,38 @@ +from sqlalchemy.future import select +from cognee.infrastructure.databases.relational import get_relational_engine +from ...models import User, ACL, Resource, Permission + +async def give_permission_on_document( + user: User, + document_id: str, + permission_name: str, +): + db_engine = get_relational_engine() + + document_resource = Resource(resource_id = document_id) + + async with db_engine.get_async_session() as session: + permission = (await session.execute(select(Permission).filter(Permission.name == permission_name))).first() + + if permission is None: + permission = Permission(name = permission_name) + + acl = ACL(principal_id = user.id) + acl.permission = permission + acl.resources.append(document_resource) + + session.add(acl) + + await session.commit() + + + # if user.is_superuser: + # permission = "all_permissions" # Example permission, change as needed + + # acl_entry = ACL( + # document_id=document_id, + # user_id=user.id, + # permission=permission + # ) + # session.add(acl_entry) + # await session.commit() \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 9dfd54cee..2ef05170a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,6 +60,7 @@ services: - 3001:3000 networks: - cognee-network + postgres: image: postgres:latest container_name: postgres diff --git a/poetry.lock b/poetry.lock index d952b574a..b2e39ed3c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -1259,13 +1259,13 @@ files = [ [[package]] name = "dlt" -version = "0.5.1" +version = "0.5.2" description = "dlt is an open-source python-first scalable data loading library that does not require any backend to run." optional = false python-versions = "<3.13,>=3.8.1" files = [ - {file = "dlt-0.5.1-py3-none-any.whl", hash = "sha256:19d7920816fadd049a1a92c4ecc4e740bf1cd5f6484fce535715f8c214a835ce"}, - {file = "dlt-0.5.1.tar.gz", hash = "sha256:dfa11e498feec3aca0022541850b6fa7dd3fddce4c2e6fef195530638269fec4"}, + {file = "dlt-0.5.2-py3-none-any.whl", hash = "sha256:f4ebf5eb0fbdaca5a12df9bd95c259bccb33989e93fe649ecefb6cf3f2506d30"}, + {file = "dlt-0.5.2.tar.gz", hash = "sha256:6254c56421765fb1b1b81a7c68fa0221709b67654488c31595b7f98254327ac2"}, ] [package.dependencies] @@ -1282,6 +1282,8 @@ orjson = {version = ">=3.6.7,<3.9.11 || >3.9.11,<3.9.12 || >3.9.12,<3.9.13 || >3 packaging = ">=21.1" pathvalidate = ">=2.5.2" pendulum = ">=2.1.2" +psycopg2-binary = {version = ">=2.9.1", optional = true, markers = "extra == \"postgres\" or extra == \"redshift\""} +psycopg2cffi = {version = ">=2.9.0", optional = true, markers = "platform_python_implementation == \"PyPy\" and (extra == \"postgres\" or extra == \"redshift\")"} pytz = ">=2022.6" PyYAML = ">=5.4.1" requests = ">=2.26.0" @@ -4819,6 +4821,101 @@ files = [ [package.extras] test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] +[[package]] +name = "psycopg2-binary" +version = "2.9.9" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-win32.whl", hash = "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"}, +] + +[[package]] +name = "psycopg2cffi" +version = "2.9.0" +description = ".. image:: https://travis-ci.org/chtd/psycopg2cffi.svg?branch=master" +optional = false +python-versions = "*" +files = [ + {file = "psycopg2cffi-2.9.0.tar.gz", hash = "sha256:7e272edcd837de3a1d12b62185eb85c45a19feda9e62fa1b120c54f9e8d35c52"}, +] + +[package.dependencies] +cffi = ">=1.0" +six = "*" + [[package]] name = "ptyprocess" version = "0.7.0" @@ -5430,6 +5527,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6451,6 +6549,14 @@ files = [ {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:56628ca27aa17b5890391ded4e385bf0480209726f198799b7e980c6bd473bd7"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db726be58837fe5ac39859e0fa40baafe54c6d54c02aba1d47d25536170b690f"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7421c1bfdbb7214313919472307be650bd45c4dc2fcb317d64d078993de045b"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632784f7a6f12cfa0e84bf2a5003b07660addccf5563c132cd23b7cc1d7371a9"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f6f7276cf26145a888f2182a98f204541b519d9ea358a65d82095d9c9e22f917"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2a1f7ffac934bc0ea717fa1596f938483fb8c402233f9b26679b4f7b38d6ab6e"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-win32.whl", hash = "sha256:bfece2f7cec502ec5f759bbc09ce711445372deeac3628f6fa1c16b7fb45b682"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-win_amd64.whl", hash = "sha256:526b869a0f4f000d8d8ee3409d0becca30ae73f494cbb48801da0129601f72c6"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, @@ -7547,4 +7653,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<3.12" -content-hash = "003bc600a702d9e31cbe73414f5db06c38bec29faa448fede74256efce786be2" +content-hash = "e8f056b2287bd8749be814fb94a8636170fa7ef781e38c0d7666b505e429b269" diff --git a/pyproject.toml b/pyproject.toml index 092328993..a808728b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ greenlet = "^3.0.3" ruff = "^0.2.2" filetype = "^1.2.0" nltk = "^3.8.1" -dlt = "0.5.1" +dlt = {extras = ["postgres"], version = "^0.5.2"} duckdb = {version = "^0.10.0", extras = ["dlt"]} overrides = "^7.7.0" aiofiles = "^23.2.1" From 07e2bc1b39954953f1c1eb34c03fbfa833b11289 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:56:45 +0200 Subject: [PATCH 15/44] Fixes to the pipeline --- cognee/api/v1/add/add.py | 10 +- .../sqlalchemy/SqlAlchemyAdapter.py | 16 +- cognee/tests/test_library.py | 2 +- poetry.lock | 1339 +++++++++-------- 4 files changed, 705 insertions(+), 662 deletions(-) diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index 8a4d90352..3fad96e52 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -108,11 +108,13 @@ async def add_files(file_paths: List[str], dataset_name: str, user): data_id = ingestion.identify(classified_data) if user is None: - user = await create_default_user() - - await give_permission_on_document(user, data_id, "read") - await give_permission_on_document(user, data_id, "write") + try: + user = await create_default_user() + await give_permission_on_document(user, data_id, "read") + await give_permission_on_document(user, data_id, "write") + except: + pass file_metadata = classified_data.get_metadata() yield { diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index e518dda38..ae79805cf 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -153,7 +153,19 @@ class SQLAlchemyAdapter(): connection.execute(text("DELETE FROM cognify;")) connection.execute(text("DROP TABLE cognify;")) + async def drop_tables(self, connection): + try: + await connection.execute(text("DROP TABLE IF EXISTS group_permission CASCADE")) + await connection.execute(text("DROP TABLE IF EXISTS permissions CASCADE")) + # Add more DROP TABLE statements for other tables as needed + print("Database tables dropped successfully.") + except Exception as e: + print(f"Error dropping database tables: {e}") + async def delete_database(self): async with self.engine.begin() as connection: - from ..ModelBase import Base - await connection.run_sync(Base.metadata.drop_all) + try: + await self.drop_tables(connection) + print("Database tables dropped successfully.") + except Exception as e: + print(f"Error dropping database tables: {e}") \ No newline at end of file diff --git a/cognee/tests/test_library.py b/cognee/tests/test_library.py index 9580b5f5d..d00c2b360 100755 --- a/cognee/tests/test_library.py +++ b/cognee/tests/test_library.py @@ -35,7 +35,7 @@ async def main(): await cognee.add([text], dataset_name) - await cognee.cognify([dataset_name], root_node_id = "ROOT") + await cognee.cognify([dataset_name]) from cognee.infrastructure.databases.vector import get_vector_engine vector_engine = get_vector_engine() diff --git a/poetry.lock b/poetry.lock index b2e39ed3c..57d991304 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiofiles" @@ -11,92 +11,104 @@ files = [ {file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"}, ] +[[package]] +name = "aiohappyeyeballs" +version = "2.3.4" +description = "Happy Eyeballs for asyncio" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "aiohappyeyeballs-2.3.4-py3-none-any.whl", hash = "sha256:40a16ceffcf1fc9e142fd488123b2e218abc4188cf12ac20c67200e1579baa42"}, + {file = "aiohappyeyeballs-2.3.4.tar.gz", hash = "sha256:7e1ae8399c320a8adec76f6c919ed5ceae6edd4c3672f4d9eae2b27e37c80ff6"}, +] + [[package]] name = "aiohttp" -version = "3.9.5" +version = "3.10.1" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, - {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, - {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, - {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, - {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, - {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, - {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, - {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, - {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, - {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, - {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, - {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, - {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, - {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, - {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, - {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, - {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, - {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, - {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, - {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, - {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, - {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, - {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, - {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, - {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, - {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, - {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, - {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, + {file = "aiohttp-3.10.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:47b4c2412960e64d97258f40616efddaebcb34ff664c8a972119ed38fac2a62c"}, + {file = "aiohttp-3.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7dbf637f87dd315fa1f36aaed8afa929ee2c607454fb7791e74c88a0d94da59"}, + {file = "aiohttp-3.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c8fb76214b5b739ce59e2236a6489d9dc3483649cfd6f563dbf5d8e40dbdd57d"}, + {file = "aiohttp-3.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c577cdcf8f92862363b3d598d971c6a84ed8f0bf824d4cc1ce70c2fb02acb4a"}, + {file = "aiohttp-3.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:777e23609899cb230ad2642b4bdf1008890f84968be78de29099a8a86f10b261"}, + {file = "aiohttp-3.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b07286a1090483799599a2f72f76ac396993da31f6e08efedb59f40876c144fa"}, + {file = "aiohttp-3.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9db600a86414a9a653e3c1c7f6a2f6a1894ab8f83d11505247bd1b90ad57157"}, + {file = "aiohttp-3.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c3f1eb280008e51965a8d160a108c333136f4a39d46f516c64d2aa2e6a53f2"}, + {file = "aiohttp-3.10.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f5dd109a925fee4c9ac3f6a094900461a2712df41745f5d04782ebcbe6479ccb"}, + {file = "aiohttp-3.10.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8c81ff4afffef9b1186639506d70ea90888218f5ddfff03870e74ec80bb59970"}, + {file = "aiohttp-3.10.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2a384dfbe8bfebd203b778a30a712886d147c61943675f4719b56725a8bbe803"}, + {file = "aiohttp-3.10.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:b9fb6508893dc31cfcbb8191ef35abd79751db1d6871b3e2caee83959b4d91eb"}, + {file = "aiohttp-3.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:88596384c3bec644a96ae46287bb646d6a23fa6014afe3799156aef42669c6bd"}, + {file = "aiohttp-3.10.1-cp310-cp310-win32.whl", hash = "sha256:68164d43c580c2e8bf8e0eb4960142919d304052ccab92be10250a3a33b53268"}, + {file = "aiohttp-3.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:d6bbe2c90c10382ca96df33b56e2060404a4f0f88673e1e84b44c8952517e5f3"}, + {file = "aiohttp-3.10.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f6979b4f20d3e557a867da9d9227de4c156fcdcb348a5848e3e6190fd7feb972"}, + {file = "aiohttp-3.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03c0c380c83f8a8d4416224aafb88d378376d6f4cadebb56b060688251055cd4"}, + {file = "aiohttp-3.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1c2b104e81b3c3deba7e6f5bc1a9a0e9161c380530479970766a6655b8b77c7c"}, + {file = "aiohttp-3.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b023b68c61ab0cd48bd38416b421464a62c381e32b9dc7b4bdfa2905807452a4"}, + {file = "aiohttp-3.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a07c76a82390506ca0eabf57c0540cf5a60c993c442928fe4928472c4c6e5e6"}, + {file = "aiohttp-3.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:41d8dab8c64ded1edf117d2a64f353efa096c52b853ef461aebd49abae979f16"}, + {file = "aiohttp-3.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:615348fab1a9ef7d0960a905e83ad39051ae9cb0d2837da739b5d3a7671e497a"}, + {file = "aiohttp-3.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:256ee6044214ee9d66d531bb374f065ee94e60667d6bbeaa25ca111fc3997158"}, + {file = "aiohttp-3.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7d5bb926805022508b7ddeaad957f1fce7a8d77532068d7bdb431056dc630cd"}, + {file = "aiohttp-3.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:028faf71b338f069077af6315ad54281612705d68889f5d914318cbc2aab0d50"}, + {file = "aiohttp-3.10.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5c12310d153b27aa630750be44e79313acc4e864c421eb7d2bc6fa3429c41bf8"}, + {file = "aiohttp-3.10.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:de1a91d5faded9054957ed0a9e01b9d632109341942fc123947ced358c5d9009"}, + {file = "aiohttp-3.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9c186b270979fb1dee3ababe2d12fb243ed7da08b30abc83ebac3a928a4ddb15"}, + {file = "aiohttp-3.10.1-cp311-cp311-win32.whl", hash = "sha256:4a9ce70f5e00380377aac0e568abd075266ff992be2e271765f7b35d228a990c"}, + {file = "aiohttp-3.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:a77c79bac8d908d839d32c212aef2354d2246eb9deb3e2cb01ffa83fb7a6ea5d"}, + {file = "aiohttp-3.10.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:2212296cdb63b092e295c3e4b4b442e7b7eb41e8a30d0f53c16d5962efed395d"}, + {file = "aiohttp-3.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4dcb127ca3eb0a61205818a606393cbb60d93b7afb9accd2fd1e9081cc533144"}, + {file = "aiohttp-3.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb8b79a65332e1a426ccb6290ce0409e1dc16b4daac1cc5761e059127fa3d134"}, + {file = "aiohttp-3.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68cc24f707ed9cb961f6ee04020ca01de2c89b2811f3cf3361dc7c96a14bfbcc"}, + {file = "aiohttp-3.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cb54f5725b4b37af12edf6c9e834df59258c82c15a244daa521a065fbb11717"}, + {file = "aiohttp-3.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:51d03e948e53b3639ce4d438f3d1d8202898ec6655cadcc09ec99229d4adc2a9"}, + {file = "aiohttp-3.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:786299d719eb5d868f161aeec56d589396b053925b7e0ce36e983d30d0a3e55c"}, + {file = "aiohttp-3.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abda4009a30d51d3f06f36bc7411a62b3e647fa6cc935ef667e3e3d3a7dd09b1"}, + {file = "aiohttp-3.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:67f7639424c313125213954e93a6229d3a1d386855d70c292a12628f600c7150"}, + {file = "aiohttp-3.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e5a26d7aac4c0d8414a347da162696eea0629fdce939ada6aedf951abb1d745"}, + {file = "aiohttp-3.10.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:120548d89f14b76a041088b582454d89389370632ee12bf39d919cc5c561d1ca"}, + {file = "aiohttp-3.10.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f5293726943bdcea24715b121d8c4ae12581441d22623b0e6ab12d07ce85f9c4"}, + {file = "aiohttp-3.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1f8605e573ed6c44ec689d94544b2c4bb1390aaa723a8b5a2cc0a5a485987a68"}, + {file = "aiohttp-3.10.1-cp312-cp312-win32.whl", hash = "sha256:e7168782621be4448d90169a60c8b37e9b0926b3b79b6097bc180c0a8a119e73"}, + {file = "aiohttp-3.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fbf8c0ded367c5c8eaf585f85ca8dd85ff4d5b73fb8fe1e6ac9e1b5e62e11f7"}, + {file = "aiohttp-3.10.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:54b7f4a20d7cc6bfa4438abbde069d417bb7a119f870975f78a2b99890226d55"}, + {file = "aiohttp-3.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2fa643ca990323db68911b92f3f7a0ca9ae300ae340d0235de87c523601e58d9"}, + {file = "aiohttp-3.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d8311d0d690487359fe2247ec5d2cac9946e70d50dced8c01ce9e72341c21151"}, + {file = "aiohttp-3.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222821c60b8f6a64c5908cb43d69c0ee978a1188f6a8433d4757d39231b42cdb"}, + {file = "aiohttp-3.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7b55d9ede66af7feb6de87ff277e0ccf6d51c7db74cc39337fe3a0e31b5872d"}, + {file = "aiohttp-3.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a95151a5567b3b00368e99e9c5334a919514f60888a6b6d2054fea5e66e527e"}, + {file = "aiohttp-3.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e9e9171d2fe6bfd9d3838a6fe63b1e91b55e0bf726c16edf265536e4eafed19"}, + {file = "aiohttp-3.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a57e73f9523e980f6101dc9a83adcd7ac0006ea8bf7937ca3870391c7bb4f8ff"}, + {file = "aiohttp-3.10.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0df51a3d70a2bfbb9c921619f68d6d02591f24f10e9c76de6f3388c89ed01de6"}, + {file = "aiohttp-3.10.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b0de63ff0307eac3961b4af74382d30220d4813f36b7aaaf57f063a1243b4214"}, + {file = "aiohttp-3.10.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8db9b749f589b5af8e4993623dbda6716b2b7a5fcb0fa2277bf3ce4b278c7059"}, + {file = "aiohttp-3.10.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6b14c19172eb53b63931d3e62a9749d6519f7c121149493e6eefca055fcdb352"}, + {file = "aiohttp-3.10.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5cd57ad998e3038aa87c38fe85c99ed728001bf5dde8eca121cadee06ee3f637"}, + {file = "aiohttp-3.10.1-cp38-cp38-win32.whl", hash = "sha256:df31641e3f02b77eb3c5fb63c0508bee0fc067cf153da0e002ebbb0db0b6d91a"}, + {file = "aiohttp-3.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:93094eba50bc2ad4c40ff4997ead1fdcd41536116f2e7d6cfec9596a8ecb3615"}, + {file = "aiohttp-3.10.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:440954ddc6b77257e67170d57b1026aa9545275c33312357472504eef7b4cc0b"}, + {file = "aiohttp-3.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f9f8beed277488a52ee2b459b23c4135e54d6a819eaba2e120e57311015b58e9"}, + {file = "aiohttp-3.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8a8221a63602008550022aa3a4152ca357e1dde7ab3dd1da7e1925050b56863"}, + {file = "aiohttp-3.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a702bd3663b5cbf3916e84bf332400d24cdb18399f0877ca6b313ce6c08bfb43"}, + {file = "aiohttp-3.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1988b370536eb14f0ce7f3a4a5b422ab64c4e255b3f5d7752c5f583dc8c967fc"}, + {file = "aiohttp-3.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ccf1f0a304352c891d124ac1a9dea59b14b2abed1704aaa7689fc90ef9c5be1"}, + {file = "aiohttp-3.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc3ea6ef2a83edad84bbdb5d96e22f587b67c68922cd7b6f9d8f24865e655bcf"}, + {file = "aiohttp-3.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b47c125ab07f0831803b88aeb12b04c564d5f07a1c1a225d4eb4d2f26e8b5e"}, + {file = "aiohttp-3.10.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:21778552ef3d44aac3278cc6f6d13a6423504fa5f09f2df34bfe489ed9ded7f5"}, + {file = "aiohttp-3.10.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bde0693073fd5e542e46ea100aa6c1a5d36282dbdbad85b1c3365d5421490a92"}, + {file = "aiohttp-3.10.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:bf66149bb348d8e713f3a8e0b4f5b952094c2948c408e1cfef03b49e86745d60"}, + {file = "aiohttp-3.10.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:587237571a85716d6f71f60d103416c9df7d5acb55d96d3d3ced65f39bff9c0c"}, + {file = "aiohttp-3.10.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bfe33cba6e127d0b5b417623c9aa621f0a69f304742acdca929a9fdab4593693"}, + {file = "aiohttp-3.10.1-cp39-cp39-win32.whl", hash = "sha256:9fbff00646cf8211b330690eb2fd64b23e1ce5b63a342436c1d1d6951d53d8dd"}, + {file = "aiohttp-3.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:5951c328f9ac42d7bce7a6ded535879bc9ae13032818d036749631fa27777905"}, + {file = "aiohttp-3.10.1.tar.gz", hash = "sha256:8b0d058e4e425d3b45e8ec70d49b402f4d6b21041e674798b1f91ba027c73f28"}, ] [package.dependencies] +aiohappyeyeballs = ">=2.3.0" aiosignal = ">=1.1.2" async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" @@ -105,7 +117,7 @@ multidict = ">=4.5,<7.0" yarl = ">=1.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns", "brotlicffi"] +speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] [[package]] name = "aiosignal" @@ -415,22 +427,22 @@ test = ["flake8 (>=6.1,<7.0)", "uvloop (>=0.15.3)"] [[package]] name = "attrs" -version = "23.2.0" +version = "24.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, + {file = "attrs-24.1.0-py3-none-any.whl", hash = "sha256:377b47448cb61fea38533f671fba0d0f8a96fd58facd4dc518e3dac9dbea0905"}, + {file = "attrs-24.1.0.tar.gz", hash = "sha256:adbdec84af72d38be7628e353a09b6a6790d15cd71819f6e9d7b0faa8a125745"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "authlib" @@ -545,33 +557,33 @@ lxml = ["lxml"] [[package]] name = "black" -version = "24.4.2" +version = "24.8.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, - {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, - {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"}, - {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"}, - {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"}, - {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"}, - {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"}, - {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"}, - {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"}, - {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"}, - {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"}, - {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"}, - {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"}, - {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"}, - {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"}, - {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"}, - {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"}, - {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"}, - {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"}, - {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"}, - {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"}, - {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"}, + {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, + {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, + {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, + {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, + {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, + {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, + {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, + {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, + {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, + {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, + {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, + {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, + {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, + {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, + {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, + {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, + {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, + {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, + {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, + {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, + {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, + {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, ] [package.dependencies] @@ -609,17 +621,17 @@ css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "boto3" -version = "1.34.146" +version = "1.34.153" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.146-py3-none-any.whl", hash = "sha256:7ec568fb19bce82a70be51f08fddac1ef927ca3fb0896cbb34303a012ba228d8"}, - {file = "boto3-1.34.146.tar.gz", hash = "sha256:5686fe2a6d1aa1de8a88e9589cdcc33361640d3d7a13da718a30717248886124"}, + {file = "boto3-1.34.153-py3-none-any.whl", hash = "sha256:ff9af9206fb235605cb65922f9090fe60f78ea89b4adc463f8f6391b30a3df03"}, + {file = "boto3-1.34.153.tar.gz", hash = "sha256:db9f2ac64582d847003a71720cd28dfffff61e2882e5d3db8e0c1fe1902ebb5b"}, ] [package.dependencies] -botocore = ">=1.34.146,<1.35.0" +botocore = ">=1.34.153,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -628,13 +640,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.146" +version = "1.34.153" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.146-py3-none-any.whl", hash = "sha256:3fd4782362bd29c192704ebf859c5c8c5189ad05719e391eefe23088434427ae"}, - {file = "botocore-1.34.146.tar.gz", hash = "sha256:849cb8e54e042443aeabcd7822b5f2b76cb5cfe33fe3a71f91c7c069748a869c"}, + {file = "botocore-1.34.153-py3-none-any.whl", hash = "sha256:9fc2ad40be8c103ab9bfcb48b97b117d299d0b3a542cdd30134ee2935bee827a"}, + {file = "botocore-1.34.153.tar.gz", hash = "sha256:1634a00f996cfff67f0fd4d0ddc436bc3318b2202dfd82ad0bc11c7169694092"}, ] [package.dependencies] @@ -998,63 +1010,83 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.6.0" +version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, - {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, - {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, - {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, - {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, - {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, - {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, - {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, - {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, - {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, - {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, - {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, - {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, - {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, + {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, + {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, + {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, + {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, + {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, + {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, + {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, + {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, + {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, + {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, + {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, + {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, + {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, ] [package.extras] @@ -1155,33 +1187,13 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "debugpy" -version = "1.8.2" +version = "1.8.3" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7ee2e1afbf44b138c005e4380097d92532e1001580853a7cb40ed84e0ef1c3d2"}, - {file = "debugpy-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f8c3f7c53130a070f0fc845a0f2cee8ed88d220d6b04595897b66605df1edd6"}, - {file = "debugpy-1.8.2-cp310-cp310-win32.whl", hash = "sha256:f179af1e1bd4c88b0b9f0fa153569b24f6b6f3de33f94703336363ae62f4bf47"}, - {file = "debugpy-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:0600faef1d0b8d0e85c816b8bb0cb90ed94fc611f308d5fde28cb8b3d2ff0fe3"}, - {file = "debugpy-1.8.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8a13417ccd5978a642e91fb79b871baded925d4fadd4dfafec1928196292aa0a"}, - {file = "debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634"}, - {file = "debugpy-1.8.2-cp311-cp311-win32.whl", hash = "sha256:2cbd4d9a2fc5e7f583ff9bf11f3b7d78dfda8401e8bb6856ad1ed190be4281ad"}, - {file = "debugpy-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa"}, - {file = "debugpy-1.8.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:5d3ccd39e4021f2eb86b8d748a96c766058b39443c1f18b2dc52c10ac2757835"}, - {file = "debugpy-1.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62658aefe289598680193ff655ff3940e2a601765259b123dc7f89c0239b8cd3"}, - {file = "debugpy-1.8.2-cp312-cp312-win32.whl", hash = "sha256:bd11fe35d6fd3431f1546d94121322c0ac572e1bfb1f6be0e9b8655fb4ea941e"}, - {file = "debugpy-1.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:15bc2f4b0f5e99bf86c162c91a74c0631dbd9cef3c6a1d1329c946586255e859"}, - {file = "debugpy-1.8.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:5a019d4574afedc6ead1daa22736c530712465c0c4cd44f820d803d937531b2d"}, - {file = "debugpy-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40f062d6877d2e45b112c0bbade9a17aac507445fd638922b1a5434df34aed02"}, - {file = "debugpy-1.8.2-cp38-cp38-win32.whl", hash = "sha256:c78ba1680f1015c0ca7115671fe347b28b446081dada3fedf54138f44e4ba031"}, - {file = "debugpy-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cf327316ae0c0e7dd81eb92d24ba8b5e88bb4d1b585b5c0d32929274a66a5210"}, - {file = "debugpy-1.8.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:1523bc551e28e15147815d1397afc150ac99dbd3a8e64641d53425dba57b0ff9"}, - {file = "debugpy-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e24ccb0cd6f8bfaec68d577cb49e9c680621c336f347479b3fce060ba7c09ec1"}, - {file = "debugpy-1.8.2-cp39-cp39-win32.whl", hash = "sha256:7f8d57a98c5a486c5c7824bc0b9f2f11189d08d73635c326abef268f83950326"}, - {file = "debugpy-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:16c8dcab02617b75697a0a925a62943e26a0330da076e2a10437edd9f0bf3755"}, - {file = "debugpy-1.8.2-py2.py3-none-any.whl", hash = "sha256:16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca"}, - {file = "debugpy-1.8.2.zip", hash = "sha256:95378ed08ed2089221896b9b3a8d021e642c24edc8fef20e5d4342ca8be65c00"}, + {file = "debugpy-1.8.3-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:0df2c400853150af14996b8d1a4f54d45ffa98e76c0f3de30665e89e273ea293"}, + {file = "debugpy-1.8.3.zip", hash = "sha256:0f5a6326d9fc375b864ed368d06cddf2dabe5135511e71cde3758be699847d36"}, ] [[package]] @@ -2007,61 +2019,61 @@ typing-extensions = ">=4.7,<5" [[package]] name = "grpcio" -version = "1.65.1" +version = "1.65.4" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.65.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:3dc5f928815b8972fb83b78d8db5039559f39e004ec93ebac316403fe031a062"}, - {file = "grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8333ca46053c35484c9f2f7e8d8ec98c1383a8675a449163cea31a2076d93de8"}, - {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:7af64838b6e615fff0ec711960ed9b6ee83086edfa8c32670eafb736f169d719"}, - {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb64b4166362d9326f7efbf75b1c72106c1aa87f13a8c8b56a1224fac152f5c"}, - {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8422dc13ad93ec8caa2612b5032a2b9cd6421c13ed87f54db4a3a2c93afaf77"}, - {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4effc0562b6c65d4add6a873ca132e46ba5e5a46f07c93502c37a9ae7f043857"}, - {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a6c71575a2fedf259724981fd73a18906513d2f306169c46262a5bae956e6364"}, - {file = "grpcio-1.65.1-cp310-cp310-win32.whl", hash = "sha256:34966cf526ef0ea616e008d40d989463e3db157abb213b2f20c6ce0ae7928875"}, - {file = "grpcio-1.65.1-cp310-cp310-win_amd64.whl", hash = "sha256:ca931de5dd6d9eb94ff19a2c9434b23923bce6f767179fef04dfa991f282eaad"}, - {file = "grpcio-1.65.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:bbb46330cc643ecf10bd9bd4ca8e7419a14b6b9dedd05f671c90fb2c813c6037"}, - {file = "grpcio-1.65.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d827a6fb9215b961eb73459ad7977edb9e748b23e3407d21c845d1d8ef6597e5"}, - {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:6e71aed8835f8d9fbcb84babc93a9da95955d1685021cceb7089f4f1e717d719"}, - {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a1c84560b3b2d34695c9ba53ab0264e2802721c530678a8f0a227951f453462"}, - {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27adee2338d697e71143ed147fe286c05810965d5d30ec14dd09c22479bfe48a"}, - {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f62652ddcadc75d0e7aa629e96bb61658f85a993e748333715b4ab667192e4e8"}, - {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:71a05fd814700dd9cb7d9a507f2f6a1ef85866733ccaf557eedacec32d65e4c2"}, - {file = "grpcio-1.65.1-cp311-cp311-win32.whl", hash = "sha256:b590f1ad056294dfaeac0b7e1b71d3d5ace638d8dd1f1147ce4bd13458783ba8"}, - {file = "grpcio-1.65.1-cp311-cp311-win_amd64.whl", hash = "sha256:12e9bdf3b5fd48e5fbe5b3da382ad8f97c08b47969f3cca81dd9b36b86ed39e2"}, - {file = "grpcio-1.65.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:54cb822e177374b318b233e54b6856c692c24cdbd5a3ba5335f18a47396bac8f"}, - {file = "grpcio-1.65.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aaf3c54419a28d45bd1681372029f40e5bfb58e5265e3882eaf21e4a5f81a119"}, - {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:557de35bdfbe8bafea0a003dbd0f4da6d89223ac6c4c7549d78e20f92ead95d9"}, - {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bfd95ef3b097f0cc86ade54eafefa1c8ed623aa01a26fbbdcd1a3650494dd11"}, - {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6a8f3d6c41e6b642870afe6cafbaf7b61c57317f9ec66d0efdaf19db992b90"}, - {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1faaf7355ceed07ceaef0b9dcefa4c98daf1dd8840ed75c2de128c3f4a4d859d"}, - {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:60f1f38eed830488ad2a1b11579ef0f345ff16fffdad1d24d9fbc97ba31804ff"}, - {file = "grpcio-1.65.1-cp312-cp312-win32.whl", hash = "sha256:e75acfa52daf5ea0712e8aa82f0003bba964de7ae22c26d208cbd7bc08500177"}, - {file = "grpcio-1.65.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff5a84907e51924973aa05ed8759210d8cdae7ffcf9e44fd17646cf4a902df59"}, - {file = "grpcio-1.65.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:1fbd6331f18c3acd7e09d17fd840c096f56eaf0ef830fbd50af45ae9dc8dfd83"}, - {file = "grpcio-1.65.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:de5b6be29116e094c5ef9d9e4252e7eb143e3d5f6bd6d50a78075553ab4930b0"}, - {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:e4a3cdba62b2d6aeae6027ae65f350de6dc082b72e6215eccf82628e79efe9ba"}, - {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941c4869aa229d88706b78187d60d66aca77fe5c32518b79e3c3e03fc26109a2"}, - {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f40cebe5edb518d78b8131e87cb83b3ee688984de38a232024b9b44e74ee53d3"}, - {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2ca684ba331fb249d8a1ce88db5394e70dbcd96e58d8c4b7e0d7b141a453dce9"}, - {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8558f0083ddaf5de64a59c790bffd7568e353914c0c551eae2955f54ee4b857f"}, - {file = "grpcio-1.65.1-cp38-cp38-win32.whl", hash = "sha256:8d8143a3e3966f85dce6c5cc45387ec36552174ba5712c5dc6fcc0898fb324c0"}, - {file = "grpcio-1.65.1-cp38-cp38-win_amd64.whl", hash = "sha256:76e81a86424d6ca1ce7c16b15bdd6a964a42b40544bf796a48da241fdaf61153"}, - {file = "grpcio-1.65.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb5175f45c980ff418998723ea1b3869cce3766d2ab4e4916fbd3cedbc9d0ed3"}, - {file = "grpcio-1.65.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b12c1aa7b95abe73b3e04e052c8b362655b41c7798da69f1eaf8d186c7d204df"}, - {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:3019fb50128b21a5e018d89569ffaaaa361680e1346c2f261bb84a91082eb3d3"}, - {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ae15275ed98ea267f64ee9ddedf8ecd5306a5b5bb87972a48bfe24af24153e8"}, - {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f096ffb881f37e8d4f958b63c74bfc400c7cebd7a944b027357cd2fb8d91a57"}, - {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2f56b5a68fdcf17a0a1d524bf177218c3c69b3947cb239ea222c6f1867c3ab68"}, - {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:941596d419b9736ab548aa0feb5bbba922f98872668847bf0720b42d1d227b9e"}, - {file = "grpcio-1.65.1-cp39-cp39-win32.whl", hash = "sha256:5fd7337a823b890215f07d429f4f193d24b80d62a5485cf88ee06648591a0c57"}, - {file = "grpcio-1.65.1-cp39-cp39-win_amd64.whl", hash = "sha256:1bceeec568372cbebf554eae1b436b06c2ff24cfaf04afade729fb9035408c6c"}, - {file = "grpcio-1.65.1.tar.gz", hash = "sha256:3c492301988cd720cd145d84e17318d45af342e29ef93141228f9cd73222368b"}, + {file = "grpcio-1.65.4-cp310-cp310-linux_armv7l.whl", hash = "sha256:0e85c8766cf7f004ab01aff6a0393935a30d84388fa3c58d77849fcf27f3e98c"}, + {file = "grpcio-1.65.4-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:e4a795c02405c7dfa8affd98c14d980f4acea16ea3b539e7404c645329460e5a"}, + {file = "grpcio-1.65.4-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:d7b984a8dd975d949c2042b9b5ebcf297d6d5af57dcd47f946849ee15d3c2fb8"}, + {file = "grpcio-1.65.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:644a783ce604a7d7c91412bd51cf9418b942cf71896344b6dc8d55713c71ce82"}, + {file = "grpcio-1.65.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5764237d751d3031a36fafd57eb7d36fd2c10c658d2b4057c516ccf114849a3e"}, + {file = "grpcio-1.65.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ee40d058cf20e1dd4cacec9c39e9bce13fedd38ce32f9ba00f639464fcb757de"}, + {file = "grpcio-1.65.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4482a44ce7cf577a1f8082e807a5b909236bce35b3e3897f839f2fbd9ae6982d"}, + {file = "grpcio-1.65.4-cp310-cp310-win32.whl", hash = "sha256:66bb051881c84aa82e4f22d8ebc9d1704b2e35d7867757f0740c6ef7b902f9b1"}, + {file = "grpcio-1.65.4-cp310-cp310-win_amd64.whl", hash = "sha256:870370524eff3144304da4d1bbe901d39bdd24f858ce849b7197e530c8c8f2ec"}, + {file = "grpcio-1.65.4-cp311-cp311-linux_armv7l.whl", hash = "sha256:85e9c69378af02e483bc626fc19a218451b24a402bdf44c7531e4c9253fb49ef"}, + {file = "grpcio-1.65.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2bd672e005afab8bf0d6aad5ad659e72a06dd713020554182a66d7c0c8f47e18"}, + {file = "grpcio-1.65.4-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:abccc5d73f5988e8f512eb29341ed9ced923b586bb72e785f265131c160231d8"}, + {file = "grpcio-1.65.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:886b45b29f3793b0c2576201947258782d7e54a218fe15d4a0468d9a6e00ce17"}, + {file = "grpcio-1.65.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be952436571dacc93ccc7796db06b7daf37b3b56bb97e3420e6503dccfe2f1b4"}, + {file = "grpcio-1.65.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8dc9ddc4603ec43f6238a5c95400c9a901b6d079feb824e890623da7194ff11e"}, + {file = "grpcio-1.65.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ade1256c98cba5a333ef54636095f2c09e6882c35f76acb04412f3b1aa3c29a5"}, + {file = "grpcio-1.65.4-cp311-cp311-win32.whl", hash = "sha256:280e93356fba6058cbbfc6f91a18e958062ef1bdaf5b1caf46c615ba1ae71b5b"}, + {file = "grpcio-1.65.4-cp311-cp311-win_amd64.whl", hash = "sha256:d2b819f9ee27ed4e3e737a4f3920e337e00bc53f9e254377dd26fc7027c4d558"}, + {file = "grpcio-1.65.4-cp312-cp312-linux_armv7l.whl", hash = "sha256:926a0750a5e6fb002542e80f7fa6cab8b1a2ce5513a1c24641da33e088ca4c56"}, + {file = "grpcio-1.65.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:2a1d4c84d9e657f72bfbab8bedf31bdfc6bfc4a1efb10b8f2d28241efabfaaf2"}, + {file = "grpcio-1.65.4-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:17de4fda50967679677712eec0a5c13e8904b76ec90ac845d83386b65da0ae1e"}, + {file = "grpcio-1.65.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dee50c1b69754a4228e933696408ea87f7e896e8d9797a3ed2aeed8dbd04b74"}, + {file = "grpcio-1.65.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74c34fc7562bdd169b77966068434a93040bfca990e235f7a67cdf26e1bd5c63"}, + {file = "grpcio-1.65.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:24a2246e80a059b9eb981e4c2a6d8111b1b5e03a44421adbf2736cc1d4988a8a"}, + {file = "grpcio-1.65.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:18c10f0d054d2dce34dd15855fcca7cc44ec3b811139437543226776730c0f28"}, + {file = "grpcio-1.65.4-cp312-cp312-win32.whl", hash = "sha256:d72962788b6c22ddbcdb70b10c11fbb37d60ae598c51eb47ec019db66ccfdff0"}, + {file = "grpcio-1.65.4-cp312-cp312-win_amd64.whl", hash = "sha256:7656376821fed8c89e68206a522522317787a3d9ed66fb5110b1dff736a5e416"}, + {file = "grpcio-1.65.4-cp38-cp38-linux_armv7l.whl", hash = "sha256:4934077b33aa6fe0b451de8b71dabde96bf2d9b4cb2b3187be86e5adebcba021"}, + {file = "grpcio-1.65.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0cef8c919a3359847c357cb4314e50ed1f0cca070f828ee8f878d362fd744d52"}, + {file = "grpcio-1.65.4-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:a925446e6aa12ca37114840d8550f308e29026cdc423a73da3043fd1603a6385"}, + {file = "grpcio-1.65.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf53e6247f1e2af93657e62e240e4f12e11ee0b9cef4ddcb37eab03d501ca864"}, + {file = "grpcio-1.65.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdb34278e4ceb224c89704cd23db0d902e5e3c1c9687ec9d7c5bb4c150f86816"}, + {file = "grpcio-1.65.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e6cbdd107e56bde55c565da5fd16f08e1b4e9b0674851d7749e7f32d8645f524"}, + {file = "grpcio-1.65.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:626319a156b1f19513156a3b0dbfe977f5f93db63ca673a0703238ebd40670d7"}, + {file = "grpcio-1.65.4-cp38-cp38-win32.whl", hash = "sha256:3d1bbf7e1dd1096378bd83c83f554d3b93819b91161deaf63e03b7022a85224a"}, + {file = "grpcio-1.65.4-cp38-cp38-win_amd64.whl", hash = "sha256:a99e6dffefd3027b438116f33ed1261c8d360f0dd4f943cb44541a2782eba72f"}, + {file = "grpcio-1.65.4-cp39-cp39-linux_armv7l.whl", hash = "sha256:874acd010e60a2ec1e30d5e505b0651ab12eb968157cd244f852b27c6dbed733"}, + {file = "grpcio-1.65.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b07f36faf01fca5427d4aa23645e2d492157d56c91fab7e06fe5697d7e171ad4"}, + {file = "grpcio-1.65.4-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:b81711bf4ec08a3710b534e8054c7dcf90f2edc22bebe11c1775a23f145595fe"}, + {file = "grpcio-1.65.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88fcabc332a4aef8bcefadc34a02e9ab9407ab975d2c7d981a8e12c1aed92aa1"}, + {file = "grpcio-1.65.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9ba3e63108a8749994f02c7c0e156afb39ba5bdf755337de8e75eb685be244b"}, + {file = "grpcio-1.65.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8eb485801957a486bf5de15f2c792d9f9c897a86f2f18db8f3f6795a094b4bb2"}, + {file = "grpcio-1.65.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075f3903bc1749ace93f2b0664f72964ee5f2da5c15d4b47e0ab68e4f442c257"}, + {file = "grpcio-1.65.4-cp39-cp39-win32.whl", hash = "sha256:0a0720299bdb2cc7306737295d56e41ce8827d5669d4a3cd870af832e3b17c4d"}, + {file = "grpcio-1.65.4-cp39-cp39-win_amd64.whl", hash = "sha256:a146bc40fa78769f22e1e9ff4f110ef36ad271b79707577bf2a31e3e931141b9"}, + {file = "grpcio-1.65.4.tar.gz", hash = "sha256:2a4f476209acffec056360d3e647ae0e14ae13dcf3dfb130c227ae1c594cbe39"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.65.1)"] +protobuf = ["grpcio-tools (>=1.65.4)"] [[package]] name = "grpcio-health-checking" @@ -2359,13 +2371,13 @@ files = [ [[package]] name = "importlib-metadata" -version = "8.0.0" +version = "8.2.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, - {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, + {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"}, + {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"}, ] [package.dependencies] @@ -2964,13 +2976,13 @@ test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-v [[package]] name = "jupytext" -version = "1.16.3" +version = "1.16.4" description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts" optional = false python-versions = ">=3.8" files = [ - {file = "jupytext-1.16.3-py3-none-any.whl", hash = "sha256:870e0d7a716dcb1303df6ad1cec65e3315a20daedd808a55cb3dae2d56e4ed20"}, - {file = "jupytext-1.16.3.tar.gz", hash = "sha256:1ebac990461dd9f477ff7feec9e3003fa1acc89f3c16ba01b73f79fd76f01a98"}, + {file = "jupytext-1.16.4-py3-none-any.whl", hash = "sha256:76989d2690e65667ea6fb411d8056abe7cd0437c07bd774660b83d62acf9490a"}, + {file = "jupytext-1.16.4.tar.gz", hash = "sha256:28e33f46f2ce7a41fb9d677a4a2c95327285579b64ca104437c4b9eb1e4174e9"}, ] [package.dependencies] @@ -3142,13 +3154,13 @@ tests = ["aiohttp", "boto3", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pyt [[package]] name = "langfuse" -version = "2.39.3" +version = "2.40.0" description = "A client library for accessing langfuse" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langfuse-2.39.3-py3-none-any.whl", hash = "sha256:24b12cbb23f866b22706c1ea9631781f99fe37b0b15889d241198c4d1c07516b"}, - {file = "langfuse-2.39.3.tar.gz", hash = "sha256:4d2df8f9344572370703db103ddf97176df518699593254e6d6c2b8ca3bf2f12"}, + {file = "langfuse-2.40.0-py3-none-any.whl", hash = "sha256:2aaebc179ec2edf7645805f680bf81affcb375d9cf33d0ba0e51ac3f8686000a"}, + {file = "langfuse-2.40.0.tar.gz", hash = "sha256:5b16c8b2ded418119212a295309300fd253dd80fd49f9713b4516067d499bf85"}, ] [package.dependencies] @@ -3333,40 +3345,40 @@ files = [ [[package]] name = "matplotlib" -version = "3.9.1" +version = "3.9.0" description = "Python plotting package" optional = false python-versions = ">=3.9" files = [ - {file = "matplotlib-3.9.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ccd6270066feb9a9d8e0705aa027f1ff39f354c72a87efe8fa07632f30fc6bb"}, - {file = "matplotlib-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:591d3a88903a30a6d23b040c1e44d1afdd0d778758d07110eb7596f811f31842"}, - {file = "matplotlib-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd2a59ff4b83d33bca3b5ec58203cc65985367812cb8c257f3e101632be86d92"}, - {file = "matplotlib-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fc001516ffcf1a221beb51198b194d9230199d6842c540108e4ce109ac05cc0"}, - {file = "matplotlib-3.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:83c6a792f1465d174c86d06f3ae85a8fe36e6f5964633ae8106312ec0921fdf5"}, - {file = "matplotlib-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:421851f4f57350bcf0811edd754a708d2275533e84f52f6760b740766c6747a7"}, - {file = "matplotlib-3.9.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b3fce58971b465e01b5c538f9d44915640c20ec5ff31346e963c9e1cd66fa812"}, - {file = "matplotlib-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a973c53ad0668c53e0ed76b27d2eeeae8799836fd0d0caaa4ecc66bf4e6676c0"}, - {file = "matplotlib-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82cd5acf8f3ef43f7532c2f230249720f5dc5dd40ecafaf1c60ac8200d46d7eb"}, - {file = "matplotlib-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab38a4f3772523179b2f772103d8030215b318fef6360cb40558f585bf3d017f"}, - {file = "matplotlib-3.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2315837485ca6188a4b632c5199900e28d33b481eb083663f6a44cfc8987ded3"}, - {file = "matplotlib-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a0c977c5c382f6696caf0bd277ef4f936da7e2aa202ff66cad5f0ac1428ee15b"}, - {file = "matplotlib-3.9.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:565d572efea2b94f264dd86ef27919515aa6d629252a169b42ce5f570db7f37b"}, - {file = "matplotlib-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d397fd8ccc64af2ec0af1f0efc3bacd745ebfb9d507f3f552e8adb689ed730a"}, - {file = "matplotlib-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26040c8f5121cd1ad712abffcd4b5222a8aec3a0fe40bc8542c94331deb8780d"}, - {file = "matplotlib-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12cb1837cffaac087ad6b44399d5e22b78c729de3cdae4629e252067b705e2b"}, - {file = "matplotlib-3.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0e835c6988edc3d2d08794f73c323cc62483e13df0194719ecb0723b564e0b5c"}, - {file = "matplotlib-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:44a21d922f78ce40435cb35b43dd7d573cf2a30138d5c4b709d19f00e3907fd7"}, - {file = "matplotlib-3.9.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0c584210c755ae921283d21d01f03a49ef46d1afa184134dd0f95b0202ee6f03"}, - {file = "matplotlib-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11fed08f34fa682c2b792942f8902e7aefeed400da71f9e5816bea40a7ce28fe"}, - {file = "matplotlib-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0000354e32efcfd86bda75729716b92f5c2edd5b947200be9881f0a671565c33"}, - {file = "matplotlib-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db17fea0ae3aceb8e9ac69c7e3051bae0b3d083bfec932240f9bf5d0197a049"}, - {file = "matplotlib-3.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:208cbce658b72bf6a8e675058fbbf59f67814057ae78165d8a2f87c45b48d0ff"}, - {file = "matplotlib-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:dc23f48ab630474264276be156d0d7710ac6c5a09648ccdf49fef9200d8cbe80"}, - {file = "matplotlib-3.9.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3fda72d4d472e2ccd1be0e9ccb6bf0d2eaf635e7f8f51d737ed7e465ac020cb3"}, - {file = "matplotlib-3.9.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:84b3ba8429935a444f1fdc80ed930babbe06725bcf09fbeb5c8757a2cd74af04"}, - {file = "matplotlib-3.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b918770bf3e07845408716e5bbda17eadfc3fcbd9307dc67f37d6cf834bb3d98"}, - {file = "matplotlib-3.9.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f1f2e5d29e9435c97ad4c36fb6668e89aee13d48c75893e25cef064675038ac9"}, - {file = "matplotlib-3.9.1.tar.gz", hash = "sha256:de06b19b8db95dd33d0dc17c926c7c9ebed9f572074b6fac4f65068a6814d010"}, + {file = "matplotlib-3.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2bcee1dffaf60fe7656183ac2190bd630842ff87b3153afb3e384d966b57fe56"}, + {file = "matplotlib-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f988bafb0fa39d1074ddd5bacd958c853e11def40800c5824556eb630f94d3b"}, + {file = "matplotlib-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe428e191ea016bb278758c8ee82a8129c51d81d8c4bc0846c09e7e8e9057241"}, + {file = "matplotlib-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf3978060a106fab40c328778b148f590e27f6fa3cd15a19d6892575bce387d"}, + {file = "matplotlib-3.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e7f03e5cbbfacdd48c8ea394d365d91ee8f3cae7e6ec611409927b5ed997ee4"}, + {file = "matplotlib-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:13beb4840317d45ffd4183a778685e215939be7b08616f431c7795276e067463"}, + {file = "matplotlib-3.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:063af8587fceeac13b0936c42a2b6c732c2ab1c98d38abc3337e430e1ff75e38"}, + {file = "matplotlib-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a2fa6d899e17ddca6d6526cf6e7ba677738bf2a6a9590d702c277204a7c6152"}, + {file = "matplotlib-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550cdda3adbd596078cca7d13ed50b77879104e2e46392dcd7c75259d8f00e85"}, + {file = "matplotlib-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cce0f31b351e3551d1f3779420cf8f6ec0d4a8cf9c0237a3b549fd28eb4abb"}, + {file = "matplotlib-3.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c53aeb514ccbbcbab55a27f912d79ea30ab21ee0531ee2c09f13800efb272674"}, + {file = "matplotlib-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5be985db2596d761cdf0c2eaf52396f26e6a64ab46bd8cd810c48972349d1be"}, + {file = "matplotlib-3.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c79f3a585f1368da6049318bdf1f85568d8d04b2e89fc24b7e02cc9b62017382"}, + {file = "matplotlib-3.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bdd1ecbe268eb3e7653e04f451635f0fb0f77f07fd070242b44c076c9106da84"}, + {file = "matplotlib-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e85a1a6d732f645f1403ce5e6727fd9418cd4574521d5803d3d94911038e5"}, + {file = "matplotlib-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a490715b3b9984fa609116481b22178348c1a220a4499cda79132000a79b4db"}, + {file = "matplotlib-3.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8146ce83cbc5dc71c223a74a1996d446cd35cfb6a04b683e1446b7e6c73603b7"}, + {file = "matplotlib-3.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:d91a4ffc587bacf5c4ce4ecfe4bcd23a4b675e76315f2866e588686cc97fccdf"}, + {file = "matplotlib-3.9.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:616fabf4981a3b3c5a15cd95eba359c8489c4e20e03717aea42866d8d0465956"}, + {file = "matplotlib-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cd53c79fd02f1c1808d2cfc87dd3cf4dbc63c5244a58ee7944497107469c8d8a"}, + {file = "matplotlib-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06a478f0d67636554fa78558cfbcd7b9dba85b51f5c3b5a0c9be49010cf5f321"}, + {file = "matplotlib-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81c40af649d19c85f8073e25e5806926986806fa6d54be506fbf02aef47d5a89"}, + {file = "matplotlib-3.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52146fc3bd7813cc784562cb93a15788be0b2875c4655e2cc6ea646bfa30344b"}, + {file = "matplotlib-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:0fc51eaa5262553868461c083d9adadb11a6017315f3a757fc45ec6ec5f02888"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bd4f2831168afac55b881db82a7730992aa41c4f007f1913465fb182d6fb20c0"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:290d304e59be2b33ef5c2d768d0237f5bd132986bdcc66f80bc9bcc300066a03"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff2e239c26be4f24bfa45860c20ffccd118d270c5b5d081fa4ea409b5469fcd"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:af4001b7cae70f7eaacfb063db605280058246de590fa7874f00f62259f2df7e"}, + {file = "matplotlib-3.9.0.tar.gz", hash = "sha256:e6d29ea6c19e34b30fb7d88b7081f869a03014f66fe06d62cc77d5a6ea88ed7a"}, ] [package.dependencies] @@ -3546,13 +3558,13 @@ pygments = ">2.12.0" [[package]] name = "mkdocs-material" -version = "9.5.30" +version = "9.5.31" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.30-py3-none-any.whl", hash = "sha256:fc070689c5250a180e9b9d79d8491ef9a3a7acb240db0728728d6c31eeb131d4"}, - {file = "mkdocs_material-9.5.30.tar.gz", hash = "sha256:3fd417dd42d679e3ba08b9e2d72cd8b8af142cc4a3969676ad6b00993dd182ec"}, + {file = "mkdocs_material-9.5.31-py3-none-any.whl", hash = "sha256:1b1f49066fdb3824c1e96d6bacd2d4375de4ac74580b47e79ff44c4d835c5fcb"}, + {file = "mkdocs_material-9.5.31.tar.gz", hash = "sha256:31833ec664772669f5856f4f276bf3fdf0e642a445e64491eda459249c3a1ca8"}, ] [package.dependencies] @@ -3791,38 +3803,38 @@ files = [ [[package]] name = "mypy" -version = "1.11.0" +version = "1.11.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"}, - {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"}, - {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"}, - {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"}, - {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"}, - {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"}, - {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"}, - {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"}, - {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"}, - {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"}, - {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"}, - {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"}, - {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"}, - {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"}, - {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"}, - {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"}, - {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"}, - {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"}, - {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"}, - {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"}, - {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"}, - {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"}, - {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"}, - {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"}, - {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"}, - {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"}, - {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"}, + {file = "mypy-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a32fc80b63de4b5b3e65f4be82b4cfa362a46702672aa6a0f443b4689af7008c"}, + {file = "mypy-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c1952f5ea8a5a959b05ed5f16452fddadbaae48b5d39235ab4c3fc444d5fd411"}, + {file = "mypy-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1e30dc3bfa4e157e53c1d17a0dad20f89dc433393e7702b813c10e200843b03"}, + {file = "mypy-1.11.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2c63350af88f43a66d3dfeeeb8d77af34a4f07d760b9eb3a8697f0386c7590b4"}, + {file = "mypy-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:a831671bad47186603872a3abc19634f3011d7f83b083762c942442d51c58d58"}, + {file = "mypy-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b6343d338390bb946d449677726edf60102a1c96079b4f002dedff375953fc5"}, + {file = "mypy-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4fe9f4e5e521b458d8feb52547f4bade7ef8c93238dfb5bbc790d9ff2d770ca"}, + {file = "mypy-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:886c9dbecc87b9516eff294541bf7f3655722bf22bb898ee06985cd7269898de"}, + {file = "mypy-1.11.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca4a60e1dd9fd0193ae0067eaeeb962f2d79e0d9f0f66223a0682f26ffcc809"}, + {file = "mypy-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:0bd53faf56de9643336aeea1c925012837432b5faf1701ccca7fde70166ccf72"}, + {file = "mypy-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f39918a50f74dc5969807dcfaecafa804fa7f90c9d60506835036cc1bc891dc8"}, + {file = "mypy-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bc71d1fb27a428139dd78621953effe0d208aed9857cb08d002280b0422003a"}, + {file = "mypy-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b868d3bcff720dd7217c383474008ddabaf048fad8d78ed948bb4b624870a417"}, + {file = "mypy-1.11.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a707ec1527ffcdd1c784d0924bf5cb15cd7f22683b919668a04d2b9c34549d2e"}, + {file = "mypy-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:64f4a90e3ea07f590c5bcf9029035cf0efeae5ba8be511a8caada1a4893f5525"}, + {file = "mypy-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:749fd3213916f1751fff995fccf20c6195cae941dc968f3aaadf9bb4e430e5a2"}, + {file = "mypy-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b639dce63a0b19085213ec5fdd8cffd1d81988f47a2dec7100e93564f3e8fb3b"}, + {file = "mypy-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c956b49c5d865394d62941b109728c5c596a415e9c5b2be663dd26a1ff07bc0"}, + {file = "mypy-1.11.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45df906e8b6804ef4b666af29a87ad9f5921aad091c79cc38e12198e220beabd"}, + {file = "mypy-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:d44be7551689d9d47b7abc27c71257adfdb53f03880841a5db15ddb22dc63edb"}, + {file = "mypy-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2684d3f693073ab89d76da8e3921883019ea8a3ec20fa5d8ecca6a2db4c54bbe"}, + {file = "mypy-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79c07eb282cb457473add5052b63925e5cc97dfab9812ee65a7c7ab5e3cb551c"}, + {file = "mypy-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11965c2f571ded6239977b14deebd3f4c3abd9a92398712d6da3a772974fad69"}, + {file = "mypy-1.11.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a2b43895a0f8154df6519706d9bca8280cda52d3d9d1514b2d9c3e26792a0b74"}, + {file = "mypy-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:1a81cf05975fd61aec5ae16501a091cfb9f605dc3e3c878c0da32f250b74760b"}, + {file = "mypy-1.11.1-py3-none-any.whl", hash = "sha256:0624bdb940255d2dd24e829d99a13cfeb72e4e9031f9492148f410ed30bcab54"}, + {file = "mypy-1.11.1.tar.gz", hash = "sha256:f404a0b069709f18bbdb702eb3dcfe51910602995de00bd39cea3050b5772d08"}, ] [package.dependencies] @@ -4087,37 +4099,37 @@ files = [ [[package]] name = "onnx" -version = "1.16.1" +version = "1.16.2" description = "Open Neural Network Exchange" optional = false python-versions = ">=3.8" files = [ - {file = "onnx-1.16.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:bb2d392e5b7060082c2fb38eb5c44f67eb34ff5f0681bd6f45beff9abc6f7094"}, - {file = "onnx-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15abf94a7868eed6db15a8b5024ba570c891cae77ca4d0e7258dabdad76980df"}, - {file = "onnx-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6251910e554f811fdd070164b0bc76d76b067b95576cb9dad4d52ae64fe014b5"}, - {file = "onnx-1.16.1-cp310-cp310-win32.whl", hash = "sha256:c11e3b15eee46cd20767e505cc3ba97457ef5ac93c3e459cdfb77943ff8fe9a7"}, - {file = "onnx-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:b3d10405706807ec2ef493b2a78519fa0264cf190363e89478585aac1179b596"}, - {file = "onnx-1.16.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:006ba5059c85ce43e89a1486cc0276d0f1a8ec9c6efd1a9334fd3fa0f6e33b64"}, - {file = "onnx-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1521ea7cd3497ecaf57d3b5e72d637ca5ebca632122a0806a9df99bedbeecdf8"}, - {file = "onnx-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45cf20421aeac03872bea5fd6ebf92abe15c4d1461a2572eb839add5059e2a09"}, - {file = "onnx-1.16.1-cp311-cp311-win32.whl", hash = "sha256:f98e275b4f46a617a9c527e60c02531eae03cf67a04c26db8a1c20acee539533"}, - {file = "onnx-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:95aa20aa65a9035d7543e81713e8b0f611e213fc02171959ef4ee09311d1bf28"}, - {file = "onnx-1.16.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:32e11d39bee04f927fab09f74c46cf76584094462311bab1aca9ccdae6ed3366"}, - {file = "onnx-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8884bf53b552873c0c9b072cb8625e7d4e8f3cc0529191632d24e3de58a3b93a"}, - {file = "onnx-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595b2830093f81361961295f7b0ebb6000423bcd04123d516d081c306002e387"}, - {file = "onnx-1.16.1-cp312-cp312-win32.whl", hash = "sha256:2fde4dd5bc278b3fc8148f460bce8807b2874c66f48529df9444cdbc9ecf456b"}, - {file = "onnx-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:e69ad8c110d8c37d759cad019d498fdf3fd24e0bfaeb960e52fed0469a5d2974"}, - {file = "onnx-1.16.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:0fc189195a40b5862fb77d97410c89823197fe19c1088ce150444eec72f200c1"}, - {file = "onnx-1.16.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:496ba17b16a74711081772e1b03f3207959972e351298e51abdc600051027a22"}, - {file = "onnx-1.16.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3faf239b48418b3ea6fe73bd4d86807b903d0b2ebd20b8b8c84f83741b0f18"}, - {file = "onnx-1.16.1-cp38-cp38-win32.whl", hash = "sha256:18b22143836838591f6551b089196e69f60c47fabce52b4b72b4cb37522645aa"}, - {file = "onnx-1.16.1-cp38-cp38-win_amd64.whl", hash = "sha256:8c2b70d602acfb90056fbdc60ef26f4658f964591212a4e9dbbda922ff43061b"}, - {file = "onnx-1.16.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:2bed6fe05905b073206cabbb4463c58050cf8d544192303c09927b229f93ac14"}, - {file = "onnx-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5798414332534a41404a7ff83677d49ced01d70160e1541484cce647f2295051"}, - {file = "onnx-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa7518d6d27f357261a4014079dec364cad6fef827d0b3fe1d3ff59939a68394"}, - {file = "onnx-1.16.1-cp39-cp39-win32.whl", hash = "sha256:67f372db4fe8fe61e00b762af5b0833aa72b5baa37e7e2f47d8668964ebff411"}, - {file = "onnx-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:1c059fea6229c44d2d39c8f6e2f2f0d676d587c97f4c854c86f3e7bc97e0b31c"}, - {file = "onnx-1.16.1.tar.gz", hash = "sha256:8299193f0f2a3849bfc069641aa8e4f93696602da8d165632af8ee48ec7556b6"}, + {file = "onnx-1.16.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:ab0a1aa6b0470020ea3636afdce3e2a67f856fefe4be8c73b20371b07fcde69c"}, + {file = "onnx-1.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a449122a49534bb9c2b6f16c8493b606ef0accda6b9dbf0c513ca4b31ebe8b38"}, + {file = "onnx-1.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec6a425e59291fff430da4a884aa07a1d0cbb5dcd22cc78f6cf4ba5adb9f3367"}, + {file = "onnx-1.16.2-cp310-cp310-win32.whl", hash = "sha256:55fbaf38acd4cd8fdd0b4f36871fb596b075518d3e981acc893f2ab887d1891a"}, + {file = "onnx-1.16.2-cp310-cp310-win_amd64.whl", hash = "sha256:4e496d301756e0a22fd2bdfac24b861c7b1ddbdd9ce7677b2a252c00c4c8f2a7"}, + {file = "onnx-1.16.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:859b41574243c9bfd0abce03c15c78a1f270cc03c7f99629b984daf7adfa5003"}, + {file = "onnx-1.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39a57d196fe5d73861e70d9625674e6caf8ca13c5e9c740462cf530a07cd2e1c"}, + {file = "onnx-1.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b98aa9733bd4b781eb931d33b4078ff2837e7d68062460726d6dd011f332bd4"}, + {file = "onnx-1.16.2-cp311-cp311-win32.whl", hash = "sha256:e9f018b2e172efeea8c2473a51a825652767726374145d7cfdebdc7a27446fdd"}, + {file = "onnx-1.16.2-cp311-cp311-win_amd64.whl", hash = "sha256:e66e4512a30df8916db5cf84f47d47b3250b9ab9a98d9cffe142c98c54598ba0"}, + {file = "onnx-1.16.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:bfdb8c2eb4c92f55626376e00993db8fcc753da4b80babf28d99636af8dbae6b"}, + {file = "onnx-1.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b77a6c138f284dfc9b06fa370768aa4fd167efc49ff740e2158dd02eedde8d0"}, + {file = "onnx-1.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca12e47965e590b63f31681c8c563c75449a04178f27eac1ff64bad314314fb3"}, + {file = "onnx-1.16.2-cp312-cp312-win32.whl", hash = "sha256:324fe3551e91ffd74b43dbcf1d48e96579f4c1be2ff1224591ecd3ec6daa6139"}, + {file = "onnx-1.16.2-cp312-cp312-win_amd64.whl", hash = "sha256:080b19b0bd2b5536b4c61812464fe495758d6c9cfed3fdd3f20516e616212bee"}, + {file = "onnx-1.16.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:c42a5db2db36fc46d3a93ab6aeff0f11abe10a4a16a85f2aad8879a58a898ee5"}, + {file = "onnx-1.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9635437ffe51cc71343f3067bc548a068bd287ac690f65a9f6223ea9dca441bf"}, + {file = "onnx-1.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9e22be82c3447ba6d2fe851973a736a7013e97b398e8beb7a25fd2ad4df219e"}, + {file = "onnx-1.16.2-cp38-cp38-win32.whl", hash = "sha256:e16012431643c66124eba0089acdad0df71d5c9d4e6bec4721999f9eecab72b7"}, + {file = "onnx-1.16.2-cp38-cp38-win_amd64.whl", hash = "sha256:42231a467e5be2974d426b410987073ed85bee34af7b50c93ab221a8696b0cfd"}, + {file = "onnx-1.16.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:e79edba750ae06059d82d8ff8129a6488a7e692cd23cd7fe010f7ec7d6a14bad"}, + {file = "onnx-1.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d192db8501103fede9c1725861e65ed41efb65da1ce915ba969aae40073eb94"}, + {file = "onnx-1.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01d4a3bd7a0d0ee5084f65441fc9ca38450fc18835b7f9d5da5b9e7ca8b85d"}, + {file = "onnx-1.16.2-cp39-cp39-win32.whl", hash = "sha256:0b765b09bdb01fa2338ea52483aa3d9c75e249f85446f0d9ad1dc5bd2b149082"}, + {file = "onnx-1.16.2-cp39-cp39-win_amd64.whl", hash = "sha256:bfee781a59919e797f4dae380e63a0390ec01ce5c337a1459b992aac2f49a3c2"}, + {file = "onnx-1.16.2.tar.gz", hash = "sha256:b33a282b038813c4b69e73ea65c2909768e8dd6cc10619b70632335daf094646"}, ] [package.dependencies] @@ -4125,7 +4137,7 @@ numpy = ">=1.20" protobuf = ">=3.20.2" [package.extras] -reference = ["Pillow", "google-re2"] +reference = ["google-re2", "pillow"] [[package]] name = "onnxruntime" @@ -4774,22 +4786,22 @@ wcwidth = "*" [[package]] name = "protobuf" -version = "4.25.3" +version = "4.25.4" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, - {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, - {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, - {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, - {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, - {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, - {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, - {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, - {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, + {file = "protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4"}, + {file = "protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d"}, + {file = "protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b"}, + {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835"}, + {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040"}, + {file = "protobuf-4.25.4-cp38-cp38-win32.whl", hash = "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1"}, + {file = "protobuf-4.25.4-cp38-cp38-win_amd64.whl", hash = "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1"}, + {file = "protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca"}, + {file = "protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f"}, + {file = "protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978"}, + {file = "protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d"}, ] [[package]] @@ -5152,13 +5164,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-settings" -version = "2.3.4" +version = "2.4.0" description = "Settings management using Pydantic" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.3.4-py3-none-any.whl", hash = "sha256:11ad8bacb68a045f00e4f862c7a718c8a9ec766aa8fd4c32e39a0594b207b53a"}, - {file = "pydantic_settings-2.3.4.tar.gz", hash = "sha256:c5802e3d62b78e82522319bbc9b8f8ffb28ad1c988a99311d04f2a6051fca0a7"}, + {file = "pydantic_settings-2.4.0-py3-none-any.whl", hash = "sha256:bb6849dc067f1687574c12a639e231f3a6feeed0a12d710c1382045c5db1c315"}, + {file = "pydantic_settings-2.4.0.tar.gz", hash = "sha256:ed81c3a0f46392b4d7c0a565c05884e6e54b3456e6f0fe4d8814981172dc9a88"}, ] [package.dependencies] @@ -5166,6 +5178,7 @@ pydantic = ">=2.7.0" python-dotenv = ">=0.21.0" [package.extras] +azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] toml = ["tomli (>=2.0.1)"] yaml = ["pyyaml (>=6.0.1)"] @@ -5260,13 +5273,13 @@ testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" -version = "10.8.1" +version = "10.9" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"}, - {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"}, + {file = "pymdown_extensions-10.9-py3-none-any.whl", hash = "sha256:d323f7e90d83c86113ee78f3fe62fc9dee5f56b54d912660703ea1816fed5626"}, + {file = "pymdown_extensions-10.9.tar.gz", hash = "sha256:6ff740bcd99ec4172a938970d42b96128bdc9d4b9bcad72494f29921dc69b753"}, ] [package.dependencies] @@ -5527,7 +5540,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -5578,99 +5590,120 @@ pyyaml = "*" [[package]] name = "pyzmq" -version = "26.0.3" +version = "26.1.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.7" files = [ - {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:44dd6fc3034f1eaa72ece33588867df9e006a7303725a12d64c3dff92330f625"}, - {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acb704195a71ac5ea5ecf2811c9ee19ecdc62b91878528302dd0be1b9451cc90"}, - {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbb9c997932473a27afa93954bb77a9f9b786b4ccf718d903f35da3232317de"}, - {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bcb34f869d431799c3ee7d516554797f7760cb2198ecaa89c3f176f72d062be"}, - {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ece17ec5f20d7d9b442e5174ae9f020365d01ba7c112205a4d59cf19dc38ee"}, - {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ba6e5e6588e49139a0979d03a7deb9c734bde647b9a8808f26acf9c547cab1bf"}, - {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3bf8b000a4e2967e6dfdd8656cd0757d18c7e5ce3d16339e550bd462f4857e59"}, - {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2136f64fbb86451dbbf70223635a468272dd20075f988a102bf8a3f194a411dc"}, - {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e8918973fbd34e7814f59143c5f600ecd38b8038161239fd1a3d33d5817a38b8"}, - {file = "pyzmq-26.0.3-cp310-cp310-win32.whl", hash = "sha256:0aaf982e68a7ac284377d051c742610220fd06d330dcd4c4dbb4cdd77c22a537"}, - {file = "pyzmq-26.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:f1a9b7d00fdf60b4039f4455afd031fe85ee8305b019334b72dcf73c567edc47"}, - {file = "pyzmq-26.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:80b12f25d805a919d53efc0a5ad7c0c0326f13b4eae981a5d7b7cc343318ebb7"}, - {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32"}, - {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ca684ee649b55fd8f378127ac8462fb6c85f251c2fb027eb3c887e8ee347bcd"}, - {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7"}, - {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f17cde1db0754c35a91ac00b22b25c11da6eec5746431d6e5092f0cd31a3fea9"}, - {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7c0c0b3244bb2275abe255d4a30c050d541c6cb18b870975553f1fb6f37527"}, - {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a"}, - {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:88b88282e55fa39dd556d7fc04160bcf39dea015f78e0cecec8ff4f06c1fc2b5"}, - {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:72b67f966b57dbd18dcc7efbc1c7fc9f5f983e572db1877081f075004614fcdd"}, - {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4b6cecbbf3b7380f3b61de3a7b93cb721125dc125c854c14ddc91225ba52f83"}, - {file = "pyzmq-26.0.3-cp311-cp311-win32.whl", hash = "sha256:eed56b6a39216d31ff8cd2f1d048b5bf1700e4b32a01b14379c3b6dde9ce3aa3"}, - {file = "pyzmq-26.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500"}, - {file = "pyzmq-26.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:b6907da3017ef55139cf0e417c5123a84c7332520e73a6902ff1f79046cd3b94"}, - {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:068ca17214038ae986d68f4a7021f97e187ed278ab6dccb79f837d765a54d753"}, - {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7821d44fe07335bea256b9f1f41474a642ca55fa671dfd9f00af8d68a920c2d4"}, - {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb438a26d87c123bb318e5f2b3d86a36060b01f22fbdffd8cf247d52f7c9a2b"}, - {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69ea9d6d9baa25a4dc9cef5e2b77b8537827b122214f210dd925132e34ae9b12"}, - {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7daa3e1369355766dea11f1d8ef829905c3b9da886ea3152788dc25ee6079e02"}, - {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6ca7a9a06b52d0e38ccf6bca1aeff7be178917893f3883f37b75589d42c4ac20"}, - {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1b7d0e124948daa4d9686d421ef5087c0516bc6179fdcf8828b8444f8e461a77"}, - {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e746524418b70f38550f2190eeee834db8850088c834d4c8406fbb9bc1ae10b2"}, - {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:6b3146f9ae6af82c47a5282ac8803523d381b3b21caeae0327ed2f7ecb718798"}, - {file = "pyzmq-26.0.3-cp312-cp312-win32.whl", hash = "sha256:2b291d1230845871c00c8462c50565a9cd6026fe1228e77ca934470bb7d70ea0"}, - {file = "pyzmq-26.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:926838a535c2c1ea21c903f909a9a54e675c2126728c21381a94ddf37c3cbddf"}, - {file = "pyzmq-26.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:5bf6c237f8c681dfb91b17f8435b2735951f0d1fad10cc5dfd96db110243370b"}, - {file = "pyzmq-26.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c0991f5a96a8e620f7691e61178cd8f457b49e17b7d9cfa2067e2a0a89fc1d5"}, - {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dbf012d8fcb9f2cf0643b65df3b355fdd74fc0035d70bb5c845e9e30a3a4654b"}, - {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:01fbfbeb8249a68d257f601deb50c70c929dc2dfe683b754659569e502fbd3aa"}, - {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c8eb19abe87029c18f226d42b8a2c9efdd139d08f8bf6e085dd9075446db450"}, - {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5344b896e79800af86ad643408ca9aa303a017f6ebff8cee5a3163c1e9aec987"}, - {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:204e0f176fd1d067671157d049466869b3ae1fc51e354708b0dc41cf94e23a3a"}, - {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a42db008d58530efa3b881eeee4991146de0b790e095f7ae43ba5cc612decbc5"}, - {file = "pyzmq-26.0.3-cp37-cp37m-win32.whl", hash = "sha256:8d7a498671ca87e32b54cb47c82a92b40130a26c5197d392720a1bce1b3c77cf"}, - {file = "pyzmq-26.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:3b4032a96410bdc760061b14ed6a33613ffb7f702181ba999df5d16fb96ba16a"}, - {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:2cc4e280098c1b192c42a849de8de2c8e0f3a84086a76ec5b07bfee29bda7d18"}, - {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bde86a2ed3ce587fa2b207424ce15b9a83a9fa14422dcc1c5356a13aed3df9d"}, - {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:34106f68e20e6ff253c9f596ea50397dbd8699828d55e8fa18bd4323d8d966e6"}, - {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ebbbd0e728af5db9b04e56389e2299a57ea8b9dd15c9759153ee2455b32be6ad"}, - {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6b1d1c631e5940cac5a0b22c5379c86e8df6a4ec277c7a856b714021ab6cfad"}, - {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e891ce81edd463b3b4c3b885c5603c00141151dd9c6936d98a680c8c72fe5c67"}, - {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9b273ecfbc590a1b98f014ae41e5cf723932f3b53ba9367cfb676f838038b32c"}, - {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b32bff85fb02a75ea0b68f21e2412255b5731f3f389ed9aecc13a6752f58ac97"}, - {file = "pyzmq-26.0.3-cp38-cp38-win32.whl", hash = "sha256:f6c21c00478a7bea93caaaef9e7629145d4153b15a8653e8bb4609d4bc70dbfc"}, - {file = "pyzmq-26.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:3401613148d93ef0fd9aabdbddb212de3db7a4475367f49f590c837355343972"}, - {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:2ed8357f4c6e0daa4f3baf31832df8a33334e0fe5b020a61bc8b345a3db7a606"}, - {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1c8f2a2ca45292084c75bb6d3a25545cff0ed931ed228d3a1810ae3758f975f"}, - {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b63731993cdddcc8e087c64e9cf003f909262b359110070183d7f3025d1c56b5"}, - {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3cd31f859b662ac5d7f4226ec7d8bd60384fa037fc02aee6ff0b53ba29a3ba8"}, - {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115f8359402fa527cf47708d6f8a0f8234f0e9ca0cab7c18c9c189c194dbf620"}, - {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:715bdf952b9533ba13dfcf1f431a8f49e63cecc31d91d007bc1deb914f47d0e4"}, - {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e1258c639e00bf5e8a522fec6c3eaa3e30cf1c23a2f21a586be7e04d50c9acab"}, - {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:15c59e780be8f30a60816a9adab900c12a58d79c1ac742b4a8df044ab2a6d920"}, - {file = "pyzmq-26.0.3-cp39-cp39-win32.whl", hash = "sha256:d0cdde3c78d8ab5b46595054e5def32a755fc028685add5ddc7403e9f6de9879"}, - {file = "pyzmq-26.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:ce828058d482ef860746bf532822842e0ff484e27f540ef5c813d516dd8896d2"}, - {file = "pyzmq-26.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:788f15721c64109cf720791714dc14afd0f449d63f3a5487724f024345067381"}, - {file = "pyzmq-26.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c18645ef6294d99b256806e34653e86236eb266278c8ec8112622b61db255de"}, - {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e6bc96ebe49604df3ec2c6389cc3876cabe475e6bfc84ced1bf4e630662cb35"}, - {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:971e8990c5cc4ddcff26e149398fc7b0f6a042306e82500f5e8db3b10ce69f84"}, - {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8416c23161abd94cc7da80c734ad7c9f5dbebdadfdaa77dad78244457448223"}, - {file = "pyzmq-26.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:082a2988364b60bb5de809373098361cf1dbb239623e39e46cb18bc035ed9c0c"}, - {file = "pyzmq-26.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d57dfbf9737763b3a60d26e6800e02e04284926329aee8fb01049635e957fe81"}, - {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:77a85dca4c2430ac04dc2a2185c2deb3858a34fe7f403d0a946fa56970cf60a1"}, - {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c82a6d952a1d555bf4be42b6532927d2a5686dd3c3e280e5f63225ab47ac1f5"}, - {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4496b1282c70c442809fc1b151977c3d967bfb33e4e17cedbf226d97de18f709"}, - {file = "pyzmq-26.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e4946d6bdb7ba972dfda282f9127e5756d4f299028b1566d1245fa0d438847e6"}, - {file = "pyzmq-26.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03c0ae165e700364b266876d712acb1ac02693acd920afa67da2ebb91a0b3c09"}, - {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3e3070e680f79887d60feeda051a58d0ac36622e1759f305a41059eff62c6da7"}, - {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6ca08b840fe95d1c2bd9ab92dac5685f949fc6f9ae820ec16193e5ddf603c3b2"}, - {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e76654e9dbfb835b3518f9938e565c7806976c07b37c33526b574cc1a1050480"}, - {file = "pyzmq-26.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:871587bdadd1075b112e697173e946a07d722459d20716ceb3d1bd6c64bd08ce"}, - {file = "pyzmq-26.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d0a2d1bd63a4ad79483049b26514e70fa618ce6115220da9efdff63688808b17"}, - {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0270b49b6847f0d106d64b5086e9ad5dc8a902413b5dbbb15d12b60f9c1747a4"}, - {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:703c60b9910488d3d0954ca585c34f541e506a091a41930e663a098d3b794c67"}, - {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74423631b6be371edfbf7eabb02ab995c2563fee60a80a30829176842e71722a"}, - {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4adfbb5451196842a88fda3612e2c0414134874bffb1c2ce83ab4242ec9e027d"}, - {file = "pyzmq-26.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3516119f4f9b8671083a70b6afaa0a070f5683e431ab3dc26e9215620d7ca1ad"}, - {file = "pyzmq-26.0.3.tar.gz", hash = "sha256:dba7d9f2e047dfa2bca3b01f4f84aa5246725203d6284e3790f2ca15fba6b40a"}, + {file = "pyzmq-26.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:263cf1e36862310bf5becfbc488e18d5d698941858860c5a8c079d1511b3b18e"}, + {file = "pyzmq-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d5c8b17f6e8f29138678834cf8518049e740385eb2dbf736e8f07fc6587ec682"}, + {file = "pyzmq-26.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75a95c2358fcfdef3374cb8baf57f1064d73246d55e41683aaffb6cfe6862917"}, + {file = "pyzmq-26.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f99de52b8fbdb2a8f5301ae5fc0f9e6b3ba30d1d5fc0421956967edcc6914242"}, + {file = "pyzmq-26.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bcbfbab4e1895d58ab7da1b5ce9a327764f0366911ba5b95406c9104bceacb0"}, + {file = "pyzmq-26.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77ce6a332c7e362cb59b63f5edf730e83590d0ab4e59c2aa5bd79419a42e3449"}, + {file = "pyzmq-26.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba0a31d00e8616149a5ab440d058ec2da621e05d744914774c4dde6837e1f545"}, + {file = "pyzmq-26.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8b88641384e84a258b740801cd4dbc45c75f148ee674bec3149999adda4a8598"}, + {file = "pyzmq-26.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2fa76ebcebe555cce90f16246edc3ad83ab65bb7b3d4ce408cf6bc67740c4f88"}, + {file = "pyzmq-26.1.0-cp310-cp310-win32.whl", hash = "sha256:fbf558551cf415586e91160d69ca6416f3fce0b86175b64e4293644a7416b81b"}, + {file = "pyzmq-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a7b8aab50e5a288c9724d260feae25eda69582be84e97c012c80e1a5e7e03fb2"}, + {file = "pyzmq-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:08f74904cb066e1178c1ec706dfdb5c6c680cd7a8ed9efebeac923d84c1f13b1"}, + {file = "pyzmq-26.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:46d6800b45015f96b9d92ece229d92f2aef137d82906577d55fadeb9cf5fcb71"}, + {file = "pyzmq-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5bc2431167adc50ba42ea3e5e5f5cd70d93e18ab7b2f95e724dd8e1bd2c38120"}, + {file = "pyzmq-26.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3bb34bebaa1b78e562931a1687ff663d298013f78f972a534f36c523311a84d"}, + {file = "pyzmq-26.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd3f6329340cef1c7ba9611bd038f2d523cea79f09f9c8f6b0553caba59ec562"}, + {file = "pyzmq-26.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:471880c4c14e5a056a96cd224f5e71211997d40b4bf5e9fdded55dafab1f98f2"}, + {file = "pyzmq-26.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ce6f2b66799971cbae5d6547acefa7231458289e0ad481d0be0740535da38d8b"}, + {file = "pyzmq-26.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a1f6ea5b1d6cdbb8cfa0536f0d470f12b4b41ad83625012e575f0e3ecfe97f0"}, + {file = "pyzmq-26.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b45e6445ac95ecb7d728604bae6538f40ccf4449b132b5428c09918523abc96d"}, + {file = "pyzmq-26.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:94c4262626424683feea0f3c34951d39d49d354722db2745c42aa6bb50ecd93b"}, + {file = "pyzmq-26.1.0-cp311-cp311-win32.whl", hash = "sha256:a0f0ab9df66eb34d58205913f4540e2ad17a175b05d81b0b7197bc57d000e829"}, + {file = "pyzmq-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:8efb782f5a6c450589dbab4cb0f66f3a9026286333fe8f3a084399149af52f29"}, + {file = "pyzmq-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f133d05aaf623519f45e16ab77526e1e70d4e1308e084c2fb4cedb1a0c764bbb"}, + {file = "pyzmq-26.1.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:3d3146b1c3dcc8a1539e7cc094700b2be1e605a76f7c8f0979b6d3bde5ad4072"}, + {file = "pyzmq-26.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d9270fbf038bf34ffca4855bcda6e082e2c7f906b9eb8d9a8ce82691166060f7"}, + {file = "pyzmq-26.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:995301f6740a421afc863a713fe62c0aaf564708d4aa057dfdf0f0f56525294b"}, + {file = "pyzmq-26.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7eca8b89e56fb8c6c26dd3e09bd41b24789022acf1cf13358e96f1cafd8cae3"}, + {file = "pyzmq-26.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d4feb2e83dfe9ace6374a847e98ee9d1246ebadcc0cb765482e272c34e5820"}, + {file = "pyzmq-26.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d4fafc2eb5d83f4647331267808c7e0c5722c25a729a614dc2b90479cafa78bd"}, + {file = "pyzmq-26.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:58c33dc0e185dd97a9ac0288b3188d1be12b756eda67490e6ed6a75cf9491d79"}, + {file = "pyzmq-26.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:68a0a1d83d33d8367ddddb3e6bb4afbb0f92bd1dac2c72cd5e5ddc86bdafd3eb"}, + {file = "pyzmq-26.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ae7c57e22ad881af78075e0cea10a4c778e67234adc65c404391b417a4dda83"}, + {file = "pyzmq-26.1.0-cp312-cp312-win32.whl", hash = "sha256:347e84fc88cc4cb646597f6d3a7ea0998f887ee8dc31c08587e9c3fd7b5ccef3"}, + {file = "pyzmq-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:9f136a6e964830230912f75b5a116a21fe8e34128dcfd82285aa0ef07cb2c7bd"}, + {file = "pyzmq-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:a4b7a989c8f5a72ab1b2bbfa58105578753ae77b71ba33e7383a31ff75a504c4"}, + {file = "pyzmq-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d416f2088ac8f12daacffbc2e8918ef4d6be8568e9d7155c83b7cebed49d2322"}, + {file = "pyzmq-26.1.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:ecb6c88d7946166d783a635efc89f9a1ff11c33d680a20df9657b6902a1d133b"}, + {file = "pyzmq-26.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:471312a7375571857a089342beccc1a63584315188560c7c0da7e0a23afd8a5c"}, + {file = "pyzmq-26.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e6cea102ffa16b737d11932c426f1dc14b5938cf7bc12e17269559c458ac334"}, + {file = "pyzmq-26.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec7248673ffc7104b54e4957cee38b2f3075a13442348c8d651777bf41aa45ee"}, + {file = "pyzmq-26.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:0614aed6f87d550b5cecb03d795f4ddbb1544b78d02a4bd5eecf644ec98a39f6"}, + {file = "pyzmq-26.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:e8746ce968be22a8a1801bf4a23e565f9687088580c3ed07af5846580dd97f76"}, + {file = "pyzmq-26.1.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:7688653574392d2eaeef75ddcd0b2de5b232d8730af29af56c5adf1df9ef8d6f"}, + {file = "pyzmq-26.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:8d4dac7d97f15c653a5fedcafa82626bd6cee1450ccdaf84ffed7ea14f2b07a4"}, + {file = "pyzmq-26.1.0-cp313-cp313-win32.whl", hash = "sha256:ccb42ca0a4a46232d716779421bbebbcad23c08d37c980f02cc3a6bd115ad277"}, + {file = "pyzmq-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e1e5d0a25aea8b691a00d6b54b28ac514c8cc0d8646d05f7ca6cb64b97358250"}, + {file = "pyzmq-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:fc82269d24860cfa859b676d18850cbb8e312dcd7eada09e7d5b007e2f3d9eb1"}, + {file = "pyzmq-26.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:416ac51cabd54f587995c2b05421324700b22e98d3d0aa2cfaec985524d16f1d"}, + {file = "pyzmq-26.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:ff832cce719edd11266ca32bc74a626b814fff236824aa1aeaad399b69fe6eae"}, + {file = "pyzmq-26.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:393daac1bcf81b2a23e696b7b638eedc965e9e3d2112961a072b6cd8179ad2eb"}, + {file = "pyzmq-26.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9869fa984c8670c8ab899a719eb7b516860a29bc26300a84d24d8c1b71eae3ec"}, + {file = "pyzmq-26.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b3b8e36fd4c32c0825b4461372949ecd1585d326802b1321f8b6dc1d7e9318c"}, + {file = "pyzmq-26.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:3ee647d84b83509b7271457bb428cc347037f437ead4b0b6e43b5eba35fec0aa"}, + {file = "pyzmq-26.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:45cb1a70eb00405ce3893041099655265fabcd9c4e1e50c330026e82257892c1"}, + {file = "pyzmq-26.1.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:5cca7b4adb86d7470e0fc96037771981d740f0b4cb99776d5cb59cd0e6684a73"}, + {file = "pyzmq-26.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:91d1a20bdaf3b25f3173ff44e54b1cfbc05f94c9e8133314eb2962a89e05d6e3"}, + {file = "pyzmq-26.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c0665d85535192098420428c779361b8823d3d7ec4848c6af3abb93bc5c915bf"}, + {file = "pyzmq-26.1.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:96d7c1d35ee4a495df56c50c83df7af1c9688cce2e9e0edffdbf50889c167595"}, + {file = "pyzmq-26.1.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b281b5ff5fcc9dcbfe941ac5c7fcd4b6c065adad12d850f95c9d6f23c2652384"}, + {file = "pyzmq-26.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5384c527a9a004445c5074f1e20db83086c8ff1682a626676229aafd9cf9f7d1"}, + {file = "pyzmq-26.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:754c99a9840839375ee251b38ac5964c0f369306eddb56804a073b6efdc0cd88"}, + {file = "pyzmq-26.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9bdfcb74b469b592972ed881bad57d22e2c0acc89f5e8c146782d0d90fb9f4bf"}, + {file = "pyzmq-26.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bd13f0231f4788db619347b971ca5f319c5b7ebee151afc7c14632068c6261d3"}, + {file = "pyzmq-26.1.0-cp37-cp37m-win32.whl", hash = "sha256:c5668dac86a869349828db5fc928ee3f58d450dce2c85607067d581f745e4fb1"}, + {file = "pyzmq-26.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad875277844cfaeca7fe299ddf8c8d8bfe271c3dc1caf14d454faa5cdbf2fa7a"}, + {file = "pyzmq-26.1.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:65c6e03cc0222eaf6aad57ff4ecc0a070451e23232bb48db4322cc45602cede0"}, + {file = "pyzmq-26.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:038ae4ffb63e3991f386e7fda85a9baab7d6617fe85b74a8f9cab190d73adb2b"}, + {file = "pyzmq-26.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bdeb2c61611293f64ac1073f4bf6723b67d291905308a7de9bb2ca87464e3273"}, + {file = "pyzmq-26.1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:61dfa5ee9d7df297c859ac82b1226d8fefaf9c5113dc25c2c00ecad6feeeb04f"}, + {file = "pyzmq-26.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3292d384537b9918010769b82ab3e79fca8b23d74f56fc69a679106a3e2c2cf"}, + {file = "pyzmq-26.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f9499c70c19ff0fbe1007043acb5ad15c1dec7d8e84ab429bca8c87138e8f85c"}, + {file = "pyzmq-26.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d3dd5523ed258ad58fed7e364c92a9360d1af8a9371e0822bd0146bdf017ef4c"}, + {file = "pyzmq-26.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baba2fd199b098c5544ef2536b2499d2e2155392973ad32687024bd8572a7d1c"}, + {file = "pyzmq-26.1.0-cp38-cp38-win32.whl", hash = "sha256:ddbb2b386128d8eca92bd9ca74e80f73fe263bcca7aa419f5b4cbc1661e19741"}, + {file = "pyzmq-26.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:79e45a4096ec8388cdeb04a9fa5e9371583bcb826964d55b8b66cbffe7b33c86"}, + {file = "pyzmq-26.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:add52c78a12196bc0fda2de087ba6c876ea677cbda2e3eba63546b26e8bf177b"}, + {file = "pyzmq-26.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c03bd7f3339ff47de7ea9ac94a2b34580a8d4df69b50128bb6669e1191a895"}, + {file = "pyzmq-26.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dcc37d9d708784726fafc9c5e1232de655a009dbf97946f117aefa38d5985a0f"}, + {file = "pyzmq-26.1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a6ed52f0b9bf8dcc64cc82cce0607a3dfed1dbb7e8c6f282adfccc7be9781de"}, + {file = "pyzmq-26.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451e16ae8bea3d95649317b463c9f95cd9022641ec884e3d63fc67841ae86dfe"}, + {file = "pyzmq-26.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:906e532c814e1d579138177a00ae835cd6becbf104d45ed9093a3aaf658f6a6a"}, + {file = "pyzmq-26.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05bacc4f94af468cc82808ae3293390278d5f3375bb20fef21e2034bb9a505b6"}, + {file = "pyzmq-26.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:57bb2acba798dc3740e913ffadd56b1fcef96f111e66f09e2a8db3050f1f12c8"}, + {file = "pyzmq-26.1.0-cp39-cp39-win32.whl", hash = "sha256:f774841bb0e8588505002962c02da420bcfb4c5056e87a139c6e45e745c0e2e2"}, + {file = "pyzmq-26.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:359c533bedc62c56415a1f5fcfd8279bc93453afdb0803307375ecf81c962402"}, + {file = "pyzmq-26.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:7907419d150b19962138ecec81a17d4892ea440c184949dc29b358bc730caf69"}, + {file = "pyzmq-26.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b24079a14c9596846bf7516fe75d1e2188d4a528364494859106a33d8b48be38"}, + {file = "pyzmq-26.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59d0acd2976e1064f1b398a00e2c3e77ed0a157529779e23087d4c2fb8aaa416"}, + {file = "pyzmq-26.1.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:911c43a4117915203c4cc8755e0f888e16c4676a82f61caee2f21b0c00e5b894"}, + {file = "pyzmq-26.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10163e586cc609f5f85c9b233195554d77b1e9a0801388907441aaeb22841c5"}, + {file = "pyzmq-26.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:28a8b2abb76042f5fd7bd720f7fea48c0fd3e82e9de0a1bf2c0de3812ce44a42"}, + {file = "pyzmq-26.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bef24d3e4ae2c985034439f449e3f9e06bf579974ce0e53d8a507a1577d5b2ab"}, + {file = "pyzmq-26.1.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2cd0f4d314f4a2518e8970b6f299ae18cff7c44d4a1fc06fc713f791c3a9e3ea"}, + {file = "pyzmq-26.1.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fa25a620eed2a419acc2cf10135b995f8f0ce78ad00534d729aa761e4adcef8a"}, + {file = "pyzmq-26.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef3b048822dca6d231d8a8ba21069844ae38f5d83889b9b690bf17d2acc7d099"}, + {file = "pyzmq-26.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:9a6847c92d9851b59b9f33f968c68e9e441f9a0f8fc972c5580c5cd7cbc6ee24"}, + {file = "pyzmq-26.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9b9305004d7e4e6a824f4f19b6d8f32b3578aad6f19fc1122aaf320cbe3dc83"}, + {file = "pyzmq-26.1.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:63c1d3a65acb2f9c92dce03c4e1758cc552f1ae5c78d79a44e3bb88d2fa71f3a"}, + {file = "pyzmq-26.1.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d36b8fffe8b248a1b961c86fbdfa0129dfce878731d169ede7fa2631447331be"}, + {file = "pyzmq-26.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67976d12ebfd61a3bc7d77b71a9589b4d61d0422282596cf58c62c3866916544"}, + {file = "pyzmq-26.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:998444debc8816b5d8d15f966e42751032d0f4c55300c48cc337f2b3e4f17d03"}, + {file = "pyzmq-26.1.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e5c88b2f13bcf55fee78ea83567b9fe079ba1a4bef8b35c376043440040f7edb"}, + {file = "pyzmq-26.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d906d43e1592be4b25a587b7d96527cb67277542a5611e8ea9e996182fae410"}, + {file = "pyzmq-26.1.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80b0c9942430d731c786545da6be96d824a41a51742e3e374fedd9018ea43106"}, + {file = "pyzmq-26.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:314d11564c00b77f6224d12eb3ddebe926c301e86b648a1835c5b28176c83eab"}, + {file = "pyzmq-26.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:093a1a3cae2496233f14b57f4b485da01b4ff764582c854c0f42c6dd2be37f3d"}, + {file = "pyzmq-26.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3c397b1b450f749a7e974d74c06d69bd22dd362142f370ef2bd32a684d6b480c"}, + {file = "pyzmq-26.1.0.tar.gz", hash = "sha256:6c5aeea71f018ebd3b9115c7cb13863dd850e98ca6b9258509de1246461a7e7f"}, ] [package.dependencies] @@ -5731,90 +5764,90 @@ rpds-py = ">=0.7.0" [[package]] name = "regex" -version = "2024.5.15" +version = "2024.7.24" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" files = [ - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, - {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, - {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, - {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, - {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, - {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, - {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, - {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, - {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, - {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, - {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, - {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, + {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"}, + {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"}, + {file = "regex-2024.7.24-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5"}, + {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce"}, + {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa"}, + {file = "regex-2024.7.24-cp310-cp310-win32.whl", hash = "sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66"}, + {file = "regex-2024.7.24-cp310-cp310-win_amd64.whl", hash = "sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e"}, + {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281"}, + {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b"}, + {file = "regex-2024.7.24-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51"}, + {file = "regex-2024.7.24-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1"}, + {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e"}, + {file = "regex-2024.7.24-cp311-cp311-win32.whl", hash = "sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c"}, + {file = "regex-2024.7.24-cp311-cp311-win_amd64.whl", hash = "sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52"}, + {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"}, + {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"}, + {file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"}, + {file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"}, + {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"}, + {file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"}, + {file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"}, + {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0"}, + {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b"}, + {file = "regex-2024.7.24-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b"}, + {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169"}, + {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8"}, + {file = "regex-2024.7.24-cp38-cp38-win32.whl", hash = "sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96"}, + {file = "regex-2024.7.24-cp38-cp38-win_amd64.whl", hash = "sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5"}, + {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24"}, + {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d"}, + {file = "regex-2024.7.24-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be"}, + {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759"}, + {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9"}, + {file = "regex-2024.7.24-cp39-cp39-win32.whl", hash = "sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1"}, + {file = "regex-2024.7.24-cp39-cp39-win_amd64.whl", hash = "sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9"}, + {file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"}, ] [[package]] @@ -5840,13 +5873,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requirements-parser" -version = "0.10.0" +version = "0.10.2" description = "This is a small Python module for parsing Pip requirement files." optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "requirements_parser-0.10.0-py3-none-any.whl", hash = "sha256:3c165f679f2c69fc8b4910a8cd86cea1f2c125d8624eb272e90db86dfddff064"}, - {file = "requirements_parser-0.10.0.tar.gz", hash = "sha256:8eebcb5abc2ec300b5d4ff7777354564cab495af524336438d72688672d49dc6"}, + {file = "requirements_parser-0.10.2-py3-none-any.whl", hash = "sha256:c55ad80ed7c441fabaaad563931dc4538027989b81be698780a43f1c9fa1c2b2"}, + {file = "requirements_parser-0.10.2.tar.gz", hash = "sha256:ce58a31dd0405413a6e1233bda5ea2667a7ec838679f65055eca75bc5ddb8e70"}, ] [package.dependencies] @@ -5912,110 +5945,114 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.19.0" +version = "0.19.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.19.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:fb37bd599f031f1a6fb9e58ec62864ccf3ad549cf14bac527dbfa97123edcca4"}, - {file = "rpds_py-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3384d278df99ec2c6acf701d067147320b864ef6727405d6470838476e44d9e8"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54548e0be3ac117595408fd4ca0ac9278fde89829b0b518be92863b17ff67a2"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8eb488ef928cdbc05a27245e52de73c0d7c72a34240ef4d9893fdf65a8c1a955"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5da93debdfe27b2bfc69eefb592e1831d957b9535e0943a0ee8b97996de21b5"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79e205c70afddd41f6ee79a8656aec738492a550247a7af697d5bd1aee14f766"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959179efb3e4a27610e8d54d667c02a9feaa86bbabaf63efa7faa4dfa780d4f1"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a6e605bb9edcf010f54f8b6a590dd23a4b40a8cb141255eec2a03db249bc915b"}, - {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9133d75dc119a61d1a0ded38fb9ba40a00ef41697cc07adb6ae098c875195a3f"}, - {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd36b712d35e757e28bf2f40a71e8f8a2d43c8b026d881aa0c617b450d6865c9"}, - {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354f3a91718489912f2e0fc331c24eaaf6a4565c080e00fbedb6015857c00582"}, - {file = "rpds_py-0.19.0-cp310-none-win32.whl", hash = "sha256:ebcbf356bf5c51afc3290e491d3722b26aaf5b6af3c1c7f6a1b757828a46e336"}, - {file = "rpds_py-0.19.0-cp310-none-win_amd64.whl", hash = "sha256:75a6076289b2df6c8ecb9d13ff79ae0cad1d5fb40af377a5021016d58cd691ec"}, - {file = "rpds_py-0.19.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6d45080095e585f8c5097897313def60caa2046da202cdb17a01f147fb263b81"}, - {file = "rpds_py-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5c9581019c96f865483d031691a5ff1cc455feb4d84fc6920a5ffc48a794d8a"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1540d807364c84516417115c38f0119dfec5ea5c0dd9a25332dea60b1d26fc4d"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e65489222b410f79711dc3d2d5003d2757e30874096b2008d50329ea4d0f88c"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da6f400eeb8c36f72ef6646ea530d6d175a4f77ff2ed8dfd6352842274c1d8b"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f46bb11858717e0efa7893c0f7055c43b44c103e40e69442db5061cb26ed34"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071d4adc734de562bd11d43bd134330fb6249769b2f66b9310dab7460f4bf714"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9625367c8955e4319049113ea4f8fee0c6c1145192d57946c6ffcd8fe8bf48dd"}, - {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e19509145275d46bc4d1e16af0b57a12d227c8253655a46bbd5ec317e941279d"}, - {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d438e4c020d8c39961deaf58f6913b1bf8832d9b6f62ec35bd93e97807e9cbc"}, - {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90bf55d9d139e5d127193170f38c584ed3c79e16638890d2e36f23aa1630b952"}, - {file = "rpds_py-0.19.0-cp311-none-win32.whl", hash = "sha256:8d6ad132b1bc13d05ffe5b85e7a01a3998bf3a6302ba594b28d61b8c2cf13aaf"}, - {file = "rpds_py-0.19.0-cp311-none-win_amd64.whl", hash = "sha256:7ec72df7354e6b7f6eb2a17fa6901350018c3a9ad78e48d7b2b54d0412539a67"}, - {file = "rpds_py-0.19.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5095a7c838a8647c32aa37c3a460d2c48debff7fc26e1136aee60100a8cd8f68"}, - {file = "rpds_py-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f2f78ef14077e08856e788fa482107aa602636c16c25bdf59c22ea525a785e9"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7cc6cb44f8636fbf4a934ca72f3e786ba3c9f9ba4f4d74611e7da80684e48d2"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf902878b4af334a09de7a45badbff0389e7cf8dc2e4dcf5f07125d0b7c2656d"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:688aa6b8aa724db1596514751ffb767766e02e5c4a87486ab36b8e1ebc1aedac"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57dbc9167d48e355e2569346b5aa4077f29bf86389c924df25c0a8b9124461fb"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4cf5a9497874822341c2ebe0d5850fed392034caadc0bad134ab6822c0925b"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a790d235b9d39c70a466200d506bb33a98e2ee374a9b4eec7a8ac64c2c261fa"}, - {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d16089dfa58719c98a1c06f2daceba6d8e3fb9b5d7931af4a990a3c486241cb"}, - {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bc9128e74fe94650367fe23f37074f121b9f796cabbd2f928f13e9661837296d"}, - {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8f77e661ffd96ff104bebf7d0f3255b02aa5d5b28326f5408d6284c4a8b3248"}, - {file = "rpds_py-0.19.0-cp312-none-win32.whl", hash = "sha256:5f83689a38e76969327e9b682be5521d87a0c9e5a2e187d2bc6be4765f0d4600"}, - {file = "rpds_py-0.19.0-cp312-none-win_amd64.whl", hash = "sha256:06925c50f86da0596b9c3c64c3837b2481337b83ef3519e5db2701df695453a4"}, - {file = "rpds_py-0.19.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:52e466bea6f8f3a44b1234570244b1cff45150f59a4acae3fcc5fd700c2993ca"}, - {file = "rpds_py-0.19.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e21cc693045fda7f745c790cb687958161ce172ffe3c5719ca1764e752237d16"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b31f059878eb1f5da8b2fd82480cc18bed8dcd7fb8fe68370e2e6285fa86da6"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dd46f309e953927dd018567d6a9e2fb84783963650171f6c5fe7e5c41fd5666"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a01a4490e170376cd79258b7f755fa13b1a6c3667e872c8e35051ae857a92b"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcf426a8c38eb57f7bf28932e68425ba86def6e756a5b8cb4731d8e62e4e0223"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68eea5df6347d3f1378ce992d86b2af16ad7ff4dcb4a19ccdc23dea901b87fb"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dab8d921b55a28287733263c0e4c7db11b3ee22aee158a4de09f13c93283c62d"}, - {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6fe87efd7f47266dfc42fe76dae89060038f1d9cb911f89ae7e5084148d1cc08"}, - {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:535d4b52524a961d220875688159277f0e9eeeda0ac45e766092bfb54437543f"}, - {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8b1a94b8afc154fbe36978a511a1f155f9bd97664e4f1f7a374d72e180ceb0ae"}, - {file = "rpds_py-0.19.0-cp38-none-win32.whl", hash = "sha256:7c98298a15d6b90c8f6e3caa6457f4f022423caa5fa1a1ca7a5e9e512bdb77a4"}, - {file = "rpds_py-0.19.0-cp38-none-win_amd64.whl", hash = "sha256:b0da31853ab6e58a11db3205729133ce0df26e6804e93079dee095be3d681dc1"}, - {file = "rpds_py-0.19.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5039e3cef7b3e7a060de468a4a60a60a1f31786da94c6cb054e7a3c75906111c"}, - {file = "rpds_py-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab1932ca6cb8c7499a4d87cb21ccc0d3326f172cfb6a64021a889b591bb3045c"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2afd2164a1e85226fcb6a1da77a5c8896c18bfe08e82e8ceced5181c42d2179"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1c30841f5040de47a0046c243fc1b44ddc87d1b12435a43b8edff7e7cb1e0d0"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f757f359f30ec7dcebca662a6bd46d1098f8b9fb1fcd661a9e13f2e8ce343ba1"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15e65395a59d2e0e96caf8ee5389ffb4604e980479c32742936ddd7ade914b22"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb0f6eb3a320f24b94d177e62f4074ff438f2ad9d27e75a46221904ef21a7b05"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b228e693a2559888790936e20f5f88b6e9f8162c681830eda303bad7517b4d5a"}, - {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2575efaa5d949c9f4e2cdbe7d805d02122c16065bfb8d95c129372d65a291a0b"}, - {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5c872814b77a4e84afa293a1bee08c14daed1068b2bb1cc312edbf020bbbca2b"}, - {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850720e1b383df199b8433a20e02b25b72f0fded28bc03c5bd79e2ce7ef050be"}, - {file = "rpds_py-0.19.0-cp39-none-win32.whl", hash = "sha256:ce84a7efa5af9f54c0aa7692c45861c1667080814286cacb9958c07fc50294fb"}, - {file = "rpds_py-0.19.0-cp39-none-win_amd64.whl", hash = "sha256:1c26da90b8d06227d7769f34915913911222d24ce08c0ab2d60b354e2d9c7aff"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:75969cf900d7be665ccb1622a9aba225cf386bbc9c3bcfeeab9f62b5048f4a07"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8445f23f13339da640d1be8e44e5baf4af97e396882ebbf1692aecd67f67c479"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5a7c1062ef8aea3eda149f08120f10795835fc1c8bc6ad948fb9652a113ca55"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:462b0c18fbb48fdbf980914a02ee38c423a25fcc4cf40f66bacc95a2d2d73bc8"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3208f9aea18991ac7f2b39721e947bbd752a1abbe79ad90d9b6a84a74d44409b"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3444fe52b82f122d8a99bf66777aed6b858d392b12f4c317da19f8234db4533"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb4bac7185a9f0168d38c01d7a00addece9822a52870eee26b8d5b61409213"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b130bd4163c93798a6b9bb96be64a7c43e1cec81126ffa7ffaa106e1fc5cef5"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a707b158b4410aefb6b054715545bbb21aaa5d5d0080217290131c49c2124a6e"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dc9ac4659456bde7c567107556ab065801622396b435a3ff213daef27b495388"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81ea573aa46d3b6b3d890cd3c0ad82105985e6058a4baed03cf92518081eec8c"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f148c3f47f7f29a79c38cc5d020edcb5ca780020fab94dbc21f9af95c463581"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0906357f90784a66e89ae3eadc2654f36c580a7d65cf63e6a616e4aec3a81be"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f629ecc2db6a4736b5ba95a8347b0089240d69ad14ac364f557d52ad68cf94b0"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6feacd1d178c30e5bc37184526e56740342fd2aa6371a28367bad7908d454fc"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b6068ee374fdfab63689be0963333aa83b0815ead5d8648389a8ded593378"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d57546bad81e0da13263e4c9ce30e96dcbe720dbff5ada08d2600a3502e526"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b6683a37338818646af718c9ca2a07f89787551057fae57c4ec0446dc6224b"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8481b946792415adc07410420d6fc65a352b45d347b78fec45d8f8f0d7496f0"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bec35eb20792ea64c3c57891bc3ca0bedb2884fbac2c8249d9b731447ecde4fa"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:aa5476c3e3a402c37779e95f7b4048db2cb5b0ed0b9d006983965e93f40fe05a"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:19d02c45f2507b489fd4df7b827940f1420480b3e2e471e952af4d44a1ea8e34"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3e2fd14c5d49ee1da322672375963f19f32b3d5953f0615b175ff7b9d38daed"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:93a91c2640645303e874eada51f4f33351b84b351a689d470f8108d0e0694210"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b9fc03bf76a94065299d4a2ecd8dfbae4ae8e2e8098bbfa6ab6413ca267709"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a4b07cdf3f84310c08c1de2c12ddadbb7a77568bcb16e95489f9c81074322ed"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba0ed0dc6763d8bd6e5de5cf0d746d28e706a10b615ea382ac0ab17bb7388633"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:474bc83233abdcf2124ed3f66230a1c8435896046caa4b0b5ab6013c640803cc"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329c719d31362355a96b435f4653e3b4b061fcc9eba9f91dd40804ca637d914e"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef9101f3f7b59043a34f1dccbb385ca760467590951952d6701df0da9893ca0c"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0121803b0f424ee2109d6e1f27db45b166ebaa4b32ff47d6aa225642636cd834"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8344127403dea42f5970adccf6c5957a71a47f522171fafaf4c6ddb41b61703a"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:443cec402ddd650bb2b885113e1dcedb22b1175c6be223b14246a714b61cd521"}, - {file = "rpds_py-0.19.0.tar.gz", hash = "sha256:4fdc9afadbeb393b4bbbad75481e0ea78e4469f2e1d713a90811700830b553a9"}, + {file = "rpds_py-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:aaf71f95b21f9dc708123335df22e5a2fef6307e3e6f9ed773b2e0938cc4d491"}, + {file = "rpds_py-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca0dda0c5715efe2ab35bb83f813f681ebcd2840d8b1b92bfc6fe3ab382fae4a"}, + {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81db2e7282cc0487f500d4db203edc57da81acde9e35f061d69ed983228ffe3b"}, + {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1a8dfa125b60ec00c7c9baef945bb04abf8ac772d8ebefd79dae2a5f316d7850"}, + {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271accf41b02687cef26367c775ab220372ee0f4925591c6796e7c148c50cab5"}, + {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9bc4161bd3b970cd6a6fcda70583ad4afd10f2750609fb1f3ca9505050d4ef3"}, + {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0cf2a0dbb5987da4bd92a7ca727eadb225581dd9681365beba9accbe5308f7d"}, + {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b5e28e56143750808c1c79c70a16519e9bc0a68b623197b96292b21b62d6055c"}, + {file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c7af6f7b80f687b33a4cdb0a785a5d4de1fb027a44c9a049d8eb67d5bfe8a687"}, + {file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e429fc517a1c5e2a70d576077231538a98d59a45dfc552d1ac45a132844e6dfb"}, + {file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d2dbd8f4990d4788cb122f63bf000357533f34860d269c1a8e90ae362090ff3a"}, + {file = "rpds_py-0.19.1-cp310-none-win32.whl", hash = "sha256:e0f9d268b19e8f61bf42a1da48276bcd05f7ab5560311f541d22557f8227b866"}, + {file = "rpds_py-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:df7c841813f6265e636fe548a49664c77af31ddfa0085515326342a751a6ba51"}, + {file = "rpds_py-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:902cf4739458852fe917104365ec0efbea7d29a15e4276c96a8d33e6ed8ec137"}, + {file = "rpds_py-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f3d73022990ab0c8b172cce57c69fd9a89c24fd473a5e79cbce92df87e3d9c48"}, + {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3837c63dd6918a24de6c526277910e3766d8c2b1627c500b155f3eecad8fad65"}, + {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cdb7eb3cf3deb3dd9e7b8749323b5d970052711f9e1e9f36364163627f96da58"}, + {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26ab43b6d65d25b1a333c8d1b1c2f8399385ff683a35ab5e274ba7b8bb7dc61c"}, + {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75130df05aae7a7ac171b3b5b24714cffeabd054ad2ebc18870b3aa4526eba23"}, + {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34f751bf67cab69638564eee34023909380ba3e0d8ee7f6fe473079bf93f09b"}, + {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2671cb47e50a97f419a02cd1e0c339b31de017b033186358db92f4d8e2e17d8"}, + {file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c73254c256081704dba0a333457e2fb815364018788f9b501efe7c5e0ada401"}, + {file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4383beb4a29935b8fa28aca8fa84c956bf545cb0c46307b091b8d312a9150e6a"}, + {file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dbceedcf4a9329cc665452db1aaf0845b85c666e4885b92ee0cddb1dbf7e052a"}, + {file = "rpds_py-0.19.1-cp311-none-win32.whl", hash = "sha256:f0a6d4a93d2a05daec7cb885157c97bbb0be4da739d6f9dfb02e101eb40921cd"}, + {file = "rpds_py-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:c149a652aeac4902ecff2dd93c3b2681c608bd5208c793c4a99404b3e1afc87c"}, + {file = "rpds_py-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:56313be667a837ff1ea3508cebb1ef6681d418fa2913a0635386cf29cff35165"}, + {file = "rpds_py-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d1d7539043b2b31307f2c6c72957a97c839a88b2629a348ebabe5aa8b626d6b"}, + {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1dc59a5e7bc7f44bd0c048681f5e05356e479c50be4f2c1a7089103f1621d5"}, + {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8f78398e67a7227aefa95f876481485403eb974b29e9dc38b307bb6eb2315ea"}, + {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ef07a0a1d254eeb16455d839cef6e8c2ed127f47f014bbda64a58b5482b6c836"}, + {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8124101e92c56827bebef084ff106e8ea11c743256149a95b9fd860d3a4f331f"}, + {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08ce9c95a0b093b7aec75676b356a27879901488abc27e9d029273d280438505"}, + {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b02dd77a2de6e49078c8937aadabe933ceac04b41c5dde5eca13a69f3cf144e"}, + {file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4dd02e29c8cbed21a1875330b07246b71121a1c08e29f0ee3db5b4cfe16980c4"}, + {file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9c7042488165f7251dc7894cd533a875d2875af6d3b0e09eda9c4b334627ad1c"}, + {file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f809a17cc78bd331e137caa25262b507225854073fd319e987bd216bed911b7c"}, + {file = "rpds_py-0.19.1-cp312-none-win32.whl", hash = "sha256:3ddab996807c6b4227967fe1587febade4e48ac47bb0e2d3e7858bc621b1cace"}, + {file = "rpds_py-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:32e0db3d6e4f45601b58e4ac75c6f24afbf99818c647cc2066f3e4b192dabb1f"}, + {file = "rpds_py-0.19.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:747251e428406b05fc86fee3904ee19550c4d2d19258cef274e2151f31ae9d38"}, + {file = "rpds_py-0.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dc733d35f861f8d78abfaf54035461e10423422999b360966bf1c443cbc42705"}, + {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbda75f245caecff8faa7e32ee94dfaa8312a3367397975527f29654cd17a6ed"}, + {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd04d8cab16cab5b0a9ffc7d10f0779cf1120ab16c3925404428f74a0a43205a"}, + {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2d66eb41ffca6cc3c91d8387509d27ba73ad28371ef90255c50cb51f8953301"}, + {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdf4890cda3b59170009d012fca3294c00140e7f2abe1910e6a730809d0f3f9b"}, + {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1fa67ef839bad3815124f5f57e48cd50ff392f4911a9f3cf449d66fa3df62a5"}, + {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b82c9514c6d74b89a370c4060bdb80d2299bc6857e462e4a215b4ef7aa7b090e"}, + {file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c7b07959866a6afb019abb9564d8a55046feb7a84506c74a6f197cbcdf8a208e"}, + {file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4f580ae79d0b861dfd912494ab9d477bea535bfb4756a2269130b6607a21802e"}, + {file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c6d20c8896c00775e6f62d8373aba32956aa0b850d02b5ec493f486c88e12859"}, + {file = "rpds_py-0.19.1-cp313-none-win32.whl", hash = "sha256:afedc35fe4b9e30ab240b208bb9dc8938cb4afe9187589e8d8d085e1aacb8309"}, + {file = "rpds_py-0.19.1-cp313-none-win_amd64.whl", hash = "sha256:1d4af2eb520d759f48f1073ad3caef997d1bfd910dc34e41261a595d3f038a94"}, + {file = "rpds_py-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:34bca66e2e3eabc8a19e9afe0d3e77789733c702c7c43cd008e953d5d1463fde"}, + {file = "rpds_py-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:24f8ae92c7fae7c28d0fae9b52829235df83f34847aa8160a47eb229d9666c7b"}, + {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71157f9db7f6bc6599a852852f3389343bea34315b4e6f109e5cbc97c1fb2963"}, + {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d494887d40dc4dd0d5a71e9d07324e5c09c4383d93942d391727e7a40ff810b"}, + {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3661e6d4ba63a094138032c1356d557de5b3ea6fd3cca62a195f623e381c76"}, + {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97fbb77eaeb97591efdc654b8b5f3ccc066406ccfb3175b41382f221ecc216e8"}, + {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cc4bc73e53af8e7a42c8fd7923bbe35babacfa7394ae9240b3430b5dcf16b2a"}, + {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:35af5e4d5448fa179fd7fff0bba0fba51f876cd55212f96c8bbcecc5c684ae5c"}, + {file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3511f6baf8438326e351097cecd137eb45c5f019944fe0fd0ae2fea2fd26be39"}, + {file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:57863d16187995c10fe9cf911b897ed443ac68189179541734502353af33e693"}, + {file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9e318e6786b1e750a62f90c6f7fa8b542102bdcf97c7c4de2a48b50b61bd36ec"}, + {file = "rpds_py-0.19.1-cp38-none-win32.whl", hash = "sha256:53dbc35808c6faa2ce3e48571f8f74ef70802218554884787b86a30947842a14"}, + {file = "rpds_py-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:8df1c283e57c9cb4d271fdc1875f4a58a143a2d1698eb0d6b7c0d7d5f49c53a1"}, + {file = "rpds_py-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e76c902d229a3aa9d5ceb813e1cbcc69bf5bda44c80d574ff1ac1fa3136dea71"}, + {file = "rpds_py-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de1f7cd5b6b351e1afd7568bdab94934d656abe273d66cda0ceea43bbc02a0c2"}, + {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fc5a84777cb61692d17988989690d6f34f7f95968ac81398d67c0d0994a897"}, + {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74129d5ffc4cde992d89d345f7f7d6758320e5d44a369d74d83493429dad2de5"}, + {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e360188b72f8080fefa3adfdcf3618604cc8173651c9754f189fece068d2a45"}, + {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13e6d4840897d4e4e6b2aa1443e3a8eca92b0402182aafc5f4ca1f5e24f9270a"}, + {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f09529d2332264a902688031a83c19de8fda5eb5881e44233286b9c9ec91856d"}, + {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d4b52811dcbc1aba08fd88d475f75b4f6db0984ba12275d9bed1a04b2cae9b5"}, + {file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd635c2c4043222d80d80ca1ac4530a633102a9f2ad12252183bcf338c1b9474"}, + {file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f35b34a5184d5e0cc360b61664c1c06e866aab077b5a7c538a3e20c8fcdbf90b"}, + {file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d4ec0046facab83012d821b33cead742a35b54575c4edfb7ed7445f63441835f"}, + {file = "rpds_py-0.19.1-cp39-none-win32.whl", hash = "sha256:f5b8353ea1a4d7dfb59a7f45c04df66ecfd363bb5b35f33b11ea579111d4655f"}, + {file = "rpds_py-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:1fb93d3486f793d54a094e2bfd9cd97031f63fcb5bc18faeb3dd4b49a1c06523"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7d5c7e32f3ee42f77d8ff1a10384b5cdcc2d37035e2e3320ded909aa192d32c3"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:89cc8921a4a5028d6dd388c399fcd2eef232e7040345af3d5b16c04b91cf3c7e"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca34e913d27401bda2a6f390d0614049f5a95b3b11cd8eff80fe4ec340a1208"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5953391af1405f968eb5701ebbb577ebc5ced8d0041406f9052638bafe52209d"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:840e18c38098221ea6201f091fc5d4de6128961d2930fbbc96806fb43f69aec1"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d8b735c4d162dc7d86a9cf3d717f14b6c73637a1f9cd57fe7e61002d9cb1972"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce757c7c90d35719b38fa3d4ca55654a76a40716ee299b0865f2de21c146801c"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9421b23c85f361a133aa7c5e8ec757668f70343f4ed8fdb5a4a14abd5437244"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3b823be829407393d84ee56dc849dbe3b31b6a326f388e171555b262e8456cc1"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:5e58b61dcbb483a442c6239c3836696b79f2cd8e7eec11e12155d3f6f2d886d1"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39d67896f7235b2c886fb1ee77b1491b77049dcef6fbf0f401e7b4cbed86bbd4"}, + {file = "rpds_py-0.19.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8b32cd4ab6db50c875001ba4f5a6b30c0f42151aa1fbf9c2e7e3674893fb1dc4"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c32e41de995f39b6b315d66c27dea3ef7f7c937c06caab4c6a79a5e09e2c415"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a129c02b42d46758c87faeea21a9f574e1c858b9f358b6dd0bbd71d17713175"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:346557f5b1d8fd9966059b7a748fd79ac59f5752cd0e9498d6a40e3ac1c1875f"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31e450840f2f27699d014cfc8865cc747184286b26d945bcea6042bb6aa4d26e"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01227f8b3e6c8961490d869aa65c99653df80d2f0a7fde8c64ebddab2b9b02fd"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69084fd29bfeff14816666c93a466e85414fe6b7d236cfc108a9c11afa6f7301"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d2b88efe65544a7d5121b0c3b003ebba92bfede2ea3577ce548b69c5235185"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ea961a674172ed2235d990d7edf85d15d8dfa23ab8575e48306371c070cda67"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:5beffdbe766cfe4fb04f30644d822a1080b5359df7db3a63d30fa928375b2720"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:720f3108fb1bfa32e51db58b832898372eb5891e8472a8093008010911e324c5"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c2087dbb76a87ec2c619253e021e4fb20d1a72580feeaa6892b0b3d955175a71"}, + {file = "rpds_py-0.19.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ddd50f18ebc05ec29a0d9271e9dbe93997536da3546677f8ca00b76d477680c"}, + {file = "rpds_py-0.19.1.tar.gz", hash = "sha256:31dd5794837f00b46f4096aa8ccaa5972f73a938982e32ed817bb520c465e520"}, ] [[package]] @@ -6299,13 +6336,13 @@ win32 = ["pywin32"] [[package]] name = "sentry-sdk" -version = "2.10.0" +version = "2.12.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.10.0-py2.py3-none-any.whl", hash = "sha256:87b3d413c87d8e7f816cc9334bff255a83d8b577db2b22042651c30c19c09190"}, - {file = "sentry_sdk-2.10.0.tar.gz", hash = "sha256:545fcc6e36c335faa6d6cda84669b6e17025f31efbf3b2211ec14efe008b75d1"}, + {file = "sentry_sdk-2.12.0-py2.py3-none-any.whl", hash = "sha256:7a8d5163d2ba5c5f4464628c6b68f85e86972f7c636acc78aed45c61b98b7a5e"}, + {file = "sentry_sdk-2.12.0.tar.gz", hash = "sha256:8763840497b817d44c49b3fe3f5f7388d083f2337ffedf008b2cdb63b5c86dc6"}, ] [package.dependencies] @@ -6336,7 +6373,7 @@ langchain = ["langchain (>=0.0.210)"] loguru = ["loguru (>=0.5)"] openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] opentelemetry = ["opentelemetry-distro (>=0.35b0)"] -opentelemetry-experimental = ["opentelemetry-instrumentation-aio-pika (==0.46b0)", "opentelemetry-instrumentation-aiohttp-client (==0.46b0)", "opentelemetry-instrumentation-aiopg (==0.46b0)", "opentelemetry-instrumentation-asgi (==0.46b0)", "opentelemetry-instrumentation-asyncio (==0.46b0)", "opentelemetry-instrumentation-asyncpg (==0.46b0)", "opentelemetry-instrumentation-aws-lambda (==0.46b0)", "opentelemetry-instrumentation-boto (==0.46b0)", "opentelemetry-instrumentation-boto3sqs (==0.46b0)", "opentelemetry-instrumentation-botocore (==0.46b0)", "opentelemetry-instrumentation-cassandra (==0.46b0)", "opentelemetry-instrumentation-celery (==0.46b0)", "opentelemetry-instrumentation-confluent-kafka (==0.46b0)", "opentelemetry-instrumentation-dbapi (==0.46b0)", "opentelemetry-instrumentation-django (==0.46b0)", "opentelemetry-instrumentation-elasticsearch (==0.46b0)", "opentelemetry-instrumentation-falcon (==0.46b0)", "opentelemetry-instrumentation-fastapi (==0.46b0)", "opentelemetry-instrumentation-flask (==0.46b0)", "opentelemetry-instrumentation-grpc (==0.46b0)", "opentelemetry-instrumentation-httpx (==0.46b0)", "opentelemetry-instrumentation-jinja2 (==0.46b0)", "opentelemetry-instrumentation-kafka-python (==0.46b0)", "opentelemetry-instrumentation-logging (==0.46b0)", "opentelemetry-instrumentation-mysql (==0.46b0)", "opentelemetry-instrumentation-mysqlclient (==0.46b0)", "opentelemetry-instrumentation-pika (==0.46b0)", "opentelemetry-instrumentation-psycopg (==0.46b0)", "opentelemetry-instrumentation-psycopg2 (==0.46b0)", "opentelemetry-instrumentation-pymemcache (==0.46b0)", "opentelemetry-instrumentation-pymongo (==0.46b0)", "opentelemetry-instrumentation-pymysql (==0.46b0)", "opentelemetry-instrumentation-pyramid (==0.46b0)", "opentelemetry-instrumentation-redis (==0.46b0)", "opentelemetry-instrumentation-remoulade (==0.46b0)", "opentelemetry-instrumentation-requests (==0.46b0)", "opentelemetry-instrumentation-sklearn (==0.46b0)", "opentelemetry-instrumentation-sqlalchemy (==0.46b0)", "opentelemetry-instrumentation-sqlite3 (==0.46b0)", "opentelemetry-instrumentation-starlette (==0.46b0)", "opentelemetry-instrumentation-system-metrics (==0.46b0)", "opentelemetry-instrumentation-threading (==0.46b0)", "opentelemetry-instrumentation-tornado (==0.46b0)", "opentelemetry-instrumentation-tortoiseorm (==0.46b0)", "opentelemetry-instrumentation-urllib (==0.46b0)", "opentelemetry-instrumentation-urllib3 (==0.46b0)", "opentelemetry-instrumentation-wsgi (==0.46b0)"] +opentelemetry-experimental = ["opentelemetry-distro"] pure-eval = ["asttokens", "executing", "pure-eval"] pymongo = ["pymongo (>=3.1)"] pyspark = ["pyspark (>=2.4.4)"] @@ -6350,13 +6387,13 @@ tornado = ["tornado (>=6)"] [[package]] name = "setuptools" -version = "71.1.0" +version = "72.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, - {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, + {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"}, + {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"}, ] [package.extras] @@ -6549,14 +6586,6 @@ files = [ {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:56628ca27aa17b5890391ded4e385bf0480209726f198799b7e980c6bd473bd7"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db726be58837fe5ac39859e0fa40baafe54c6d54c02aba1d47d25536170b690f"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7421c1bfdbb7214313919472307be650bd45c4dc2fcb317d64d078993de045b"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632784f7a6f12cfa0e84bf2a5003b07660addccf5563c132cd23b7cc1d7371a9"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f6f7276cf26145a888f2182a98f204541b519d9ea358a65d82095d9c9e22f917"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2a1f7ffac934bc0ea717fa1596f938483fb8c402233f9b26679b4f7b38d6ab6e"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-win32.whl", hash = "sha256:bfece2f7cec502ec5f759bbc09ce711445372deeac3628f6fa1c16b7fb45b682"}, - {file = "SQLAlchemy-2.0.21-cp312-cp312-win_amd64.whl", hash = "sha256:526b869a0f4f000d8d8ee3409d0becca30ae73f494cbb48801da0129601f72c6"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, @@ -7034,13 +7063,13 @@ files = [ [[package]] name = "tqdm" -version = "4.66.4" +version = "4.66.5" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, - {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, + {file = "tqdm-4.66.5-py3-none-any.whl", hash = "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd"}, + {file = "tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad"}, ] [package.dependencies] @@ -7165,13 +7194,13 @@ files = [ [[package]] name = "types-setuptools" -version = "71.1.0.20240723" +version = "71.1.0.20240726" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-71.1.0.20240723.tar.gz", hash = "sha256:8a9349038c7e22d88e6c5d9c6705b347b22930424114a452c1712899e85131ff"}, - {file = "types_setuptools-71.1.0.20240723-py3-none-any.whl", hash = "sha256:ac9fc263f59d1e02bca49cb7270a12c47ab80b3b911fb4d92f1fecf978bfe88a"}, + {file = "types-setuptools-71.1.0.20240726.tar.gz", hash = "sha256:85ba28e9461bb1be86ebba4db0f1c2408f2b11115b1966334ea9dc464e29303e"}, + {file = "types_setuptools-71.1.0.20240726-py3-none-any.whl", hash = "sha256:a7775376f36e0ff09bcad236bf265777590a66b11623e48c20bfc30f1444ea36"}, ] [[package]] @@ -7395,13 +7424,13 @@ test = ["websockets"] [[package]] name = "wheel" -version = "0.43.0" +version = "0.44.0" description = "A built-package format for Python" optional = false python-versions = ">=3.8" files = [ - {file = "wheel-0.43.0-py3-none-any.whl", hash = "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"}, - {file = "wheel-0.43.0.tar.gz", hash = "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85"}, + {file = "wheel-0.44.0-py3-none-any.whl", hash = "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f"}, + {file = "wheel-0.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"}, ] [package.extras] From 085ca5ece895eb8c7680a14df4f46de88021d4f8 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:05:00 +0200 Subject: [PATCH 16/44] Fixes to the users --- .../relational/sqlalchemy/SqlAlchemyAdapter.py | 8 ++++---- cognee/modules/users/methods/get_default_user.py | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index ae79805cf..7de1ca785 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -57,11 +57,11 @@ class SQLAlchemyAdapter(): result = connection.execute(text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) return [dict(row) for row in result] - def create_table(self, schema_name: str, table_name: str, table_config: list[dict]): + async def create_table(self, schema_name: str, table_name: str, table_config: list[dict]): fields_query_parts = [f"{item['name']} {item['type']}" for item in table_config] - with self.engine.connect() as connection: - connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema_name};")) - connection.execute(text(f"CREATE TABLE IF NOT EXISTS {schema_name}.{table_name} ({', '.join(fields_query_parts)});")) + async with self.engine.connect() as connection: + await connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema_name};")) + await connection.execute(text(f"CREATE TABLE IF NOT EXISTS {schema_name}.{table_name} ({', '.join(fields_query_parts)});")) def delete_table(self, table_name: str): with self.engine.connect() as connection: diff --git a/cognee/modules/users/methods/get_default_user.py b/cognee/modules/users/methods/get_default_user.py index 011c06ec4..5e0d3bcfe 100644 --- a/cognee/modules/users/methods/get_default_user.py +++ b/cognee/modules/users/methods/get_default_user.py @@ -1,8 +1,12 @@ from cognee.modules.users.models import User from cognee.infrastructure.databases.relational import get_relational_engine -async def get_default_user() -> User: - db_engine = get_relational_engine() +from sqlalchemy.future import select +async def get_default_user(): + db_engine = get_relational_engine() async with db_engine.get_async_session() as session: - return session.query(User).filter(User.email == "default_user@example.com").first() + stmt = select(User).where(User.email == "default_user@example.com") + result = await session.execute(stmt) + user = result.scalars().first() + return user \ No newline at end of file From 7d3e124e4f3149a2175d0004eae37ddc826cd372 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:31:52 +0200 Subject: [PATCH 17/44] Fixes to the sqlalchemy adapter --- cognee/api/v1/cognify/cognify.py | 2 +- cognee/api/v1/cognify/cognify_v2.py | 2 +- .../sqlalchemy/SqlAlchemyAdapter.py | 82 ++++++++++--------- .../modules/tasks/create_task_status_table.py | 10 +-- 4 files changed, 49 insertions(+), 47 deletions(-) diff --git a/cognee/api/v1/cognify/cognify.py b/cognee/api/v1/cognify/cognify.py index 77f19f1ec..e695be405 100644 --- a/cognee/api/v1/cognify/cognify.py +++ b/cognee/api/v1/cognify/cognify.py @@ -45,7 +45,7 @@ async def cognify(datasets: Union[str, List[str]] = None): # Has to be loaded in advance, multithreading doesn't work without it. nltk.download("stopwords", quiet=True) stopwords.ensure_loaded() - create_task_status_table() + await create_task_status_table() graph_client = await get_graph_engine() diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 6b2502c46..7c6139b3c 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -35,7 +35,7 @@ class PermissionDeniedException(Exception): async def cognify(datasets: Union[str, list[str]] = None, user: User = None): db_engine = get_relational_engine() - create_task_status_table() + await create_task_status_table() if datasets is None or len(datasets) == 0: return await cognify(await db_engine.get_datasets()) diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index 7de1ca785..5b5b1fcbe 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -43,39 +43,39 @@ class SQLAlchemyAdapter(): async def get_datasets(self): async with self.engine.connect() as connection: - result = await connection.execute(text("SELECT DISTINCT schema_name FROM information_schema.tables;")) - tables = [row["schema_name"] for row in result] + result = await connection.execute(text("SELECT DISTINCT table_schema FROM information_schema.tables;")) + tables = [row[0] for row in result] return list( filter( - lambda schema_name: not schema_name.endswith("staging") and schema_name != "cognee", + lambda table_schema: not table_schema.endswith("staging") and table_schema != "cognee", tables ) ) - def get_files_metadata(self, dataset_name: str): - with self.engine.connect() as connection: - result = connection.execute(text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) - return [dict(row) for row in result] - async def create_table(self, schema_name: str, table_name: str, table_config: list[dict]): fields_query_parts = [f"{item['name']} {item['type']}" for item in table_config] - async with self.engine.connect() as connection: + async with self.engine.begin() as connection: await connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema_name};")) await connection.execute(text(f"CREATE TABLE IF NOT EXISTS {schema_name}.{table_name} ({', '.join(fields_query_parts)});")) - def delete_table(self, table_name: str): - with self.engine.connect() as connection: - connection.execute(text(f"DROP TABLE IF EXISTS {table_name};")) + async def get_files_metadata(self, dataset_name: str): + async with self.engine.connect() as connection: + result = await connection.execute(text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) + return [dict(row) for row in result] - def insert_data(self, schema_name: str, table_name: str, data: list[dict]): + async def delete_table(self, table_name: str): + async with self.engine.connect() as connection: + await connection.execute(text(f"DROP TABLE IF EXISTS {table_name};")) + + async def insert_data(self, schema_name: str, table_name: str, data: list[dict]): columns = ", ".join(data[0].keys()) values = ", ".join([f"({', '.join([f':{key}' for key in row.keys()])})" for row in data]) insert_query = text(f"INSERT INTO {schema_name}.{table_name} ({columns}) VALUES {values};") - with self.engine.connect() as connection: - connection.execute(insert_query, data) + async with self.engine.connect() as connection: + await connection.execute(insert_query, data) - def get_data(self, table_name: str, filters: dict = None): - with self.engine.connect() as connection: + async def get_data(self, table_name: str, filters: dict = None): + async with self.engine.connect() as connection: query = f"SELECT * FROM {table_name}" if filters: filter_conditions = " AND ".join([ @@ -84,19 +84,19 @@ class SQLAlchemyAdapter(): ]) query += f" WHERE {filter_conditions};" query = text(query) - results = connection.execute(query, filters) + results = await connection.execute(query, filters) else: query += ";" query = text(query) - results = connection.execute(query) + results = await connection.execute(query) return {result["data_id"]: result["status"] for result in results} - def execute_query(self, query): - with self.engine.connect() as connection: - result = connection.execute(text(query)) + async def execute_query(self, query): + async with self.engine.connect() as connection: + result = await connection.execute(text(query)) return [dict(row) for row in result] - def load_cognify_data(self, data): + async def load_cognify_data(self, data): metadata = MetaData() cognify_table = Table( @@ -109,21 +109,22 @@ class SQLAlchemyAdapter(): Column("document_id_target", String, nullable=True) ) - metadata.create_all(self.engine) + async with self.engine.begin() as connection: + await connection.run_sync(metadata.create_all) insert_query = cognify_table.insert().values(document_id=text(":document_id")) - with self.engine.connect() as connection: - connection.execute(insert_query, data) + async with self.engine.connect() as connection: + await connection.execute(insert_query, data) - def fetch_cognify_data(self, excluded_document_id: str): - with self.engine.connect() as connection: - connection.execute(text(""" + async def fetch_cognify_data(self, excluded_document_id: str): + async with self.engine.connect() as connection: + await connection.execute(text(""" CREATE TABLE IF NOT EXISTS cognify ( - document_id STRING, + document_id VARCHAR, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, - document_id_target STRING NULL + document_id_target VARCHAR NULL ); """)) query = text(""" @@ -131,27 +132,28 @@ class SQLAlchemyAdapter(): FROM cognify WHERE document_id != :excluded_document_id AND processed = FALSE; """) - records = connection.execute(query, {"excluded_document_id": excluded_document_id}).fetchall() + records = await connection.execute(query, {"excluded_document_id": excluded_document_id}) + records = records.fetchall() if records: document_ids = tuple(record["document_id"] for record in records) update_query = text("UPDATE cognify SET processed = TRUE WHERE document_id IN :document_ids;") - connection.execute(update_query, {"document_ids": document_ids}) + await connection.execute(update_query, {"document_ids": document_ids}) return [dict(record) for record in records] - def delete_cognify_data(self): - with self.engine.connect() as connection: - connection.execute(text(""" + async def delete_cognify_data(self): + async with self.engine.connect() as connection: + await connection.execute(text(""" CREATE TABLE IF NOT EXISTS cognify ( - document_id STRING, + document_id VARCHAR, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT NULL, processed BOOLEAN DEFAULT FALSE, - document_id_target STRING NULL + document_id_target VARCHAR NULL ); """)) - connection.execute(text("DELETE FROM cognify;")) - connection.execute(text("DROP TABLE cognify;")) + await connection.execute(text("DELETE FROM cognify;")) + await connection.execute(text("DROP TABLE cognify;")) async def drop_tables(self, connection): try: diff --git a/cognee/modules/tasks/create_task_status_table.py b/cognee/modules/tasks/create_task_status_table.py index 42b6a0333..48763600d 100644 --- a/cognee/modules/tasks/create_task_status_table.py +++ b/cognee/modules/tasks/create_task_status_table.py @@ -1,10 +1,10 @@ from cognee.infrastructure.databases.relational import get_relational_engine -def create_task_status_table(): +async def create_task_status_table(): db_engine = get_relational_engine() - db_engine.create_table("cognee.cognee", "cognee_task_status", [ - dict(name = "data_id", type = "STRING"), - dict(name = "status", type = "STRING"), - dict(name = "created_at", type = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"), + await db_engine.create_table("cognee", "cognee_task_status", [ + dict(name="data_id", type="VARCHAR"), + dict(name="status", type="VARCHAR"), + dict(name="created_at", type="TIMESTAMP DEFAULT CURRENT_TIMESTAMP"), ]) From b5a3b69e49ae616076570a6e8a42dc089e579081 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:54:59 +0200 Subject: [PATCH 18/44] Fixes to the sqlalchemy adapter --- cognee/api/v1/cognify/cognify_v2.py | 2 +- .../databases/relational/sqlalchemy/SqlAlchemyAdapter.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 7c6139b3c..d3f20ba17 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -119,7 +119,7 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): dataset_name = generate_dataset_name(dataset) if dataset_name in existing_datasets: - awaitables.append(run_cognify_pipeline(dataset, db_engine.get_files_metadata(dataset_name))) + awaitables.append(run_cognify_pipeline(dataset, await db_engine.get_files_metadata(dataset_name))) return await asyncio.gather(*awaitables) diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index 5b5b1fcbe..4ca533aca 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -60,8 +60,12 @@ class SQLAlchemyAdapter(): async def get_files_metadata(self, dataset_name: str): async with self.engine.connect() as connection: - result = await connection.execute(text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) - return [dict(row) for row in result] + result = await connection.execute( + text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) + rows = result.fetchall() + metadata = [{"id": row.id, "name": row.name, "file_path": row.file_path, "extension": row.extension, + "mime_type": row.mime_type} for row in rows] + return metadata async def delete_table(self, table_name: str): async with self.engine.connect() as connection: From 9a2cde95d05dd9d85e4bcdbc2bfb66d8525d2747 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:41:38 +0200 Subject: [PATCH 19/44] Fixes to the sqlalchemy adapter --- cognee/api/v1/cognify/cognify_v2.py | 144 +++++++++--------- .../modules/users/methods/get_default_user.py | 11 +- .../methods/check_permissions_on_documents.py | 43 +++--- 3 files changed, 103 insertions(+), 95 deletions(-) diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index d3f20ba17..d17cab4f2 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -40,88 +40,92 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): if datasets is None or len(datasets) == 0: return await cognify(await db_engine.get_datasets()) - if user is None: - user = await get_default_user() - async def run_cognify_pipeline(dataset_name: str, files: list[dict]): - documents = [ - PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else - AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else - ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else - TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) - for file in files - ] + db_engine = get_relational_engine() + async with db_engine.get_async_session() as session: - await check_permissions_on_documents(user, "read", [document.id for document in documents]) + if user is None: + user = await get_default_user(session= session) - async with update_status_lock: - task_status = get_task_status([dataset_name]) - - if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": - logger.info(f"Dataset {dataset_name} is being processed.") - return - - update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") - try: - cognee_config = get_cognify_config() - graph_config = get_graph_config() - root_node_id = None - - if graph_config.infer_graph_topology and graph_config.graph_topology_task: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - root_node_id = await topology_engine.add_graph_topology(files = files) - elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - await topology_engine.add_graph_topology(graph_config.topology_file_path) - elif not graph_config.graph_topology_task: - root_node_id = "ROOT" - - tasks = [ - Task(process_documents, parent_node_id = root_node_id), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type - Task(establish_graph_topology, topology_model = KnowledgeGraph, task_config = { "batch_size": 10 }), # Set the graph topology for the document chunk data - Task(expand_knowledge_graph, graph_model = KnowledgeGraph, collection_name = "entities"), # Generate knowledge graphs from the document chunks and attach it to chunk nodes - Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks - Task( - save_data_chunks, - collection_name = "chunks", - ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) - run_tasks_parallel([ - Task( - summarize_text_chunks, - summarization_model = cognee_config.summarization_model, - collection_name = "chunk_summaries", - ), # Summarize the document chunks - Task( - classify_text_chunks, - classification_model = cognee_config.classification_model, - ), - ]), - Task(remove_obsolete_chunks), # Remove the obsolete document chunks. + async def run_cognify_pipeline(dataset_name: str, files: list[dict]): + documents = [ + PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else + AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else + ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else + TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) + for file in files ] - pipeline = run_tasks(tasks, documents) + await check_permissions_on_documents(user, "read", [document.id for document in documents], session=session) - async for result in pipeline: - print(result) + async with update_status_lock: + task_status = get_task_status([dataset_name]) - update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") - except Exception as error: - update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") - raise error + if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": + logger.info(f"Dataset {dataset_name} is being processed.") + return + + update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") + try: + cognee_config = get_cognify_config() + graph_config = get_graph_config() + root_node_id = None + + if graph_config.infer_graph_topology and graph_config.graph_topology_task: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + root_node_id = await topology_engine.add_graph_topology(files = files) + elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + await topology_engine.add_graph_topology(graph_config.topology_file_path) + elif not graph_config.graph_topology_task: + root_node_id = "ROOT" + + tasks = [ + Task(process_documents, parent_node_id = root_node_id), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(establish_graph_topology, topology_model = KnowledgeGraph, task_config = { "batch_size": 10 }), # Set the graph topology for the document chunk data + Task(expand_knowledge_graph, graph_model = KnowledgeGraph, collection_name = "entities"), # Generate knowledge graphs from the document chunks and attach it to chunk nodes + Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks + Task( + save_data_chunks, + collection_name = "chunks", + ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) + run_tasks_parallel([ + Task( + summarize_text_chunks, + summarization_model = cognee_config.summarization_model, + collection_name = "chunk_summaries", + ), # Summarize the document chunks + Task( + classify_text_chunks, + classification_model = cognee_config.classification_model, + ), + ]), + Task(remove_obsolete_chunks), # Remove the obsolete document chunks. + ] + + pipeline = run_tasks(tasks, documents) + + async for result in pipeline: + print(result) + + update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") + except Exception as error: + update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") + raise error - existing_datasets = await db_engine.get_datasets() - awaitables = [] + existing_datasets = await db_engine.get_datasets() + awaitables = [] - for dataset in datasets: - dataset_name = generate_dataset_name(dataset) + for dataset in datasets: + dataset_name = generate_dataset_name(dataset) - if dataset_name in existing_datasets: - awaitables.append(run_cognify_pipeline(dataset, await db_engine.get_files_metadata(dataset_name))) + if dataset_name in existing_datasets: + awaitables.append(run_cognify_pipeline(dataset, await db_engine.get_files_metadata(dataset_name))) - return await asyncio.gather(*awaitables) + return await asyncio.gather(*awaitables) def generate_dataset_name(dataset_name: str) -> str: return dataset_name.replace(".", "_").replace(" ", "_") diff --git a/cognee/modules/users/methods/get_default_user.py b/cognee/modules/users/methods/get_default_user.py index 5e0d3bcfe..fd384e50d 100644 --- a/cognee/modules/users/methods/get_default_user.py +++ b/cognee/modules/users/methods/get_default_user.py @@ -3,10 +3,9 @@ from cognee.infrastructure.databases.relational import get_relational_engine from sqlalchemy.future import select -async def get_default_user(): - db_engine = get_relational_engine() - async with db_engine.get_async_session() as session: - stmt = select(User).where(User.email == "default_user@example.com") - result = await session.execute(stmt) - user = result.scalars().first() +async def get_default_user(session): + + stmt = select(User).where(User.email == "default_user@example.com") + result = await session.execute(stmt) + user = result.scalars().first() return user \ No newline at end of file diff --git a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py index 4bc6f82c7..474855114 100644 --- a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py +++ b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py @@ -1,32 +1,37 @@ import logging + +from sqlalchemy import select + from cognee.infrastructure.databases.relational import get_relational_engine from ...models.User import User from ...models.ACL import ACL logger = logging.getLogger(__name__) -async def check_permissions_on_documents( - user: User, - permission_type: str, - document_ids: list[str], -): +class PermissionDeniedException(Exception): + def __init__(self, message: str): + self.message = message + super().__init__(self.message) + + +async def check_permissions_on_documents(user: User, permission_type: str, document_ids: list[str], session): try: - relational_engine = get_relational_engine() + user_group_ids = [group.id for group in user.groups] - async with relational_engine.get_async_session() as session: - user_group_ids = [group.id for group in user.groups] + result = await session.execute( + select(ACL).filter( + ACL.principal_id.in_([user.id, *user_group_ids]), + ACL.permission.name == permission_type + ) + ) + acls = result.scalars().all() - acls = session.query(ACL) \ - .filter(ACL.principal_id.in_([user.id, *user_group_ids])) \ - .filter(ACL.permission.name == permission_type) \ - .all() + resource_ids = [resource.resource_id for acl in acls for resource in acl.resources] + has_permissions = all(document_id in resource_ids for document_id in document_ids) - resource_ids = [resource.resource_id for resource in acl.resources for acl in acls] - - has_permissions = all([document_id in resource_ids for document_id in document_ids]) - - if not has_permissions: - raise Exception(f"User {user.username} does not have {permission_type} permission on documents") + if not has_permissions: + raise PermissionDeniedException(f"User {user.username} does not have {permission_type} permission on documents") except Exception as error: logger.error("Error checking permissions on documents: %s", str(error)) - raise error + raise + From 60350100367f3e13563d37b1b2257f5d1495b151 Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:59:36 +0200 Subject: [PATCH 20/44] Fixes to the sqlalchemy adapter --- cognee/modules/users/methods/get_default_user.py | 5 +++-- cognee/modules/users/models/User.py | 2 +- .../methods/check_permissions_on_documents.py | 16 ++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cognee/modules/users/methods/get_default_user.py b/cognee/modules/users/methods/get_default_user.py index fd384e50d..8ab330d4c 100644 --- a/cognee/modules/users/methods/get_default_user.py +++ b/cognee/modules/users/methods/get_default_user.py @@ -1,11 +1,12 @@ +from sqlalchemy.orm import joinedload + from cognee.modules.users.models import User from cognee.infrastructure.databases.relational import get_relational_engine from sqlalchemy.future import select async def get_default_user(session): - - stmt = select(User).where(User.email == "default_user@example.com") + stmt = select(User).options(joinedload(User.groups)).where(User.email == "default_user@example.com") result = await session.execute(stmt) user = result.scalars().first() return user \ No newline at end of file diff --git a/cognee/modules/users/models/User.py b/cognee/modules/users/models/User.py index fba04e6a0..4e792bbd5 100644 --- a/cognee/modules/users/models/User.py +++ b/cognee/modules/users/models/User.py @@ -24,7 +24,7 @@ class User(SQLAlchemyBaseUserTableUUID, Principal): from fastapi_users import schemas class UserRead(schemas.BaseUser[uuid_UUID]): - pass + groups: list[uuid_UUID] # Add groups attribute class UserCreate(schemas.BaseUserCreate): pass diff --git a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py index 474855114..3f2724ac8 100644 --- a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py +++ b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py @@ -15,18 +15,18 @@ class PermissionDeniedException(Exception): async def check_permissions_on_documents(user: User, permission_type: str, document_ids: list[str], session): + + logging.info("This is the user: %s", user.__dict__) try: user_group_ids = [group.id for group in user.groups] - result = await session.execute( - select(ACL).filter( - ACL.principal_id.in_([user.id, *user_group_ids]), - ACL.permission.name == permission_type - ) + acls = await session.execute( + select(ACL) + .join(ACL.permission) + .where(ACL.principal_id.in_([user.id, *user_group_ids])) + .where(ACL.permission.has(name=permission_type)) ) - acls = result.scalars().all() - - resource_ids = [resource.resource_id for acl in acls for resource in acl.resources] + resource_ids = [resource.resource_id for acl in acls.scalars().all() for resource in acl.resources] has_permissions = all(document_id in resource_ids for document_id in document_ids) if not has_permissions: From 709a10c50c94617570a0dcbfc347f473289e87f0 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Mon, 5 Aug 2024 23:42:36 +0200 Subject: [PATCH 21/44] fix: add dataset and data models --- cognee/api/client.py | 58 ++++-- cognee/api/v1/add/add.py | 54 ++++-- cognee/api/v1/cognify/cognify_v2.py | 165 ++++++++++-------- cognee/api/v1/datasets/datasets.py | 14 +- cognee/infrastructure/data/__init__.py | 3 - cognee/infrastructure/data/models/Data.py | 23 --- .../infrastructure/data/models/DatasetData.py | 12 -- cognee/infrastructure/data/models/__init__.py | 0 .../sqlalchemy/SqlAlchemyAdapter.py | 89 ++-------- cognee/modules/data/models/Data.py | 25 +++ .../data/models/Dataset.py | 11 +- cognee/modules/data/models/DatasetData.py | 11 ++ cognee/modules/data/models/__init__.py | 2 + .../data/operations/ensure_dataset_exists.py | 26 +++ .../document_types/AudioDocument.py | 14 +- .../document_types/ImageDocument.py | 16 +- .../processing/document_types/PdfDocument.py | 10 +- .../processing/document_types/TextDocument.py | 10 +- .../ingestion/data_types/BinaryData.py | 2 +- cognee/modules/ingestion/identify.py | 6 +- cognee/modules/pipelines/models/Pipeline.py | 2 +- .../modules/pipelines/models/PipelineRun.py | 8 +- .../modules/pipelines/models/PipelineTask.py | 7 +- cognee/modules/pipelines/models/Task.py | 2 +- cognee/modules/pipelines/models/TaskRun.py | 17 ++ cognee/modules/pipelines/models/TaskStatus.py | 0 cognee/modules/pipelines/models/__init__.py | 1 + .../modules/pipelines/operations/add_task.py | 4 - .../operations/get_pipeline_status.py | 40 +++++ .../operations/log_pipeline_status.py | 14 ++ cognee/modules/tasks/__init__.py | 3 - .../modules/tasks/create_task_status_table.py | 10 -- cognee/modules/tasks/get_task_status.py | 18 -- cognee/modules/tasks/update_task_status.py | 5 - .../users/methods/create_default_user.py | 6 +- cognee/modules/users/methods/create_user.py | 5 + .../modules/users/methods/get_default_user.py | 18 +- .../methods/check_permissions_on_documents.py | 34 ++-- .../methods/get_document_ids_for_user.py | 2 +- .../methods/give_permission_on_document.py | 12 +- cognee/tests/test_library.py | 22 +-- 41 files changed, 422 insertions(+), 359 deletions(-) delete mode 100644 cognee/infrastructure/data/models/Data.py delete mode 100644 cognee/infrastructure/data/models/DatasetData.py delete mode 100644 cognee/infrastructure/data/models/__init__.py create mode 100644 cognee/modules/data/models/Data.py rename cognee/{infrastructure => modules}/data/models/Dataset.py (57%) create mode 100644 cognee/modules/data/models/DatasetData.py create mode 100644 cognee/modules/data/models/__init__.py create mode 100644 cognee/modules/data/operations/ensure_dataset_exists.py create mode 100644 cognee/modules/pipelines/models/TaskRun.py delete mode 100644 cognee/modules/pipelines/models/TaskStatus.py create mode 100644 cognee/modules/pipelines/models/__init__.py delete mode 100644 cognee/modules/pipelines/operations/add_task.py create mode 100644 cognee/modules/pipelines/operations/get_pipeline_status.py create mode 100644 cognee/modules/pipelines/operations/log_pipeline_status.py delete mode 100644 cognee/modules/tasks/__init__.py delete mode 100644 cognee/modules/tasks/create_task_status_table.py delete mode 100644 cognee/modules/tasks/get_task_status.py delete mode 100644 cognee/modules/tasks/update_task_status.py diff --git a/cognee/api/client.py b/cognee/api/client.py index 50252319e..b8f578d22 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -39,6 +39,7 @@ async def lifespan(app: FastAPI): app = FastAPI(debug = os.getenv("ENV") != "prod", lifespan = lifespan) origins = [ + "http://127.0.0.1:3000", "http://frontend:3000", "http://localhost:3000", "http://localhost:3001", @@ -107,21 +108,33 @@ def health_check(): """ return {"status": "OK"} -class Payload(BaseModel): - payload: Dict[str, Any] - @app.get("/datasets", response_model=list) async def get_datasets(): - from cognee.api.v1.datasets.datasets import datasets - return await datasets.list_datasets() + try: + from cognee.api.v1.datasets.datasets import datasets + datasets = await datasets.list_datasets() + + return JSONResponse( + status_code = 200, + content = [{ + "id": str(dataset.id), + "name": dataset.name, + "created_at": dataset.created_at, + "updated_at": dataset.updated_at, + "data": dataset.data, + } for dataset in datasets], + ) + except Exception as error: + raise HTTPException(status_code = 500, detail=f"Error retrieving datasets: {str(error)}") from error @app.delete("/datasets/{dataset_id}", response_model=dict) async def delete_dataset(dataset_id: str): from cognee.api.v1.datasets.datasets import datasets - datasets.delete_dataset(dataset_id) + await datasets.delete_dataset(dataset_id) + return JSONResponse( - status_code=200, - content="OK", + status_code = 200, + content = "OK", ) @app.get("/datasets/{dataset_id}/graph", response_model=list) @@ -146,7 +159,7 @@ async def get_dataset_graph(dataset_id: str): @app.get("/datasets/{dataset_id}/data", response_model=list) async def get_dataset_data(dataset_id: str): from cognee.api.v1.datasets.datasets import datasets - dataset_data = datasets.list_data(dataset_id) + dataset_data = await datasets.list_data(dataset_id) if dataset_data is None: raise HTTPException(status_code=404, detail=f"Dataset ({dataset_id}) not found.") return [ @@ -162,17 +175,24 @@ async def get_dataset_data(dataset_id: str): @app.get("/datasets/status", response_model=dict) async def get_dataset_status(datasets: Annotated[List[str], Query(alias="dataset")] = None): from cognee.api.v1.datasets.datasets import datasets as cognee_datasets - datasets_statuses = cognee_datasets.get_status(datasets) - return JSONResponse( - status_code = 200, - content = datasets_statuses, - ) + try: + datasets_statuses = await cognee_datasets.get_status(datasets) + + return JSONResponse( + status_code = 200, + content = datasets_statuses, + ) + except Exception as error: + return JSONResponse( + status_code = 409, + content = {"error": str(error)} + ) @app.get("/datasets/{dataset_id}/data/{data_id}/raw", response_class=FileResponse) async def get_raw_data(dataset_id: str, data_id: str): from cognee.api.v1.datasets.datasets import datasets - dataset_data = datasets.list_data(dataset_id) + dataset_data = await datasets.list_data(dataset_id) if dataset_data is None: raise HTTPException(status_code=404, detail=f"Dataset ({dataset_id}) not found.") data = [data for data in dataset_data if data["id"] == data_id][0] @@ -312,10 +332,10 @@ def start_api_server(host: str = "0.0.0.0", port: int = 8000): try: logger.info("Starting server at %s:%s", host, port) - import asyncio - from cognee.modules.data.deletion import prune_system, prune_data - asyncio.run(prune_data()) - asyncio.run(prune_system(metadata = True)) + # import asyncio + # from cognee.modules.data.deletion import prune_system, prune_data + # asyncio.run(prune_data()) + # asyncio.run(prune_system(metadata = True)) uvicorn.run(app, host = host, port = port) except Exception as e: diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index 3fad96e52..31a36316b 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -9,10 +9,11 @@ from cognee.infrastructure.files.storage import LocalStorage from cognee.modules.ingestion import get_matched_datasets, save_data_to_file from cognee.shared.utils import send_telemetry from cognee.base_config import get_base_config -from cognee.infrastructure.databases.relational import get_relational_config, create_db_and_tables -from cognee.modules.users.methods import create_default_user +from cognee.infrastructure.databases.relational import get_relational_config, get_relational_engine, create_db_and_tables +from cognee.modules.users.methods import create_default_user, get_default_user from cognee.modules.users.permissions.methods import give_permission_on_document from cognee.modules.users.models import User +from cognee.modules.data.operations.ensure_dataset_exists import ensure_dataset_exists async def add(data: Union[BinaryIO, List[BinaryIO], str, List[str]], dataset_name: str = "main_dataset", user: User = None): await create_db_and_tables() @@ -99,6 +100,9 @@ async def add_files(file_paths: List[str], dataset_name: str, user): destination = destination, ) + dataset_name = dataset_name.replace(" ", "_").replace(".", "_") if dataset_name is not None else "main_dataset" + dataset = await ensure_dataset_exists(dataset_name) + @dlt.resource(standalone = True, merge_key = "id") async def data_resources(file_paths: str, user: User): for file_path in file_paths: @@ -107,16 +111,34 @@ async def add_files(file_paths: List[str], dataset_name: str, user): data_id = ingestion.identify(classified_data) - if user is None: - try: - user = await create_default_user() - - await give_permission_on_document(user, data_id, "read") - await give_permission_on_document(user, data_id, "write") - except: - pass file_metadata = classified_data.get_metadata() + from sqlalchemy import select + from cognee.modules.data.models import Data + db_engine = get_relational_engine() + async with db_engine.get_async_session() as session: + data = (await session.execute( + select(Data).filter(Data.id == data_id) + )).scalar_one_or_none() + + if data is not None: + data.name = file_metadata["name"] + data.raw_data_location = file_metadata["file_path"] + data.extension = file_metadata["extension"] + data.mime_type = file_metadata["mime_type"] + + await session.merge(data) + else: + data = Data( + name = file_metadata["name"], + raw_data_location = file_metadata["file_path"], + extension = file_metadata["extension"], + mime_type = file_metadata["mime_type"], + ) + dataset.data.append(data) + + await session.merge(dataset) + yield { "id": data_id, "name": file_metadata["name"], @@ -125,10 +147,20 @@ async def add_files(file_paths: List[str], dataset_name: str, user): "mime_type": file_metadata["mime_type"], } + await give_permission_on_document(user, data_id, "read") + await give_permission_on_document(user, data_id, "write") + + + if user is None: + user = await get_default_user() + + if user is None: + user = await create_default_user() + run_info = pipeline.run( data_resources(processed_file_paths, user), table_name = "file_metadata", - dataset_name = dataset_name.replace(" ", "_").replace(".", "_") if dataset_name is not None else "main_dataset", + dataset_name = dataset_name, write_disposition = "merge", ) send_telemetry("cognee.add") diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index d17cab4f2..163dda67d 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -19,10 +19,11 @@ from cognee.modules.data.extraction.knowledge_graph.expand_knowledge_graph impor from cognee.modules.data.extraction.knowledge_graph.establish_graph_topology import establish_graph_topology from cognee.modules.pipelines.tasks.Task import Task from cognee.modules.pipelines import run_tasks, run_tasks_parallel -from cognee.modules.tasks import create_task_status_table, update_task_status, get_task_status from cognee.modules.users.models import User from cognee.modules.users.methods import get_default_user from cognee.modules.users.permissions.methods import check_permissions_on_documents +from cognee.modules.pipelines.operations.get_pipeline_status import get_pipeline_status +from cognee.modules.pipelines.operations.log_pipeline_status import log_pipeline_status logger = logging.getLogger("cognify.v2") @@ -35,97 +36,109 @@ class PermissionDeniedException(Exception): async def cognify(datasets: Union[str, list[str]] = None, user: User = None): db_engine = get_relational_engine() - await create_task_status_table() if datasets is None or len(datasets) == 0: return await cognify(await db_engine.get_datasets()) - db_engine = get_relational_engine() - async with db_engine.get_async_session() as session: + if user is None: + user = await get_default_user() - if user is None: - user = await get_default_user(session= session) + async def run_cognify_pipeline(dataset_name: str, files: list[dict]): + documents = [ + PdfDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else + AudioDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else + ImageDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else + TextDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) + for file in files + ] - async def run_cognify_pipeline(dataset_name: str, files: list[dict]): - documents = [ - PdfDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else - AudioDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else - ImageDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else - TextDocument(title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) - for file in files + document_ids = [document.id for document in documents] + + await check_permissions_on_documents( + user, + "read", + document_ids, + ) + + async with update_status_lock: + task_status = await get_pipeline_status([dataset_name]) + + if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": + logger.info(f"Dataset {dataset_name} is being processed.") + return + + await log_pipeline_status(dataset_name, "DATASET_PROCESSING_STARTED", { + "dataset_name": dataset_name, + "files": document_ids, + }) + try: + cognee_config = get_cognify_config() + graph_config = get_graph_config() + root_node_id = None + + if graph_config.infer_graph_topology and graph_config.graph_topology_task: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + root_node_id = await topology_engine.add_graph_topology(files = files) + elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: + from cognee.modules.topology.topology import TopologyEngine + topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) + await topology_engine.add_graph_topology(graph_config.topology_file_path) + elif not graph_config.graph_topology_task: + root_node_id = "ROOT" + + tasks = [ + Task(process_documents, parent_node_id = root_node_id), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type + Task(establish_graph_topology, topology_model = KnowledgeGraph, task_config = { "batch_size": 10 }), # Set the graph topology for the document chunk data + Task(expand_knowledge_graph, graph_model = KnowledgeGraph, collection_name = "entities"), # Generate knowledge graphs from the document chunks and attach it to chunk nodes + Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks + Task( + save_data_chunks, + collection_name = "chunks", + ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) + run_tasks_parallel([ + Task( + summarize_text_chunks, + summarization_model = cognee_config.summarization_model, + collection_name = "chunk_summaries", + ), # Summarize the document chunks + Task( + classify_text_chunks, + classification_model = cognee_config.classification_model, + ), + ]), + Task(remove_obsolete_chunks), # Remove the obsolete document chunks. ] - await check_permissions_on_documents(user, "read", [document.id for document in documents], session=session) + pipeline = run_tasks(tasks, documents) - async with update_status_lock: - task_status = get_task_status([dataset_name]) + async for result in pipeline: + print(result) - if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": - logger.info(f"Dataset {dataset_name} is being processed.") - return - - update_task_status(dataset_name, "DATASET_PROCESSING_STARTED") - try: - cognee_config = get_cognify_config() - graph_config = get_graph_config() - root_node_id = None - - if graph_config.infer_graph_topology and graph_config.graph_topology_task: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - root_node_id = await topology_engine.add_graph_topology(files = files) - elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: - from cognee.modules.topology.topology import TopologyEngine - topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - await topology_engine.add_graph_topology(graph_config.topology_file_path) - elif not graph_config.graph_topology_task: - root_node_id = "ROOT" - - tasks = [ - Task(process_documents, parent_node_id = root_node_id), # Classify documents and save them as a nodes in graph db, extract text chunks based on the document type - Task(establish_graph_topology, topology_model = KnowledgeGraph, task_config = { "batch_size": 10 }), # Set the graph topology for the document chunk data - Task(expand_knowledge_graph, graph_model = KnowledgeGraph, collection_name = "entities"), # Generate knowledge graphs from the document chunks and attach it to chunk nodes - Task(filter_affected_chunks, collection_name = "chunks"), # Find all affected chunks, so we don't process unchanged chunks - Task( - save_data_chunks, - collection_name = "chunks", - ), # Save the document chunks in vector db and as nodes in graph db (connected to the document node and between each other) - run_tasks_parallel([ - Task( - summarize_text_chunks, - summarization_model = cognee_config.summarization_model, - collection_name = "chunk_summaries", - ), # Summarize the document chunks - Task( - classify_text_chunks, - classification_model = cognee_config.classification_model, - ), - ]), - Task(remove_obsolete_chunks), # Remove the obsolete document chunks. - ] - - pipeline = run_tasks(tasks, documents) - - async for result in pipeline: - print(result) - - update_task_status(dataset_name, "DATASET_PROCESSING_FINISHED") - except Exception as error: - update_task_status(dataset_name, "DATASET_PROCESSING_ERROR") - raise error + await log_pipeline_status(dataset_name, "DATASET_PROCESSING_FINISHED", { + "dataset_name": dataset_name, + "files": document_ids, + }) + except Exception as error: + await log_pipeline_status(dataset_name, "DATASET_PROCESSING_ERROR", { + "dataset_name": dataset_name, + "files": document_ids, + }) + raise error - existing_datasets = await db_engine.get_datasets() - awaitables = [] + existing_datasets = [dataset.name for dataset in list(await db_engine.get_datasets())] + awaitables = [] - for dataset in datasets: - dataset_name = generate_dataset_name(dataset) + for dataset_name in datasets: + dataset_name = generate_dataset_name(dataset_name) - if dataset_name in existing_datasets: - awaitables.append(run_cognify_pipeline(dataset, await db_engine.get_files_metadata(dataset_name))) + if dataset_name in existing_datasets: + awaitables.append(run_cognify_pipeline(dataset_name, await db_engine.get_files_metadata(dataset_name))) + + return await asyncio.gather(*awaitables) - return await asyncio.gather(*awaitables) def generate_dataset_name(dataset_name: str) -> str: return dataset_name.replace(".", "_").replace(" ", "_") diff --git a/cognee/api/v1/datasets/datasets.py b/cognee/api/v1/datasets/datasets.py index d46fd2413..8a44e0411 100644 --- a/cognee/api/v1/datasets/datasets.py +++ b/cognee/api/v1/datasets/datasets.py @@ -1,6 +1,6 @@ from duckdb import CatalogException from cognee.modules.ingestion import discover_directory_datasets -from cognee.modules.tasks import get_task_status +from cognee.modules.pipelines.operations.get_pipeline_status import get_pipeline_status from cognee.infrastructure.databases.relational import get_relational_engine class datasets(): @@ -14,24 +14,24 @@ class datasets(): return list(discover_directory_datasets(directory_path).keys()) @staticmethod - def list_data(dataset_name: str): + async def list_data(dataset_name: str): db = get_relational_engine() try: - return db.get_files_metadata(dataset_name) + return await db.get_files_metadata(dataset_name) except CatalogException: return None @staticmethod - def get_status(dataset_ids: list[str]) -> dict: + async def get_status(dataset_ids: list[str]) -> dict: try: - return get_task_status(dataset_ids) + return await get_pipeline_status(dataset_ids) except CatalogException: return {} @staticmethod - def delete_dataset(dataset_id: str): + async def delete_dataset(dataset_id: str): db = get_relational_engine() try: - return db.delete_table(dataset_id) + return await db.delete_table(dataset_id) except CatalogException: return {} diff --git a/cognee/infrastructure/data/__init__.py b/cognee/infrastructure/data/__init__.py index 6aaaf6b41..e69de29bb 100644 --- a/cognee/infrastructure/data/__init__.py +++ b/cognee/infrastructure/data/__init__.py @@ -1,3 +0,0 @@ -from .models.Data import Data -from .models.Dataset import Dataset -from .models.DatasetData import DatasetData diff --git a/cognee/infrastructure/data/models/Data.py b/cognee/infrastructure/data/models/Data.py deleted file mode 100644 index da389e154..000000000 --- a/cognee/infrastructure/data/models/Data.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import List -from datetime import datetime, timezone -from sqlalchemy.orm import relationship, MappedColumn, Mapped -from sqlalchemy import Column, String, DateTime, UUID, Text, JSON -from cognee.infrastructure.databases.relational import Base -from .DatasetData import DatasetData - -class Data(Base): - __tablename__ = "data" - - id = Column(UUID, primary_key = True) - name = Column(String, nullable = True) - description = Column(Text, nullable = True) - raw_data_location = Column(String) - meta_data: Mapped[dict] = MappedColumn(type_ = JSON) # metadata is reserved word - - created_at = Column(DateTime, default = datetime.now(timezone.utc)) - updated_at = Column(DateTime, onupdate = datetime.now(timezone.utc)) - - datasets: Mapped[List["Dataset"]] = relationship( - secondary = DatasetData.__tablename__, - back_populates = "data" - ) diff --git a/cognee/infrastructure/data/models/DatasetData.py b/cognee/infrastructure/data/models/DatasetData.py deleted file mode 100644 index c84d890ae..000000000 --- a/cognee/infrastructure/data/models/DatasetData.py +++ /dev/null @@ -1,12 +0,0 @@ -from uuid import uuid4 -from datetime import datetime, timezone -from sqlalchemy import Column, DateTime, UUID, ForeignKey -from cognee.infrastructure.databases.relational import Base - -class DatasetData(Base): - __tablename__ = "dataset_data" - - id = Column(UUID, primary_key=True, default=uuid4) - - dataset_id = Column(UUID, ForeignKey("dataset.id"), nullable=False) - data_id = Column(UUID, ForeignKey("data.id"), nullable=False) diff --git a/cognee/infrastructure/data/models/__init__.py b/cognee/infrastructure/data/models/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index 4ca533aca..7fcced7ec 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -2,11 +2,12 @@ import os import asyncio from typing import AsyncGenerator from contextlib import asynccontextmanager -from sqlalchemy import create_engine, MetaData, Table, Column, String, Boolean, TIMESTAMP, text -from sqlalchemy.orm import sessionmaker +from sqlalchemy import create_engine, text, select +from sqlalchemy.orm import sessionmaker, joinedload from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker from cognee.infrastructure.files.storage import LocalStorage from cognee.infrastructure.databases.relational.FakeAsyncSession import FakeAsyncSession +from ..ModelBase import Base def make_async_sessionmaker(sessionmaker): @asynccontextmanager @@ -19,6 +20,7 @@ def make_async_sessionmaker(sessionmaker): class SQLAlchemyAdapter(): def __init__(self, db_type: str, db_path: str, db_name: str, db_user: str, db_password: str, db_host: str, db_port: str): self.db_location = os.path.abspath(os.path.join(db_path, db_name)) + self.db_name = db_name if db_type == "duckdb": LocalStorage.ensure_directory_exists(db_path) @@ -42,15 +44,11 @@ class SQLAlchemyAdapter(): yield session async def get_datasets(self): - async with self.engine.connect() as connection: - result = await connection.execute(text("SELECT DISTINCT table_schema FROM information_schema.tables;")) - tables = [row[0] for row in result] - return list( - filter( - lambda table_schema: not table_schema.endswith("staging") and table_schema != "cognee", - tables - ) - ) + from cognee.modules.data.models import Dataset + + async with self.get_async_session() as session: + datasets = (await session.execute(select(Dataset).options(joinedload(Dataset.data)))).unique().scalars().all() + return datasets async def create_table(self, schema_name: str, table_name: str, table_config: list[dict]): fields_query_parts = [f"{item['name']} {item['type']}" for item in table_config] @@ -100,65 +98,6 @@ class SQLAlchemyAdapter(): result = await connection.execute(text(query)) return [dict(row) for row in result] - async def load_cognify_data(self, data): - metadata = MetaData() - - cognify_table = Table( - "cognify", - metadata, - Column("document_id", String), - Column("created_at", TIMESTAMP, server_default=text("CURRENT_TIMESTAMP")), - Column("updated_at", TIMESTAMP, nullable=True, default=None), - Column("processed", Boolean, default=False), - Column("document_id_target", String, nullable=True) - ) - - async with self.engine.begin() as connection: - await connection.run_sync(metadata.create_all) - - insert_query = cognify_table.insert().values(document_id=text(":document_id")) - async with self.engine.connect() as connection: - await connection.execute(insert_query, data) - - async def fetch_cognify_data(self, excluded_document_id: str): - async with self.engine.connect() as connection: - await connection.execute(text(""" - CREATE TABLE IF NOT EXISTS cognify ( - document_id VARCHAR, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT NULL, - processed BOOLEAN DEFAULT FALSE, - document_id_target VARCHAR NULL - ); - """)) - query = text(""" - SELECT document_id, created_at, updated_at, processed - FROM cognify - WHERE document_id != :excluded_document_id AND processed = FALSE; - """) - records = await connection.execute(query, {"excluded_document_id": excluded_document_id}) - records = records.fetchall() - - if records: - document_ids = tuple(record["document_id"] for record in records) - update_query = text("UPDATE cognify SET processed = TRUE WHERE document_id IN :document_ids;") - await connection.execute(update_query, {"document_ids": document_ids}) - return [dict(record) for record in records] - - async def delete_cognify_data(self): - async with self.engine.connect() as connection: - await connection.execute(text(""" - CREATE TABLE IF NOT EXISTS cognify ( - document_id VARCHAR, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT NULL, - processed BOOLEAN DEFAULT FALSE, - document_id_target VARCHAR NULL - ); - """)) - await connection.execute(text("DELETE FROM cognify;")) - await connection.execute(text("DROP TABLE cognify;")) - async def drop_tables(self, connection): try: await connection.execute(text("DROP TABLE IF EXISTS group_permission CASCADE")) @@ -169,9 +108,11 @@ class SQLAlchemyAdapter(): print(f"Error dropping database tables: {e}") async def delete_database(self): - async with self.engine.begin() as connection: + async with self.engine.connect() as connection: try: - await self.drop_tables(connection) - print("Database tables dropped successfully.") + async with self.engine.begin() as connection: + await connection.run_sync(Base.metadata.drop_all) + + print("Database deleted successfully.") except Exception as e: - print(f"Error dropping database tables: {e}") \ No newline at end of file + print(f"Error deleting database: {e}") diff --git a/cognee/modules/data/models/Data.py b/cognee/modules/data/models/Data.py new file mode 100644 index 000000000..a1d20ebee --- /dev/null +++ b/cognee/modules/data/models/Data.py @@ -0,0 +1,25 @@ +from uuid import uuid4 +from typing import List +from datetime import datetime, timezone +from sqlalchemy.orm import relationship, Mapped +from sqlalchemy import Column, String, DateTime, UUID +from cognee.infrastructure.databases.relational import Base +from .DatasetData import DatasetData + +class Data(Base): + __tablename__ = "data" + + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) + + name = Column(String) + extension = Column(String) + mime_type = Column(String) + raw_data_location = Column(String) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) + + datasets: Mapped[List["Dataset"]] = relationship( + secondary = DatasetData.__tablename__, + back_populates = "data" + ) diff --git a/cognee/infrastructure/data/models/Dataset.py b/cognee/modules/data/models/Dataset.py similarity index 57% rename from cognee/infrastructure/data/models/Dataset.py rename to cognee/modules/data/models/Dataset.py index 918cd5b28..32d26dac5 100644 --- a/cognee/infrastructure/data/models/Dataset.py +++ b/cognee/modules/data/models/Dataset.py @@ -1,3 +1,4 @@ +from uuid import uuid4 from typing import List from datetime import datetime, timezone from sqlalchemy.orm import relationship, Mapped @@ -6,14 +7,14 @@ from cognee.infrastructure.databases.relational import Base from .DatasetData import DatasetData class Dataset(Base): - __tablename__ = "dataset" + __tablename__ = "datasets" + + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) - id = Column(UUID, primary_key = True) name = Column(Text) - description = Column(Text, nullable = True) - created_at = Column(DateTime, default = datetime.now(timezone.utc)) - updated_at = Column(DateTime, onupdate = datetime.now(timezone.utc)) + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + updated_at = Column(DateTime(timezone = True), onupdate = lambda: datetime.now(timezone.utc)) data: Mapped[List["Data"]] = relationship( secondary = DatasetData.__tablename__, diff --git a/cognee/modules/data/models/DatasetData.py b/cognee/modules/data/models/DatasetData.py new file mode 100644 index 000000000..d340889f2 --- /dev/null +++ b/cognee/modules/data/models/DatasetData.py @@ -0,0 +1,11 @@ +from datetime import datetime, timezone +from sqlalchemy import Column, DateTime, UUID, ForeignKey +from cognee.infrastructure.databases.relational import Base + +class DatasetData(Base): + __tablename__ = "dataset_data" + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + + dataset_id = Column(UUID(as_uuid = True), ForeignKey("datasets.id"), primary_key = True) + data_id = Column(UUID(as_uuid = True), ForeignKey("data.id"), primary_key = True) diff --git a/cognee/modules/data/models/__init__.py b/cognee/modules/data/models/__init__.py new file mode 100644 index 000000000..5d79dbd40 --- /dev/null +++ b/cognee/modules/data/models/__init__.py @@ -0,0 +1,2 @@ +from .Data import Data +from .Dataset import Dataset diff --git a/cognee/modules/data/operations/ensure_dataset_exists.py b/cognee/modules/data/operations/ensure_dataset_exists.py new file mode 100644 index 000000000..9de662cae --- /dev/null +++ b/cognee/modules/data/operations/ensure_dataset_exists.py @@ -0,0 +1,26 @@ +from sqlalchemy import select +from sqlalchemy.orm import joinedload +from cognee.modules.data.models import Dataset +from cognee.infrastructure.databases.relational import get_relational_engine + +async def ensure_dataset_exists(dataset_name: str) -> Dataset: + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + dataset = (await session.scalars( + select(Dataset)\ + .options(joinedload(Dataset.data))\ + .filter(Dataset.name == dataset_name) + )).first() + + if dataset is None: + dataset = Dataset( + name = dataset_name, + data = [] + ) + + session.add(dataset) + + await session.commit() + + return dataset diff --git a/cognee/modules/data/processing/document_types/AudioDocument.py b/cognee/modules/data/processing/document_types/AudioDocument.py index bc129b66b..e3aa6dca7 100644 --- a/cognee/modules/data/processing/document_types/AudioDocument.py +++ b/cognee/modules/data/processing/document_types/AudioDocument.py @@ -1,5 +1,5 @@ -from uuid import uuid5, NAMESPACE_OID -from typing import Optional, Generator +from uuid import UUID, uuid5, NAMESPACE_OID +from typing import Optional from cognee.infrastructure.llm.get_llm_client import get_llm_client from cognee.modules.data.chunking import chunk_by_paragraph @@ -7,10 +7,10 @@ from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChu from cognee.modules.data.processing.document_types.Document import Document class AudioReader: - id: str + id: UUID file_path: str - def __init__(self, id: str, file_path: str): + def __init__(self, id: UUID, file_path: str): self.id = id self.file_path = file_path self.llm_client = get_llm_client() # You can choose different models like "tiny", "base", "small", etc. @@ -87,13 +87,11 @@ class AudioDocument(Document): title: str file_path: str - def __init__(self, title: str, file_path: str): - self.id = uuid5(NAMESPACE_OID, title) + def __init__(self, id: UUID, title: str, file_path: str): + self.id = id or uuid5(NAMESPACE_OID, title) self.title = title self.file_path = file_path - reader = AudioReader(self.id, self.file_path) - def get_reader(self) -> AudioReader: reader = AudioReader(self.id, self.file_path) return reader diff --git a/cognee/modules/data/processing/document_types/ImageDocument.py b/cognee/modules/data/processing/document_types/ImageDocument.py index aa99c672b..faddb3120 100644 --- a/cognee/modules/data/processing/document_types/ImageDocument.py +++ b/cognee/modules/data/processing/document_types/ImageDocument.py @@ -1,5 +1,5 @@ -from uuid import uuid5, NAMESPACE_OID -from typing import Optional, Generator +from uuid import UUID, uuid5, NAMESPACE_OID +from typing import Optional from cognee.infrastructure.llm.get_llm_client import get_llm_client from cognee.modules.data.chunking import chunk_by_paragraph @@ -7,10 +7,10 @@ from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChu from cognee.modules.data.processing.document_types.Document import Document class ImageReader: - id: str + id: UUID file_path: str - def __init__(self, id: str, file_path: str): + def __init__(self, id: UUID, file_path: str): self.id = id self.file_path = file_path self.llm_client = get_llm_client() # You can choose different models like "tiny", "base", "small", etc. @@ -24,10 +24,8 @@ class ImageReader: # Transcribe the image file result = self.llm_client.transcribe_image(self.file_path) - print("Transcription result: ", result.choices[0].message.content) text = result.choices[0].message.content - # Simulate reading text in chunks as done in TextReader def read_text_chunks(text, chunk_size): for i in range(0, len(text), chunk_size): @@ -89,13 +87,11 @@ class ImageDocument(Document): title: str file_path: str - def __init__(self, title: str, file_path: str): - self.id = uuid5(NAMESPACE_OID, title) + def __init__(self, id: UUID, title: str, file_path: str): + self.id = id or uuid5(NAMESPACE_OID, title) self.title = title self.file_path = file_path - reader = ImageReader(self.id, self.file_path) - def get_reader(self) -> ImageReader: reader = ImageReader(self.id, self.file_path) return reader diff --git a/cognee/modules/data/processing/document_types/PdfDocument.py b/cognee/modules/data/processing/document_types/PdfDocument.py index 9402da7c9..b2579a06a 100644 --- a/cognee/modules/data/processing/document_types/PdfDocument.py +++ b/cognee/modules/data/processing/document_types/PdfDocument.py @@ -1,6 +1,6 @@ # import pdfplumber import logging -from uuid import uuid5, NAMESPACE_OID +from uuid import UUID, uuid5, NAMESPACE_OID from typing import Optional from pypdf import PdfReader as pypdf_PdfReader from cognee.modules.data.chunking import chunk_by_paragraph @@ -8,10 +8,10 @@ from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChu from .Document import Document class PdfReader(): - id: str + id: UUID file_path: str - def __init__(self, id: str, file_path: str): + def __init__(self, id: UUID, file_path: str): self.id = id self.file_path = file_path @@ -86,8 +86,8 @@ class PdfDocument(Document): num_pages: int file_path: str - def __init__(self, title: str, file_path: str): - self.id = uuid5(NAMESPACE_OID, title) + def __init__(self, id: UUID, title: str, file_path: str): + self.id = id or uuid5(NAMESPACE_OID, title) self.title = title self.file_path = file_path logging.debug("file_path: %s", self.file_path) diff --git a/cognee/modules/data/processing/document_types/TextDocument.py b/cognee/modules/data/processing/document_types/TextDocument.py index 2e5bf4452..7e9ca8862 100644 --- a/cognee/modules/data/processing/document_types/TextDocument.py +++ b/cognee/modules/data/processing/document_types/TextDocument.py @@ -1,14 +1,14 @@ -from uuid import uuid5, NAMESPACE_OID +from uuid import UUID, uuid5, NAMESPACE_OID from typing import Optional from cognee.modules.data.chunking import chunk_by_paragraph from cognee.modules.data.processing.chunk_types.DocumentChunk import DocumentChunk from .Document import Document class TextReader(): - id: str + id: UUID file_path: str - def __init__(self, id: str, file_path: str): + def __init__(self, id: UUID, file_path: str): self.id = id self.file_path = file_path @@ -90,8 +90,8 @@ class TextDocument(Document): num_pages: int file_path: str - def __init__(self, title: str, file_path: str): - self.id = uuid5(NAMESPACE_OID, title) + def __init__(self, id: UUID, title: str, file_path: str): + self.id = id or uuid5(NAMESPACE_OID, title) self.title = title self.file_path = file_path diff --git a/cognee/modules/ingestion/data_types/BinaryData.py b/cognee/modules/ingestion/data_types/BinaryData.py index 5531fec86..6959eb15f 100644 --- a/cognee/modules/ingestion/data_types/BinaryData.py +++ b/cognee/modules/ingestion/data_types/BinaryData.py @@ -17,7 +17,7 @@ class BinaryData(IngestionData): def get_identifier(self): metadata = self.get_metadata() - return self.name + "_" + metadata["mime_type"] + return self.name + "." + metadata["extension"] def get_metadata(self): self.ensure_metadata() diff --git a/cognee/modules/ingestion/identify.py b/cognee/modules/ingestion/identify.py index 89c347449..745aab913 100644 --- a/cognee/modules/ingestion/identify.py +++ b/cognee/modules/ingestion/identify.py @@ -1,9 +1,7 @@ -from uuid import uuid5, UUID +from uuid import uuid5, NAMESPACE_OID from .data_types import IngestionData -null_uuid: UUID = UUID("00000000-0000-0000-0000-000000000000") - def identify(data: IngestionData) -> str: data_id: str = data.get_identifier() - return str(uuid5(null_uuid, data_id)).replace("-", "") + return uuid5(NAMESPACE_OID, data_id) diff --git a/cognee/modules/pipelines/models/Pipeline.py b/cognee/modules/pipelines/models/Pipeline.py index 8005844be..8904e00dc 100644 --- a/cognee/modules/pipelines/models/Pipeline.py +++ b/cognee/modules/pipelines/models/Pipeline.py @@ -8,7 +8,7 @@ from .PipelineTask import PipelineTask class Pipeline(Base): __tablename__ = "pipelines" - id = Column(UUID, primary_key = True, default = uuid4) + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) name = Column(String) description = Column(Text, nullable = True) diff --git a/cognee/modules/pipelines/models/PipelineRun.py b/cognee/modules/pipelines/models/PipelineRun.py index bc5f890d9..fd34b8d98 100644 --- a/cognee/modules/pipelines/models/PipelineRun.py +++ b/cognee/modules/pipelines/models/PipelineRun.py @@ -6,10 +6,12 @@ from cognee.infrastructure.databases.relational import Base class PipelineRun(Base): __tablename__ = "pipeline_runs" - id = Column(UUID, primary_key = True, default = uuid4) - - dataset_name = Column(String) + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + run_name = Column(String, index = True) + + status = Column(String) + run_info = Column(JSON) diff --git a/cognee/modules/pipelines/models/PipelineTask.py b/cognee/modules/pipelines/models/PipelineTask.py index 0c70baddc..079b12f47 100644 --- a/cognee/modules/pipelines/models/PipelineTask.py +++ b/cognee/modules/pipelines/models/PipelineTask.py @@ -1,4 +1,3 @@ -from uuid import uuid4 from datetime import datetime, timezone from sqlalchemy import Column, DateTime, UUID, ForeignKey from cognee.infrastructure.databases.relational import Base @@ -6,9 +5,7 @@ from cognee.infrastructure.databases.relational import Base class PipelineTask(Base): __tablename__ = "pipeline_task" - id = Column(UUID, primary_key = True, default = uuid4) - created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) - pipeline_id = Column("pipeline", UUID, ForeignKey("pipeline.id"), primary_key = True) - task_id = Column("task", UUID, ForeignKey("task.id"), primary_key = True) + pipeline_id = Column("pipeline", UUID(as_uuid = True), ForeignKey("pipeline.id"), primary_key = True) + task_id = Column("task", UUID(as_uuid = True), ForeignKey("task.id"), primary_key = True) diff --git a/cognee/modules/pipelines/models/Task.py b/cognee/modules/pipelines/models/Task.py index c3ee89e41..3a56f4b71 100644 --- a/cognee/modules/pipelines/models/Task.py +++ b/cognee/modules/pipelines/models/Task.py @@ -8,7 +8,7 @@ from .PipelineTask import PipelineTask class Task(Base): __tablename__ = "tasks" - id = Column(UUID, primary_key = True, default = uuid4) + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) name = Column(String) description = Column(Text, nullable = True) diff --git a/cognee/modules/pipelines/models/TaskRun.py b/cognee/modules/pipelines/models/TaskRun.py new file mode 100644 index 000000000..89cda8b44 --- /dev/null +++ b/cognee/modules/pipelines/models/TaskRun.py @@ -0,0 +1,17 @@ +from uuid import uuid4 +from datetime import datetime, timezone +from sqlalchemy import Column, UUID, DateTime, String, JSON +from cognee.infrastructure.databases.relational import Base + +class TaskRun(Base): + __tablename__ = "task_runs" + + id = Column(UUID(as_uuid = True), primary_key = True, default = uuid4) + + task_name = Column(String) + + created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) + + status = Column(String) + + run_info = Column(JSON) diff --git a/cognee/modules/pipelines/models/TaskStatus.py b/cognee/modules/pipelines/models/TaskStatus.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/cognee/modules/pipelines/models/__init__.py b/cognee/modules/pipelines/models/__init__.py new file mode 100644 index 000000000..27a936983 --- /dev/null +++ b/cognee/modules/pipelines/models/__init__.py @@ -0,0 +1 @@ +from .PipelineRun import PipelineRun diff --git a/cognee/modules/pipelines/operations/add_task.py b/cognee/modules/pipelines/operations/add_task.py deleted file mode 100644 index deb491993..000000000 --- a/cognee/modules/pipelines/operations/add_task.py +++ /dev/null @@ -1,4 +0,0 @@ -from ..models import Pipeline, Task - -def add_task(pipeline: Pipeline, task: Task): - pipeline.tasks.append(task) diff --git a/cognee/modules/pipelines/operations/get_pipeline_status.py b/cognee/modules/pipelines/operations/get_pipeline_status.py new file mode 100644 index 000000000..2f190ac3b --- /dev/null +++ b/cognee/modules/pipelines/operations/get_pipeline_status.py @@ -0,0 +1,40 @@ +from sqlalchemy import func, select +from sqlalchemy.orm import aliased +from cognee.infrastructure.databases.relational import get_relational_engine +from ..models import PipelineRun + +async def get_pipeline_status(pipeline_names: [str]): + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + query = select( + PipelineRun, + func.row_number().over( + partition_by = PipelineRun.run_name, + order_by = PipelineRun.created_at.desc(), + ).label("rn") + ).filter(PipelineRun.run_name.in_(pipeline_names)).subquery() + + aliased_pipeline_run = aliased(PipelineRun, query) + + latest_runs = ( + select(aliased_pipeline_run).filter(query.c.rn == 1) + ) + + runs = (await session.execute(latest_runs)).scalars().all() + + pipeline_statuses = { + run.run_name: run.status for run in runs + } + + return pipeline_statuses + + # f"""SELECT data_id, status + # FROM ( + # SELECT data_id, status, ROW_NUMBER() OVER (PARTITION BY data_id ORDER BY created_at DESC) as rn + # FROM cognee.cognee.task_runs + # WHERE data_id IN ({formatted_data_ids}) + # ) t + # WHERE rn = 1;""" + + # return { dataset["data_id"]: dataset["status"] for dataset in datasets_statuses } diff --git a/cognee/modules/pipelines/operations/log_pipeline_status.py b/cognee/modules/pipelines/operations/log_pipeline_status.py new file mode 100644 index 000000000..5b484ebf3 --- /dev/null +++ b/cognee/modules/pipelines/operations/log_pipeline_status.py @@ -0,0 +1,14 @@ +from cognee.infrastructure.databases.relational import get_relational_engine +from ..models.PipelineRun import PipelineRun + +async def log_pipeline_status(run_name: str, status: str, run_info: dict): + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + session.add(PipelineRun( + run_name = run_name, + status = status, + run_info = run_info, + )) + + await session.commit() diff --git a/cognee/modules/tasks/__init__.py b/cognee/modules/tasks/__init__.py deleted file mode 100644 index e0cc3da4a..000000000 --- a/cognee/modules/tasks/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .get_task_status import get_task_status -from .update_task_status import update_task_status -from .create_task_status_table import create_task_status_table diff --git a/cognee/modules/tasks/create_task_status_table.py b/cognee/modules/tasks/create_task_status_table.py deleted file mode 100644 index 48763600d..000000000 --- a/cognee/modules/tasks/create_task_status_table.py +++ /dev/null @@ -1,10 +0,0 @@ -from cognee.infrastructure.databases.relational import get_relational_engine - -async def create_task_status_table(): - db_engine = get_relational_engine() - - await db_engine.create_table("cognee", "cognee_task_status", [ - dict(name="data_id", type="VARCHAR"), - dict(name="status", type="VARCHAR"), - dict(name="created_at", type="TIMESTAMP DEFAULT CURRENT_TIMESTAMP"), - ]) diff --git a/cognee/modules/tasks/get_task_status.py b/cognee/modules/tasks/get_task_status.py deleted file mode 100644 index 17b796084..000000000 --- a/cognee/modules/tasks/get_task_status.py +++ /dev/null @@ -1,18 +0,0 @@ -from cognee.infrastructure.databases.relational import get_relational_engine - -def get_task_status(data_ids: [str]): - db_engine = get_relational_engine() - - formatted_data_ids = ", ".join([f"'{data_id}'" for data_id in data_ids]) - - datasets_statuses = db_engine.execute_query( - f"""SELECT data_id, status - FROM ( - SELECT data_id, status, ROW_NUMBER() OVER (PARTITION BY data_id ORDER BY created_at DESC) as rn - FROM cognee.cognee.cognee_task_status - WHERE data_id IN ({formatted_data_ids}) - ) t - WHERE rn = 1;""" - ) - - return { dataset["data_id"]: dataset["status"] for dataset in datasets_statuses } diff --git a/cognee/modules/tasks/update_task_status.py b/cognee/modules/tasks/update_task_status.py deleted file mode 100644 index 0676a5a92..000000000 --- a/cognee/modules/tasks/update_task_status.py +++ /dev/null @@ -1,5 +0,0 @@ -from cognee.infrastructure.databases.relational import get_relational_engine - -def update_task_status(data_id: str, status: str): - db_engine = get_relational_engine() - db_engine.insert_data("cognee.cognee", "cognee_task_status", [dict(data_id = data_id, status = status)]) diff --git a/cognee/modules/users/methods/create_default_user.py b/cognee/modules/users/methods/create_default_user.py index 673756ed1..3fae3c10f 100644 --- a/cognee/modules/users/methods/create_default_user.py +++ b/cognee/modules/users/methods/create_default_user.py @@ -1,5 +1,4 @@ import hashlib -# from cognee.infrastructure.databases.relational import get_relational_engine from .create_user import create_user async def create_default_user(): @@ -12,12 +11,9 @@ async def create_default_user(): is_superuser = True, is_active = True, is_verified = True, + auto_login = True, ) - # db_engine = get_relational_engine() - # async with db_engine.get_async_session() as session: - # await session.refresh(user) - return user async def hash_password(password: str) -> str: diff --git a/cognee/modules/users/methods/create_user.py b/cognee/modules/users/methods/create_user.py index f2886caae..3145fd799 100644 --- a/cognee/modules/users/methods/create_user.py +++ b/cognee/modules/users/methods/create_user.py @@ -10,6 +10,7 @@ async def create_user( is_superuser: bool = False, is_active: bool = True, is_verified: bool = False, + auto_login: bool = False, ): try: relational_engine = get_relational_engine() @@ -26,6 +27,10 @@ async def create_user( is_verified = is_verified, ) ) + + if auto_login: + await session.refresh(user) + return user print(f"User created: {user.email}") except UserAlreadyExists as error: diff --git a/cognee/modules/users/methods/get_default_user.py b/cognee/modules/users/methods/get_default_user.py index 8ab330d4c..72faef3c8 100644 --- a/cognee/modules/users/methods/get_default_user.py +++ b/cognee/modules/users/methods/get_default_user.py @@ -1,12 +1,16 @@ from sqlalchemy.orm import joinedload - +from sqlalchemy.future import select from cognee.modules.users.models import User from cognee.infrastructure.databases.relational import get_relational_engine -from sqlalchemy.future import select +async def get_default_user(): + db_engine = get_relational_engine() -async def get_default_user(session): - stmt = select(User).options(joinedload(User.groups)).where(User.email == "default_user@example.com") - result = await session.execute(stmt) - user = result.scalars().first() - return user \ No newline at end of file + async with db_engine.get_async_session() as session: + query = select(User).options(joinedload(User.groups))\ + .where(User.email == "default_user@example.com") + + result = await session.execute(query) + user = result.scalars().first() + + return user diff --git a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py index 3f2724ac8..4464f0f24 100644 --- a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py +++ b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py @@ -1,8 +1,8 @@ import logging - from sqlalchemy import select - +from sqlalchemy.orm import joinedload from cognee.infrastructure.databases.relational import get_relational_engine + from ...models.User import User from ...models.ACL import ACL @@ -14,24 +14,26 @@ class PermissionDeniedException(Exception): super().__init__(self.message) -async def check_permissions_on_documents(user: User, permission_type: str, document_ids: list[str], session): - - logging.info("This is the user: %s", user.__dict__) +async def check_permissions_on_documents(user: User, permission_type: str, document_ids: list[str]): try: user_group_ids = [group.id for group in user.groups] - acls = await session.execute( - select(ACL) - .join(ACL.permission) - .where(ACL.principal_id.in_([user.id, *user_group_ids])) - .where(ACL.permission.has(name=permission_type)) - ) - resource_ids = [resource.resource_id for acl in acls.scalars().all() for resource in acl.resources] - has_permissions = all(document_id in resource_ids for document_id in document_ids) + db_engine = get_relational_engine() - if not has_permissions: - raise PermissionDeniedException(f"User {user.username} does not have {permission_type} permission on documents") + async with db_engine.get_async_session() as session: + result = await session.execute( + select(ACL) + .join(ACL.permission) + .options(joinedload(ACL.resources)) + .where(ACL.principal_id.in_([user.id, *user_group_ids])) + .where(ACL.permission.has(name = permission_type)) + ) + acls = result.unique().scalars().all() + resource_ids = [str(resource.resource_id) for acl in acls for resource in acl.resources] + has_permissions = all(document_id in resource_ids for document_id in document_ids) + + if not has_permissions: + raise PermissionDeniedException(f"User {user.username} does not have {permission_type} permission on documents") except Exception as error: logger.error("Error checking permissions on documents: %s", str(error)) raise - diff --git a/cognee/modules/users/permissions/methods/get_document_ids_for_user.py b/cognee/modules/users/permissions/methods/get_document_ids_for_user.py index 31f031d75..47f33b2c7 100644 --- a/cognee/modules/users/permissions/methods/get_document_ids_for_user.py +++ b/cognee/modules/users/permissions/methods/get_document_ids_for_user.py @@ -16,7 +16,7 @@ async def get_document_ids_for_user(user_id: UUID) -> list[str]: ACL.permission.name == "read", ) ) - document_ids = [row[0] for row in result.fetchall()] + document_ids = [row[0] for row in result.scalars().all()] return document_ids diff --git a/cognee/modules/users/permissions/methods/give_permission_on_document.py b/cognee/modules/users/permissions/methods/give_permission_on_document.py index f4dabfd6b..65516f7cd 100644 --- a/cognee/modules/users/permissions/methods/give_permission_on_document.py +++ b/cognee/modules/users/permissions/methods/give_permission_on_document.py @@ -12,18 +12,18 @@ async def give_permission_on_document( document_resource = Resource(resource_id = document_id) async with db_engine.get_async_session() as session: - permission = (await session.execute(select(Permission).filter(Permission.name == permission_name))).first() + permission = (await session.execute(select(Permission).filter(Permission.name == permission_name))).scalars().first() if permission is None: permission = Permission(name = permission_name) - acl = ACL(principal_id = user.id) - acl.permission = permission - acl.resources.append(document_resource) + acl = ACL(principal_id = user.id) + acl.permission = permission + acl.resources.append(document_resource) - session.add(acl) + session.add(acl) - await session.commit() + await session.commit() # if user.is_superuser: diff --git a/cognee/tests/test_library.py b/cognee/tests/test_library.py index d00c2b360..1480020d5 100755 --- a/cognee/tests/test_library.py +++ b/cognee/tests/test_library.py @@ -27,13 +27,13 @@ async def main(): # In principle, a non-quantum (classical) computer can solve the same computational problems as a quantum computer, given enough time. Quantum advantage comes in the form of time complexity rather than computability, and quantum complexity theory shows that some quantum algorithms for carefully selected tasks require exponentially fewer computational steps than the best known non-quantum algorithms. Such tasks can in theory be solved on a large-scale quantum computer whereas classical computers would not finish computations in any reasonable amount of time. However, quantum speedup is not universal or even typical across computational tasks, since basic tasks such as sorting are proven to not allow any asymptotic quantum speedup. Claims of quantum supremacy have drawn significant attention to the discipline, but are demonstrated on contrived tasks, while near-term practical use cases remain limited. # """ - text = """A large language model (LLM) is a language model notable for its ability to achieve general-purpose language generation and other natural language processing tasks such as classification. LLMs acquire these abilities by learning statistical relationships from text documents during a computationally intensive self-supervised and semi-supervised training process. LLMs can be used for text generation, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. - LLMs are artificial neural networks. The largest and most capable, as of March 2024, are built with a decoder-only transformer-based architecture while some recent implementations are based on other architectures, such as recurrent neural network variants and Mamba (a state space model). - Up to 2020, fine tuning was the only way a model could be adapted to be able to accomplish specific tasks. Larger sized models, such as GPT-3, however, can be prompt-engineered to achieve similar results.[6] They are thought to acquire knowledge about syntax, semantics and "ontology" inherent in human language corpora, but also inaccuracies and biases present in the corpora. - Some notable LLMs are OpenAI's GPT series of models (e.g., GPT-3.5 and GPT-4, used in ChatGPT and Microsoft Copilot), Google's PaLM and Gemini (the latter of which is currently used in the chatbot of the same name), xAI's Grok, Meta's LLaMA family of open-source models, Anthropic's Claude models, Mistral AI's open source models, and Databricks' open source DBRX. - """ + # text = """A large language model (LLM) is a language model notable for its ability to achieve general-purpose language generation and other natural language processing tasks such as classification. LLMs acquire these abilities by learning statistical relationships from text documents during a computationally intensive self-supervised and semi-supervised training process. LLMs can be used for text generation, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. + # LLMs are artificial neural networks. The largest and most capable, as of March 2024, are built with a decoder-only transformer-based architecture while some recent implementations are based on other architectures, such as recurrent neural network variants and Mamba (a state space model). + # Up to 2020, fine tuning was the only way a model could be adapted to be able to accomplish specific tasks. Larger sized models, such as GPT-3, however, can be prompt-engineered to achieve similar results.[6] They are thought to acquire knowledge about syntax, semantics and "ontology" inherent in human language corpora, but also inaccuracies and biases present in the corpora. + # Some notable LLMs are OpenAI's GPT series of models (e.g., GPT-3.5 and GPT-4, used in ChatGPT and Microsoft Copilot), Google's PaLM and Gemini (the latter of which is currently used in the chatbot of the same name), xAI's Grok, Meta's LLaMA family of open-source models, Anthropic's Claude models, Mistral AI's open source models, and Databricks' open source DBRX. + # """ - await cognee.add([text], dataset_name) + # await cognee.add([text], dataset_name) await cognee.cognify([dataset_name]) @@ -42,27 +42,27 @@ async def main(): random_node = (await vector_engine.search("entities", "AI"))[0] random_node_name = random_node.payload["name"] - search_results = await cognee.search("SIMILARITY", { "query": random_node_name }) + search_results = await cognee.search("SIMILARITY", params = { "query": random_node_name }) assert len(search_results) != 0, "The search results list is empty." print("\n\nExtracted sentences are:\n") for result in search_results: print(f"{result}\n") - search_results = await cognee.search("TRAVERSE", { "query": random_node_name }) + search_results = await cognee.search("TRAVERSE", params = { "query": random_node_name }) assert len(search_results) != 0, "The search results list is empty." print("\n\nExtracted sentences are:\n") for result in search_results: print(f"{result}\n") - search_results = await cognee.search("SUMMARY", { "query": random_node_name }) + search_results = await cognee.search("SUMMARY", params = { "query": random_node_name }) assert len(search_results) != 0, "Query related summaries don't exist." print("\n\nQuery related summaries exist:\n") for result in search_results: print(f"{result}\n") - search_results = await cognee.search("ADJACENT", { "query": random_node_name }) + search_results = await cognee.search("ADJACENT", params = { "query": random_node_name }) assert len(search_results) != 0, "Large language model query found no neighbours." - print("\n\Large language model query found neighbours.\n") + print("\n\nLarge language model query found neighbours.\n") for result in search_results: print(f"{result}\n") From 73dd6c26b8ad8ec8d7deec612e4973deb1907d1c Mon Sep 17 00:00:00 2001 From: Vasilije <8619304+Vasilije1990@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:58:13 +0200 Subject: [PATCH 22/44] Fix to neo4j flow --- .github/workflows/test_neo4j.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/test_neo4j.yml b/.github/workflows/test_neo4j.yml index fa6e30e27..e2236f9e3 100644 --- a/.github/workflows/test_neo4j.yml +++ b/.github/workflows/test_neo4j.yml @@ -28,6 +28,18 @@ jobs: run: shell: bash + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + steps: - name: Check out uses: actions/checkout@v2 @@ -44,6 +56,13 @@ jobs: virtualenvs-in-project: true installer-parallel: true + - name: Wait for PostgreSQL to be ready + run: | + echo "Waiting for PostgreSQL to be ready..." + until pg_isready -h localhost -p 5432 -U cognee; do + sleep 1 + done + - name: Install dependencies run: poetry install --no-interaction @@ -60,4 +79,9 @@ jobs: GRAPH_DATABASE_PASSWORD: ${{ secrets.NEO4J_API_KEY }} GRAPH_DATABASE_USERNAME: "neo4j" ENV: 'dev' + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 run: poetry run python ./cognee/tests/test_neo4j.py From cb9bfa27ea23899127678e227a767d98cd83bcbd Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:23:36 +0200 Subject: [PATCH 23/44] fix: search results preview --- cognee-frontend/src/app/page.tsx | 8 +-- .../src/modules/datasets/cognifyDataset.ts | 2 +- .../ingestion/DataView/DataView.module.css | 1 + .../modules/ingestion/DataView/DataView.tsx | 8 +-- .../ingestion/DatasetsView/DatasetsView.tsx | 4 +- .../src/modules/ingestion/useDatasets.ts | 1 - .../src/ui/Partials/SearchView/SearchView.tsx | 6 +- cognee/api/client.py | 46 ++++++------- cognee/api/v1/add/add.py | 3 + cognee/api/v1/cognify/cognify.py | 3 +- cognee/api/v1/cognify/cognify_v2.py | 68 +++++++++---------- cognee/api/v1/datasets/datasets.py | 6 +- cognee/api/v1/search/search.py | 58 ++++------------ .../sqlalchemy/SqlAlchemyAdapter.py | 9 --- .../data_summary/summarize_text_chunks.py | 1 + cognee/modules/data/models/Data.py | 12 ++++ cognee/modules/data/models/Dataset.py | 9 +++ .../data/operations/get_dataset_data.py | 18 +++++ .../data/operations/retrieve_datasets.py | 13 ++++ .../modules/pipelines/models/PipelineRun.py | 3 +- .../operations/get_pipeline_status.py | 9 +-- .../operations/log_pipeline_status.py | 5 +- .../modules/search/graph/search_similarity.py | 12 +++- cognee/modules/topology/topology.py | 56 --------------- cognee/modules/users/models/Permission.py | 8 +-- .../methods/check_permissions_on_documents.py | 5 +- .../methods/get_document_ids_for_user.py | 25 +++---- 27 files changed, 177 insertions(+), 222 deletions(-) create mode 100644 cognee/modules/data/operations/get_dataset_data.py create mode 100644 cognee/modules/data/operations/retrieve_datasets.py diff --git a/cognee-frontend/src/app/page.tsx b/cognee-frontend/src/app/page.tsx index 20676c15e..e1aafe01b 100644 --- a/cognee-frontend/src/app/page.tsx +++ b/cognee-frontend/src/app/page.tsx @@ -48,15 +48,15 @@ export default function Home() { }); }, [showNotification]) - const onDatasetCognify = useCallback((dataset: { id: string }) => { - showNotification(`Cognification started for dataset "${dataset.id}".`, 5000); + const onDatasetCognify = useCallback((dataset: { id: string, name: string }) => { + showNotification(`Cognification started for dataset "${dataset.name}".`, 5000); return cognifyDataset(dataset) .then(() => { - showNotification(`Dataset "${dataset.id}" cognified.`, 5000); + showNotification(`Dataset "${dataset.name}" cognified.`, 5000); }) .catch(() => { - showNotification(`Dataset "${dataset.id}" cognification failed. Please try again.`, 5000); + showNotification(`Dataset "${dataset.name}" cognification failed. Please try again.`, 5000); }); }, [showNotification]); diff --git a/cognee-frontend/src/modules/datasets/cognifyDataset.ts b/cognee-frontend/src/modules/datasets/cognifyDataset.ts index ae7a8e827..18bb56c5d 100644 --- a/cognee-frontend/src/modules/datasets/cognifyDataset.ts +++ b/cognee-frontend/src/modules/datasets/cognifyDataset.ts @@ -1,4 +1,4 @@ -export default function cognifyDataset(dataset: { id: string }) { +export default function cognifyDataset(dataset: { id: string, name: string }) { return fetch('http://127.0.0.1:8000/cognify', { method: 'POST', headers: { diff --git a/cognee-frontend/src/modules/ingestion/DataView/DataView.module.css b/cognee-frontend/src/modules/ingestion/DataView/DataView.module.css index 69ce64e54..e79e63c31 100644 --- a/cognee-frontend/src/modules/ingestion/DataView/DataView.module.css +++ b/cognee-frontend/src/modules/ingestion/DataView/DataView.module.css @@ -12,6 +12,7 @@ } .dataTable { + color: white; border-collapse: collapse; } .dataTable td, .dataTable th { diff --git a/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx b/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx index 288241e43..617929793 100644 --- a/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx +++ b/cognee-frontend/src/modules/ingestion/DataView/DataView.tsx @@ -13,8 +13,9 @@ import RawDataPreview from './RawDataPreview'; export interface Data { id: string; name: string; - filePath: string; mimeType: string; + extension: string; + rawDataLocation: string; } interface DatasetLike { @@ -80,7 +81,6 @@ export default function DataView({ datasetId, data, onClose, onDataAdd }: DataVi Name File path MIME type - Keywords @@ -104,10 +104,10 @@ export default function DataView({ datasetId, data, onClose, onDataAdd }: DataVi {dataItem.id} - {dataItem.name} + {dataItem.name}.{dataItem.extension} - {dataItem.filePath} + {dataItem.rawDataLocation} {dataItem.mimeType} diff --git a/cognee-frontend/src/modules/ingestion/DatasetsView/DatasetsView.tsx b/cognee-frontend/src/modules/ingestion/DatasetsView/DatasetsView.tsx index 6babeaa3e..2b27fee32 100644 --- a/cognee-frontend/src/modules/ingestion/DatasetsView/DatasetsView.tsx +++ b/cognee-frontend/src/modules/ingestion/DatasetsView/DatasetsView.tsx @@ -40,7 +40,7 @@ export default function DatasetsView({ .finally(() => enableCognifyRun()); } - const [dataset, setExplorationDataset] = useState<{ id: string } | null>(null); + const [dataset, setExplorationDataset] = useState<{ id: string, name: string } | null>(null); const { value: isExplorationWindowShown, setTrue: showExplorationWindow, @@ -97,7 +97,7 @@ export default function DatasetsView({ - {dataset?.id} + {dataset?.name} diff --git a/cognee-frontend/src/modules/ingestion/useDatasets.ts b/cognee-frontend/src/modules/ingestion/useDatasets.ts index 402b25a07..53d94e2ab 100644 --- a/cognee-frontend/src/modules/ingestion/useDatasets.ts +++ b/cognee-frontend/src/modules/ingestion/useDatasets.ts @@ -67,7 +67,6 @@ function useDatasets() { const fetchDatasets = useCallback(() => { fetch('http://127.0.0.1:8000/datasets') .then((response) => response.json()) - .then((datasets) => datasets.map((dataset: string) => ({ id: dataset, name: dataset }))) .then((datasets) => { setDatasets(datasets); diff --git a/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx b/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx index d94c83004..3d3b6af85 100644 --- a/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx +++ b/cognee-frontend/src/ui/Partials/SearchView/SearchView.tsx @@ -7,7 +7,7 @@ import styles from './SearchView.module.css'; interface Message { id: string; user: 'user' | 'system'; - text: string; + text: any; } interface SelectOption { @@ -98,7 +98,9 @@ export default function SearchView() { [styles.userMessage]: message.user === "user", })} > - {message.text} + {message?.text && ( + typeof(message.text) == "string" ? message.text : JSON.stringify(message.text) + )} ))} diff --git a/cognee/api/client.py b/cognee/api/client.py index b8f578d22..89292cd39 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -108,7 +108,7 @@ def health_check(): """ return {"status": "OK"} -@app.get("/datasets", response_model=list) +@app.get("/datasets", response_model = list) async def get_datasets(): try: from cognee.api.v1.datasets.datasets import datasets @@ -116,18 +116,12 @@ async def get_datasets(): return JSONResponse( status_code = 200, - content = [{ - "id": str(dataset.id), - "name": dataset.name, - "created_at": dataset.created_at, - "updated_at": dataset.updated_at, - "data": dataset.data, - } for dataset in datasets], + content = [dataset.to_json() for dataset in datasets], ) except Exception as error: raise HTTPException(status_code = 500, detail=f"Error retrieving datasets: {str(error)}") from error -@app.delete("/datasets/{dataset_id}", response_model=dict) +@app.delete("/datasets/{dataset_id}", response_model = dict) async def delete_dataset(dataset_id: str): from cognee.api.v1.datasets.datasets import datasets await datasets.delete_dataset(dataset_id) @@ -159,17 +153,14 @@ async def get_dataset_graph(dataset_id: str): @app.get("/datasets/{dataset_id}/data", response_model=list) async def get_dataset_data(dataset_id: str): from cognee.api.v1.datasets.datasets import datasets - dataset_data = await datasets.list_data(dataset_id) + + dataset_data = await datasets.list_data(dataset_id = dataset_id) + if dataset_data is None: - raise HTTPException(status_code=404, detail=f"Dataset ({dataset_id}) not found.") + raise HTTPException(status_code = 404, detail = f"Dataset ({dataset_id}) not found.") + return [ - dict( - id=data["id"], - name=f"{data['name']}.{data['extension']}", - filePath=data["file_path"], - mimeType=data["mime_type"], - ) - for data in dataset_data + data.to_json() for data in dataset_data ] @app.get("/datasets/status", response_model=dict) @@ -193,10 +184,12 @@ async def get_dataset_status(datasets: Annotated[List[str], Query(alias="dataset async def get_raw_data(dataset_id: str, data_id: str): from cognee.api.v1.datasets.datasets import datasets dataset_data = await datasets.list_data(dataset_id) + if dataset_data is None: - raise HTTPException(status_code=404, detail=f"Dataset ({dataset_id}) not found.") - data = [data for data in dataset_data if data["id"] == data_id][0] - return data["file_path"] + raise HTTPException(status_code = 404, detail = f"Dataset ({dataset_id}) not found.") + + data = [data for data in dataset_data if str(data.id) == data_id][0] + return data.raw_data_location class AddPayload(BaseModel): data: Union[str, UploadFile, List[Union[str, UploadFile]]] @@ -276,18 +269,21 @@ async def search(payload: SearchPayload): from cognee.api.v1.search import search as cognee_search try: search_type = payload.query_params["searchType"] + params = { "query": payload.query_params["query"], } + results = await cognee_search(search_type, params) + return JSONResponse( - status_code=200, - content=json.dumps(results) + status_code = 200, + content = results, ) except Exception as error: return JSONResponse( - status_code=409, - content={"error": str(error)} + status_code = 409, + content = {"error": str(error)} ) @app.get("/settings", response_model=dict) diff --git a/cognee/api/v1/add/add.py b/cognee/api/v1/add/add.py index 31a36316b..90e259508 100644 --- a/cognee/api/v1/add/add.py +++ b/cognee/api/v1/add/add.py @@ -130,6 +130,7 @@ async def add_files(file_paths: List[str], dataset_name: str, user): await session.merge(data) else: data = Data( + id = data_id, name = file_metadata["name"], raw_data_location = file_metadata["file_path"], extension = file_metadata["extension"], @@ -139,6 +140,8 @@ async def add_files(file_paths: List[str], dataset_name: str, user): await session.merge(dataset) + await session.commit() + yield { "id": data_id, "name": file_metadata["name"], diff --git a/cognee/api/v1/cognify/cognify.py b/cognee/api/v1/cognify/cognify.py index e695be405..a11a2cb8b 100644 --- a/cognee/api/v1/cognify/cognify.py +++ b/cognee/api/v1/cognify/cognify.py @@ -30,6 +30,7 @@ from cognee.shared.utils import send_telemetry from cognee.modules.tasks import create_task_status_table, update_task_status from cognee.shared.SourceCodeGraph import SourceCodeGraph from cognee.modules.tasks import get_task_status +from cognee.modules.data.operations.get_dataset_data import get_dataset_data from cognee.infrastructure.data.chunking.config import get_chunk_config from cognee.modules.cognify.config import get_cognify_config from cognee.infrastructure.databases.relational import get_relational_engine @@ -90,7 +91,7 @@ async def cognify(datasets: Union[str, List[str]] = None): for added_dataset in added_datasets: if dataset_name in added_dataset: - dataset_files.append((added_dataset, db_engine.get_files_metadata(added_dataset))) + dataset_files.append((added_dataset, await get_dataset_data(dataset_name = added_dataset))) chunk_config = get_chunk_config() chunk_engine = get_chunk_engine() diff --git a/cognee/api/v1/cognify/cognify_v2.py b/cognee/api/v1/cognify/cognify_v2.py index 163dda67d..9f2f95398 100644 --- a/cognee/api/v1/cognify/cognify_v2.py +++ b/cognee/api/v1/cognify/cognify_v2.py @@ -17,6 +17,9 @@ from cognee.modules.data.processing.filter_affected_chunks import filter_affecte from cognee.modules.data.processing.remove_obsolete_chunks import remove_obsolete_chunks from cognee.modules.data.extraction.knowledge_graph.expand_knowledge_graph import expand_knowledge_graph from cognee.modules.data.extraction.knowledge_graph.establish_graph_topology import establish_graph_topology +from cognee.modules.data.models import Dataset, Data +from cognee.modules.data.operations.get_dataset_data import get_dataset_data +from cognee.modules.data.operations.retrieve_datasets import retrieve_datasets from cognee.modules.pipelines.tasks.Task import Task from cognee.modules.pipelines import run_tasks, run_tasks_parallel from cognee.modules.users.models import User @@ -40,20 +43,25 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): if datasets is None or len(datasets) == 0: return await cognify(await db_engine.get_datasets()) + if type(datasets[0]) == str: + datasets = await retrieve_datasets(datasets) if user is None: user = await get_default_user() - async def run_cognify_pipeline(dataset_name: str, files: list[dict]): + async def run_cognify_pipeline(dataset: Dataset): + data: list[Data] = await get_dataset_data(dataset_id = dataset.id) + documents = [ - PdfDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "pdf" else - AudioDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "audio" else - ImageDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) if file["extension"] == "image" else - TextDocument(id = file["id"], title=f"{file['name']}.{file['extension']}", file_path=file["file_path"]) - for file in files + PdfDocument(id = data_item.id, title=f"{data_item.name}.{data_item.extension}", file_path=data_item.raw_data_location) if data_item.extension == "pdf" else + AudioDocument(id = data_item.id, title=f"{data_item.name}.{data_item.extension}", file_path=data_item.raw_data_location) if data_item.extension == "audio" else + ImageDocument(id = data_item.id, title=f"{data_item.name}.{data_item.extension}", file_path=data_item.raw_data_location) if data_item.extension == "image" else + TextDocument(id = data_item.id, title=f"{data_item.name}.{data_item.extension}", file_path=data_item.raw_data_location) + for data_item in data ] document_ids = [document.id for document in documents] + document_ids_str = list(map(str, document_ids)) await check_permissions_on_documents( user, @@ -61,16 +69,19 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): document_ids, ) - async with update_status_lock: - task_status = await get_pipeline_status([dataset_name]) + dataset_id = dataset.id + dataset_name = generate_dataset_name(dataset.name) - if dataset_name in task_status and task_status[dataset_name] == "DATASET_PROCESSING_STARTED": - logger.info(f"Dataset {dataset_name} is being processed.") + async with update_status_lock: + task_status = await get_pipeline_status([dataset_id]) + + if dataset_id in task_status and task_status[dataset_id] == "DATASET_PROCESSING_STARTED": + logger.info("Dataset %s is already being processed.", dataset_name) return - await log_pipeline_status(dataset_name, "DATASET_PROCESSING_STARTED", { + await log_pipeline_status(dataset_id, "DATASET_PROCESSING_STARTED", { "dataset_name": dataset_name, - "files": document_ids, + "files": document_ids_str, }) try: cognee_config = get_cognify_config() @@ -80,7 +91,7 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): if graph_config.infer_graph_topology and graph_config.graph_topology_task: from cognee.modules.topology.topology import TopologyEngine topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) - root_node_id = await topology_engine.add_graph_topology(files = files) + root_node_id = await topology_engine.add_graph_topology(files = data) elif graph_config.infer_graph_topology and not graph_config.infer_graph_topology: from cognee.modules.topology.topology import TopologyEngine topology_engine = TopologyEngine(infer=graph_config.infer_graph_topology) @@ -116,14 +127,14 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): async for result in pipeline: print(result) - await log_pipeline_status(dataset_name, "DATASET_PROCESSING_FINISHED", { + await log_pipeline_status(dataset_id, "DATASET_PROCESSING_FINISHED", { "dataset_name": dataset_name, - "files": document_ids, + "files": document_ids_str, }) except Exception as error: - await log_pipeline_status(dataset_name, "DATASET_PROCESSING_ERROR", { + await log_pipeline_status(dataset_id, "DATASET_PROCESSING_ERROR", { "dataset_name": dataset_name, - "files": document_ids, + "files": document_ids_str, }) raise error @@ -131,31 +142,14 @@ async def cognify(datasets: Union[str, list[str]] = None, user: User = None): existing_datasets = [dataset.name for dataset in list(await db_engine.get_datasets())] awaitables = [] - for dataset_name in datasets: - dataset_name = generate_dataset_name(dataset_name) + for dataset in datasets: + dataset_name = generate_dataset_name(dataset.name) if dataset_name in existing_datasets: - awaitables.append(run_cognify_pipeline(dataset_name, await db_engine.get_files_metadata(dataset_name))) + awaitables.append(run_cognify_pipeline(dataset)) return await asyncio.gather(*awaitables) def generate_dataset_name(dataset_name: str) -> str: return dataset_name.replace(".", "_").replace(" ", "_") - -# -# if __name__ == "__main__": -# from cognee.api.v1.add import add -# from cognee.api.v1.datasets.datasets import datasets -# -# -# async def aa(): -# await add("TEXT ABOUT NLP AND MONKEYS") -# -# print(datasets.discover_datasets()) -# -# return - - - - # asyncio.run(cognify()) diff --git a/cognee/api/v1/datasets/datasets.py b/cognee/api/v1/datasets/datasets.py index 8a44e0411..2054d7dcd 100644 --- a/cognee/api/v1/datasets/datasets.py +++ b/cognee/api/v1/datasets/datasets.py @@ -1,5 +1,6 @@ from duckdb import CatalogException from cognee.modules.ingestion import discover_directory_datasets +from cognee.modules.data.operations.get_dataset_data import get_dataset_data from cognee.modules.pipelines.operations.get_pipeline_status import get_pipeline_status from cognee.infrastructure.databases.relational import get_relational_engine @@ -14,10 +15,9 @@ class datasets(): return list(discover_directory_datasets(directory_path).keys()) @staticmethod - async def list_data(dataset_name: str): - db = get_relational_engine() + async def list_data(dataset_id: str, dataset_name: str = None): try: - return await db.get_files_metadata(dataset_name) + return await get_dataset_data(dataset_id = dataset_id, dataset_name = dataset_name) except CatalogException: return None diff --git a/cognee/api/v1/search/search.py b/cognee/api/v1/search/search.py index 08c325576..551bb270e 100644 --- a/cognee/api/v1/search/search.py +++ b/cognee/api/v1/search/search.py @@ -28,15 +28,15 @@ class SearchType(Enum): def from_str(name: str): try: return SearchType[name.upper()] - except KeyError: - raise ValueError(f"{name} is not a valid SearchType") + except KeyError as error: + raise ValueError(f"{name} is not a valid SearchType") from error class SearchParameters(BaseModel): search_type: SearchType params: Dict[str, Any] @field_validator("search_type", mode="before") - def convert_string_to_enum(cls, value): + def convert_string_to_enum(cls, value): # pylint: disable=no-self-argument if isinstance(value, str): return SearchType.from_str(value) return value @@ -46,20 +46,21 @@ async def search(search_type: str, params: Dict[str, Any], user: User = None) -> if user is None: user = await get_default_user() - extract_documents = await get_document_ids_for_user(user.id) + own_document_ids = await get_document_ids_for_user(user.id) search_params = SearchParameters(search_type = search_type, params = params) - searches = await specific_search([search_params]) + search_results = await specific_search([search_params]) - filtered_searches = [] - for document in searches: - for document_id in extract_documents: - if document_id in document: - filtered_searches.append(document) + from uuid import UUID + filtered_search_results = [] - return filtered_searches + for search_result in search_results: + result_document_id = UUID(search_result["document_id"]) if "document_id" in search_result else None + if result_document_id is None or result_document_id in own_document_ids: + filtered_search_results.append(search_result) + return filtered_search_results async def specific_search(query_params: List[SearchParameters]) -> List: @@ -71,7 +72,6 @@ async def specific_search(query_params: List[SearchParameters]) -> List: SearchType.SIMILARITY: search_similarity, } - results = [] search_tasks = [] for search_param in query_params: @@ -84,38 +84,6 @@ async def specific_search(query_params: List[SearchParameters]) -> List: # Use asyncio.gather to run all scheduled tasks concurrently search_results = await asyncio.gather(*search_tasks) - # Update the results set with the results from all tasks - results.extend(search_results) - send_telemetry("cognee.search") - return results[0] if len(results) == 1 else results - - - -if __name__ == "__main__": - async def main(): - # Assuming 'graph' is your graph object, obtained from somewhere - search_type = 'CATEGORIES' - params = {'query': 'Ministarstvo', 'other_param': {"node_id": "LLM_LAYER_SUMMARY:DOCUMENT:881ecb36-2819-54c3-8147-ed80293084d6"}} - - results = await search(search_type, params) - print(results) - - # Run the async main function - asyncio.run(main()) -# if __name__ == "__main__": -# import asyncio - -# query_params = { -# SearchType.SIMILARITY: {'query': 'your search query here'} -# } -# async def main(): -# graph_client = get_graph_engine() - -# await graph_client.load_graph_from_file() -# graph = graph_client.graph -# results = await search(graph, query_params) -# print(results) - -# asyncio.run(main()) + return search_results[0] if len(search_results) == 1 else search_results diff --git a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py index 7fcced7ec..c4b0a1e01 100644 --- a/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +++ b/cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py @@ -56,15 +56,6 @@ class SQLAlchemyAdapter(): await connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema_name};")) await connection.execute(text(f"CREATE TABLE IF NOT EXISTS {schema_name}.{table_name} ({', '.join(fields_query_parts)});")) - async def get_files_metadata(self, dataset_name: str): - async with self.engine.connect() as connection: - result = await connection.execute( - text(f"SELECT id, name, file_path, extension, mime_type FROM {dataset_name}.file_metadata;")) - rows = result.fetchall() - metadata = [{"id": row.id, "name": row.name, "file_path": row.file_path, "extension": row.extension, - "mime_type": row.mime_type} for row in rows] - return metadata - async def delete_table(self, table_name: str): async with self.engine.connect() as connection: await connection.execute(text(f"DROP TABLE IF EXISTS {table_name};")) diff --git a/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py b/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py index fa481a7d9..922ece6c9 100644 --- a/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py +++ b/cognee/modules/data/extraction/data_summary/summarize_text_chunks.py @@ -26,6 +26,7 @@ async def summarize_text_chunks(data_chunks: list[DocumentChunk], summarization_ id = str(chunk.chunk_id), payload = dict( chunk_id = str(chunk.chunk_id), + document_id = str(chunk.document_id), text = chunk_summaries[chunk_index].summary, ), embed_field = "text", diff --git a/cognee/modules/data/models/Data.py b/cognee/modules/data/models/Data.py index a1d20ebee..3985d4971 100644 --- a/cognee/modules/data/models/Data.py +++ b/cognee/modules/data/models/Data.py @@ -23,3 +23,15 @@ class Data(Base): secondary = DatasetData.__tablename__, back_populates = "data" ) + + def to_json(self) -> dict: + return { + "id": str(self.id), + "name": self.name, + "extension": self.extension, + "mimeType": self.mime_type, + "rawDataLocation": self.raw_data_location, + "createdAt": self.created_at.isoformat(), + "updatedAt": self.updated_at.isoformat() if self.updated_at else None, + # "datasets": [dataset.to_json() for dataset in self.datasets] + } diff --git a/cognee/modules/data/models/Dataset.py b/cognee/modules/data/models/Dataset.py index 32d26dac5..da52e7b09 100644 --- a/cognee/modules/data/models/Dataset.py +++ b/cognee/modules/data/models/Dataset.py @@ -20,3 +20,12 @@ class Dataset(Base): secondary = DatasetData.__tablename__, back_populates = "datasets" ) + + def to_json(self) -> dict: + return { + "id": str(self.id), + "name": self.name, + "createdAt": self.created_at.isoformat(), + "updatedAt": self.updated_at.isoformat() if self.updated_at else None, + "data": [data.to_json() for data in self.data] + } diff --git a/cognee/modules/data/operations/get_dataset_data.py b/cognee/modules/data/operations/get_dataset_data.py new file mode 100644 index 000000000..f086591eb --- /dev/null +++ b/cognee/modules/data/operations/get_dataset_data.py @@ -0,0 +1,18 @@ +from uuid import UUID +from sqlalchemy import select +from cognee.modules.data.models import Data, Dataset +from cognee.infrastructure.databases.relational import get_relational_engine + +async def get_dataset_data(dataset_id: UUID = None, dataset_name: str = None): + if dataset_id is None and dataset_name is None: + raise ValueError("get_dataset_data: Either dataset_id or dataset_name must be provided.") + + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + result = await session.execute( + select(Data).join(Data.datasets).filter((Dataset.id == dataset_id) | (Dataset.name == dataset_name)) + ) + data = result.scalars().all() + + return data diff --git a/cognee/modules/data/operations/retrieve_datasets.py b/cognee/modules/data/operations/retrieve_datasets.py new file mode 100644 index 000000000..0be2071c0 --- /dev/null +++ b/cognee/modules/data/operations/retrieve_datasets.py @@ -0,0 +1,13 @@ +from sqlalchemy import select +from cognee.infrastructure.databases.relational import get_relational_engine +from ..models import Dataset + +async def retrieve_datasets(dataset_names: list[str]) -> list[Dataset]: + db_engine = get_relational_engine() + + async with db_engine.get_async_session() as session: + datasets = (await session.scalars( + select(Dataset).filter(Dataset.name.in_(dataset_names)) + )).all() + + return datasets diff --git a/cognee/modules/pipelines/models/PipelineRun.py b/cognee/modules/pipelines/models/PipelineRun.py index fd34b8d98..ccd5e9eeb 100644 --- a/cognee/modules/pipelines/models/PipelineRun.py +++ b/cognee/modules/pipelines/models/PipelineRun.py @@ -10,8 +10,7 @@ class PipelineRun(Base): created_at = Column(DateTime(timezone = True), default = lambda: datetime.now(timezone.utc)) - run_name = Column(String, index = True) - status = Column(String) + run_id = Column(UUID(as_uuid = True), index = True) run_info = Column(JSON) diff --git a/cognee/modules/pipelines/operations/get_pipeline_status.py b/cognee/modules/pipelines/operations/get_pipeline_status.py index 2f190ac3b..4249d3bf0 100644 --- a/cognee/modules/pipelines/operations/get_pipeline_status.py +++ b/cognee/modules/pipelines/operations/get_pipeline_status.py @@ -1,19 +1,20 @@ +from uuid import UUID from sqlalchemy import func, select from sqlalchemy.orm import aliased from cognee.infrastructure.databases.relational import get_relational_engine from ..models import PipelineRun -async def get_pipeline_status(pipeline_names: [str]): +async def get_pipeline_status(pipeline_ids: list[UUID]): db_engine = get_relational_engine() async with db_engine.get_async_session() as session: query = select( PipelineRun, func.row_number().over( - partition_by = PipelineRun.run_name, + partition_by = PipelineRun.run_id, order_by = PipelineRun.created_at.desc(), ).label("rn") - ).filter(PipelineRun.run_name.in_(pipeline_names)).subquery() + ).filter(PipelineRun.run_id.in_(pipeline_ids)).subquery() aliased_pipeline_run = aliased(PipelineRun, query) @@ -24,7 +25,7 @@ async def get_pipeline_status(pipeline_names: [str]): runs = (await session.execute(latest_runs)).scalars().all() pipeline_statuses = { - run.run_name: run.status for run in runs + str(run.run_id): run.status for run in runs } return pipeline_statuses diff --git a/cognee/modules/pipelines/operations/log_pipeline_status.py b/cognee/modules/pipelines/operations/log_pipeline_status.py index 5b484ebf3..94872dee4 100644 --- a/cognee/modules/pipelines/operations/log_pipeline_status.py +++ b/cognee/modules/pipelines/operations/log_pipeline_status.py @@ -1,12 +1,13 @@ +from uuid import UUID from cognee.infrastructure.databases.relational import get_relational_engine from ..models.PipelineRun import PipelineRun -async def log_pipeline_status(run_name: str, status: str, run_info: dict): +async def log_pipeline_status(run_id: UUID, status: str, run_info: dict): db_engine = get_relational_engine() async with db_engine.get_async_session() as session: session.add(PipelineRun( - run_name = run_name, + run_id = run_id, status = status, run_info = run_info, )) diff --git a/cognee/modules/search/graph/search_similarity.py b/cognee/modules/search/graph/search_similarity.py index 24bb17ba4..dd48ce382 100644 --- a/cognee/modules/search/graph/search_similarity.py +++ b/cognee/modules/search/graph/search_similarity.py @@ -12,6 +12,16 @@ async def search_similarity(query: str) -> list[str, str]: similar_results = await vector_engine.search("chunks", query, limit = 5) - results = [result.payload for result in similar_results] + results = [ + parse_payload(result.payload) for result in similar_results + ] return results + + +def parse_payload(payload: dict) -> dict: + return { + "text": payload["text"], + "chunk_id": payload["chunk_id"], + "document_id": payload["document_id"], + } diff --git a/cognee/modules/topology/topology.py b/cognee/modules/topology/topology.py index 95ee510e5..9f8c82bee 100644 --- a/cognee/modules/topology/topology.py +++ b/cognee/modules/topology/topology.py @@ -3,10 +3,8 @@ import csv import json import logging -import os from typing import Any, Dict, List, Optional, Union, Type -import asyncio import aiofiles import pandas as pd from pydantic import BaseModel @@ -14,16 +12,10 @@ from pydantic import BaseModel from cognee.infrastructure.data.chunking.config import get_chunk_config from cognee.infrastructure.data.chunking.get_chunking_engine import get_chunk_engine from cognee.infrastructure.databases.graph.get_graph_engine import get_graph_engine -from cognee.infrastructure.databases.relational import get_relational_engine from cognee.infrastructure.files.utils.extract_text_from_file import extract_text_from_file from cognee.infrastructure.files.utils.guess_file_type import guess_file_type, FileTypeException -from cognee.modules.cognify.config import get_cognify_config -from cognee.base_config import get_base_config from cognee.modules.topology.topology_data_models import NodeModel -cognify_config = get_cognify_config() -base_config = get_base_config() - logger = logging.getLogger("topology") class TopologyEngine: @@ -136,51 +128,3 @@ class TopologyEngine: return except Exception as e: raise RuntimeError(f"Failed to add graph topology from {file_path}: {e}") from e - - - -async def main(): - # text = """Conservative PP in the lead in Spain, according to estimate - # An estimate has been published for Spain: - # - # Opposition leader Alberto Núñez Feijóo’s conservative People’s party (PP): 32.4% - # - # Spanish prime minister Pedro Sánchez’s Socialist party (PSOE): 30.2% - # - # The far-right Vox party: 10.4% - # - # In Spain, the right has sought to turn the European election into a referendum on Sánchez. - # - # Ahead of the vote, public attention has focused on a saga embroiling the prime minister’s wife, Begoña Gómez, who is being investigated over allegations of corruption and influence-peddling, which Sanchez has dismissed as politically-motivated and totally baseless.""" - # text_two = """The far-right Vox party: 10.4%""" - - from cognee.api.v1.add import add - dataset_name = "explanations" - print(os.getcwd()) - data_dir = os.path.abspath("../../.data") - print(os.getcwd()) - - await add(f"data://{data_dir}", dataset_name="explanations") - - db_engine = get_relational_engine() - - datasets = await db_engine.get_datasets() - dataset_files =[] - - for added_dataset in datasets: - if dataset_name in added_dataset: - dataset_files.append((added_dataset, db_engine.get_files_metadata(added_dataset))) - - - - print(dataset_files) - topology_engine = TopologyEngine(infer=True) - file_path = "example_data.json" # or 'example_data.csv' - # - # # Adding graph topology - graph = await topology_engine.add_graph_topology(file_path, files = dataset_files) - print(graph) - -# Run the main function -if __name__ == "__main__": - asyncio.run(main()) diff --git a/cognee/modules/users/models/Permission.py b/cognee/modules/users/models/Permission.py index 41ed8b135..44d719f99 100644 --- a/cognee/modules/users/models/Permission.py +++ b/cognee/modules/users/models/Permission.py @@ -1,6 +1,6 @@ from uuid import uuid4 from datetime import datetime, timezone -# from sqlalchemy.orm import relationship, Mapped +# from sqlalchemy.orm import relationship from sqlalchemy import Column, DateTime, UUID, String from cognee.infrastructure.databases.relational import Base @@ -15,9 +15,3 @@ class Permission(Base): name = Column(String, unique = True, nullable = False, index = True) # acls = relationship("ACL", back_populates = "permission") - - # groups: Mapped[list["Group"]] = relationship( - # "Group", - # secondary = "group_permissions", - # back_populates = "permissions", - # ) diff --git a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py index 4464f0f24..01e04ae26 100644 --- a/cognee/modules/users/permissions/methods/check_permissions_on_documents.py +++ b/cognee/modules/users/permissions/methods/check_permissions_on_documents.py @@ -1,4 +1,5 @@ import logging +from uuid import UUID from sqlalchemy import select from sqlalchemy.orm import joinedload from cognee.infrastructure.databases.relational import get_relational_engine @@ -14,7 +15,7 @@ class PermissionDeniedException(Exception): super().__init__(self.message) -async def check_permissions_on_documents(user: User, permission_type: str, document_ids: list[str]): +async def check_permissions_on_documents(user: User, permission_type: str, document_ids: list[UUID]): try: user_group_ids = [group.id for group in user.groups] @@ -29,7 +30,7 @@ async def check_permissions_on_documents(user: User, permission_type: str, docum .where(ACL.permission.has(name = permission_type)) ) acls = result.unique().scalars().all() - resource_ids = [str(resource.resource_id) for acl in acls for resource in acl.resources] + resource_ids = [resource.resource_id for acl in acls for resource in acl.resources] has_permissions = all(document_id in resource_ids for document_id in document_ids) if not has_permissions: diff --git a/cognee/modules/users/permissions/methods/get_document_ids_for_user.py b/cognee/modules/users/permissions/methods/get_document_ids_for_user.py index 47f33b2c7..79736db0f 100644 --- a/cognee/modules/users/permissions/methods/get_document_ids_for_user.py +++ b/cognee/modules/users/permissions/methods/get_document_ids_for_user.py @@ -1,24 +1,21 @@ from uuid import UUID from sqlalchemy import select from cognee.infrastructure.databases.relational import get_relational_engine -from ...models import ACL +from ...models import ACL, Resource, Permission async def get_document_ids_for_user(user_id: UUID) -> list[str]: db_engine = get_relational_engine() async with db_engine.get_async_session() as session: async with session.begin(): - result = await session.execute( - select(ACL.resources.resource_id) \ - .join(ACL.resources) \ - .filter_by( - ACL.principal_id == user_id, - ACL.permission.name == "read", - ) - ) - document_ids = [row[0] for row in result.scalars().all()] + document_ids = (await session.scalars( + select(Resource.resource_id) + .join(ACL.resources) + .join(ACL.permission) + .where( + ACL.principal_id == user_id, + Permission.name == "read", + ) + )).all() + return document_ids - - - - From 78462912ccd0e591a4a265557dd42b27fd750996 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:33:09 +0200 Subject: [PATCH 24/44] fix: add buildx action --- .github/workflows/docker_compose.yml | 12 +++--------- .github/workflows/test_neo4j.yml | 4 ++++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docker_compose.yml b/.github/workflows/docker_compose.yml index bba26cd74..8ef6f3c31 100644 --- a/.github/workflows/docker_compose.yml +++ b/.github/workflows/docker_compose.yml @@ -21,24 +21,18 @@ jobs: - name: Build Docker images run: | - docker-compose -f docker-compose.yml build + docker compose -f docker-compose.yml build - name: Run Docker Compose run: | - docker-compose -f docker-compose.yml up -d + docker compose -f docker-compose.yml up -d - name: Wait for services to be ready run: | # Add any necessary health checks or wait commands sleep 30 - # - name: Run tests - # run: | - # docker-compose -f docker-compose.yml run --rm - # # Replace with the name of the service running the tests - # # Replace with the actual command to run your tests - - name: Shut down Docker Compose if: always() run: | - docker-compose -f docker-compose.yml down + docker compose -f docker-compose.yml down diff --git a/.github/workflows/test_neo4j.yml b/.github/workflows/test_neo4j.yml index e2236f9e3..8f6c742ef 100644 --- a/.github/workflows/test_neo4j.yml +++ b/.github/workflows/test_neo4j.yml @@ -18,6 +18,10 @@ jobs: name: docs changes uses: ./.github/workflows/get_docs_changes.yml + setup_docker: + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + run_neo4j_integration_test: name: test needs: get_docs_changes From acf41ff6449b90a2a1c763ac94383a4e7e144758 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:36:15 +0200 Subject: [PATCH 25/44] fix: upgrade setup-buildx-action --- .github/workflows/test_neo4j.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_neo4j.yml b/.github/workflows/test_neo4j.yml index 8f6c742ef..09ca2b1bf 100644 --- a/.github/workflows/test_neo4j.yml +++ b/.github/workflows/test_neo4j.yml @@ -20,7 +20,7 @@ jobs: setup_docker: name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 run_neo4j_integration_test: name: test From 3f35a45a479218e22f7a5c49520a1c86c9f7995d Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:41:51 +0200 Subject: [PATCH 26/44] fix: add setup_docker job --- .github/workflows/test_neo4j.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_neo4j.yml b/.github/workflows/test_neo4j.yml index 09ca2b1bf..45c4fd198 100644 --- a/.github/workflows/test_neo4j.yml +++ b/.github/workflows/test_neo4j.yml @@ -20,13 +20,16 @@ jobs: setup_docker: name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + runs-on: ubuntu-latest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 run_neo4j_integration_test: name: test needs: get_docs_changes if: needs.get_docs_changes.outputs.changes_outside_docs == 'true' - runs-on: macos-latest + runs-on: ubuntu-latest defaults: run: From 3e3134b19fbe2dc83ebd6802a5efb301337eb36f Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:45:40 +0200 Subject: [PATCH 27/44] fix: fix debugpy version --- poetry.lock | 391 +++++++++++++++++++++++++++---------------------- pyproject.toml | 2 +- 2 files changed, 213 insertions(+), 180 deletions(-) diff --git a/poetry.lock b/poetry.lock index 57d991304..b20898e95 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -621,17 +621,17 @@ css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "boto3" -version = "1.34.153" +version = "1.34.154" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.153-py3-none-any.whl", hash = "sha256:ff9af9206fb235605cb65922f9090fe60f78ea89b4adc463f8f6391b30a3df03"}, - {file = "boto3-1.34.153.tar.gz", hash = "sha256:db9f2ac64582d847003a71720cd28dfffff61e2882e5d3db8e0c1fe1902ebb5b"}, + {file = "boto3-1.34.154-py3-none-any.whl", hash = "sha256:7ca22adef4c77ee128e1e1dc7d48bc9512a87cc6fe3d771b3f913d5ecd41c057"}, + {file = "boto3-1.34.154.tar.gz", hash = "sha256:864f06528c583dc7b02adf12db395ecfadbf9cb0da90e907e848ffb27128ce19"}, ] [package.dependencies] -botocore = ">=1.34.153,<1.35.0" +botocore = ">=1.34.154,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -640,13 +640,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.153" +version = "1.34.154" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.153-py3-none-any.whl", hash = "sha256:9fc2ad40be8c103ab9bfcb48b97b117d299d0b3a542cdd30134ee2935bee827a"}, - {file = "botocore-1.34.153.tar.gz", hash = "sha256:1634a00f996cfff67f0fd4d0ddc436bc3318b2202dfd82ad0bc11c7169694092"}, + {file = "botocore-1.34.154-py3-none-any.whl", hash = "sha256:4eef4b1bb809b382ba9dc9c88f5fcc4a133f221a1acb693ee6bee4de9f325979"}, + {file = "botocore-1.34.154.tar.gz", hash = "sha256:64d9b4c85a504d77cb56dabb2ad717cd8e1717424a88edb458b01d1e5797262a"}, ] [package.dependencies] @@ -1187,13 +1187,33 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "debugpy" -version = "1.8.3" +version = "1.8.2" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.3-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:0df2c400853150af14996b8d1a4f54d45ffa98e76c0f3de30665e89e273ea293"}, - {file = "debugpy-1.8.3.zip", hash = "sha256:0f5a6326d9fc375b864ed368d06cddf2dabe5135511e71cde3758be699847d36"}, + {file = "debugpy-1.8.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7ee2e1afbf44b138c005e4380097d92532e1001580853a7cb40ed84e0ef1c3d2"}, + {file = "debugpy-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f8c3f7c53130a070f0fc845a0f2cee8ed88d220d6b04595897b66605df1edd6"}, + {file = "debugpy-1.8.2-cp310-cp310-win32.whl", hash = "sha256:f179af1e1bd4c88b0b9f0fa153569b24f6b6f3de33f94703336363ae62f4bf47"}, + {file = "debugpy-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:0600faef1d0b8d0e85c816b8bb0cb90ed94fc611f308d5fde28cb8b3d2ff0fe3"}, + {file = "debugpy-1.8.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8a13417ccd5978a642e91fb79b871baded925d4fadd4dfafec1928196292aa0a"}, + {file = "debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634"}, + {file = "debugpy-1.8.2-cp311-cp311-win32.whl", hash = "sha256:2cbd4d9a2fc5e7f583ff9bf11f3b7d78dfda8401e8bb6856ad1ed190be4281ad"}, + {file = "debugpy-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa"}, + {file = "debugpy-1.8.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:5d3ccd39e4021f2eb86b8d748a96c766058b39443c1f18b2dc52c10ac2757835"}, + {file = "debugpy-1.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62658aefe289598680193ff655ff3940e2a601765259b123dc7f89c0239b8cd3"}, + {file = "debugpy-1.8.2-cp312-cp312-win32.whl", hash = "sha256:bd11fe35d6fd3431f1546d94121322c0ac572e1bfb1f6be0e9b8655fb4ea941e"}, + {file = "debugpy-1.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:15bc2f4b0f5e99bf86c162c91a74c0631dbd9cef3c6a1d1329c946586255e859"}, + {file = "debugpy-1.8.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:5a019d4574afedc6ead1daa22736c530712465c0c4cd44f820d803d937531b2d"}, + {file = "debugpy-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40f062d6877d2e45b112c0bbade9a17aac507445fd638922b1a5434df34aed02"}, + {file = "debugpy-1.8.2-cp38-cp38-win32.whl", hash = "sha256:c78ba1680f1015c0ca7115671fe347b28b446081dada3fedf54138f44e4ba031"}, + {file = "debugpy-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cf327316ae0c0e7dd81eb92d24ba8b5e88bb4d1b585b5c0d32929274a66a5210"}, + {file = "debugpy-1.8.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:1523bc551e28e15147815d1397afc150ac99dbd3a8e64641d53425dba57b0ff9"}, + {file = "debugpy-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e24ccb0cd6f8bfaec68d577cb49e9c680621c336f347479b3fce060ba7c09ec1"}, + {file = "debugpy-1.8.2-cp39-cp39-win32.whl", hash = "sha256:7f8d57a98c5a486c5c7824bc0b9f2f11189d08d73635c326abef268f83950326"}, + {file = "debugpy-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:16c8dcab02617b75697a0a925a62943e26a0330da076e2a10437edd9f0bf3755"}, + {file = "debugpy-1.8.2-py2.py3-none-any.whl", hash = "sha256:16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca"}, + {file = "debugpy-1.8.2.zip", hash = "sha256:95378ed08ed2089221896b9b3a8d021e642c24edc8fef20e5d4342ca8be65c00"}, ] [[package]] @@ -2077,84 +2097,78 @@ protobuf = ["grpcio-tools (>=1.65.4)"] [[package]] name = "grpcio-health-checking" -version = "1.62.2" +version = "1.62.3" description = "Standard Health Checking Service for gRPC" optional = false python-versions = ">=3.6" files = [ - {file = "grpcio-health-checking-1.62.2.tar.gz", hash = "sha256:a44d1ea1e1510b5c62265dada04d86621bb1491d75de987713c9c0ea005c10a8"}, - {file = "grpcio_health_checking-1.62.2-py3-none-any.whl", hash = "sha256:f0d77e02457aa00e98ce12c741dca6df7e34dbcc3859681c4a473dc589288e56"}, + {file = "grpcio-health-checking-1.62.3.tar.gz", hash = "sha256:5074ba0ce8f0dcfe328408ec5c7551b2a835720ffd9b69dade7fa3e0dc1c7a93"}, + {file = "grpcio_health_checking-1.62.3-py3-none-any.whl", hash = "sha256:f29da7dd144d73b4465fe48f011a91453e9ff6c8af0d449254cf80021cab3e0d"}, ] [package.dependencies] -grpcio = ">=1.62.2" +grpcio = ">=1.62.3" protobuf = ">=4.21.6" [[package]] name = "grpcio-tools" -version = "1.62.2" +version = "1.62.3" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-tools-1.62.2.tar.gz", hash = "sha256:5fd5e1582b678e6b941ee5f5809340be5e0724691df5299aae8226640f94e18f"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-linux_armv7l.whl", hash = "sha256:1679b4903aed2dc5bd8cb22a452225b05dc8470a076f14fd703581efc0740cdb"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:9d41e0e47dd075c075bb8f103422968a65dd0d8dc8613288f573ae91eb1053ba"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:987e774f74296842bbffd55ea8826370f70c499e5b5f71a8cf3103838b6ee9c3"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd4eeea4b25bcb6903b82930d579027d034ba944393c4751cdefd9c49e6989"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6746bc823958499a3cf8963cc1de00072962fb5e629f26d658882d3f4c35095"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2ed775e844566ce9ce089be9a81a8b928623b8ee5820f5e4d58c1a9d33dfc5ae"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bdc5dd3f57b5368d5d661d5d3703bcaa38bceca59d25955dff66244dbc987271"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-win32.whl", hash = "sha256:3a8d6f07e64c0c7756f4e0c4781d9d5a2b9cc9cbd28f7032a6fb8d4f847d0445"}, - {file = "grpcio_tools-1.62.2-cp310-cp310-win_amd64.whl", hash = "sha256:e33b59fb3efdddeb97ded988a871710033e8638534c826567738d3edce528752"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-linux_armv7l.whl", hash = "sha256:472505d030135d73afe4143b0873efe0dcb385bd6d847553b4f3afe07679af00"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:ec674b4440ef4311ac1245a709e87b36aca493ddc6850eebe0b278d1f2b6e7d1"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:184b4174d4bd82089d706e8223e46c42390a6ebac191073b9772abc77308f9fa"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c195d74fe98541178ece7a50dad2197d43991e0f77372b9a88da438be2486f12"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a34d97c62e61bfe9e6cff0410fe144ac8cca2fc979ad0be46b7edf026339d161"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb8453ae83a1db2452b7fe0f4b78e4a8dd32be0f2b2b73591ae620d4d784d3d"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f989e5cebead3ae92c6abf6bf7b19949e1563a776aea896ac5933f143f0c45d"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-win32.whl", hash = "sha256:c48fabe40b9170f4e3d7dd2c252e4f1ff395dc24e49ac15fc724b1b6f11724da"}, - {file = "grpcio_tools-1.62.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c616d0ad872e3780693fce6a3ac8ef00fc0963e6d7815ce9dcfae68ba0fc287"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-linux_armv7l.whl", hash = "sha256:10cc3321704ecd17c93cf68c99c35467a8a97ffaaed53207e9b2da6ae0308ee1"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9be84ff6d47fd61462be7523b49d7ba01adf67ce4e1447eae37721ab32464dd8"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:d82f681c9a9d933a9d8068e8e382977768e7779ddb8870fa0cf918d8250d1532"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04c607029ae3660fb1624ed273811ffe09d57d84287d37e63b5b802a35897329"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72b61332f1b439c14cbd3815174a8f1d35067a02047c32decd406b3a09bb9890"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8214820990d01b52845f9fbcb92d2b7384a0c321b303e3ac614c219dc7d1d3af"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:462e0ab8dd7c7b70bfd6e3195eebc177549ede5cf3189814850c76f9a340d7ce"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-win32.whl", hash = "sha256:fa107460c842e4c1a6266150881694fefd4f33baa544ea9489601810c2210ef8"}, - {file = "grpcio_tools-1.62.2-cp312-cp312-win_amd64.whl", hash = "sha256:759c60f24c33a181bbbc1232a6752f9b49fbb1583312a4917e2b389fea0fb0f2"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-linux_armv7l.whl", hash = "sha256:45db5da2bcfa88f2b86b57ef35daaae85c60bd6754a051d35d9449c959925b57"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:ab84bae88597133f6ea7a2bdc57b2fda98a266fe8d8d4763652cbefd20e73ad7"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:7a49bccae1c7d154b78e991885c3111c9ad8c8fa98e91233de425718f47c6139"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7e439476b29d6dac363b321781a113794397afceeb97dad85349db5f1cb5e9a"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ea369c4d1567d1acdf69c8ea74144f4ccad9e545df7f9a4fc64c94fa7684ba3"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f955702dc4b530696375251319d05223b729ed24e8673c2129f7a75d2caefbb"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3708a747aa4b6b505727282ca887041174e146ae030ebcadaf4c1d346858df62"}, - {file = "grpcio_tools-1.62.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce149ea55eadb486a7fb75a20f63ef3ac065ee6a0240ed25f3549ce7954c653"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-linux_armv7l.whl", hash = "sha256:58cbb24b3fa6ae35aa9c210fcea3a51aa5fef0cd25618eb4fd94f746d5a9b703"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:6413581e14a80e0b4532577766cf0586de4dd33766a31b3eb5374a746771c07d"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:47117c8a7e861382470d0e22d336e5a91fdc5f851d1db44fa784b9acea190d87"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f1ba79a253df9e553d20319c615fa2b429684580fa042dba618d7f6649ac7e4"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04a394cf5e51ba9be412eb9f6c482b6270bd81016e033e8eb7d21b8cc28fe8b5"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3c53b221378b035ae2f1881cbc3aca42a6075a8e90e1a342c2f205eb1d1aa6a1"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c384c838b34d1b67068e51b5bbe49caa6aa3633acd158f1ab16b5da8d226bc53"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-win32.whl", hash = "sha256:19ea69e41c3565932aa28a202d1875ec56786aea46a2eab54a3b28e8a27f9517"}, - {file = "grpcio_tools-1.62.2-cp38-cp38-win_amd64.whl", hash = "sha256:1d768a5c07279a4c461ebf52d0cec1c6ca85c6291c71ec2703fe3c3e7e28e8c4"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-linux_armv7l.whl", hash = "sha256:5b07b5874187e170edfbd7aa2ca3a54ebf3b2952487653e8c0b0d83601c33035"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:d58389fe8be206ddfb4fa703db1e24c956856fcb9a81da62b13577b3a8f7fda7"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:7d8b4e00c3d7237b92260fc18a561cd81f1da82e8be100db1b7d816250defc66"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe08d2038f2b7c53259b5c49e0ad08c8e0ce2b548d8185993e7ef67e8592cca"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19216e1fb26dbe23d12a810517e1b3fbb8d4f98b1a3fbebeec9d93a79f092de4"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b8574469ecc4ff41d6bb95f44e0297cdb0d95bade388552a9a444db9cd7485cd"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4f6f32d39283ea834a493fccf0ebe9cfddee7577bdcc27736ad4be1732a36399"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-win32.whl", hash = "sha256:76eb459bdf3fb666e01883270beee18f3f11ed44488486b61cd210b4e0e17cc1"}, - {file = "grpcio_tools-1.62.2-cp39-cp39-win_amd64.whl", hash = "sha256:217c2ee6a7ce519a55958b8622e21804f6fdb774db08c322f4c9536c35fdce7c"}, + {file = "grpcio-tools-1.62.3.tar.gz", hash = "sha256:7c7136015c3d62c3eef493efabaf9e3380e3e66d24ee8e94c01cb71377f57833"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2f968b049c2849540751ec2100ab05e8086c24bead769ca734fdab58698408c1"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0a8c0c4724ae9c2181b7dbc9b186df46e4f62cb18dc184e46d06c0ebeccf569e"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5782883a27d3fae8c425b29a9d3dcf5f47d992848a1b76970da3b5a28d424b26"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d812daffd0c2d2794756bd45a353f89e55dc8f91eb2fc840c51b9f6be62667"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b47d0dda1bdb0a0ba7a9a6de88e5a1ed61f07fad613964879954961e36d49193"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ca246dffeca0498be9b4e1ee169b62e64694b0f92e6d0be2573e65522f39eea9"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-win32.whl", hash = "sha256:6a56d344b0bab30bf342a67e33d386b0b3c4e65868ffe93c341c51e1a8853ca5"}, + {file = "grpcio_tools-1.62.3-cp310-cp310-win_amd64.whl", hash = "sha256:710fecf6a171dcbfa263a0a3e7070e0df65ba73158d4c539cec50978f11dad5d"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:703f46e0012af83a36082b5f30341113474ed0d91e36640da713355cd0ea5d23"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:7cc83023acd8bc72cf74c2edbe85b52098501d5b74d8377bfa06f3e929803492"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ff7d58a45b75df67d25f8f144936a3e44aabd91afec833ee06826bd02b7fbe7"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f2483ea232bd72d98a6dc6d7aefd97e5bc80b15cd909b9e356d6f3e326b6e43"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:962c84b4da0f3b14b3cdb10bc3837ebc5f136b67d919aea8d7bb3fd3df39528a"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8ad0473af5544f89fc5a1ece8676dd03bdf160fb3230f967e05d0f4bf89620e3"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-win32.whl", hash = "sha256:db3bc9fa39afc5e4e2767da4459df82b095ef0cab2f257707be06c44a1c2c3e5"}, + {file = "grpcio_tools-1.62.3-cp311-cp311-win_amd64.whl", hash = "sha256:e0898d412a434e768a0c7e365acabe13ff1558b767e400936e26b5b6ed1ee51f"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:d102b9b21c4e1e40af9a2ab3c6d41afba6bd29c0aa50ca013bf85c99cdc44ac5"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:0a52cc9444df978438b8d2332c0ca99000521895229934a59f94f37ed896b133"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141d028bf5762d4a97f981c501da873589df3f7e02f4c1260e1921e565b376fa"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47a5c093ab256dec5714a7a345f8cc89315cb57c298b276fa244f37a0ba507f0"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f6831fdec2b853c9daa3358535c55eed3694325889aa714070528cf8f92d7d6d"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e02d7c1a02e3814c94ba0cfe43d93e872c758bd8fd5c2797f894d0c49b4a1dfc"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-win32.whl", hash = "sha256:b881fd9505a84457e9f7e99362eeedd86497b659030cf57c6f0070df6d9c2b9b"}, + {file = "grpcio_tools-1.62.3-cp312-cp312-win_amd64.whl", hash = "sha256:11c625eebefd1fd40a228fc8bae385e448c7e32a6ae134e43cf13bbc23f902b7"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:ec6fbded0c61afe6f84e3c2a43e6d656791d95747d6d28b73eff1af64108c434"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:bfda6ee8990997a9df95c5606f3096dae65f09af7ca03a1e9ca28f088caca5cf"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b77f9f9cee87cd798f0fe26b7024344d1b03a7cd2d2cba7035f8433b13986325"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e02d3b96f2d0e4bab9ceaa30f37d4f75571e40c6272e95364bff3125a64d184"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1da38070738da53556a4b35ab67c1b9884a5dd48fa2f243db35dc14079ea3d0c"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ace43b26d88a58dcff16c20d23ff72b04d0a415f64d2820f4ff06b1166f50557"}, + {file = "grpcio_tools-1.62.3-cp37-cp37m-win_amd64.whl", hash = "sha256:350a80485e302daaa95d335a931f97b693e170e02d43767ab06552c708808950"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:c3a1ac9d394f8e229eb28eec2e04b9a6f5433fa19c9d32f1cb6066e3c5114a1d"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:11f363570dea661dde99e04a51bd108a5807b5df32a6f8bdf4860e34e94a4dbf"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9ad9950119d8ae27634e68b7663cc8d340ae535a0f80d85a55e56a6973ab1f"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c5d22b252dcef11dd1e0fbbe5bbfb9b4ae048e8880d33338215e8ccbdb03edc"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:27cd9ef5c5d68d5ed104b6dcb96fe9c66b82050e546c9e255716903c3d8f0373"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f4b1615adf67bd8bb71f3464146a6f9949972d06d21a4f5e87e73f6464d97f57"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-win32.whl", hash = "sha256:e18e15287c31baf574fcdf8251fb7f997d64e96c6ecf467906e576da0a079af6"}, + {file = "grpcio_tools-1.62.3-cp38-cp38-win_amd64.whl", hash = "sha256:6c3064610826f50bd69410c63101954676edc703e03f9e8f978a135f1aaf97c1"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:8e62cc7164b0b7c5128e637e394eb2ef3db0e61fc798e80c301de3b2379203ed"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:c8ad5cce554e2fcaf8842dee5d9462583b601a3a78f8b76a153c38c963f58c10"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec279dcf3518201fc592c65002754f58a6b542798cd7f3ecd4af086422f33f29"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c989246c2aebc13253f08be32538a4039a64e12d9c18f6d662d7aee641dc8b5"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca4f5eeadbb57cf03317d6a2857823239a63a59cc935f5bd6cf6e8b7af7a7ecc"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0cb3a3436ac119cbd37a7d3331d9bdf85dad21a6ac233a3411dff716dcbf401e"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-win32.whl", hash = "sha256:3eae6ea76d62fcac091e1f15c2dcedf1dc3f114f8df1a972a8a0745e89f4cf61"}, + {file = "grpcio_tools-1.62.3-cp39-cp39-win_amd64.whl", hash = "sha256:eec73a005443061f4759b71a056f745e3b000dc0dc125c9f20560232dfbcbd14"}, ] [package.dependencies] -grpcio = ">=1.62.2" +grpcio = ">=1.62.3" protobuf = ">=4.21.6,<5.0dev" setuptools = "*" @@ -3154,13 +3168,13 @@ tests = ["aiohttp", "boto3", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pyt [[package]] name = "langfuse" -version = "2.40.0" +version = "2.41.0" description = "A client library for accessing langfuse" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langfuse-2.40.0-py3-none-any.whl", hash = "sha256:2aaebc179ec2edf7645805f680bf81affcb375d9cf33d0ba0e51ac3f8686000a"}, - {file = "langfuse-2.40.0.tar.gz", hash = "sha256:5b16c8b2ded418119212a295309300fd253dd80fd49f9713b4516067d499bf85"}, + {file = "langfuse-2.41.0-py3-none-any.whl", hash = "sha256:f7db4078ff629c9c067970dac35419be199d46aeff272d903a74c5ec29e5969b"}, + {file = "langfuse-2.41.0.tar.gz", hash = "sha256:d529408079af54ddf84ac72290a756e6721357b09236cbeae728eb04c7371c6c"}, ] [package.dependencies] @@ -5540,6 +5554,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6100,111 +6115,121 @@ crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] [[package]] name = "safetensors" -version = "0.4.3" +version = "0.4.4" description = "" optional = false python-versions = ">=3.7" files = [ - {file = "safetensors-0.4.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:dcf5705cab159ce0130cd56057f5f3425023c407e170bca60b4868048bae64fd"}, - {file = "safetensors-0.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bb4f8c5d0358a31e9a08daeebb68f5e161cdd4018855426d3f0c23bb51087055"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70a5319ef409e7f88686a46607cbc3c428271069d8b770076feaf913664a07ac"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb9c65bd82f9ef3ce4970dc19ee86be5f6f93d032159acf35e663c6bea02b237"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edb5698a7bc282089f64c96c477846950358a46ede85a1c040e0230344fdde10"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efcc860be094b8d19ac61b452ec635c7acb9afa77beb218b1d7784c6d41fe8ad"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d88b33980222085dd6001ae2cad87c6068e0991d4f5ccf44975d216db3b57376"}, - {file = "safetensors-0.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5fc6775529fb9f0ce2266edd3e5d3f10aab068e49f765e11f6f2a63b5367021d"}, - {file = "safetensors-0.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9c6ad011c1b4e3acff058d6b090f1da8e55a332fbf84695cf3100c649cc452d1"}, - {file = "safetensors-0.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c496c5401c1b9c46d41a7688e8ff5b0310a3b9bae31ce0f0ae870e1ea2b8caf"}, - {file = "safetensors-0.4.3-cp310-none-win32.whl", hash = "sha256:38e2a8666178224a51cca61d3cb4c88704f696eac8f72a49a598a93bbd8a4af9"}, - {file = "safetensors-0.4.3-cp310-none-win_amd64.whl", hash = "sha256:393e6e391467d1b2b829c77e47d726f3b9b93630e6a045b1d1fca67dc78bf632"}, - {file = "safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a"}, - {file = "safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9afd5358719f1b2cf425fad638fc3c887997d6782da317096877e5b15b2ce93"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8c5093206ef4b198600ae484230402af6713dab1bd5b8e231905d754022bec7"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0b2104df1579d6ba9052c0ae0e3137c9698b2d85b0645507e6fd1813b70931a"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cf18888606dad030455d18f6c381720e57fc6a4170ee1966adb7ebc98d4d6a3"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b"}, - {file = "safetensors-0.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:585c9ae13a205807b63bef8a37994f30c917ff800ab8a1ca9c9b5d73024f97ee"}, - {file = "safetensors-0.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faefeb3b81bdfb4e5a55b9bbdf3d8d8753f65506e1d67d03f5c851a6c87150e9"}, - {file = "safetensors-0.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:befdf0167ad626f22f6aac6163477fcefa342224a22f11fdd05abb3995c1783c"}, - {file = "safetensors-0.4.3-cp311-none-win32.whl", hash = "sha256:a7cef55929dcbef24af3eb40bedec35d82c3c2fa46338bb13ecf3c5720af8a61"}, - {file = "safetensors-0.4.3-cp311-none-win_amd64.whl", hash = "sha256:840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67"}, - {file = "safetensors-0.4.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:22d21760dc6ebae42e9c058d75aa9907d9f35e38f896e3c69ba0e7b213033856"}, - {file = "safetensors-0.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d22c1a10dff3f64d0d68abb8298a3fd88ccff79f408a3e15b3e7f637ef5c980"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1648568667f820b8c48317c7006221dc40aced1869908c187f493838a1362bc"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:446e9fe52c051aeab12aac63d1017e0f68a02a92a027b901c4f8e931b24e5397"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fef5d70683643618244a4f5221053567ca3e77c2531e42ad48ae05fae909f542"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a1f4430cc0c9d6afa01214a4b3919d0a029637df8e09675ceef1ca3f0dfa0df"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d603846a8585b9432a0fd415db1d4c57c0f860eb4aea21f92559ff9902bae4d"}, - {file = "safetensors-0.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a844cdb5d7cbc22f5f16c7e2a0271170750763c4db08381b7f696dbd2c78a361"}, - {file = "safetensors-0.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:88887f69f7a00cf02b954cdc3034ffb383b2303bc0ab481d4716e2da51ddc10e"}, - {file = "safetensors-0.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ee463219d9ec6c2be1d331ab13a8e0cd50d2f32240a81d498266d77d07b7e71e"}, - {file = "safetensors-0.4.3-cp312-none-win32.whl", hash = "sha256:d0dd4a1db09db2dba0f94d15addc7e7cd3a7b0d393aa4c7518c39ae7374623c3"}, - {file = "safetensors-0.4.3-cp312-none-win_amd64.whl", hash = "sha256:d14d30c25897b2bf19b6fb5ff7e26cc40006ad53fd4a88244fdf26517d852dd7"}, - {file = "safetensors-0.4.3-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d1456f814655b224d4bf6e7915c51ce74e389b413be791203092b7ff78c936dd"}, - {file = "safetensors-0.4.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:455d538aa1aae4a8b279344a08136d3f16334247907b18a5c3c7fa88ef0d3c46"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf476bca34e1340ee3294ef13e2c625833f83d096cfdf69a5342475602004f95"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02ef3a24face643456020536591fbd3c717c5abaa2737ec428ccbbc86dffa7a4"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7de32d0d34b6623bb56ca278f90db081f85fb9c5d327e3c18fd23ac64f465768"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a0deb16a1d3ea90c244ceb42d2c6c276059616be21a19ac7101aa97da448faf"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c59d51f182c729f47e841510b70b967b0752039f79f1de23bcdd86462a9b09ee"}, - {file = "safetensors-0.4.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f598b713cc1a4eb31d3b3203557ac308acf21c8f41104cdd74bf640c6e538e3"}, - {file = "safetensors-0.4.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5757e4688f20df083e233b47de43845d1adb7e17b6cf7da5f8444416fc53828d"}, - {file = "safetensors-0.4.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fe746d03ed8d193674a26105e4f0fe6c726f5bb602ffc695b409eaf02f04763d"}, - {file = "safetensors-0.4.3-cp37-none-win32.whl", hash = "sha256:0d5ffc6a80f715c30af253e0e288ad1cd97a3d0086c9c87995e5093ebc075e50"}, - {file = "safetensors-0.4.3-cp37-none-win_amd64.whl", hash = "sha256:a11c374eb63a9c16c5ed146457241182f310902bd2a9c18255781bb832b6748b"}, - {file = "safetensors-0.4.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1e31be7945f66be23f4ec1682bb47faa3df34cb89fc68527de6554d3c4258a4"}, - {file = "safetensors-0.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:03a4447c784917c9bf01d8f2ac5080bc15c41692202cd5f406afba16629e84d6"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d244bcafeb1bc06d47cfee71727e775bca88a8efda77a13e7306aae3813fa7e4"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53c4879b9c6bd7cd25d114ee0ef95420e2812e676314300624594940a8d6a91f"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74707624b81f1b7f2b93f5619d4a9f00934d5948005a03f2c1845ffbfff42212"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d52c958dc210265157573f81d34adf54e255bc2b59ded6218500c9b15a750eb"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f9568f380f513a60139971169c4a358b8731509cc19112369902eddb33faa4d"}, - {file = "safetensors-0.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d9cd8e1560dfc514b6d7859247dc6a86ad2f83151a62c577428d5102d872721"}, - {file = "safetensors-0.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:89f9f17b0dacb913ed87d57afbc8aad85ea42c1085bd5de2f20d83d13e9fc4b2"}, - {file = "safetensors-0.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1139eb436fd201c133d03c81209d39ac57e129f5e74e34bb9ab60f8d9b726270"}, - {file = "safetensors-0.4.3-cp38-none-win32.whl", hash = "sha256:d9c289f140a9ae4853fc2236a2ffc9a9f2d5eae0cb673167e0f1b8c18c0961ac"}, - {file = "safetensors-0.4.3-cp38-none-win_amd64.whl", hash = "sha256:622afd28968ef3e9786562d352659a37de4481a4070f4ebac883f98c5836563e"}, - {file = "safetensors-0.4.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8651c7299cbd8b4161a36cd6a322fa07d39cd23535b144d02f1c1972d0c62f3c"}, - {file = "safetensors-0.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e375d975159ac534c7161269de24ddcd490df2157b55c1a6eeace6cbb56903f0"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:084fc436e317f83f7071fc6a62ca1c513b2103db325cd09952914b50f51cf78f"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:41a727a7f5e6ad9f1db6951adee21bbdadc632363d79dc434876369a17de6ad6"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7dbbde64b6c534548696808a0e01276d28ea5773bc9a2dfb97a88cd3dffe3df"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bbae3b4b9d997971431c346edbfe6e41e98424a097860ee872721e176040a893"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01e4b22e3284cd866edeabe4f4d896229495da457229408d2e1e4810c5187121"}, - {file = "safetensors-0.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dd37306546b58d3043eb044c8103a02792cc024b51d1dd16bd3dd1f334cb3ed"}, - {file = "safetensors-0.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8815b5e1dac85fc534a97fd339e12404db557878c090f90442247e87c8aeaea"}, - {file = "safetensors-0.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e011cc162503c19f4b1fd63dfcddf73739c7a243a17dac09b78e57a00983ab35"}, - {file = "safetensors-0.4.3-cp39-none-win32.whl", hash = "sha256:01feb3089e5932d7e662eda77c3ecc389f97c0883c4a12b5cfdc32b589a811c3"}, - {file = "safetensors-0.4.3-cp39-none-win_amd64.whl", hash = "sha256:3f9cdca09052f585e62328c1c2923c70f46814715c795be65f0b93f57ec98a02"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1b89381517891a7bb7d1405d828b2bf5d75528299f8231e9346b8eba092227f9"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:cd6fff9e56df398abc5866b19a32124815b656613c1c5ec0f9350906fd798aac"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:840caf38d86aa7014fe37ade5d0d84e23dcfbc798b8078015831996ecbc206a3"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9650713b2cfa9537a2baf7dd9fee458b24a0aaaa6cafcea8bdd5fb2b8efdc34"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e4119532cd10dba04b423e0f86aecb96cfa5a602238c0aa012f70c3a40c44b50"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e066e8861eef6387b7c772344d1fe1f9a72800e04ee9a54239d460c400c72aab"}, - {file = "safetensors-0.4.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:90964917f5b0fa0fa07e9a051fbef100250c04d150b7026ccbf87a34a54012e0"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c41e1893d1206aa7054029681778d9a58b3529d4c807002c156d58426c225173"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae7613a119a71a497d012ccc83775c308b9c1dab454806291427f84397d852fd"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9bac020faba7f5dc481e881b14b6425265feabb5bfc552551d21189c0eddc3"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:420a98f593ff9930f5822560d14c395ccbc57342ddff3b463bc0b3d6b1951550"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f5e6883af9a68c0028f70a4c19d5a6ab6238a379be36ad300a22318316c00cb0"}, - {file = "safetensors-0.4.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:cdd0a3b5da66e7f377474599814dbf5cbf135ff059cc73694de129b58a5e8a2c"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9bfb92f82574d9e58401d79c70c716985dc049b635fef6eecbb024c79b2c46ad"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3615a96dd2dcc30eb66d82bc76cda2565f4f7bfa89fcb0e31ba3cea8a1a9ecbb"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:868ad1b6fc41209ab6bd12f63923e8baeb1a086814cb2e81a65ed3d497e0cf8f"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7ffba80aa49bd09195145a7fd233a7781173b422eeb995096f2b30591639517"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0acbe31340ab150423347e5b9cc595867d814244ac14218932a5cf1dd38eb39"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19bbdf95de2cf64f25cd614c5236c8b06eb2cfa47cbf64311f4b5d80224623a3"}, - {file = "safetensors-0.4.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b852e47eb08475c2c1bd8131207b405793bfc20d6f45aff893d3baaad449ed14"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d07cbca5b99babb692d76d8151bec46f461f8ad8daafbfd96b2fca40cadae65"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1ab6527a20586d94291c96e00a668fa03f86189b8a9defa2cdd34a1a01acc7d5"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02318f01e332cc23ffb4f6716e05a492c5f18b1d13e343c49265149396284a44"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec4b52ce9a396260eb9731eb6aea41a7320de22ed73a1042c2230af0212758ce"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:018b691383026a2436a22b648873ed11444a364324e7088b99cd2503dd828400"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:309b10dbcab63269ecbf0e2ca10ce59223bb756ca5d431ce9c9eeabd446569da"}, - {file = "safetensors-0.4.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b277482120df46e27a58082df06a15aebda4481e30a1c21eefd0921ae7e03f65"}, - {file = "safetensors-0.4.3.tar.gz", hash = "sha256:2f85fc50c4e07a21e95c24e07460fe6f7e2859d0ce88092838352b798ce711c2"}, + {file = "safetensors-0.4.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2adb497ada13097f30e386e88c959c0fda855a5f6f98845710f5bb2c57e14f12"}, + {file = "safetensors-0.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7db7fdc2d71fd1444d85ca3f3d682ba2df7d61a637dfc6d80793f439eae264ab"}, + {file = "safetensors-0.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d4f0eed76b430f009fbefca1a0028ddb112891b03cb556d7440d5cd68eb89a9"}, + {file = "safetensors-0.4.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:57d216fab0b5c432aabf7170883d7c11671622bde8bd1436c46d633163a703f6"}, + {file = "safetensors-0.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d9b76322e49c056bcc819f8bdca37a2daa5a6d42c07f30927b501088db03309"}, + {file = "safetensors-0.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32f0d1f6243e90ee43bc6ee3e8c30ac5b09ca63f5dd35dbc985a1fc5208c451a"}, + {file = "safetensors-0.4.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44d464bdc384874601a177375028012a5f177f1505279f9456fea84bbc575c7f"}, + {file = "safetensors-0.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63144e36209ad8e4e65384dbf2d52dd5b1866986079c00a72335402a38aacdc5"}, + {file = "safetensors-0.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:051d5ecd490af7245258000304b812825974d5e56f14a3ff7e1b8b2ba6dc2ed4"}, + {file = "safetensors-0.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51bc8429d9376224cd3cf7e8ce4f208b4c930cd10e515b6ac6a72cbc3370f0d9"}, + {file = "safetensors-0.4.4-cp310-none-win32.whl", hash = "sha256:fb7b54830cee8cf9923d969e2df87ce20e625b1af2fd194222ab902d3adcc29c"}, + {file = "safetensors-0.4.4-cp310-none-win_amd64.whl", hash = "sha256:4b3e8aa8226d6560de8c2b9d5ff8555ea482599c670610758afdc97f3e021e9c"}, + {file = "safetensors-0.4.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:bbaa31f2cb49013818bde319232ccd72da62ee40f7d2aa532083eda5664e85ff"}, + {file = "safetensors-0.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9fdcb80f4e9fbb33b58e9bf95e7dbbedff505d1bcd1c05f7c7ce883632710006"}, + {file = "safetensors-0.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55c14c20be247b8a1aeaf3ab4476265e3ca83096bb8e09bb1a7aa806088def4f"}, + {file = "safetensors-0.4.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:949aaa1118660f992dbf0968487b3e3cfdad67f948658ab08c6b5762e90cc8b6"}, + {file = "safetensors-0.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c11a4ab7debc456326a2bac67f35ee0ac792bcf812c7562a4a28559a5c795e27"}, + {file = "safetensors-0.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0cea44bba5c5601b297bc8307e4075535b95163402e4906b2e9b82788a2a6df"}, + {file = "safetensors-0.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9d752c97f6bbe327352f76e5b86442d776abc789249fc5e72eacb49e6916482"}, + {file = "safetensors-0.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:03f2bb92e61b055ef6cc22883ad1ae898010a95730fa988c60a23800eb742c2c"}, + {file = "safetensors-0.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:87bf3f91a9328a941acc44eceffd4e1f5f89b030985b2966637e582157173b98"}, + {file = "safetensors-0.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:20d218ec2b6899d29d6895419a58b6e44cc5ff8f0cc29fac8d236a8978ab702e"}, + {file = "safetensors-0.4.4-cp311-none-win32.whl", hash = "sha256:8079486118919f600c603536e2490ca37b3dbd3280e3ad6eaacfe6264605ac8a"}, + {file = "safetensors-0.4.4-cp311-none-win_amd64.whl", hash = "sha256:2f8c2eb0615e2e64ee27d478c7c13f51e5329d7972d9e15528d3e4cfc4a08f0d"}, + {file = "safetensors-0.4.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:baec5675944b4a47749c93c01c73d826ef7d42d36ba8d0dba36336fa80c76426"}, + {file = "safetensors-0.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f15117b96866401825f3e94543145028a2947d19974429246ce59403f49e77c6"}, + {file = "safetensors-0.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a13a9caea485df164c51be4eb0c87f97f790b7c3213d635eba2314d959fe929"}, + {file = "safetensors-0.4.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b54bc4ca5f9b9bba8cd4fb91c24b2446a86b5ae7f8975cf3b7a277353c3127c"}, + {file = "safetensors-0.4.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08332c22e03b651c8eb7bf5fc2de90044f3672f43403b3d9ac7e7e0f4f76495e"}, + {file = "safetensors-0.4.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb62841e839ee992c37bb75e75891c7f4904e772db3691c59daaca5b4ab960e1"}, + {file = "safetensors-0.4.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e5b927acc5f2f59547270b0309a46d983edc44be64e1ca27a7fcb0474d6cd67"}, + {file = "safetensors-0.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a69c71b1ae98a8021a09a0b43363b0143b0ce74e7c0e83cacba691b62655fb8"}, + {file = "safetensors-0.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23654ad162c02a5636f0cd520a0310902c4421aab1d91a0b667722a4937cc445"}, + {file = "safetensors-0.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0677c109d949cf53756859160b955b2e75b0eefe952189c184d7be30ecf7e858"}, + {file = "safetensors-0.4.4-cp312-none-win32.whl", hash = "sha256:a51d0ddd4deb8871c6de15a772ef40b3dbd26a3c0451bb9e66bc76fc5a784e5b"}, + {file = "safetensors-0.4.4-cp312-none-win_amd64.whl", hash = "sha256:2d065059e75a798bc1933c293b68d04d79b586bb7f8c921e0ca1e82759d0dbb1"}, + {file = "safetensors-0.4.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9d625692578dd40a112df30c02a1adf068027566abd8e6a74893bb13d441c150"}, + {file = "safetensors-0.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7cabcf39c81e5b988d0adefdaea2eb9b4fd9bd62d5ed6559988c62f36bfa9a89"}, + {file = "safetensors-0.4.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8359bef65f49d51476e9811d59c015f0ddae618ee0e44144f5595278c9f8268c"}, + {file = "safetensors-0.4.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1a32c662e7df9226fd850f054a3ead0e4213a96a70b5ce37b2d26ba27004e013"}, + {file = "safetensors-0.4.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c329a4dcc395364a1c0d2d1574d725fe81a840783dda64c31c5a60fc7d41472c"}, + {file = "safetensors-0.4.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:239ee093b1db877c9f8fe2d71331a97f3b9c7c0d3ab9f09c4851004a11f44b65"}, + {file = "safetensors-0.4.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd574145d930cf9405a64f9923600879a5ce51d9f315443a5f706374841327b6"}, + {file = "safetensors-0.4.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f6784eed29f9e036acb0b7769d9e78a0dc2c72c2d8ba7903005350d817e287a4"}, + {file = "safetensors-0.4.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:65a4a6072436bf0a4825b1c295d248cc17e5f4651e60ee62427a5bcaa8622a7a"}, + {file = "safetensors-0.4.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:df81e3407630de060ae8313da49509c3caa33b1a9415562284eaf3d0c7705f9f"}, + {file = "safetensors-0.4.4-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:e4a0f374200e8443d9746e947ebb346c40f83a3970e75a685ade0adbba5c48d9"}, + {file = "safetensors-0.4.4-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:181fb5f3dee78dae7fd7ec57d02e58f7936498d587c6b7c1c8049ef448c8d285"}, + {file = "safetensors-0.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb4ac1d8f6b65ec84ddfacd275079e89d9df7c92f95675ba96c4f790a64df6e"}, + {file = "safetensors-0.4.4-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76897944cd9239e8a70955679b531b9a0619f76e25476e57ed373322d9c2075d"}, + {file = "safetensors-0.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a9e9d1a27e51a0f69e761a3d581c3af46729ec1c988fa1f839e04743026ae35"}, + {file = "safetensors-0.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:005ef9fc0f47cb9821c40793eb029f712e97278dae84de91cb2b4809b856685d"}, + {file = "safetensors-0.4.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26987dac3752688c696c77c3576f951dbbdb8c57f0957a41fb6f933cf84c0b62"}, + {file = "safetensors-0.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c05270b290acd8d249739f40d272a64dd597d5a4b90f27d830e538bc2549303c"}, + {file = "safetensors-0.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:068d3a33711fc4d93659c825a04480ff5a3854e1d78632cdc8f37fee917e8a60"}, + {file = "safetensors-0.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:063421ef08ca1021feea8b46951251b90ae91f899234dd78297cbe7c1db73b99"}, + {file = "safetensors-0.4.4-cp37-none-win32.whl", hash = "sha256:d52f5d0615ea83fd853d4e1d8acf93cc2e0223ad4568ba1e1f6ca72e94ea7b9d"}, + {file = "safetensors-0.4.4-cp37-none-win_amd64.whl", hash = "sha256:88a5ac3280232d4ed8e994cbc03b46a1807ce0aa123867b40c4a41f226c61f94"}, + {file = "safetensors-0.4.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3467ab511bfe3360967d7dc53b49f272d59309e57a067dd2405b4d35e7dcf9dc"}, + {file = "safetensors-0.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2ab4c96d922e53670ce25fbb9b63d5ea972e244de4fa1dd97b590d9fd66aacef"}, + {file = "safetensors-0.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87df18fce4440477c3ef1fd7ae17c704a69a74a77e705a12be135ee0651a0c2d"}, + {file = "safetensors-0.4.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e5fe345b2bc7d88587149ac11def1f629d2671c4c34f5df38aed0ba59dc37f8"}, + {file = "safetensors-0.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f1a3e01dce3cd54060791e7e24588417c98b941baa5974700eeb0b8eb65b0a0"}, + {file = "safetensors-0.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c6bf35e9a8998d8339fd9a05ac4ce465a4d2a2956cc0d837b67c4642ed9e947"}, + {file = "safetensors-0.4.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:166c0c52f6488b8538b2a9f3fbc6aad61a7261e170698779b371e81b45f0440d"}, + {file = "safetensors-0.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87e9903b8668a16ef02c08ba4ebc91e57a49c481e9b5866e31d798632805014b"}, + {file = "safetensors-0.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9c421153aa23c323bd8483d4155b4eee82c9a50ac11cccd83539104a8279c64"}, + {file = "safetensors-0.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a4b8617499b2371c7353302c5116a7e0a3a12da66389ce53140e607d3bf7b3d3"}, + {file = "safetensors-0.4.4-cp38-none-win32.whl", hash = "sha256:c6280f5aeafa1731f0a3709463ab33d8e0624321593951aefada5472f0b313fd"}, + {file = "safetensors-0.4.4-cp38-none-win_amd64.whl", hash = "sha256:6ceed6247fc2d33b2a7b7d25d8a0fe645b68798856e0bc7a9800c5fd945eb80f"}, + {file = "safetensors-0.4.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5cf6c6f6193797372adf50c91d0171743d16299491c75acad8650107dffa9269"}, + {file = "safetensors-0.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:419010156b914a3e5da4e4adf992bee050924d0fe423c4b329e523e2c14c3547"}, + {file = "safetensors-0.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88f6fd5a5c1302ce79993cc5feeadcc795a70f953c762544d01fb02b2db4ea33"}, + {file = "safetensors-0.4.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d468cffb82d90789696d5b4d8b6ab8843052cba58a15296691a7a3df55143cd2"}, + {file = "safetensors-0.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9353c2af2dd467333d4850a16edb66855e795561cd170685178f706c80d2c71e"}, + {file = "safetensors-0.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83c155b4a33368d9b9c2543e78f2452090fb030c52401ca608ef16fa58c98353"}, + {file = "safetensors-0.4.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9850754c434e636ce3dc586f534bb23bcbd78940c304775bee9005bf610e98f1"}, + {file = "safetensors-0.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:275f500b4d26f67b6ec05629a4600645231bd75e4ed42087a7c1801bff04f4b3"}, + {file = "safetensors-0.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5c2308de665b7130cd0e40a2329278226e4cf083f7400c51ca7e19ccfb3886f3"}, + {file = "safetensors-0.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e06a9ebc8656e030ccfe44634f2a541b4b1801cd52e390a53ad8bacbd65f8518"}, + {file = "safetensors-0.4.4-cp39-none-win32.whl", hash = "sha256:ef73df487b7c14b477016947c92708c2d929e1dee2bacdd6fff5a82ed4539537"}, + {file = "safetensors-0.4.4-cp39-none-win_amd64.whl", hash = "sha256:83d054818a8d1198d8bd8bc3ea2aac112a2c19def2bf73758321976788706398"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1d1f34c71371f0e034004a0b583284b45d233dd0b5f64a9125e16b8a01d15067"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a8043a33d58bc9b30dfac90f75712134ca34733ec3d8267b1bd682afe7194f5"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8db8f0c59c84792c12661f8efa85de160f80efe16b87a9d5de91b93f9e0bce3c"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfc1fc38e37630dd12d519bdec9dcd4b345aec9930bb9ce0ed04461f49e58b52"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e5c9d86d9b13b18aafa88303e2cd21e677f5da2a14c828d2c460fe513af2e9a5"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:43251d7f29a59120a26f5a0d9583b9e112999e500afabcfdcb91606d3c5c89e3"}, + {file = "safetensors-0.4.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2c42e9b277513b81cf507e6121c7b432b3235f980cac04f39f435b7902857f91"}, + {file = "safetensors-0.4.4-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3daacc9a4e3f428a84dd56bf31f20b768eb0b204af891ed68e1f06db9edf546f"}, + {file = "safetensors-0.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218bbb9b883596715fc9997bb42470bf9f21bb832c3b34c2bf744d6fa8f2bbba"}, + {file = "safetensors-0.4.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bd5efc26b39f7fc82d4ab1d86a7f0644c8e34f3699c33f85bfa9a717a030e1b"}, + {file = "safetensors-0.4.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56ad9776b65d8743f86698a1973292c966cf3abff627efc44ed60e66cc538ddd"}, + {file = "safetensors-0.4.4-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:30f23e6253c5f43a809dea02dc28a9f5fa747735dc819f10c073fe1b605e97d4"}, + {file = "safetensors-0.4.4-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5512078d00263de6cb04e9d26c9ae17611098f52357fea856213e38dc462f81f"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b96c3d9266439d17f35fc2173111d93afc1162f168e95aed122c1ca517b1f8f1"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:08d464aa72a9a13826946b4fb9094bb4b16554bbea2e069e20bd903289b6ced9"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:210160816d5a36cf41f48f38473b6f70d7bcb4b0527bedf0889cc0b4c3bb07db"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb276a53717f2bcfb6df0bcf284d8a12069002508d4c1ca715799226024ccd45"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a2c28c6487f17d8db0089e8b2cdc13de859366b94cc6cdc50e1b0a4147b56551"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7915f0c60e4e6e65d90f136d85dd3b429ae9191c36b380e626064694563dbd9f"}, + {file = "safetensors-0.4.4-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:00eea99ae422fbfa0b46065acbc58b46bfafadfcec179d4b4a32d5c45006af6c"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb1ed4fcb0b3c2f3ea2c5767434622fe5d660e5752f21ac2e8d737b1e5e480bb"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:73fc9a0a4343188bdb421783e600bfaf81d0793cd4cce6bafb3c2ed567a74cd5"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c37e6b714200824c73ca6eaf007382de76f39466a46e97558b8dc4cf643cfbf"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f75698c5c5c542417ac4956acfc420f7d4a2396adca63a015fd66641ea751759"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca1a209157f242eb183e209040097118472e169f2e069bfbd40c303e24866543"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:177f2b60a058f92a3cec7a1786c9106c29eca8987ecdfb79ee88126e5f47fa31"}, + {file = "safetensors-0.4.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ee9622e84fe6e4cd4f020e5fda70d6206feff3157731df7151d457fdae18e541"}, + {file = "safetensors-0.4.4.tar.gz", hash = "sha256:5fe3e9b705250d0172ed4e100a811543108653fb2b66b9e702a088ad03772a07"}, ] [package.extras] @@ -6586,6 +6611,14 @@ files = [ {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:56628ca27aa17b5890391ded4e385bf0480209726f198799b7e980c6bd473bd7"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db726be58837fe5ac39859e0fa40baafe54c6d54c02aba1d47d25536170b690f"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7421c1bfdbb7214313919472307be650bd45c4dc2fcb317d64d078993de045b"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632784f7a6f12cfa0e84bf2a5003b07660addccf5563c132cd23b7cc1d7371a9"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f6f7276cf26145a888f2182a98f204541b519d9ea358a65d82095d9c9e22f917"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2a1f7ffac934bc0ea717fa1596f938483fb8c402233f9b26679b4f7b38d6ab6e"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-win32.whl", hash = "sha256:bfece2f7cec502ec5f759bbc09ce711445372deeac3628f6fa1c16b7fb45b682"}, + {file = "SQLAlchemy-2.0.21-cp312-cp312-win_amd64.whl", hash = "sha256:526b869a0f4f000d8d8ee3409d0becca30ae73f494cbb48801da0129601f72c6"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, @@ -7194,13 +7227,13 @@ files = [ [[package]] name = "types-setuptools" -version = "71.1.0.20240726" +version = "71.1.0.20240806" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-71.1.0.20240726.tar.gz", hash = "sha256:85ba28e9461bb1be86ebba4db0f1c2408f2b11115b1966334ea9dc464e29303e"}, - {file = "types_setuptools-71.1.0.20240726-py3-none-any.whl", hash = "sha256:a7775376f36e0ff09bcad236bf265777590a66b11623e48c20bfc30f1444ea36"}, + {file = "types-setuptools-71.1.0.20240806.tar.gz", hash = "sha256:ae5e7b4d643ab9e99fc00ac00041804118cabe72a56183c30d524fb064897ad6"}, + {file = "types_setuptools-71.1.0.20240806-py3-none-any.whl", hash = "sha256:3bd8dd02039be0bb79ad880d8893b8eefcb022fabbeeb61245c61b20c9ab1ed0"}, ] [[package]] @@ -7682,4 +7715,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<3.12" -content-hash = "e8f056b2287bd8749be814fb94a8636170fa7ef781e38c0d7666b505e429b269" +content-hash = "3cee8932228d75648fb926457902dd35c9e7b2edb013590588e906126ce45782" diff --git a/pyproject.toml b/pyproject.toml index a808728b1..dcbd820e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ gunicorn = "^20.1.0" sqlalchemy = "2.0.21" instructor = "1.3.5" networkx = "^3.2.1" -debugpy = "^1.8.0" +debugpy = "1.8.2" pyarrow = "15.0.0" pylint = "^3.0.3" aiosqlite = "^0.20.0" From 0dad12c6cf55e5a59629ee00c95b28c38a9495d8 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:48:50 +0200 Subject: [PATCH 28/44] fix: upgrade buildx action --- .github/workflows/docker_compose.yml | 2 +- .github/workflows/test_common.yml | 7 +++++++ .github/workflows/test_qdrant.yml | 7 +++++++ .github/workflows/test_weaviate.yml | 7 +++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker_compose.yml b/.github/workflows/docker_compose.yml index 8ef6f3c31..b66330325 100644 --- a/.github/workflows/docker_compose.yml +++ b/.github/workflows/docker_compose.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Build Docker images run: | diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 638536f8c..23dc490f9 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -18,6 +18,13 @@ jobs: name: docs changes uses: ./.github/workflows/get_docs_changes.yml + setup_docker: + name: Set up Docker Buildx + runs-on: ubuntu-latest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + run_common: name: test needs: get_docs_changes diff --git a/.github/workflows/test_qdrant.yml b/.github/workflows/test_qdrant.yml index d9c5444d2..009a49b9f 100644 --- a/.github/workflows/test_qdrant.yml +++ b/.github/workflows/test_qdrant.yml @@ -18,6 +18,13 @@ jobs: name: docs changes uses: ./.github/workflows/get_docs_changes.yml + setup_docker: + name: Set up Docker Buildx + runs-on: ubuntu-latest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + run_qdrant_integration_test: name: test needs: get_docs_changes diff --git a/.github/workflows/test_weaviate.yml b/.github/workflows/test_weaviate.yml index 132ee3e8f..4b2f26b97 100644 --- a/.github/workflows/test_weaviate.yml +++ b/.github/workflows/test_weaviate.yml @@ -18,6 +18,13 @@ jobs: name: docs changes uses: ./.github/workflows/get_docs_changes.yml + setup_docker: + name: Set up Docker Buildx + runs-on: ubuntu-latest + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + run_weaviate_integration_test: name: test needs: get_docs_changes From a590c6ae5bb6f4de9c5ea882bcbef539df014014 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:50:40 +0200 Subject: [PATCH 29/44] fix: run tests on ubuntu --- .github/workflows/test_qdrant.yml | 2 +- .github/workflows/test_weaviate.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_qdrant.yml b/.github/workflows/test_qdrant.yml index 009a49b9f..247460732 100644 --- a/.github/workflows/test_qdrant.yml +++ b/.github/workflows/test_qdrant.yml @@ -29,7 +29,7 @@ jobs: name: test needs: get_docs_changes if: needs.get_docs_changes.outputs.changes_outside_docs == 'true' - runs-on: macos-latest + runs-on: ubuntu-latest defaults: run: diff --git a/.github/workflows/test_weaviate.yml b/.github/workflows/test_weaviate.yml index 4b2f26b97..4035390e8 100644 --- a/.github/workflows/test_weaviate.yml +++ b/.github/workflows/test_weaviate.yml @@ -29,7 +29,7 @@ jobs: name: test needs: get_docs_changes if: needs.get_docs_changes.outputs.changes_outside_docs == 'true' - runs-on: macos-latest + runs-on: ubuntu-latest defaults: run: From 896a2ce953022ab42ffe7ca819648a9753448a30 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:54:56 +0200 Subject: [PATCH 30/44] fix: add postgres service to tests --- .github/workflows/test_common.yml | 12 ++++++++++++ .github/workflows/test_qdrant.yml | 12 ++++++++++++ .github/workflows/test_weaviate.yml | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 23dc490f9..67ce30cf7 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -47,6 +47,18 @@ jobs: run: shell: bash + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/test_qdrant.yml b/.github/workflows/test_qdrant.yml index 247460732..8d345362b 100644 --- a/.github/workflows/test_qdrant.yml +++ b/.github/workflows/test_qdrant.yml @@ -35,6 +35,18 @@ jobs: run: shell: bash + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + steps: - name: Check out uses: actions/checkout@v2 diff --git a/.github/workflows/test_weaviate.yml b/.github/workflows/test_weaviate.yml index 4035390e8..d1092dc3b 100644 --- a/.github/workflows/test_weaviate.yml +++ b/.github/workflows/test_weaviate.yml @@ -35,6 +35,18 @@ jobs: run: shell: bash + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - 5432:5432 + steps: - name: Check out uses: actions/checkout@v2 From e492a18987806963bcb8d38dcf44ba77ab37c561 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 15:59:33 +0200 Subject: [PATCH 31/44] fix: add env variables to test workflows --- .github/workflows/test_common.yml | 9 +++++++++ .github/workflows/test_neo4j.yml | 4 ++++ .github/workflows/test_qdrant.yml | 9 +++++++++ .github/workflows/test_weaviate.yml | 9 +++++++++ 4 files changed, 31 insertions(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 67ce30cf7..7ce0fb99c 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -107,6 +107,15 @@ jobs: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }} ENV: 'dev' + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 + DESTINATION__POSTGRES__CREDENTIALS__HOST: 127.0.0.1 + DESTINATION__POSTGRES__CREDENTIALS__USERNAME: cognee + DESTINATION__POSTGRES__CREDENTIALS__PASSWORD: cognee + DESTINATION__POSTGRES__CREDENTIALS__DATABASE: cognee_db run: poetry run python ./cognee/tests/test_library.py - name: Clean up disk space diff --git a/.github/workflows/test_neo4j.yml b/.github/workflows/test_neo4j.yml index 45c4fd198..3e04bcaa8 100644 --- a/.github/workflows/test_neo4j.yml +++ b/.github/workflows/test_neo4j.yml @@ -91,4 +91,8 @@ jobs: POSTGRES_DB: cognee_db POSTGRES_HOST: localhost POSTGRES_PORT: 5432 + DESTINATION__POSTGRES__CREDENTIALS__HOST: 127.0.0.1 + DESTINATION__POSTGRES__CREDENTIALS__USERNAME: cognee + DESTINATION__POSTGRES__CREDENTIALS__PASSWORD: cognee + DESTINATION__POSTGRES__CREDENTIALS__DATABASE: cognee_db run: poetry run python ./cognee/tests/test_neo4j.py diff --git a/.github/workflows/test_qdrant.yml b/.github/workflows/test_qdrant.yml index 8d345362b..b35ee1f2e 100644 --- a/.github/workflows/test_qdrant.yml +++ b/.github/workflows/test_qdrant.yml @@ -78,4 +78,13 @@ jobs: VECTOR_DB_URL: ${{ secrets.QDRANT_API_URL }} VECTOR_DB_KEY: ${{ secrets.QDRANT_API_KEY }} ENV: 'dev' + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 + DESTINATION__POSTGRES__CREDENTIALS__HOST: 127.0.0.1 + DESTINATION__POSTGRES__CREDENTIALS__USERNAME: cognee + DESTINATION__POSTGRES__CREDENTIALS__PASSWORD: cognee + DESTINATION__POSTGRES__CREDENTIALS__DATABASE: cognee_db run: poetry run python ./cognee/tests/test_qdrant.py diff --git a/.github/workflows/test_weaviate.yml b/.github/workflows/test_weaviate.yml index d1092dc3b..48cc63c52 100644 --- a/.github/workflows/test_weaviate.yml +++ b/.github/workflows/test_weaviate.yml @@ -78,4 +78,13 @@ jobs: VECTOR_DB_URL: ${{ secrets.WEAVIATE_API_URL }} VECTOR_DB_KEY: ${{ secrets.WEAVIATE_API_KEY }} ENV: 'dev' + POSTGRES_USER: cognee + POSTGRES_PASSWORD: cognee + POSTGRES_DB: cognee_db + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 + DESTINATION__POSTGRES__CREDENTIALS__HOST: 127.0.0.1 + DESTINATION__POSTGRES__CREDENTIALS__USERNAME: cognee + DESTINATION__POSTGRES__CREDENTIALS__PASSWORD: cognee + DESTINATION__POSTGRES__CREDENTIALS__DATABASE: cognee_db run: poetry run python ./cognee/tests/test_weaviate.py From ed6e8eb0d2856e0be10c01a0982669d86654be13 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 16:11:48 +0200 Subject: [PATCH 32/44] fix: wait for postgres to be ready before tests --- .github/workflows/test_common.yml | 6 ++++++ .github/workflows/test_neo4j.yml | 14 +++++++------- .github/workflows/test_qdrant.yml | 7 +++++++ .github/workflows/test_weaviate.yml | 6 ++++++ .../databases/graph/neo4j_driver/adapter.py | 3 ++- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 7ce0fb99c..d0f14a61e 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -98,6 +98,12 @@ jobs: mkdir .cognee_system echo $(pwd)/.cognee_system + - name: Wait for PostgreSQL to be ready + run: | + echo "Waiting for PostgreSQL to be ready..." + until pg_isready -h localhost -p 5432 -U cognee; do + sleep 1 + done - name: Run tests run: poetry run pytest tests/ diff --git a/.github/workflows/test_neo4j.yml b/.github/workflows/test_neo4j.yml index 3e04bcaa8..c2d04a467 100644 --- a/.github/workflows/test_neo4j.yml +++ b/.github/workflows/test_neo4j.yml @@ -63,13 +63,6 @@ jobs: virtualenvs-in-project: true installer-parallel: true - - name: Wait for PostgreSQL to be ready - run: | - echo "Waiting for PostgreSQL to be ready..." - until pg_isready -h localhost -p 5432 -U cognee; do - sleep 1 - done - - name: Install dependencies run: poetry install --no-interaction @@ -78,6 +71,13 @@ jobs: mkdir .cognee_system echo $(pwd)/.cognee_system + - name: Wait for PostgreSQL to be ready + run: | + echo "Waiting for PostgreSQL to be ready..." + until pg_isready -h localhost -p 5432 -U cognee; do + sleep 1 + done + - name: Run default Neo4j env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} diff --git a/.github/workflows/test_qdrant.yml b/.github/workflows/test_qdrant.yml index b35ee1f2e..b291be771 100644 --- a/.github/workflows/test_qdrant.yml +++ b/.github/workflows/test_qdrant.yml @@ -71,6 +71,13 @@ jobs: mkdir .cognee_system echo $(pwd)/.cognee_system + - name: Wait for PostgreSQL to be ready + run: | + echo "Waiting for PostgreSQL to be ready..." + until pg_isready -h localhost -p 5432 -U cognee; do + sleep 1 + done + - name: Run default Qdrant env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} diff --git a/.github/workflows/test_weaviate.yml b/.github/workflows/test_weaviate.yml index 48cc63c52..6534050be 100644 --- a/.github/workflows/test_weaviate.yml +++ b/.github/workflows/test_weaviate.yml @@ -71,6 +71,12 @@ jobs: mkdir .cognee_system echo $(pwd)/.cognee_system + - name: Wait for PostgreSQL to be ready + run: | + echo "Waiting for PostgreSQL to be ready..." + until pg_isready -h localhost -p 5432 -U cognee; do + sleep 1 + - name: Run default Weaviate env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} diff --git a/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py b/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py index 1c55f1e39..e7ccfb917 100644 --- a/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py +++ b/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py @@ -21,7 +21,8 @@ class Neo4jAdapter(GraphDBInterface): ): self.driver = driver or AsyncGraphDatabase.driver( graph_database_url, - auth = (graph_database_username, graph_database_password) + auth = (graph_database_username, graph_database_password), + max_connection_lifetime = 120 ) async def close(self) -> None: From a34acbc0ce990f17be76fcca73482b2e28c132d4 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 16:22:17 +0200 Subject: [PATCH 33/44] fix: update neo4j lib --- .github/workflows/test_weaviate.yml | 1 + poetry.lock | 7 ++++--- pyproject.toml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_weaviate.yml b/.github/workflows/test_weaviate.yml index 6534050be..3b0d49b3b 100644 --- a/.github/workflows/test_weaviate.yml +++ b/.github/workflows/test_weaviate.yml @@ -76,6 +76,7 @@ jobs: echo "Waiting for PostgreSQL to be ready..." until pg_isready -h localhost -p 5432 -U cognee; do sleep 1 + done - name: Run default Weaviate env: diff --git a/poetry.lock b/poetry.lock index b20898e95..c5660ca5a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3956,12 +3956,13 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] [[package]] name = "neo4j" -version = "5.20.0" +version = "5.23.1" description = "Neo4j Bolt driver for Python" optional = false python-versions = ">=3.7" files = [ - {file = "neo4j-5.20.0.tar.gz", hash = "sha256:c59e54a0c0fa1f109f1d2fa5293c29c2bb30ba388b4f9dd9656919793c10063a"}, + {file = "neo4j-5.23.1-py3-none-any.whl", hash = "sha256:97996fbf39421e0677fdcb8afe50b6810cbe8027e055a9dcf81da6070a82a009"}, + {file = "neo4j-5.23.1.tar.gz", hash = "sha256:e2d3399d1124319489b25d5eda99833ae086e1fffef9946d36241652d26b26a0"}, ] [package.dependencies] @@ -7715,4 +7716,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<3.12" -content-hash = "3cee8932228d75648fb926457902dd35c9e7b2edb013590588e906126ce45782" +content-hash = "943c25a4cb79907260cef7b8f71edc81a73ee79960ea43e75016a7e09c9022df" diff --git a/pyproject.toml b/pyproject.toml index dcbd820e4..489348fa7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ weaviate-client = "4.6.7" scikit-learn = "^1.5.0" fastembed = "0.2.7" pypdf = "^4.1.0" -neo4j = "5.20.0" +neo4j = "^5.20.0" jinja2 = "^3.1.3" matplotlib = "^3.8.3" structlog = "^24.1.0" From 1c891194879d0c04f09868eff8009303bac1c30d Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 16:35:39 +0200 Subject: [PATCH 34/44] fix: uuid parsing of search results --- cognee/api/client.py | 8 ++++---- cognee/api/v1/search/search.py | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cognee/api/client.py b/cognee/api/client.py index 89292cd39..74cefcb8e 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -328,10 +328,10 @@ def start_api_server(host: str = "0.0.0.0", port: int = 8000): try: logger.info("Starting server at %s:%s", host, port) - # import asyncio - # from cognee.modules.data.deletion import prune_system, prune_data - # asyncio.run(prune_data()) - # asyncio.run(prune_system(metadata = True)) + import asyncio + from cognee.modules.data.deletion import prune_system, prune_data + asyncio.run(prune_data()) + asyncio.run(prune_system(metadata = True)) uvicorn.run(app, host = host, port = port) except Exception as e: diff --git a/cognee/api/v1/search/search.py b/cognee/api/v1/search/search.py index 551bb270e..7bd363e7d 100644 --- a/cognee/api/v1/search/search.py +++ b/cognee/api/v1/search/search.py @@ -55,9 +55,10 @@ async def search(search_type: str, params: Dict[str, Any], user: User = None) -> filtered_search_results = [] for search_result in search_results: - result_document_id = UUID(search_result["document_id"]) if "document_id" in search_result else None + document_id = search_result["document_id"] if "document_id" in search_result else None + document_id = UUID(document_id) if type(document_id) == str else document_id - if result_document_id is None or result_document_id in own_document_ids: + if document_id is None or document_id in own_document_ids: filtered_search_results.append(search_result) return filtered_search_results From 8a63aa31f216c4fc003008e2a3e3ea994099cf8c Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 16:41:46 +0200 Subject: [PATCH 35/44] fix: run buildx on all platforms --- .github/workflows/test_common.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index d0f14a61e..b16e9570f 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -20,7 +20,6 @@ jobs: setup_docker: name: Set up Docker Buildx - runs-on: ubuntu-latest steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 4f72eb5cc9b613c05bafaa4b264a7e914b9cf9c3 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 16:46:14 +0200 Subject: [PATCH 36/44] fix: install buildx on all platforms --- .github/workflows/test_common.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index b16e9570f..17349bbba 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -20,6 +20,11 @@ jobs: setup_docker: name: Set up Docker Buildx + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "macos-latest"] steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 6d38bcdfbfba3a4b463deac51815de5e8d891810 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 16:57:57 +0200 Subject: [PATCH 37/44] fix: add QEMU --- .github/workflows/test_common.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 17349bbba..f6033c9cd 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -26,6 +26,9 @@ jobs: matrix: os: ["ubuntu-latest", "macos-latest"] steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 887d4e1ece904a29b723e4b661a620a3b2ec0f62 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:07:33 +0200 Subject: [PATCH 38/44] fix: add install_docker step in github action workflow --- .github/workflows/test_common.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index f6033c9cd..ca9ce0cf3 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -18,6 +18,15 @@ jobs: name: docs changes uses: ./.github/workflows/get_docs_changes.yml + install_docker: + if: runner.os == 'macOS' + run: | + HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask docker + sudo /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components + open -a /Applications/Docker.app --args --unattended --accept-license + echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." + while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done + setup_docker: name: Set up Docker Buildx runs-on: ${{ matrix.os }} From fd20fac5be48e7a3397463c3791558291b974c9f Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:09:03 +0200 Subject: [PATCH 39/44] fix: add steps --- .github/workflows/test_common.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index ca9ce0cf3..53cd5f034 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -20,12 +20,14 @@ jobs: install_docker: if: runner.os == 'macOS' - run: | - HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask docker - sudo /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components - open -a /Applications/Docker.app --args --unattended --accept-license - echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." - while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done + steps: + - name: Install Docker + run: | + HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask docker + sudo /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components + open -a /Applications/Docker.app --args --unattended --accept-license + echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." + while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done setup_docker: name: Set up Docker Buildx From 8fa572a43755d321ee7373ba9427ddec454059aa Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:09:59 +0200 Subject: [PATCH 40/44] fix: add runs-on --- .github/workflows/test_common.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 53cd5f034..b9282af5f 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -20,6 +20,7 @@ jobs: install_docker: if: runner.os == 'macOS' + runs-on: "ubuntu-latest" steps: - name: Install Docker run: | From 9927855fdb7f1e98488088452868a86bb79f0bfd Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:12:28 +0200 Subject: [PATCH 41/44] fix: move if --- .github/workflows/test_common.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index b9282af5f..10ac9d428 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -19,7 +19,6 @@ jobs: uses: ./.github/workflows/get_docs_changes.yml install_docker: - if: runner.os == 'macOS' runs-on: "ubuntu-latest" steps: - name: Install Docker @@ -29,6 +28,7 @@ jobs: open -a /Applications/Docker.app --args --unattended --accept-license echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done + if: runner.os == 'macOS' setup_docker: name: Set up Docker Buildx From 841e7b5f460f31faa2ad4bf677e8c1da3c011e23 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:14:15 +0200 Subject: [PATCH 42/44] fix: add needs --- .github/workflows/test_common.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 10ac9d428..192e4d718 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -33,6 +33,7 @@ jobs: setup_docker: name: Set up Docker Buildx runs-on: ${{ matrix.os }} + needs: install_docker strategy: fail-fast: false matrix: From f808cf165fc64e05aa51fea098b2716b44bb80cd Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:16:44 +0200 Subject: [PATCH 43/44] fix: move install docker job --- .github/workflows/test_common.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 192e4d718..93032a25c 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -18,8 +18,13 @@ jobs: name: docs changes uses: ./.github/workflows/get_docs_changes.yml - install_docker: - runs-on: "ubuntu-latest" + setup_docker: + name: Set up Docker Buildx + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "macos-latest"] steps: - name: Install Docker run: | @@ -29,16 +34,7 @@ jobs: echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done if: runner.os == 'macOS' - - setup_docker: - name: Set up Docker Buildx - runs-on: ${{ matrix.os }} - needs: install_docker - strategy: - fail-fast: false - matrix: - os: ["ubuntu-latest", "macos-latest"] - steps: + - name: Set up QEMU uses: docker/setup-qemu-action@v3 From e3c3f358f9d23aba2aa0132b93c2a1e46ebb9d22 Mon Sep 17 00:00:00 2001 From: Boris Arzentar Date: Tue, 6 Aug 2024 17:20:10 +0200 Subject: [PATCH 44/44] fix: remove macos test --- .github/workflows/test_common.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test_common.yml b/.github/workflows/test_common.yml index 93032a25c..b28fd977a 100644 --- a/.github/workflows/test_common.yml +++ b/.github/workflows/test_common.yml @@ -24,19 +24,20 @@ jobs: strategy: fail-fast: false matrix: - os: ["ubuntu-latest", "macos-latest"] + # os: ["ubuntu-latest", "macos-latest"] + os: ["ubuntu-latest"] steps: - - name: Install Docker - run: | - HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask docker - sudo /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components - open -a /Applications/Docker.app --args --unattended --accept-license - echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." - while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done - if: runner.os == 'macOS' + # - name: Install Docker + # run: | + # HOMEBREW_NO_AUTO_UPDATE=1 brew install --cask docker + # sudo /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components + # open -a /Applications/Docker.app --args --unattended --accept-license + # echo "We are waiting for Docker to be up and running. It can take over 2 minutes..." + # while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do sleep 1; done + # if: runner.os == 'macOS' - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + # - name: Set up QEMU + # uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -48,7 +49,7 @@ jobs: strategy: fail-fast: false matrix: - os: ["ubuntu-latest", "macos-latest"] #, "windows-latest" + os: ["ubuntu-latest"] #, "windows-latest", "macos-latest" python-version: ["3.11.x"] # Test all python versions on ubuntu only include: