diff --git a/.semversioner/next-release/patch-20250611170907043237.json b/.semversioner/next-release/patch-20250611170907043237.json new file mode 100644 index 0000000000..e6a546802a --- /dev/null +++ b/.semversioner/next-release/patch-20250611170907043237.json @@ -0,0 +1,4 @@ +{ + "type": "patch", + "description": "cleaned up logging to follow python standards." +} diff --git a/dictionary.txt b/dictionary.txt index a1210f6ff4..12cab57396 100644 --- a/dictionary.txt +++ b/dictionary.txt @@ -102,6 +102,7 @@ itertuples isin nocache nbconvert +levelno # HTML nbsp @@ -186,6 +187,7 @@ Verdantis's # English skippable upvote +unconfigured # Misc Arxiv diff --git a/docs/config/env_vars.md b/docs/config/env_vars.md index 0c2eb6ab78..004b3757e1 100644 --- a/docs/config/env_vars.md +++ b/docs/config/env_vars.md @@ -178,11 +178,11 @@ This section controls the cache mechanism used by the pipeline. This is used to ### Reporting -This section controls the reporting mechanism used by the pipeline, for common events and error messages. The default is to write reports to a file in the output directory. However, you can also choose to write reports to the console or to an Azure Blob Storage container. +This section controls the reporting mechanism used by the pipeline, for common events and error messages. The default is to write reports to a file in the output directory. However, you can also choose to write reports to an Azure Blob Storage container. | Parameter | Description | Type | Required or Optional | Default | | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | -------------------- | ------- | -| `GRAPHRAG_REPORTING_TYPE` | The type of reporter to use. Options are `file`, `console`, or `blob` | `str` | optional | `file` | +| `GRAPHRAG_REPORTING_TYPE` | The type of reporter to use. Options are `file` or `blob` | `str` | optional | `file` | | `GRAPHRAG_REPORTING_STORAGE_ACCOUNT_BLOB_URL` | The Azure Storage blob endpoint to use when in `blob` mode and using managed identity. Will have the format `https://.blob.core.windows.net` | `str` | optional | None | | `GRAPHRAG_REPORTING_CONNECTION_STRING` | The Azure Storage connection string to use when in `blob` mode. | `str` | optional | None | | `GRAPHRAG_REPORTING_CONTAINER_NAME` | The Azure Storage container name to use when in `blob` mode. | `str` | optional | None | diff --git a/docs/config/yaml.md b/docs/config/yaml.md index 6c61ffe80c..7d7dcdd9e2 100644 --- a/docs/config/yaml.md +++ b/docs/config/yaml.md @@ -149,11 +149,11 @@ This section controls the cache mechanism used by the pipeline. This is used to ### reporting -This section controls the reporting mechanism used by the pipeline, for common events and error messages. The default is to write reports to a file in the output directory. However, you can also choose to write reports to the console or to an Azure Blob Storage container. +This section controls the reporting mechanism used by the pipeline, for common events and error messages. The default is to write reports to a file in the output directory. However, you can also choose to write reports to an Azure Blob Storage container. #### Fields -- `type` **file|console|blob** - The reporting type to use. Default=`file` +- `type` **file|blob** - The reporting type to use. Default=`file` - `base_dir` **str** - The base directory to write reports to, relative to the root. - `connection_string` **str** - (blob only) The Azure Storage connection string. - `container_name` **str** - (blob only) The Azure Storage container name. diff --git a/graphrag/__init__.py b/graphrag/__init__.py index a1e9b589bf..4dd61db0f6 100644 --- a/graphrag/__init__.py +++ b/graphrag/__init__.py @@ -2,3 +2,10 @@ # Licensed under the MIT License """The GraphRAG package.""" + +import logging + +from graphrag.logger.standard_logging import init_console_logger + +logger = logging.getLogger(__name__) +init_console_logger() diff --git a/graphrag/api/index.py b/graphrag/api/index.py index b42655424c..c7f7f07898 100644 --- a/graphrag/api/index.py +++ b/graphrag/api/index.py @@ -10,7 +10,7 @@ import logging -from graphrag.callbacks.reporting import create_pipeline_reporter +from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.config.enums import IndexingMethod from graphrag.config.models.graph_rag_config import GraphRagConfig @@ -19,10 +19,9 @@ from graphrag.index.typing.pipeline_run_result import PipelineRunResult from graphrag.index.typing.workflow import WorkflowFunction from graphrag.index.workflows.factory import PipelineFactory -from graphrag.logger.base import ProgressLogger -from graphrag.logger.null_progress import NullProgressLogger +from graphrag.logger.standard_logging import init_loggers -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def build_index( @@ -31,7 +30,6 @@ async def build_index( is_update_run: bool = False, memory_profile: bool = False, callbacks: list[WorkflowCallbacks] | None = None, - progress_logger: ProgressLogger | None = None, ) -> list[PipelineRunResult]: """Run the pipeline with the given configuration. @@ -45,26 +43,25 @@ async def build_index( Whether to enable memory profiling. callbacks : list[WorkflowCallbacks] | None default=None A list of callbacks to register. - progress_logger : ProgressLogger | None default=None - The progress logger. Returns ------- list[PipelineRunResult] The list of pipeline run results """ - logger = progress_logger or NullProgressLogger() - # create a pipeline reporter and add to any additional callbacks - callbacks = callbacks or [] - callbacks.append(create_pipeline_reporter(config.reporting, None)) + init_loggers(config=config) - workflow_callbacks = create_callback_chain(callbacks, logger) + # Create callbacks for pipeline lifecycle events if provided + workflow_callbacks = ( + create_callback_chain(callbacks) if callbacks else NoopWorkflowCallbacks() + ) outputs: list[PipelineRunResult] = [] if memory_profile: - log.warning("New pipeline does not yet support memory profiling.") + logger.warning("New pipeline does not yet support memory profiling.") + logger.info("Initializing indexing pipeline...") # todo: this could propagate out to the cli for better clarity, but will be a breaking api change method = _get_method(method, is_update_run) pipeline = PipelineFactory.create_pipeline(config, method) @@ -75,15 +72,14 @@ async def build_index( pipeline, config, callbacks=workflow_callbacks, - logger=logger, is_update_run=is_update_run, ): outputs.append(output) if output.errors and len(output.errors) > 0: - logger.error(output.workflow) + logger.error("Workflow %s completed with errors", output.workflow) else: - logger.success(output.workflow) - logger.info(str(output.result)) + logger.info("Workflow %s completed successfully", output.workflow) + logger.debug(str(output.result)) workflow_callbacks.pipeline_end(outputs) return outputs diff --git a/graphrag/api/prompt_tune.py b/graphrag/api/prompt_tune.py index fb47c8c18a..168cbfc652 100644 --- a/graphrag/api/prompt_tune.py +++ b/graphrag/api/prompt_tune.py @@ -11,6 +11,7 @@ Backwards compatibility is not guaranteed at this time. """ +import logging from typing import Annotated import annotated_types @@ -20,7 +21,7 @@ from graphrag.config.defaults import graphrag_config_defaults from graphrag.config.models.graph_rag_config import GraphRagConfig from graphrag.language_model.manager import ModelManager -from graphrag.logger.base import ProgressLogger +from graphrag.logger.standard_logging import init_loggers from graphrag.prompt_tune.defaults import MAX_TOKEN_COUNT, PROMPT_TUNING_MODEL_ID from graphrag.prompt_tune.generator.community_report_rating import ( generate_community_report_rating, @@ -47,11 +48,12 @@ from graphrag.prompt_tune.loader.input import load_docs_in_chunks from graphrag.prompt_tune.types import DocSelectionType +logger = logging.getLogger(__name__) + @validate_call(config={"arbitrary_types_allowed": True}) async def generate_indexing_prompts( config: GraphRagConfig, - logger: ProgressLogger, chunk_size: PositiveInt = graphrag_config_defaults.chunks.size, overlap: Annotated[ int, annotated_types.Gt(-1) @@ -71,8 +73,6 @@ async def generate_indexing_prompts( Parameters ---------- - config: The GraphRag configuration. - - logger: The logger to use for progress updates. - - root: The root directory. - output_path: The path to store the prompts. - chunk_size: The chunk token size to use for input text units. - limit: The limit of chunks to load. @@ -89,6 +89,8 @@ async def generate_indexing_prompts( ------- tuple[str, str, str]: entity extraction prompt, entity summarization prompt, community summarization prompt """ + init_loggers(config=config) + # Retrieve documents logger.info("Chunking documents...") doc_list = await load_docs_in_chunks( @@ -187,9 +189,9 @@ async def generate_indexing_prompts( language=language, ) - logger.info(f"\nGenerated domain: {domain}") # noqa: G004 - logger.info(f"\nDetected language: {language}") # noqa: G004 - logger.info(f"\nGenerated persona: {persona}") # noqa: G004 + logger.debug("Generated domain: %s", domain) + logger.debug("Detected language: %s", language) + logger.debug("Generated persona: %s", persona) return ( extract_graph_prompt, diff --git a/graphrag/api/query.py b/graphrag/api/query.py index 5077a5745b..31017f592d 100644 --- a/graphrag/api/query.py +++ b/graphrag/api/query.py @@ -17,6 +17,7 @@ Backwards compatibility is not guaranteed at this time. """ +import logging from collections.abc import AsyncGenerator from typing import Any @@ -31,7 +32,7 @@ text_unit_text_embedding, ) from graphrag.config.models.graph_rag_config import GraphRagConfig -from graphrag.logger.print_progress import PrintProgressLogger +from graphrag.logger.standard_logging import init_loggers from graphrag.query.factory import ( get_basic_search_engine, get_drift_search_engine, @@ -50,11 +51,13 @@ from graphrag.utils.api import ( get_embedding_store, load_search_prompt, + truncate, update_context_data, ) from graphrag.utils.cli import redact -logger = PrintProgressLogger("") +# Initialize standard logger +logger = logging.getLogger(__name__) @validate_call(config={"arbitrary_types_allowed": True}) @@ -68,6 +71,7 @@ async def global_search( response_type: str, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -88,11 +92,9 @@ async def global_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + callbacks = callbacks or [] full_response = "" context_data = {} @@ -105,6 +107,7 @@ def on_context(context: Any) -> None: local_callbacks.on_context = on_context callbacks.append(local_callbacks) + logger.debug("Executing global search query: %s", query) async for chunk in global_search_streaming( config=config, entities=entities, @@ -117,6 +120,7 @@ def on_context(context: Any) -> None: callbacks=callbacks, ): full_response += chunk + logger.debug("Query response: %s", truncate(full_response, 400)) return full_response, context_data @@ -131,6 +135,7 @@ def global_search_streaming( response_type: str, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> AsyncGenerator: """Perform a global search and return the context data and response via a generator. @@ -150,11 +155,9 @@ def global_search_streaming( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + communities_ = read_indexer_communities(communities, community_reports) reports = read_indexer_reports( community_reports, @@ -173,6 +176,7 @@ def global_search_streaming( config.root_dir, config.global_search.knowledge_prompt ) + logger.debug("Executing streaming global search query: %s", query) search_engine = get_global_search_engine( config, reports=reports, @@ -201,6 +205,7 @@ async def multi_index_global_search( streaming: bool, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -223,11 +228,9 @@ async def multi_index_global_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + # Streaming not supported yet if streaming: message = "Streaming not yet implemented for multi_global_search" @@ -311,6 +314,7 @@ async def multi_index_global_search( communities_dfs, axis=0, ignore_index=True, sort=False ) + logger.debug("Executing multi-index global search query: %s", query) result = await global_search( config, entities=entities_combined, @@ -326,6 +330,7 @@ async def multi_index_global_search( # Update the context data by linking index names and community ids context = update_context_data(result[1], links) + logger.debug("Query response: %s", truncate(result[0], 400)) # type: ignore return (result[0], context) @@ -342,6 +347,7 @@ async def local_search( response_type: str, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -362,11 +368,9 @@ async def local_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + callbacks = callbacks or [] full_response = "" context_data = {} @@ -379,6 +383,7 @@ def on_context(context: Any) -> None: local_callbacks.on_context = on_context callbacks.append(local_callbacks) + logger.debug("Executing local search query: %s", query) async for chunk in local_search_streaming( config=config, entities=entities, @@ -393,6 +398,7 @@ def on_context(context: Any) -> None: callbacks=callbacks, ): full_response += chunk + logger.debug("Query response: %s", truncate(full_response, 400)) return full_response, context_data @@ -409,6 +415,7 @@ def local_search_streaming( response_type: str, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> AsyncGenerator: """Perform a local search and return the context data and response via a generator. @@ -427,16 +434,14 @@ def local_search_streaming( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + vector_store_args = {} for index, store in config.vector_store.items(): vector_store_args[index] = store.model_dump() msg = f"Vector Store Args: {redact(vector_store_args)}" - logger.info(msg) + logger.debug(msg) description_embedding_store = get_embedding_store( config_args=vector_store_args, @@ -447,6 +452,7 @@ def local_search_streaming( covariates_ = read_indexer_covariates(covariates) if covariates is not None else [] prompt = load_search_prompt(config.root_dir, config.local_search.prompt) + logger.debug("Executing streaming local search query: %s", query) search_engine = get_local_search_engine( config=config, reports=read_indexer_reports(community_reports, communities, community_level), @@ -477,6 +483,7 @@ async def multi_index_local_search( streaming: bool, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -500,11 +507,9 @@ async def multi_index_local_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + # Streaming not supported yet if streaming: message = "Streaming not yet implemented for multi_index_local_search" @@ -670,6 +675,7 @@ async def multi_index_local_search( covariates_combined = pd.concat( covariates_dfs, axis=0, ignore_index=True, sort=False ) + logger.debug("Executing multi-index local search query: %s", query) result = await local_search( config, entities=entities_combined, @@ -687,6 +693,7 @@ async def multi_index_local_search( # Update the context data by linking index names and community ids context = update_context_data(result[1], links) + logger.debug("Query response: %s", truncate(result[0], 400)) # type: ignore return (result[0], context) @@ -702,6 +709,7 @@ async def drift_search( response_type: str, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -721,11 +729,9 @@ async def drift_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + callbacks = callbacks or [] full_response = "" context_data = {} @@ -738,6 +744,7 @@ def on_context(context: Any) -> None: local_callbacks.on_context = on_context callbacks.append(local_callbacks) + logger.debug("Executing drift search query: %s", query) async for chunk in drift_search_streaming( config=config, entities=entities, @@ -751,6 +758,7 @@ def on_context(context: Any) -> None: callbacks=callbacks, ): full_response += chunk + logger.debug("Query response: %s", truncate(full_response, 400)) return full_response, context_data @@ -766,6 +774,7 @@ def drift_search_streaming( response_type: str, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> AsyncGenerator: """Perform a DRIFT search and return the context data and response. @@ -782,16 +791,14 @@ def drift_search_streaming( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + vector_store_args = {} for index, store in config.vector_store.items(): vector_store_args[index] = store.model_dump() msg = f"Vector Store Args: {redact(vector_store_args)}" - logger.info(msg) + logger.debug(msg) description_embedding_store = get_embedding_store( config_args=vector_store_args, @@ -811,6 +818,7 @@ def drift_search_streaming( config.root_dir, config.drift_search.reduce_prompt ) + logger.debug("Executing streaming drift search query: %s", query) search_engine = get_drift_search_engine( config=config, reports=reports, @@ -840,6 +848,7 @@ async def multi_index_drift_search( streaming: bool, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -862,11 +871,9 @@ async def multi_index_drift_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + # Streaming not supported yet if streaming: message = "Streaming not yet implemented for multi_drift_search" @@ -1009,6 +1016,7 @@ async def multi_index_drift_search( text_units_dfs, axis=0, ignore_index=True, sort=False ) + logger.debug("Executing multi-index drift search query: %s", query) result = await drift_search( config, entities=entities_combined, @@ -1029,6 +1037,8 @@ async def multi_index_drift_search( context[key] = update_context_data(result[1][key], links) else: context = result[1] + + logger.debug("Query response: %s", truncate(result[0], 400)) # type: ignore return (result[0], context) @@ -1038,6 +1048,7 @@ async def basic_search( text_units: pd.DataFrame, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -1053,11 +1064,9 @@ async def basic_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + callbacks = callbacks or [] full_response = "" context_data = {} @@ -1070,6 +1079,7 @@ def on_context(context: Any) -> None: local_callbacks.on_context = on_context callbacks.append(local_callbacks) + logger.debug("Executing basic search query: %s", query) async for chunk in basic_search_streaming( config=config, text_units=text_units, @@ -1077,6 +1087,7 @@ def on_context(context: Any) -> None: callbacks=callbacks, ): full_response += chunk + logger.debug("Query response: %s", truncate(full_response, 400)) return full_response, context_data @@ -1086,6 +1097,7 @@ def basic_search_streaming( text_units: pd.DataFrame, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> AsyncGenerator: """Perform a local search and return the context data and response via a generator. @@ -1098,16 +1110,14 @@ def basic_search_streaming( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + vector_store_args = {} for index, store in config.vector_store.items(): vector_store_args[index] = store.model_dump() msg = f"Vector Store Args: {redact(vector_store_args)}" - logger.info(msg) + logger.debug(msg) description_embedding_store = get_embedding_store( config_args=vector_store_args, @@ -1116,6 +1126,7 @@ def basic_search_streaming( prompt = load_search_prompt(config.root_dir, config.basic_search.prompt) + logger.debug("Executing streaming basic search query: %s", query) search_engine = get_basic_search_engine( config=config, text_units=read_indexer_text_units(text_units), @@ -1134,6 +1145,7 @@ async def multi_index_basic_search( streaming: bool, query: str, callbacks: list[QueryCallbacks] | None = None, + verbose: bool = False, ) -> tuple[ str | dict[str, Any] | list[dict[str, Any]], str | list[pd.DataFrame] | dict[str, pd.DataFrame], @@ -1151,11 +1163,9 @@ async def multi_index_basic_search( Returns ------- TODO: Document the search response type and format. - - Raises - ------ - TODO: Document any exceptions to expect. """ + init_loggers(config=config, verbose=verbose) + # Streaming not supported yet if streaming: message = "Streaming not yet implemented for multi_basic_search" @@ -1192,6 +1202,7 @@ async def multi_index_basic_search( text_units_dfs, axis=0, ignore_index=True, sort=False ) + logger.debug("Executing multi-index basic search query: %s", query) return await basic_search( config, text_units=text_units_combined, diff --git a/graphrag/callbacks/console_workflow_callbacks.py b/graphrag/callbacks/console_workflow_callbacks.py deleted file mode 100644 index b1478085de..0000000000 --- a/graphrag/callbacks/console_workflow_callbacks.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""A logger that emits updates from the indexing engine to the console.""" - -from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks - - -class ConsoleWorkflowCallbacks(NoopWorkflowCallbacks): - """A logger that writes to a console.""" - - def error( - self, - message: str, - cause: BaseException | None = None, - stack: str | None = None, - details: dict | None = None, - ): - """Handle when an error occurs.""" - print(message, str(cause), stack, details) # noqa T201 - - def warning(self, message: str, details: dict | None = None): - """Handle when a warning occurs.""" - _print_warning(message) - - def log(self, message: str, details: dict | None = None): - """Handle when a log message is produced.""" - print(message, details) # noqa T201 - - -def _print_warning(skk): - print("\033[93m {}\033[00m".format(skk)) # noqa T201 diff --git a/graphrag/callbacks/file_workflow_callbacks.py b/graphrag/callbacks/file_workflow_callbacks.py deleted file mode 100644 index 1f476f8c52..0000000000 --- a/graphrag/callbacks/file_workflow_callbacks.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""A logger that emits updates from the indexing engine to a local file.""" - -import json -import logging -from io import TextIOWrapper -from pathlib import Path - -from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks - -log = logging.getLogger(__name__) - - -class FileWorkflowCallbacks(NoopWorkflowCallbacks): - """A logger that writes to a local file.""" - - _out_stream: TextIOWrapper - - def __init__(self, directory: str): - """Create a new file-based workflow logger.""" - Path(directory).mkdir(parents=True, exist_ok=True) - self._out_stream = open( # noqa: PTH123, SIM115 - Path(directory) / "logs.json", "a", encoding="utf-8", errors="strict" - ) - - def error( - self, - message: str, - cause: BaseException | None = None, - stack: str | None = None, - details: dict | None = None, - ): - """Handle when an error occurs.""" - self._out_stream.write( - json.dumps( - { - "type": "error", - "data": message, - "stack": stack, - "source": str(cause), - "details": details, - }, - indent=4, - ensure_ascii=False, - ) - + "\n" - ) - message = f"{message} details={details}" - log.info(message) - - def warning(self, message: str, details: dict | None = None): - """Handle when a warning occurs.""" - self._out_stream.write( - json.dumps( - {"type": "warning", "data": message, "details": details}, - ensure_ascii=False, - ) - + "\n" - ) - _print_warning(message) - - def log(self, message: str, details: dict | None = None): - """Handle when a log message is produced.""" - self._out_stream.write( - json.dumps( - {"type": "log", "data": message, "details": details}, ensure_ascii=False - ) - + "\n" - ) - - message = f"{message} details={details}" - log.info(message) - - -def _print_warning(skk): - log.warning(skk) diff --git a/graphrag/callbacks/noop_workflow_callbacks.py b/graphrag/callbacks/noop_workflow_callbacks.py index 5b8eb6e41d..9f9ac2aee0 100644 --- a/graphrag/callbacks/noop_workflow_callbacks.py +++ b/graphrag/callbacks/noop_workflow_callbacks.py @@ -9,13 +9,13 @@ class NoopWorkflowCallbacks(WorkflowCallbacks): - """A no-op implementation of WorkflowCallbacks.""" + """A no-op implementation of WorkflowCallbacks that logs all events to standard logging.""" def pipeline_start(self, names: list[str]) -> None: - """Execute this callback when a the entire pipeline starts.""" + """Execute this callback to signal when the entire pipeline starts.""" def pipeline_end(self, results: list[PipelineRunResult]) -> None: - """Execute this callback when the entire pipeline ends.""" + """Execute this callback to signal when the entire pipeline ends.""" def workflow_start(self, name: str, instance: object) -> None: """Execute this callback when a workflow starts.""" @@ -25,18 +25,3 @@ def workflow_end(self, name: str, instance: object) -> None: def progress(self, progress: Progress) -> None: """Handle when progress occurs.""" - - def error( - self, - message: str, - cause: BaseException | None = None, - stack: str | None = None, - details: dict | None = None, - ) -> None: - """Handle when an error occurs.""" - - def warning(self, message: str, details: dict | None = None) -> None: - """Handle when a warning occurs.""" - - def log(self, message: str, details: dict | None = None) -> None: - """Handle when a log message occurs.""" diff --git a/graphrag/callbacks/progress_workflow_callbacks.py b/graphrag/callbacks/progress_workflow_callbacks.py deleted file mode 100644 index cff483187f..0000000000 --- a/graphrag/callbacks/progress_workflow_callbacks.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""A workflow callback manager that emits updates.""" - -from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks -from graphrag.logger.base import ProgressLogger -from graphrag.logger.progress import Progress - - -class ProgressWorkflowCallbacks(NoopWorkflowCallbacks): - """A callbackmanager that delegates to a ProgressLogger.""" - - _root_progress: ProgressLogger - _progress_stack: list[ProgressLogger] - - def __init__(self, progress: ProgressLogger) -> None: - """Create a new ProgressWorkflowCallbacks.""" - self._progress = progress - self._progress_stack = [progress] - - def _pop(self) -> None: - self._progress_stack.pop() - - def _push(self, name: str) -> None: - self._progress_stack.append(self._latest.child(name)) - - @property - def _latest(self) -> ProgressLogger: - return self._progress_stack[-1] - - def workflow_start(self, name: str, instance: object) -> None: - """Execute this callback when a workflow starts.""" - self._push(name) - - def workflow_end(self, name: str, instance: object) -> None: - """Execute this callback when a workflow ends.""" - self._pop() - - def progress(self, progress: Progress) -> None: - """Handle when progress occurs.""" - self._latest(progress) diff --git a/graphrag/callbacks/reporting.py b/graphrag/callbacks/reporting.py deleted file mode 100644 index 8c1ad3db8b..0000000000 --- a/graphrag/callbacks/reporting.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""A module containing the pipeline reporter factory.""" - -from __future__ import annotations - -from pathlib import Path -from typing import TYPE_CHECKING - -from graphrag.callbacks.blob_workflow_callbacks import BlobWorkflowCallbacks -from graphrag.callbacks.console_workflow_callbacks import ConsoleWorkflowCallbacks -from graphrag.callbacks.file_workflow_callbacks import FileWorkflowCallbacks -from graphrag.config.enums import ReportingType -from graphrag.config.models.reporting_config import ReportingConfig - -if TYPE_CHECKING: - from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks - - -def create_pipeline_reporter( - config: ReportingConfig | None, root_dir: str | None -) -> WorkflowCallbacks: - """Create a logger for the given pipeline config.""" - config = config or ReportingConfig(base_dir="logs", type=ReportingType.file) - match config.type: - case ReportingType.file: - return FileWorkflowCallbacks( - str(Path(root_dir or "") / (config.base_dir or "")) - ) - case ReportingType.console: - return ConsoleWorkflowCallbacks() - case ReportingType.blob: - return BlobWorkflowCallbacks( - config.connection_string, - config.container_name, - base_dir=config.base_dir, - storage_account_blob_url=config.storage_account_blob_url, - ) diff --git a/graphrag/callbacks/workflow_callbacks.py b/graphrag/callbacks/workflow_callbacks.py index ca699e9233..0429cff809 100644 --- a/graphrag/callbacks/workflow_callbacks.py +++ b/graphrag/callbacks/workflow_callbacks.py @@ -35,21 +35,3 @@ def workflow_end(self, name: str, instance: object) -> None: def progress(self, progress: Progress) -> None: """Handle when progress occurs.""" ... - - def error( - self, - message: str, - cause: BaseException | None = None, - stack: str | None = None, - details: dict | None = None, - ) -> None: - """Handle when an error occurs.""" - ... - - def warning(self, message: str, details: dict | None = None) -> None: - """Handle when a warning occurs.""" - ... - - def log(self, message: str, details: dict | None = None) -> None: - """Handle when a log message occurs.""" - ... diff --git a/graphrag/callbacks/workflow_callbacks_manager.py b/graphrag/callbacks/workflow_callbacks_manager.py index fd7fc356c5..1ca0c097e5 100644 --- a/graphrag/callbacks/workflow_callbacks_manager.py +++ b/graphrag/callbacks/workflow_callbacks_manager.py @@ -50,27 +50,3 @@ def progress(self, progress: Progress) -> None: for callback in self._callbacks: if hasattr(callback, "progress"): callback.progress(progress) - - def error( - self, - message: str, - cause: BaseException | None = None, - stack: str | None = None, - details: dict | None = None, - ) -> None: - """Handle when an error occurs.""" - for callback in self._callbacks: - if hasattr(callback, "error"): - callback.error(message, cause, stack, details) - - def warning(self, message: str, details: dict | None = None) -> None: - """Handle when a warning occurs.""" - for callback in self._callbacks: - if hasattr(callback, "warning"): - callback.warning(message, details) - - def log(self, message: str, details: dict | None = None) -> None: - """Handle when a log message occurs.""" - for callback in self._callbacks: - if hasattr(callback, "log"): - callback.log(message, details) diff --git a/graphrag/cli/index.py b/graphrag/cli/index.py index 29991e06ec..87b8b1af34 100644 --- a/graphrag/cli/index.py +++ b/graphrag/cli/index.py @@ -10,49 +10,26 @@ from pathlib import Path import graphrag.api as api -from graphrag.config.enums import CacheType, IndexingMethod +from graphrag.config.enums import CacheType, IndexingMethod, ReportingType from graphrag.config.load_config import load_config -from graphrag.config.logging import enable_logging_with_config from graphrag.index.validate_config import validate_config_names -from graphrag.logger.base import ProgressLogger -from graphrag.logger.factory import LoggerFactory, LoggerType from graphrag.utils.cli import redact # Ignore warnings from numba warnings.filterwarnings("ignore", message=".*NumbaDeprecationWarning.*") -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) -def _logger(logger: ProgressLogger): - def info(msg: str, verbose: bool = False): - log.info(msg) - if verbose: - logger.info(msg) - - def error(msg: str, verbose: bool = False): - log.error(msg) - if verbose: - logger.error(msg) - - def success(msg: str, verbose: bool = False): - log.info(msg) - if verbose: - logger.success(msg) - - return info, error, success - - -def _register_signal_handlers(logger: ProgressLogger): +def _register_signal_handlers(): import signal def handle_signal(signum, _): # Handle the signal here - logger.info(f"Received signal {signum}, exiting...") # noqa: G004 - logger.dispose() + logger.debug(f"Received signal {signum}, exiting...") # noqa: G004 for task in asyncio.all_tasks(): task.cancel() - logger.info("All tasks cancelled. Exiting...") + logger.debug("All tasks cancelled. Exiting...") # Register signal handlers for SIGINT and SIGHUP signal.signal(signal.SIGINT, handle_signal) @@ -67,7 +44,6 @@ def index_cli( verbose: bool, memprofile: bool, cache: bool, - logger: LoggerType, config_filepath: Path | None, dry_run: bool, skip_validation: bool, @@ -87,7 +63,6 @@ def index_cli( verbose=verbose, memprofile=memprofile, cache=cache, - logger=logger, dry_run=dry_run, skip_validation=skip_validation, ) @@ -99,7 +74,6 @@ def update_cli( verbose: bool, memprofile: bool, cache: bool, - logger: LoggerType, config_filepath: Path | None, skip_validation: bool, output_dir: Path | None, @@ -120,7 +94,6 @@ def update_cli( verbose=verbose, memprofile=memprofile, cache=cache, - logger=logger, dry_run=False, skip_validation=skip_validation, ) @@ -133,39 +106,47 @@ def _run_index( verbose, memprofile, cache, - logger, dry_run, skip_validation, ): - progress_logger = LoggerFactory().create_logger(logger) - info, error, success = _logger(progress_logger) + # Configure the root logger with the specified log level + from graphrag.logger.standard_logging import init_loggers + + # Initialize loggers and reporting config + init_loggers( + config=config, + root_dir=str(config.root_dir) if config.root_dir else None, + verbose=verbose, + ) if not cache: config.cache.type = CacheType.none - enabled_logging, log_path = enable_logging_with_config(config, verbose) - if enabled_logging: - info(f"Logging enabled at {log_path}", True) + # Log the configuration details + if config.reporting.type == ReportingType.file: + log_dir = Path(config.root_dir or "") / (config.reporting.base_dir or "") + log_path = log_dir / "logs.txt" + logger.info("Logging enabled at %s", log_path) else: - info( - f"Logging not enabled for config {redact(config.model_dump())}", - True, + logger.info( + "Logging not enabled for config %s", + redact(config.model_dump()), ) if not skip_validation: - validate_config_names(progress_logger, config) + validate_config_names(config) - info(f"Starting pipeline run. {dry_run=}", verbose) - info( - f"Using default configuration: {redact(config.model_dump())}", - verbose, + logger.info("Starting pipeline run. %s", dry_run) + logger.info( + "Using default configuration: %s", + redact(config.model_dump()), ) if dry_run: - info("Dry run complete, exiting...", True) + logger.info("Dry run complete, exiting...", True) sys.exit(0) - _register_signal_handlers(progress_logger) + _register_signal_handlers() outputs = asyncio.run( api.build_index( @@ -173,19 +154,17 @@ def _run_index( method=method, is_update_run=is_update_run, memory_profile=memprofile, - progress_logger=progress_logger, ) ) encountered_errors = any( output.errors and len(output.errors) > 0 for output in outputs ) - progress_logger.stop() if encountered_errors: - error( - "Errors occurred during the pipeline run, see logs for more details.", True + logger.error( + "Errors occurred during the pipeline run, see logs for more details." ) else: - success("All workflows completed successfully.", True) + logger.info("All workflows completed successfully.") sys.exit(1 if encountered_errors else 0) diff --git a/graphrag/cli/initialize.py b/graphrag/cli/initialize.py index 1c57c55d65..09215f8c5d 100644 --- a/graphrag/cli/initialize.py +++ b/graphrag/cli/initialize.py @@ -3,10 +3,10 @@ """CLI implementation of the initialization subcommand.""" +import logging from pathlib import Path from graphrag.config.init_content import INIT_DOTENV, INIT_YAML -from graphrag.logger.factory import LoggerFactory, LoggerType from graphrag.prompts.index.community_report import ( COMMUNITY_REPORT_PROMPT, ) @@ -31,6 +31,8 @@ from graphrag.prompts.query.local_search_system_prompt import LOCAL_SEARCH_SYSTEM_PROMPT from graphrag.prompts.query.question_gen_system_prompt import QUESTION_SYSTEM_PROMPT +logger = logging.getLogger(__name__) + def initialize_project_at(path: Path, force: bool) -> None: """ @@ -48,8 +50,7 @@ def initialize_project_at(path: Path, force: bool) -> None: ValueError If the project already exists and force is False. """ - progress_logger = LoggerFactory().create_logger(LoggerType.RICH) - progress_logger.info(f"Initializing project at {path}") # noqa: G004 + logger.info("Initializing project at %s", path) root = Path(path) if not root.exists(): root.mkdir(parents=True, exist_ok=True) diff --git a/graphrag/cli/main.py b/graphrag/cli/main.py index 7f0660d556..bc0e9f39ac 100644 --- a/graphrag/cli/main.py +++ b/graphrag/cli/main.py @@ -12,7 +12,6 @@ from graphrag.config.defaults import graphrag_config_defaults from graphrag.config.enums import IndexingMethod, SearchMethod -from graphrag.logger.types import LoggerType from graphrag.prompt_tune.defaults import LIMIT, MAX_TOKEN_COUNT, N_SUBSET_MAX, K from graphrag.prompt_tune.types import DocSelectionType @@ -157,11 +156,6 @@ def _index_cli( "--memprofile", help="Run the indexing pipeline with memory profiling", ), - logger: LoggerType = typer.Option( - LoggerType.RICH.value, - "--logger", - help="The progress logger to use.", - ), dry_run: bool = typer.Option( False, "--dry-run", @@ -201,7 +195,6 @@ def _index_cli( verbose=verbose, memprofile=memprofile, cache=cache, - logger=LoggerType(logger), config_filepath=config, dry_run=dry_run, skip_validation=skip_validation, @@ -250,11 +243,6 @@ def _update_cli( "--memprofile", help="Run the indexing pipeline with memory profiling.", ), - logger: LoggerType = typer.Option( - LoggerType.RICH.value, - "--logger", - help="The progress logger to use.", - ), cache: bool = typer.Option( True, "--cache/--no-cache", @@ -290,7 +278,6 @@ def _update_cli( verbose=verbose, memprofile=memprofile, cache=cache, - logger=LoggerType(logger), config_filepath=config, skip_validation=skip_validation, output_dir=output, @@ -327,11 +314,6 @@ def _prompt_tune_cli( "-v", help="Run the prompt tuning pipeline with verbose logging.", ), - logger: LoggerType = typer.Option( - LoggerType.RICH.value, - "--logger", - help="The progress logger to use.", - ), domain: str | None = typer.Option( None, "--domain", @@ -413,7 +395,6 @@ def _prompt_tune_cli( config=config, domain=domain, verbose=verbose, - logger=logger, selection_method=selection_method, limit=limit, max_tokens=max_tokens, @@ -453,6 +434,12 @@ def _query_cli( readable=True, autocompletion=CONFIG_AUTOCOMPLETE, ), + verbose: bool = typer.Option( + False, + "--verbose", + "-v", + help="Run the query with verbose logging.", + ), data: Path | None = typer.Option( None, "--data", @@ -520,6 +507,7 @@ def _query_cli( response_type=response_type, streaming=streaming, query=query, + verbose=verbose, ) case SearchMethod.GLOBAL: run_global_search( @@ -531,6 +519,7 @@ def _query_cli( response_type=response_type, streaming=streaming, query=query, + verbose=verbose, ) case SearchMethod.DRIFT: run_drift_search( @@ -541,6 +530,7 @@ def _query_cli( streaming=streaming, response_type=response_type, query=query, + verbose=verbose, ) case SearchMethod.BASIC: run_basic_search( @@ -549,6 +539,7 @@ def _query_cli( root_dir=root, streaming=streaming, query=query, + verbose=verbose, ) case _: raise ValueError(INVALID_METHOD_ERROR) diff --git a/graphrag/cli/prompt_tune.py b/graphrag/cli/prompt_tune.py index b531b34a30..0f0bf2abc8 100644 --- a/graphrag/cli/prompt_tune.py +++ b/graphrag/cli/prompt_tune.py @@ -3,13 +3,12 @@ """CLI implementation of the prompt-tune subcommand.""" +import logging from pathlib import Path import graphrag.api as api -from graphrag.cli.index import _logger +from graphrag.config.enums import ReportingType from graphrag.config.load_config import load_config -from graphrag.config.logging import enable_logging_with_config -from graphrag.logger.factory import LoggerFactory, LoggerType from graphrag.prompt_tune.generator.community_report_summarization import ( COMMUNITY_SUMMARIZATION_FILENAME, ) @@ -21,13 +20,14 @@ ) from graphrag.utils.cli import redact +logger = logging.getLogger(__name__) + async def prompt_tune( root: Path, config: Path | None, domain: str | None, verbose: bool, - logger: LoggerType, selection_method: api.DocSelectionType, limit: int, max_tokens: int, @@ -47,8 +47,7 @@ async def prompt_tune( - config: The configuration file. - root: The root directory. - domain: The domain to map the input documents to. - - verbose: Whether to enable verbose logging. - - logger: The logger to use. + - verbose: Enable verbose logging. - selection_method: The chunk selection method. - limit: The limit of chunks to load. - max_tokens: The maximum number of tokens to use on entity extraction prompts. @@ -70,23 +69,29 @@ async def prompt_tune( if overlap != graph_config.chunks.overlap: graph_config.chunks.overlap = overlap - progress_logger = LoggerFactory().create_logger(logger) - info, error, success = _logger(progress_logger) + # configure the root logger with the specified log level + from graphrag.logger.standard_logging import init_loggers - enabled_logging, log_path = enable_logging_with_config( - graph_config, verbose, filename="prompt-tune.log" + # initialize loggers with config + init_loggers( + config=graph_config, + root_dir=str(root_path), + verbose=verbose, ) - if enabled_logging: - info(f"Logging enabled at {log_path}", verbose) + + # log the configuration details + if graph_config.reporting.type == ReportingType.file: + log_dir = Path(root_path) / (graph_config.reporting.base_dir or "") + log_path = log_dir / "logs.txt" + logger.info("Logging enabled at %s", log_path) else: - info( - f"Logging not enabled for config {redact(graph_config.model_dump())}", - verbose, + logger.info( + "Logging not enabled for config %s", + redact(graph_config.model_dump()), ) prompts = await api.generate_indexing_prompts( config=graph_config, - logger=progress_logger, chunk_size=chunk_size, overlap=overlap, limit=limit, @@ -102,20 +107,20 @@ async def prompt_tune( output_path = output.resolve() if output_path: - info(f"Writing prompts to {output_path}") + logger.info("Writing prompts to %s", output_path) output_path.mkdir(parents=True, exist_ok=True) extract_graph_prompt_path = output_path / EXTRACT_GRAPH_FILENAME entity_summarization_prompt_path = output_path / ENTITY_SUMMARIZATION_FILENAME community_summarization_prompt_path = ( output_path / COMMUNITY_SUMMARIZATION_FILENAME ) - # Write files to output path + # write files to output path with extract_graph_prompt_path.open("wb") as file: file.write(prompts[0].encode(encoding="utf-8", errors="strict")) with entity_summarization_prompt_path.open("wb") as file: file.write(prompts[1].encode(encoding="utf-8", errors="strict")) with community_summarization_prompt_path.open("wb") as file: file.write(prompts[2].encode(encoding="utf-8", errors="strict")) - success(f"Prompts written to {output_path}") + logger.info("Prompts written to %s", output_path) else: - error("No output path provided. Skipping writing prompts.") + logger.error("No output path provided. Skipping writing prompts.") diff --git a/graphrag/cli/query.py b/graphrag/cli/query.py index 937ca69bbf..4704231f5e 100644 --- a/graphrag/cli/query.py +++ b/graphrag/cli/query.py @@ -4,6 +4,7 @@ """CLI implementation of the query subcommand.""" import asyncio +import logging import sys from pathlib import Path from typing import TYPE_CHECKING, Any @@ -12,14 +13,14 @@ from graphrag.callbacks.noop_query_callbacks import NoopQueryCallbacks from graphrag.config.load_config import load_config from graphrag.config.models.graph_rag_config import GraphRagConfig -from graphrag.logger.print_progress import PrintProgressLogger from graphrag.utils.api import create_storage_from_config from graphrag.utils.storage import load_table_from_storage, storage_has_table if TYPE_CHECKING: import pandas as pd -logger = PrintProgressLogger("") +# Initialize standard logger +logger = logging.getLogger(__name__) def run_global_search( @@ -31,6 +32,7 @@ def run_global_search( response_type: str, streaming: bool, query: str, + verbose: bool, ): """Perform a global search with a given query. @@ -59,10 +61,10 @@ def run_global_search( final_community_reports_list = dataframe_dict["community_reports"] index_names = dataframe_dict["index_names"] - logger.success( - f"Running Multi-index Global Search: {dataframe_dict['index_names']}" + logger.info( + "Running multi-index global search on indexes: %s", + dataframe_dict["index_names"], ) - response, context_data = asyncio.run( api.multi_index_global_search( config=config, @@ -75,9 +77,12 @@ def run_global_search( response_type=response_type, streaming=streaming, query=query, + verbose=verbose, ) ) - logger.success(f"Global Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("Query Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -110,6 +115,7 @@ def on_context(context: Any) -> None: response_type=response_type, query=query, callbacks=[callbacks], + verbose=verbose, ): full_response += stream_chunk print(stream_chunk, end="") # noqa: T201 @@ -129,9 +135,12 @@ def on_context(context: Any) -> None: dynamic_community_selection=dynamic_community_selection, response_type=response_type, query=query, + verbose=verbose, ) ) - logger.success(f"Global Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("Global Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -145,6 +154,7 @@ def run_local_search( response_type: str, streaming: bool, query: str, + verbose: bool, ): """Perform a local search with a given query. @@ -178,8 +188,9 @@ def run_local_search( final_relationships_list = dataframe_dict["relationships"] index_names = dataframe_dict["index_names"] - logger.success( - f"Running Multi-index Local Search: {dataframe_dict['index_names']}" + logger.info( + "Running multi-index local search on indexes: %s", + dataframe_dict["index_names"], ) # If any covariates tables are missing from any index, set the covariates list to None @@ -202,9 +213,12 @@ def run_local_search( response_type=response_type, streaming=streaming, query=query, + verbose=verbose, ) ) - logger.success(f"Local Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("Local Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -242,6 +256,7 @@ def on_context(context: Any) -> None: response_type=response_type, query=query, callbacks=[callbacks], + verbose=verbose, ): full_response += stream_chunk print(stream_chunk, end="") # noqa: T201 @@ -263,9 +278,12 @@ def on_context(context: Any) -> None: community_level=community_level, response_type=response_type, query=query, + verbose=verbose, ) ) - logger.success(f"Local Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("Local Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -279,6 +297,7 @@ def run_drift_search( response_type: str, streaming: bool, query: str, + verbose: bool, ): """Perform a local search with a given query. @@ -310,8 +329,9 @@ def run_drift_search( final_relationships_list = dataframe_dict["relationships"] index_names = dataframe_dict["index_names"] - logger.success( - f"Running Multi-index Drift Search: {dataframe_dict['index_names']}" + logger.info( + "Running multi-index drift search on indexes: %s", + dataframe_dict["index_names"], ) response, context_data = asyncio.run( @@ -327,9 +347,12 @@ def run_drift_search( response_type=response_type, streaming=streaming, query=query, + verbose=verbose, ) ) - logger.success(f"DRIFT Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("DRIFT Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -365,6 +388,7 @@ def on_context(context: Any) -> None: response_type=response_type, query=query, callbacks=[callbacks], + verbose=verbose, ): full_response += stream_chunk print(stream_chunk, end="") # noqa: T201 @@ -386,9 +410,12 @@ def on_context(context: Any) -> None: community_level=community_level, response_type=response_type, query=query, + verbose=verbose, ) ) - logger.success(f"DRIFT Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("DRIFT Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -400,6 +427,7 @@ def run_basic_search( root_dir: Path, streaming: bool, query: str, + verbose: bool, ): """Perform a basics search with a given query. @@ -423,8 +451,9 @@ def run_basic_search( final_text_units_list = dataframe_dict["text_units"] index_names = dataframe_dict["index_names"] - logger.success( - f"Running Multi-index Basic Search: {dataframe_dict['index_names']}" + logger.info( + "Running multi-index basic search on indexes: %s", + dataframe_dict["index_names"], ) response, context_data = asyncio.run( @@ -434,9 +463,12 @@ def run_basic_search( index_names=index_names, streaming=streaming, query=query, + verbose=verbose, ) ) - logger.success(f"Basic Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("Basic Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data @@ -461,6 +493,8 @@ def on_context(context: Any) -> None: config=config, text_units=final_text_units, query=query, + callbacks=[callbacks], + verbose=verbose, ): full_response += stream_chunk print(stream_chunk, end="") # noqa: T201 @@ -475,9 +509,12 @@ def on_context(context: Any) -> None: config=config, text_units=final_text_units, query=query, + verbose=verbose, ) ) - logger.success(f"Basic Search Response:\n{response}") + # log the full response at INFO level for user visibility but at DEBUG level in the API layer + logger.info("Basic Search Response:\n%s", response) + # NOTE: we return the response and context data here purely as a complete demonstration of the API. # External users should use the API directly to get the response and context data. return response, context_data diff --git a/graphrag/config/defaults.py b/graphrag/config/defaults.py index 4cac43c435..1da0081220 100644 --- a/graphrag/config/defaults.py +++ b/graphrag/config/defaults.py @@ -5,7 +5,7 @@ from dataclasses import dataclass, field from pathlib import Path -from typing import Literal +from typing import ClassVar, Literal from graphrag.config.embeddings import default_embeddings from graphrag.config.enums import ( @@ -54,7 +54,7 @@ class BasicSearchDefaults: class CacheDefaults: """Default values for cache.""" - type = CacheType.file + type: ClassVar[CacheType] = CacheType.file base_dir: str = "cache" connection_string: None = None container_name: None = None @@ -69,7 +69,7 @@ class ChunksDefaults: size: int = 1200 overlap: int = 100 group_by_columns: list[str] = field(default_factory=lambda: ["id"]) - strategy = ChunkStrategyType.tokens + strategy: ClassVar[ChunkStrategyType] = ChunkStrategyType.tokens encoding_model: str = "cl100k_base" prepend_metadata: bool = False chunk_size_includes_metadata: bool = False @@ -119,8 +119,8 @@ class DriftSearchDefaults: local_search_temperature: float = 0 local_search_top_p: float = 1 local_search_n: int = 1 - local_search_llm_max_gen_tokens = None - local_search_llm_max_gen_completion_tokens = None + local_search_llm_max_gen_tokens: int | None = None + local_search_llm_max_gen_completion_tokens: int | None = None chat_model_id: str = DEFAULT_CHAT_MODEL_ID embedding_model_id: str = DEFAULT_EMBEDDING_MODEL_ID @@ -183,7 +183,9 @@ class ExtractGraphDefaults: class TextAnalyzerDefaults: """Default values for text analyzer.""" - extractor_type = NounPhraseExtractorType.RegexEnglish + extractor_type: ClassVar[NounPhraseExtractorType] = ( + NounPhraseExtractorType.RegexEnglish + ) model_name: str = "en_core_web_md" max_word_length: int = 15 word_delimiter: str = " " @@ -257,7 +259,7 @@ class InputDefaults: """Default values for input.""" storage: InputStorageDefaults = field(default_factory=InputStorageDefaults) - file_type = InputFileType.text + file_type: ClassVar[InputFileType] = InputFileType.text encoding: str = "utf-8" file_pattern: str = "" file_filter: None = None @@ -271,7 +273,7 @@ class LanguageModelDefaults: """Default values for language model.""" api_key: None = None - auth_type = AuthType.APIKey + auth_type: ClassVar[AuthType] = AuthType.APIKey encoding_model: str = "" max_tokens: int | None = None temperature: float = 0 @@ -338,7 +340,7 @@ class PruneGraphDefaults: class ReportingDefaults: """Default values for reporting.""" - type = ReportingType.file + type: ClassVar[ReportingType] = ReportingType.file base_dir: str = "logs" connection_string: None = None container_name: None = None @@ -383,7 +385,7 @@ class UpdateIndexOutputDefaults(StorageDefaults): class VectorStoreDefaults: """Default values for vector stores.""" - type = VectorStoreType.LanceDB.value + type: ClassVar[str] = VectorStoreType.LanceDB.value db_uri: str = str(Path(DEFAULT_OUTPUT_BASE_DIR) / "lancedb") container_name: str = "default" overwrite: bool = True diff --git a/graphrag/config/enums.py b/graphrag/config/enums.py index 6c0c4ce1b1..34b7765a67 100644 --- a/graphrag/config/enums.py +++ b/graphrag/config/enums.py @@ -64,8 +64,6 @@ class ReportingType(str, Enum): file = "file" """The file reporting configuration type.""" - console = "console" - """The console reporting configuration type.""" blob = "blob" """The blob reporting configuration type.""" diff --git a/graphrag/config/logging.py b/graphrag/config/logging.py deleted file mode 100644 index a72f82ab4c..0000000000 --- a/graphrag/config/logging.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Logging utilities. A unified way for enabling logging.""" - -import logging -from pathlib import Path - -from graphrag.config.enums import ReportingType -from graphrag.config.models.graph_rag_config import GraphRagConfig - - -def enable_logging(log_filepath: str | Path, verbose: bool = False) -> None: - """Enable logging to a file. - - Parameters - ---------- - log_filepath : str | Path - The path to the log file. - verbose : bool, default=False - Whether to log debug messages. - """ - log_filepath = Path(log_filepath) - log_filepath.parent.mkdir(parents=True, exist_ok=True) - log_filepath.touch(exist_ok=True) - - logging.basicConfig( - filename=log_filepath, - filemode="a", - format="%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s", - datefmt="%H:%M:%S", - level=logging.DEBUG if verbose else logging.INFO, - ) - - -def enable_logging_with_config( - config: GraphRagConfig, verbose: bool = False, filename: str = "indexing-engine.log" -) -> tuple[bool, str]: - """Enable logging to a file based on the config. - - Parameters - ---------- - config : GraphRagConfig - The configuration. - timestamp_value : str - The timestamp value representing the directory to place the log files. - verbose : bool, default=False - Whether to log debug messages. - - Returns - ------- - tuple[bool, str] - A tuple of a boolean indicating if logging was enabled and the path to the log file. - (False, "") if logging was not enabled. - (True, str) if logging was enabled. - """ - if config.reporting.type == ReportingType.file: - log_path = Path(config.reporting.base_dir) / filename - enable_logging(log_path, verbose) - return (True, str(log_path)) - return (False, "") diff --git a/graphrag/config/read_dotenv.py b/graphrag/config/read_dotenv.py index 7e041757b3..a2da5d43fe 100644 --- a/graphrag/config/read_dotenv.py +++ b/graphrag/config/read_dotenv.py @@ -9,17 +9,17 @@ from dotenv import dotenv_values -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def read_dotenv(root: str) -> None: """Read a .env file in the given root path.""" env_path = Path(root) / ".env" if env_path.exists(): - log.info("Loading pipeline .env file") + logger.info("Loading pipeline .env file") env_config = dotenv_values(f"{env_path}") for key, value in env_config.items(): if key not in os.environ: os.environ[key] = value or "" else: - log.info("No .env file found at %s", root) + logger.info("No .env file found at %s", root) diff --git a/graphrag/index/input/csv.py b/graphrag/index/input/csv.py index bcd42fec17..eea4864b17 100644 --- a/graphrag/index/input/csv.py +++ b/graphrag/index/input/csv.py @@ -10,19 +10,17 @@ from graphrag.config.models.input_config import InputConfig from graphrag.index.input.util import load_files, process_data_columns -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def load_csv( config: InputConfig, - progress: ProgressLogger | None, storage: PipelineStorage, ) -> pd.DataFrame: """Load csv inputs from a directory.""" - log.info("Loading csv files from %s", config.storage.base_dir) + logger.info("Loading csv files from %s", config.storage.base_dir) async def load_file(path: str, group: dict | None) -> pd.DataFrame: if group is None: @@ -42,4 +40,4 @@ async def load_file(path: str, group: dict | None) -> pd.DataFrame: return data - return await load_files(load_file, config, storage, progress) + return await load_files(load_file, config, storage) diff --git a/graphrag/index/input/factory.py b/graphrag/index/input/factory.py index 096204b00f..bc4da8c7a1 100644 --- a/graphrag/index/input/factory.py +++ b/graphrag/index/input/factory.py @@ -14,11 +14,9 @@ from graphrag.index.input.csv import load_csv from graphrag.index.input.json import load_json from graphrag.index.input.text import load_text -from graphrag.logger.base import ProgressLogger -from graphrag.logger.null_progress import NullProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) loaders: dict[str, Callable[..., Awaitable[pd.DataFrame]]] = { InputFileType.text: load_text, InputFileType.csv: load_csv, @@ -29,17 +27,14 @@ async def create_input( config: InputConfig, storage: PipelineStorage, - progress_reporter: ProgressLogger | None = None, ) -> pd.DataFrame: """Instantiate input data for a pipeline.""" - progress_reporter = progress_reporter or NullProgressLogger() + logger.info("loading input from root_dir=%s", config.storage.base_dir) if config.file_type in loaders: - progress = progress_reporter.child( - f"Loading Input ({config.file_type})", transient=False - ) + logger.info("Loading Input %s", config.file_type) loader = loaders[config.file_type] - result = await loader(config, progress, storage) + result = await loader(config, storage) # Convert metadata columns to strings and collapse them into a JSON object if config.metadata: if all(col in result.columns for col in config.metadata): diff --git a/graphrag/index/input/json.py b/graphrag/index/input/json.py index df5b09cb3a..e2880bc888 100644 --- a/graphrag/index/input/json.py +++ b/graphrag/index/input/json.py @@ -10,19 +10,17 @@ from graphrag.config.models.input_config import InputConfig from graphrag.index.input.util import load_files, process_data_columns -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def load_json( config: InputConfig, - progress: ProgressLogger | None, storage: PipelineStorage, ) -> pd.DataFrame: """Load json inputs from a directory.""" - log.info("Loading json files from %s", config.storage.base_dir) + logger.info("Loading json files from %s", config.storage.base_dir) async def load_file(path: str, group: dict | None) -> pd.DataFrame: if group is None: @@ -46,4 +44,4 @@ async def load_file(path: str, group: dict | None) -> pd.DataFrame: return data - return await load_files(load_file, config, storage, progress) + return await load_files(load_file, config, storage) diff --git a/graphrag/index/input/text.py b/graphrag/index/input/text.py index 44e89ad01f..1834a532eb 100644 --- a/graphrag/index/input/text.py +++ b/graphrag/index/input/text.py @@ -11,15 +11,13 @@ from graphrag.config.models.input_config import InputConfig from graphrag.index.input.util import load_files from graphrag.index.utils.hashing import gen_sha512_hash -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def load_text( config: InputConfig, - progress: ProgressLogger | None, storage: PipelineStorage, ) -> pd.DataFrame: """Load text inputs from a directory.""" @@ -34,4 +32,4 @@ async def load_file(path: str, group: dict | None = None) -> pd.DataFrame: new_item["creation_date"] = await storage.get_creation_date(path) return pd.DataFrame([new_item]) - return await load_files(load_file, config, storage, progress) + return await load_files(load_file, config, storage) diff --git a/graphrag/index/input/util.py b/graphrag/index/input/util.py index 7335e9e862..cc15183673 100644 --- a/graphrag/index/input/util.py +++ b/graphrag/index/input/util.py @@ -11,23 +11,20 @@ from graphrag.config.models.input_config import InputConfig from graphrag.index.utils.hashing import gen_sha512_hash -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def load_files( loader: Any, config: InputConfig, storage: PipelineStorage, - progress: ProgressLogger | None, ) -> pd.DataFrame: """Load files from storage and apply a loader function.""" files = list( storage.find( re.compile(config.file_pattern), - progress=progress, file_filter=config.file_filter, ) ) @@ -42,17 +39,17 @@ async def load_files( try: files_loaded.append(await loader(file, group)) except Exception as e: # noqa: BLE001 (catching Exception is fine here) - log.warning("Warning! Error loading file %s. Skipping...", file) - log.warning("Error: %s", e) + logger.warning("Warning! Error loading file %s. Skipping...", file) + logger.warning("Error: %s", e) - log.info( + logger.info( "Found %d %s files, loading %d", len(files), config.file_type, len(files_loaded) ) result = pd.concat(files_loaded) total_files_log = ( f"Total number of unfiltered {config.file_type} rows: {len(result)}" ) - log.info(total_files_log) + logger.info(total_files_log) return result @@ -66,7 +63,7 @@ def process_data_columns( ) if config.text_column is not None and "text" not in documents.columns: if config.text_column not in documents.columns: - log.warning( + logger.warning( "text_column %s not found in csv file %s", config.text_column, path, @@ -75,7 +72,7 @@ def process_data_columns( documents["text"] = documents.apply(lambda x: x[config.text_column], axis=1) if config.title_column is not None: if config.title_column not in documents.columns: - log.warning( + logger.warning( "title_column %s not found in csv file %s", config.title_column, path, diff --git a/graphrag/index/operations/build_noun_graph/build_noun_graph.py b/graphrag/index/operations/build_noun_graph/build_noun_graph.py index 0e45e351ac..1c86859425 100644 --- a/graphrag/index/operations/build_noun_graph/build_noun_graph.py +++ b/graphrag/index/operations/build_noun_graph/build_noun_graph.py @@ -65,6 +65,7 @@ async def extract(row): extract, num_threads=num_threads, async_type=AsyncType.Threaded, + progress_msg="extract noun phrases progress: ", ) noun_node_df = text_unit_df.explode("noun_phrases") diff --git a/graphrag/index/operations/build_noun_graph/np_extractors/base.py b/graphrag/index/operations/build_noun_graph/np_extractors/base.py index 27a1d9f01a..18bb3f804c 100644 --- a/graphrag/index/operations/build_noun_graph/np_extractors/base.py +++ b/graphrag/index/operations/build_noun_graph/np_extractors/base.py @@ -8,7 +8,7 @@ import spacy -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class BaseNounPhraseExtractor(metaclass=ABCMeta): @@ -54,7 +54,7 @@ def load_spacy_model( return spacy.load(model_name, exclude=exclude) except OSError: msg = f"Model `{model_name}` not found. Attempting to download..." - log.info(msg) + logger.info(msg) from spacy.cli.download import download download(model_name) diff --git a/graphrag/index/operations/cluster_graph.py b/graphrag/index/operations/cluster_graph.py index b74d807a96..de16e2d35c 100644 --- a/graphrag/index/operations/cluster_graph.py +++ b/graphrag/index/operations/cluster_graph.py @@ -13,7 +13,7 @@ Communities = list[tuple[int, int, int, list[str]]] -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def cluster_graph( @@ -24,7 +24,7 @@ def cluster_graph( ) -> Communities: """Apply a hierarchical clustering algorithm to a graph.""" if len(graph.nodes) == 0: - log.warning("Graph has no nodes") + logger.warning("Graph has no nodes") return [] node_id_to_community_map, parent_mapping = _compute_leiden_communities( diff --git a/graphrag/index/operations/embed_text/embed_text.py b/graphrag/index/operations/embed_text/embed_text.py index b0a9e55410..96e6111e9e 100644 --- a/graphrag/index/operations/embed_text/embed_text.py +++ b/graphrag/index/operations/embed_text/embed_text.py @@ -17,7 +17,7 @@ from graphrag.vector_stores.base import BaseVectorStore, VectorStoreDocument from graphrag.vector_stores.factory import VectorStoreFactory -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) # Per Azure OpenAI Limits # https://learn.microsoft.com/en-us/azure/ai-services/openai/reference @@ -141,7 +141,14 @@ async def _text_embed_with_vector_store( all_results = [] + num_total_batches = (input.shape[0] + insert_batch_size - 1) // insert_batch_size while insert_batch_size * i < input.shape[0]: + logger.info( + "uploading text embeddings batch %d/%d of size %d to vector store", + i + 1, + num_total_batches, + insert_batch_size, + ) batch = input.iloc[insert_batch_size * i : insert_batch_size * (i + 1)] texts: list[str] = batch[embed_column].to_numpy().tolist() titles: list[str] = batch[title].to_numpy().tolist() @@ -195,7 +202,7 @@ def _get_collection_name(vector_store_config: dict, embedding_name: str) -> str: collection_name = create_collection_name(container_name, embedding_name) msg = f"using vector store {vector_store_config.get('type')} with container_name {container_name} for embedding {embedding_name}: {collection_name}" - log.info(msg) + logger.info(msg) return collection_name diff --git a/graphrag/index/operations/embed_text/strategies/mock.py b/graphrag/index/operations/embed_text/strategies/mock.py index 6aa60ff3ef..a65ad9721f 100644 --- a/graphrag/index/operations/embed_text/strategies/mock.py +++ b/graphrag/index/operations/embed_text/strategies/mock.py @@ -21,7 +21,9 @@ async def run( # noqa RUF029 async is required for interface ) -> TextEmbeddingResult: """Run the Claim extraction chain.""" input = input if isinstance(input, Iterable) else [input] - ticker = progress_ticker(callbacks.progress, len(input)) + ticker = progress_ticker( + callbacks.progress, len(input), description="generate embeddings progress: " + ) return TextEmbeddingResult( embeddings=[_embed_text(cache, text, ticker) for text in input] ) diff --git a/graphrag/index/operations/embed_text/strategies/openai.py b/graphrag/index/operations/embed_text/strategies/openai.py index b5dee44335..cad7b14255 100644 --- a/graphrag/index/operations/embed_text/strategies/openai.py +++ b/graphrag/index/operations/embed_text/strategies/openai.py @@ -19,7 +19,7 @@ from graphrag.language_model.protocol.base import EmbeddingModel from graphrag.logger.progress import ProgressTicker, progress_ticker -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run( @@ -54,7 +54,7 @@ async def run( batch_max_tokens, splitter, ) - log.info( + logger.info( "embedding %d inputs via %d snippets using %d batches. max_batch_size=%d, batch_max_tokens=%d", len(input), len(texts), @@ -62,7 +62,11 @@ async def run( batch_size, batch_max_tokens, ) - ticker = progress_ticker(callbacks.progress, len(text_batches)) + ticker = progress_ticker( + callbacks.progress, + len(text_batches), + description="generate embeddings progress: ", + ) # Embed each chunk of snippets embeddings = await _execute(model, text_batches, ticker, semaphore) diff --git a/graphrag/index/operations/extract_covariates/claim_extractor.py b/graphrag/index/operations/extract_covariates/claim_extractor.py index 6ddfe503c0..e50d05ce83 100644 --- a/graphrag/index/operations/extract_covariates/claim_extractor.py +++ b/graphrag/index/operations/extract_covariates/claim_extractor.py @@ -20,7 +20,7 @@ DEFAULT_TUPLE_DELIMITER = "<|>" DEFAULT_RECORD_DELIMITER = "##" DEFAULT_COMPLETION_DELIMITER = "<|COMPLETE|>" -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) @dataclass @@ -119,7 +119,7 @@ async def __call__( ] source_doc_map[document_id] = text except Exception as e: - log.exception("error extracting claim") + logger.exception("error extracting claim") self._on_error( e, traceback.format_exc(), diff --git a/graphrag/index/operations/extract_covariates/extract_covariates.py b/graphrag/index/operations/extract_covariates/extract_covariates.py index 7ae23e5bcf..d29ca61e9d 100644 --- a/graphrag/index/operations/extract_covariates/extract_covariates.py +++ b/graphrag/index/operations/extract_covariates/extract_covariates.py @@ -23,7 +23,7 @@ from graphrag.index.utils.derive_from_rows import derive_from_rows from graphrag.language_model.manager import ModelManager -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) DEFAULT_ENTITY_TYPES = ["organization", "person", "geo", "event"] @@ -41,7 +41,7 @@ async def extract_covariates( num_threads: int = 4, ): """Extract claims from a piece of text.""" - log.debug("extract_covariates strategy=%s", strategy) + logger.debug("extract_covariates strategy=%s", strategy) if entity_types is None: entity_types = DEFAULT_ENTITY_TYPES @@ -71,6 +71,7 @@ async def run_strategy(row): callbacks, async_type=async_mode, num_threads=num_threads, + progress_msg="extract covariates progress: ", ) return pd.DataFrame([item for row in results for item in row or []]) @@ -110,8 +111,8 @@ async def run_extract_claims( model_invoker=llm, extraction_prompt=extraction_prompt, max_gleanings=max_gleanings, - on_error=lambda e, s, d: ( - callbacks.error("Claim Extraction Error", e, s, d) if callbacks else None + on_error=lambda e, s, d: logger.error( + "Claim Extraction Error", exc_info=e, extra={"stack": s, "details": d} ), ) diff --git a/graphrag/index/operations/extract_graph/extract_graph.py b/graphrag/index/operations/extract_graph/extract_graph.py index dabfd1c005..76bcf40c76 100644 --- a/graphrag/index/operations/extract_graph/extract_graph.py +++ b/graphrag/index/operations/extract_graph/extract_graph.py @@ -18,7 +18,7 @@ ) from graphrag.index.utils.derive_from_rows import derive_from_rows -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) DEFAULT_ENTITY_TYPES = ["organization", "person", "geo", "event"] @@ -36,7 +36,7 @@ async def extract_graph( num_threads: int = 4, ) -> tuple[pd.DataFrame, pd.DataFrame]: """Extract a graph from a piece of text using a language model.""" - log.debug("entity_extract strategy=%s", strategy) + logger.debug("entity_extract strategy=%s", strategy) if entity_types is None: entity_types = DEFAULT_ENTITY_TYPES strategy = strategy or {} @@ -54,7 +54,6 @@ async def run_strategy(row): result = await strategy_exec( [Document(text=text, id=id)], entity_types, - callbacks, cache, strategy_config, ) @@ -67,6 +66,7 @@ async def run_strategy(row): callbacks, async_type=async_mode, num_threads=num_threads, + progress_msg="extract graph progress: ", ) entity_dfs = [] diff --git a/graphrag/index/operations/extract_graph/graph_extractor.py b/graphrag/index/operations/extract_graph/graph_extractor.py index f7601f2601..d1f66c3e81 100644 --- a/graphrag/index/operations/extract_graph/graph_extractor.py +++ b/graphrag/index/operations/extract_graph/graph_extractor.py @@ -27,7 +27,7 @@ DEFAULT_COMPLETION_DELIMITER = "<|COMPLETE|>" DEFAULT_ENTITY_TYPES = ["organization", "person", "geo", "event"] -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) @dataclass @@ -119,7 +119,7 @@ async def __call__( source_doc_map[doc_index] = text all_records[doc_index] = result except Exception as e: - log.exception("error extracting graph") + logger.exception("error extracting graph") self._on_error( e, traceback.format_exc(), diff --git a/graphrag/index/operations/extract_graph/graph_intelligence_strategy.py b/graphrag/index/operations/extract_graph/graph_intelligence_strategy.py index 9bb6a88db6..b335d191a6 100644 --- a/graphrag/index/operations/extract_graph/graph_intelligence_strategy.py +++ b/graphrag/index/operations/extract_graph/graph_intelligence_strategy.py @@ -3,10 +3,11 @@ """A module containing run_graph_intelligence, run_extract_graph and _create_text_splitter methods to run graph intelligence.""" +import logging + import networkx as nx from graphrag.cache.pipeline_cache import PipelineCache -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.config.defaults import graphrag_config_defaults from graphrag.config.models.language_model_config import LanguageModelConfig from graphrag.index.operations.extract_graph.graph_extractor import GraphExtractor @@ -19,11 +20,12 @@ from graphrag.language_model.manager import ModelManager from graphrag.language_model.protocol.base import ChatModel +logger = logging.getLogger(__name__) + async def run_graph_intelligence( docs: list[Document], entity_types: EntityTypes, - callbacks: WorkflowCallbacks, cache: PipelineCache, args: StrategyConfig, ) -> EntityExtractionResult: @@ -34,18 +36,16 @@ async def run_graph_intelligence( name="extract_graph", model_type=llm_config.type, config=llm_config, - callbacks=callbacks, cache=cache, ) - return await run_extract_graph(llm, docs, entity_types, callbacks, args) + return await run_extract_graph(llm, docs, entity_types, args) async def run_extract_graph( model: ChatModel, docs: list[Document], entity_types: EntityTypes, - callbacks: WorkflowCallbacks | None, args: StrategyConfig, ) -> EntityExtractionResult: """Run the entity extraction chain.""" @@ -61,8 +61,8 @@ async def run_extract_graph( model_invoker=model, prompt=extraction_prompt, max_gleanings=max_gleanings, - on_error=lambda e, s, d: ( - callbacks.error("Entity Extraction Error", e, s, d) if callbacks else None + on_error=lambda e, s, d: logger.error( + "Entity Extraction Error", exc_info=e, extra={"stack": s, "details": d} ), ) text_list = [doc.text.strip() for doc in docs] diff --git a/graphrag/index/operations/extract_graph/typing.py b/graphrag/index/operations/extract_graph/typing.py index 0361317f76..3c7c134753 100644 --- a/graphrag/index/operations/extract_graph/typing.py +++ b/graphrag/index/operations/extract_graph/typing.py @@ -11,7 +11,6 @@ import networkx as nx from graphrag.cache.pipeline_cache import PipelineCache -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks ExtractedEntity = dict[str, Any] ExtractedRelationship = dict[str, Any] @@ -40,7 +39,6 @@ class EntityExtractionResult: [ list[Document], EntityTypes, - WorkflowCallbacks, PipelineCache, StrategyConfig, ], diff --git a/graphrag/index/operations/finalize_entities.py b/graphrag/index/operations/finalize_entities.py index 4539e53b79..cd1dbb83eb 100644 --- a/graphrag/index/operations/finalize_entities.py +++ b/graphrag/index/operations/finalize_entities.py @@ -7,7 +7,6 @@ import pandas as pd -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.config.models.embed_graph_config import EmbedGraphConfig from graphrag.data_model.schemas import ENTITIES_FINAL_COLUMNS from graphrag.index.operations.compute_degree import compute_degree @@ -19,7 +18,6 @@ def finalize_entities( entities: pd.DataFrame, relationships: pd.DataFrame, - callbacks: WorkflowCallbacks, embed_config: EmbedGraphConfig | None = None, layout_enabled: bool = False, ) -> pd.DataFrame: @@ -33,7 +31,6 @@ def finalize_entities( ) layout = layout_graph( graph, - callbacks, layout_enabled, embeddings=graph_embeddings, ) diff --git a/graphrag/index/operations/layout_graph/layout_graph.py b/graphrag/index/operations/layout_graph/layout_graph.py index f004f54fe0..433ffc8a10 100644 --- a/graphrag/index/operations/layout_graph/layout_graph.py +++ b/graphrag/index/operations/layout_graph/layout_graph.py @@ -3,17 +3,19 @@ """A module containing layout_graph, _run_layout and _apply_layout_to_graph methods definition.""" +import logging + import networkx as nx import pandas as pd -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.index.operations.embed_graph.typing import NodeEmbeddings from graphrag.index.operations.layout_graph.typing import GraphLayout +logger = logging.getLogger(__name__) + def layout_graph( graph: nx.Graph, - callbacks: WorkflowCallbacks, enabled: bool, embeddings: NodeEmbeddings | None, ): @@ -44,7 +46,6 @@ def layout_graph( graph, enabled, embeddings if embeddings is not None else {}, - callbacks, ) layout_df = pd.DataFrame(layout) @@ -58,7 +59,6 @@ def _run_layout( graph: nx.Graph, enabled: bool, embeddings: NodeEmbeddings, - callbacks: WorkflowCallbacks, ) -> GraphLayout: if enabled: from graphrag.index.operations.layout_graph.umap import ( @@ -68,7 +68,9 @@ def _run_layout( return run_umap( graph, embeddings, - lambda e, stack, d: callbacks.error("Error in Umap", e, stack, d), + lambda e, stack, d: logger.error( + "Error in Umap", exc_info=e, extra={"stack": stack, "details": d} + ), ) from graphrag.index.operations.layout_graph.zero import ( run as run_zero, @@ -76,5 +78,7 @@ def _run_layout( return run_zero( graph, - lambda e, stack, d: callbacks.error("Error in Zero", e, stack, d), + lambda e, stack, d: logger.error( + "Error in Zero", exc_info=e, extra={"stack": stack, "details": d} + ), ) diff --git a/graphrag/index/operations/layout_graph/umap.py b/graphrag/index/operations/layout_graph/umap.py index 8a05a2dbcd..6550188030 100644 --- a/graphrag/index/operations/layout_graph/umap.py +++ b/graphrag/index/operations/layout_graph/umap.py @@ -20,7 +20,7 @@ # for "size" or "cluster" # We could also have a boolean to indicate to use node sizes or clusters -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def run( @@ -56,7 +56,7 @@ def run( **additional_args, ) except Exception as e: - log.exception("Error running UMAP") + logger.exception("Error running UMAP") on_error(e, traceback.format_exc(), None) # Umap may fail due to input sparseness or memory pressure. # For now, in these cases, we'll just return a layout with all nodes at (0, 0) diff --git a/graphrag/index/operations/layout_graph/zero.py b/graphrag/index/operations/layout_graph/zero.py index f42734199b..934df0030f 100644 --- a/graphrag/index/operations/layout_graph/zero.py +++ b/graphrag/index/operations/layout_graph/zero.py @@ -18,7 +18,7 @@ # for "size" or "cluster" # We could also have a boolean to indicate to use node sizes or clusters -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def run( @@ -47,7 +47,7 @@ def run( try: return get_zero_positions(node_labels=nodes, **additional_args) except Exception as e: - log.exception("Error running zero-position") + logger.exception("Error running zero-position") on_error(e, traceback.format_exc(), None) # Umap may fail due to input sparseness or memory pressure. # For now, in these cases, we'll just return a layout with all nodes at (0, 0) diff --git a/graphrag/index/operations/summarize_communities/community_reports_extractor.py b/graphrag/index/operations/summarize_communities/community_reports_extractor.py index 73ac0ec9e2..1442a44a1b 100644 --- a/graphrag/index/operations/summarize_communities/community_reports_extractor.py +++ b/graphrag/index/operations/summarize_communities/community_reports_extractor.py @@ -13,7 +13,7 @@ from graphrag.language_model.protocol.base import ChatModel from graphrag.prompts.index.community_report import COMMUNITY_REPORT_PROMPT -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) # these tokens are used in the prompt INPUT_TEXT_KEY = "input_text" @@ -86,7 +86,7 @@ async def __call__(self, input_text: str): output = response.parsed_response except Exception as e: - log.exception("error generating community report") + logger.exception("error generating community report") self._on_error(e, traceback.format_exc(), None) text_output = self._get_text_output(output) if output else "" diff --git a/graphrag/index/operations/summarize_communities/graph_context/context_builder.py b/graphrag/index/operations/summarize_communities/graph_context/context_builder.py index 8c33fe8269..bf9e4ae5e3 100644 --- a/graphrag/index/operations/summarize_communities/graph_context/context_builder.py +++ b/graphrag/index/operations/summarize_communities/graph_context/context_builder.py @@ -32,7 +32,7 @@ from graphrag.logger.progress import progress_iterable from graphrag.query.llm.text_utils import num_tokens -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def build_local_context( @@ -69,7 +69,7 @@ def _prepare_reports_at_level( """Prepare reports at a given level.""" # Filter and prepare node details level_node_df = node_df[node_df[schemas.COMMUNITY_LEVEL] == level] - log.info("Number of nodes at level=%s => %s", level, len(level_node_df)) + logger.info("Number of nodes at level=%s => %s", level, len(level_node_df)) nodes_set = set(level_node_df[schemas.TITLE]) # Filter and prepare edge details diff --git a/graphrag/index/operations/summarize_communities/strategies.py b/graphrag/index/operations/summarize_communities/strategies.py index 4a42fbf9d1..978c85b9d2 100644 --- a/graphrag/index/operations/summarize_communities/strategies.py +++ b/graphrag/index/operations/summarize_communities/strategies.py @@ -4,7 +4,6 @@ """A module containing run, _run_extractor and _load_nodes_edges_for_claim_chain methods definition.""" import logging -import traceback from graphrag.cache.pipeline_cache import PipelineCache from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks @@ -21,7 +20,7 @@ from graphrag.language_model.manager import ModelManager from graphrag.language_model.protocol.base import ChatModel -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run_graph_intelligence( @@ -42,7 +41,7 @@ async def run_graph_intelligence( cache=cache, ) - return await _run_extractor(llm, community, input, level, args, callbacks) + return await _run_extractor(llm, community, input, level, args) async def _run_extractor( @@ -51,7 +50,6 @@ async def _run_extractor( input: str, level: int, args: StrategyConfig, - callbacks: WorkflowCallbacks, ) -> CommunityReport | None: # RateLimiter rate_limiter = RateLimiter(rate=1, per=60) @@ -59,8 +57,8 @@ async def _run_extractor( model, extraction_prompt=args.get("extraction_prompt", None), max_report_length=args.get("max_report_length", None), - on_error=lambda e, stack, _data: callbacks.error( - "Community Report Extraction Error", e, stack + on_error=lambda e, stack, _data: logger.error( + "Community Report Extraction Error", exc_info=e, extra={"stack": stack} ), ) @@ -69,7 +67,7 @@ async def _run_extractor( results = await extractor(input) report = results.structured_output if report is None: - log.warning("No report found for community: %s", community) + logger.warning("No report found for community: %s", community) return None return CommunityReport( @@ -86,7 +84,6 @@ async def _run_extractor( ], full_content_json=report.model_dump_json(indent=4), ) - except Exception as e: - log.exception("Error processing community: %s", community) - callbacks.error("Community Report Extraction Error", e, traceback.format_exc()) + except Exception: + logger.exception("Error processing community: %s", community) return None diff --git a/graphrag/index/operations/summarize_communities/summarize_communities.py b/graphrag/index/operations/summarize_communities/summarize_communities.py index e64c3e23f4..92bddfd3ed 100644 --- a/graphrag/index/operations/summarize_communities/summarize_communities.py +++ b/graphrag/index/operations/summarize_communities/summarize_communities.py @@ -24,7 +24,7 @@ from graphrag.index.utils.derive_from_rows import derive_from_rows from graphrag.logger.progress import progress_ticker -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def summarize_communities( @@ -64,7 +64,7 @@ async def summarize_communities( ) level_contexts.append(level_context) - for level_context in level_contexts: + for i, level_context in enumerate(level_contexts): async def run_generate(record): result = await _generate_report( @@ -85,6 +85,7 @@ async def run_generate(record): callbacks=NoopWorkflowCallbacks(), num_threads=num_threads, async_type=async_mode, + progress_msg=f"level {levels[i]} summarize communities progress: ", ) reports.extend([lr for lr in local_reports if lr is not None]) diff --git a/graphrag/index/operations/summarize_communities/text_unit_context/context_builder.py b/graphrag/index/operations/summarize_communities/text_unit_context/context_builder.py index 95f3621858..ca2342d57e 100644 --- a/graphrag/index/operations/summarize_communities/text_unit_context/context_builder.py +++ b/graphrag/index/operations/summarize_communities/text_unit_context/context_builder.py @@ -20,7 +20,7 @@ ) from graphrag.query.llm.text_utils import num_tokens -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def build_local_context( diff --git a/graphrag/index/operations/summarize_communities/text_unit_context/prep_text_units.py b/graphrag/index/operations/summarize_communities/text_unit_context/prep_text_units.py index 083fc29ea0..af31ee74ea 100644 --- a/graphrag/index/operations/summarize_communities/text_unit_context/prep_text_units.py +++ b/graphrag/index/operations/summarize_communities/text_unit_context/prep_text_units.py @@ -9,7 +9,7 @@ import graphrag.data_model.schemas as schemas -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def prep_text_units( diff --git a/graphrag/index/operations/summarize_communities/text_unit_context/sort_context.py b/graphrag/index/operations/summarize_communities/text_unit_context/sort_context.py index 2435dfbdb6..53639f1f31 100644 --- a/graphrag/index/operations/summarize_communities/text_unit_context/sort_context.py +++ b/graphrag/index/operations/summarize_communities/text_unit_context/sort_context.py @@ -10,7 +10,7 @@ import graphrag.data_model.schemas as schemas from graphrag.query.llm.text_utils import num_tokens -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def get_context_string( diff --git a/graphrag/index/operations/summarize_descriptions/graph_intelligence_strategy.py b/graphrag/index/operations/summarize_descriptions/graph_intelligence_strategy.py index 2b95d6b1e5..d3259b290f 100644 --- a/graphrag/index/operations/summarize_descriptions/graph_intelligence_strategy.py +++ b/graphrag/index/operations/summarize_descriptions/graph_intelligence_strategy.py @@ -3,8 +3,9 @@ """A module containing run_graph_intelligence, run_resolve_entities and _create_text_list_splitter methods to run graph intelligence.""" +import logging + from graphrag.cache.pipeline_cache import PipelineCache -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.config.models.language_model_config import LanguageModelConfig from graphrag.index.operations.summarize_descriptions.description_summary_extractor import ( SummarizeExtractor, @@ -16,11 +17,12 @@ from graphrag.language_model.manager import ModelManager from graphrag.language_model.protocol.base import ChatModel +logger = logging.getLogger(__name__) + async def run_graph_intelligence( id: str | tuple[str, str], descriptions: list[str], - callbacks: WorkflowCallbacks, cache: PipelineCache, args: StrategyConfig, ) -> SummarizedDescriptionResult: @@ -30,18 +32,16 @@ async def run_graph_intelligence( name="summarize_descriptions", model_type=llm_config.type, config=llm_config, - callbacks=callbacks, cache=cache, ) - return await run_summarize_descriptions(llm, id, descriptions, callbacks, args) + return await run_summarize_descriptions(llm, id, descriptions, args) async def run_summarize_descriptions( model: ChatModel, id: str | tuple[str, str], descriptions: list[str], - callbacks: WorkflowCallbacks, args: StrategyConfig, ) -> SummarizedDescriptionResult: """Run the entity extraction chain.""" @@ -52,10 +52,10 @@ async def run_summarize_descriptions( extractor = SummarizeExtractor( model_invoker=model, summarization_prompt=summarize_prompt, - on_error=lambda e, stack, details: ( - callbacks.error("Entity Extraction Error", e, stack, details) - if callbacks - else None + on_error=lambda e, stack, details: logger.error( + "Entity Extraction Error", + exc_info=e, + extra={"stack": stack, "details": details}, ), max_summary_length=max_summary_length, max_input_tokens=max_input_tokens, diff --git a/graphrag/index/operations/summarize_descriptions/summarize_descriptions.py b/graphrag/index/operations/summarize_descriptions/summarize_descriptions.py index 92b54cf9a0..780c94b329 100644 --- a/graphrag/index/operations/summarize_descriptions/summarize_descriptions.py +++ b/graphrag/index/operations/summarize_descriptions/summarize_descriptions.py @@ -17,7 +17,7 @@ ) from graphrag.logger.progress import ProgressTicker, progress_ticker -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def summarize_descriptions( @@ -29,7 +29,7 @@ async def summarize_descriptions( num_threads: int = 4, ) -> tuple[pd.DataFrame, pd.DataFrame]: """Summarize entity and relationship descriptions from an entity graph, using a language model.""" - log.debug("summarize_descriptions strategy=%s", strategy) + logger.debug("summarize_descriptions strategy=%s", strategy) strategy = strategy or {} strategy_exec = load_strategy( strategy.get("type", SummarizeStrategyType.graph_intelligence) @@ -41,7 +41,11 @@ async def get_summarized( ): ticker_length = len(nodes) + len(edges) - ticker = progress_ticker(callbacks.progress, ticker_length) + ticker = progress_ticker( + callbacks.progress, + ticker_length, + description="Summarize entity/relationship description progress: ", + ) node_futures = [ do_summarize_descriptions( @@ -95,9 +99,7 @@ async def do_summarize_descriptions( semaphore: asyncio.Semaphore, ): async with semaphore: - results = await strategy_exec( - id, descriptions, callbacks, cache, strategy_config - ) + results = await strategy_exec(id, descriptions, cache, strategy_config) ticker(1) return results diff --git a/graphrag/index/operations/summarize_descriptions/typing.py b/graphrag/index/operations/summarize_descriptions/typing.py index 565fc8eab2..55b079090d 100644 --- a/graphrag/index/operations/summarize_descriptions/typing.py +++ b/graphrag/index/operations/summarize_descriptions/typing.py @@ -9,7 +9,6 @@ from typing import Any, NamedTuple from graphrag.cache.pipeline_cache import PipelineCache -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks StrategyConfig = dict[str, Any] @@ -26,7 +25,6 @@ class SummarizedDescriptionResult: [ str | tuple[str, str], list[str], - WorkflowCallbacks, PipelineCache, StrategyConfig, ], diff --git a/graphrag/index/run/run_pipeline.py b/graphrag/index/run/run_pipeline.py index aea402cc4c..a628b5ade8 100644 --- a/graphrag/index/run/run_pipeline.py +++ b/graphrag/index/run/run_pipeline.py @@ -7,7 +7,6 @@ import logging import re import time -import traceback from collections.abc import AsyncIterable from dataclasses import asdict @@ -17,20 +16,17 @@ from graphrag.index.typing.context import PipelineRunContext from graphrag.index.typing.pipeline import Pipeline from graphrag.index.typing.pipeline_run_result import PipelineRunResult -from graphrag.logger.base import ProgressLogger -from graphrag.logger.progress import Progress from graphrag.storage.pipeline_storage import PipelineStorage from graphrag.utils.api import create_cache_from_config, create_storage_from_config from graphrag.utils.storage import load_table_from_storage, write_table_to_storage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run_pipeline( pipeline: Pipeline, config: GraphRagConfig, callbacks: WorkflowCallbacks, - logger: ProgressLogger, is_update_run: bool = False, ) -> AsyncIterable[PipelineRunResult]: """Run all workflows using a simplified pipeline.""" @@ -66,7 +62,6 @@ async def run_pipeline( cache=cache, callbacks=callbacks, state=state, - progress_logger=logger, ) else: @@ -78,13 +73,11 @@ async def run_pipeline( cache=cache, callbacks=callbacks, state=state, - progress_logger=logger, ) async for table in _run_pipeline( pipeline=pipeline, config=config, - logger=logger, context=context, ): yield table @@ -93,7 +86,6 @@ async def run_pipeline( async def _run_pipeline( pipeline: Pipeline, config: GraphRagConfig, - logger: ProgressLogger, context: PipelineRunContext, ) -> AsyncIterable[PipelineRunResult]: start_time = time.time() @@ -103,13 +95,12 @@ async def _run_pipeline( try: await _dump_json(context) + logger.info("Executing pipeline...") for name, workflow_function in pipeline.run(): last_workflow = name - progress = logger.child(name, transient=False) context.callbacks.workflow_start(name, None) work_time = time.time() result = await workflow_function(config, context) - progress(Progress(percent=1)) context.callbacks.workflow_end(name, result) yield PipelineRunResult( workflow=name, result=result.result, state=context.state, errors=None @@ -120,11 +111,11 @@ async def _run_pipeline( break context.stats.total_runtime = time.time() - start_time + logger.info("Indexing pipeline complete.") await _dump_json(context) except Exception as e: - log.exception("error running workflow %s", last_workflow) - context.callbacks.error("Error running pipeline!", e, traceback.format_exc()) + logger.exception("error running workflow %s", last_workflow) yield PipelineRunResult( workflow=last_workflow, result=None, state=context.state, errors=[e] ) diff --git a/graphrag/index/run/utils.py b/graphrag/index/run/utils.py index 809e229b7d..52b1f0bd31 100644 --- a/graphrag/index/run/utils.py +++ b/graphrag/index/run/utils.py @@ -6,15 +6,12 @@ from graphrag.cache.memory_pipeline_cache import InMemoryCache from graphrag.cache.pipeline_cache import PipelineCache from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks -from graphrag.callbacks.progress_workflow_callbacks import ProgressWorkflowCallbacks from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.callbacks.workflow_callbacks_manager import WorkflowCallbacksManager from graphrag.config.models.graph_rag_config import GraphRagConfig from graphrag.index.typing.context import PipelineRunContext from graphrag.index.typing.state import PipelineState from graphrag.index.typing.stats import PipelineRunStats -from graphrag.logger.base import ProgressLogger -from graphrag.logger.null_progress import NullProgressLogger from graphrag.storage.memory_pipeline_storage import MemoryPipelineStorage from graphrag.storage.pipeline_storage import PipelineStorage from graphrag.utils.api import create_storage_from_config @@ -26,7 +23,6 @@ def create_run_context( previous_storage: PipelineStorage | None = None, cache: PipelineCache | None = None, callbacks: WorkflowCallbacks | None = None, - progress_logger: ProgressLogger | None = None, stats: PipelineRunStats | None = None, state: PipelineState | None = None, ) -> PipelineRunContext: @@ -37,21 +33,18 @@ def create_run_context( previous_storage=previous_storage or MemoryPipelineStorage(), cache=cache or InMemoryCache(), callbacks=callbacks or NoopWorkflowCallbacks(), - progress_logger=progress_logger or NullProgressLogger(), stats=stats or PipelineRunStats(), state=state or {}, ) def create_callback_chain( - callbacks: list[WorkflowCallbacks] | None, progress: ProgressLogger | None + callbacks: list[WorkflowCallbacks] | None, ) -> WorkflowCallbacks: """Create a callback manager that encompasses multiple callbacks.""" manager = WorkflowCallbacksManager() for callback in callbacks or []: manager.register(callback) - if progress is not None: - manager.register(ProgressWorkflowCallbacks(progress)) return manager diff --git a/graphrag/index/text_splitting/text_splitting.py b/graphrag/index/text_splitting/text_splitting.py index 57f2f23659..2674dd724d 100644 --- a/graphrag/index/text_splitting/text_splitting.py +++ b/graphrag/index/text_splitting/text_splitting.py @@ -21,7 +21,7 @@ EncodeFn = Callable[[str], EncodedText] LengthFn = Callable[[str], int] -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) @dataclass(frozen=True) @@ -100,7 +100,9 @@ def __init__( try: enc = tiktoken.encoding_for_model(model_name) except KeyError: - log.exception("Model %s not found, using %s", model_name, encoding_name) + logger.exception( + "Model %s not found, using %s", model_name, encoding_name + ) enc = tiktoken.get_encoding(encoding_name) else: enc = tiktoken.get_encoding(encoding_name) diff --git a/graphrag/index/typing/context.py b/graphrag/index/typing/context.py index 9ac0a4e31f..ef2e1f7ea5 100644 --- a/graphrag/index/typing/context.py +++ b/graphrag/index/typing/context.py @@ -10,7 +10,6 @@ from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.index.typing.state import PipelineState from graphrag.index.typing.stats import PipelineRunStats -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage @@ -29,7 +28,5 @@ class PipelineRunContext: "Cache instance for reading previous LLM responses." callbacks: WorkflowCallbacks "Callbacks to be called during the pipeline run." - progress_logger: ProgressLogger - "Progress logger for the pipeline run." state: PipelineState "Arbitrary property bag for runtime state, persistent pre-computes, or experimental features." diff --git a/graphrag/index/utils/derive_from_rows.py b/graphrag/index/utils/derive_from_rows.py index 6a29d8848f..663d78c1c8 100644 --- a/graphrag/index/utils/derive_from_rows.py +++ b/graphrag/index/utils/derive_from_rows.py @@ -37,17 +37,18 @@ async def derive_from_rows( callbacks: WorkflowCallbacks | None = None, num_threads: int = 4, async_type: AsyncType = AsyncType.AsyncIO, + progress_msg: str = "", ) -> list[ItemType | None]: """Apply a generic transform function to each row. Any errors will be reported and thrown.""" callbacks = callbacks or NoopWorkflowCallbacks() match async_type: case AsyncType.AsyncIO: return await derive_from_rows_asyncio( - input, transform, callbacks, num_threads + input, transform, callbacks, num_threads, progress_msg ) case AsyncType.Threaded: return await derive_from_rows_asyncio_threads( - input, transform, callbacks, num_threads + input, transform, callbacks, num_threads, progress_msg ) case _: msg = f"Unsupported scheduling type {async_type}" @@ -62,6 +63,7 @@ async def derive_from_rows_asyncio_threads( transform: Callable[[pd.Series], Awaitable[ItemType]], callbacks: WorkflowCallbacks, num_threads: int | None = 4, + progress_msg: str = "", ) -> list[ItemType | None]: """ Derive from rows asynchronously. @@ -81,7 +83,9 @@ async def execute_task(task: Coroutine) -> ItemType | None: return await asyncio.gather(*[execute_task(task) for task in tasks]) - return await _derive_from_rows_base(input, transform, callbacks, gather) + return await _derive_from_rows_base( + input, transform, callbacks, gather, progress_msg + ) """A module containing the derive_from_rows_async method.""" @@ -92,6 +96,7 @@ async def derive_from_rows_asyncio( transform: Callable[[pd.Series], Awaitable[ItemType]], callbacks: WorkflowCallbacks, num_threads: int = 4, + progress_msg: str = "", ) -> list[ItemType | None]: """ Derive from rows asynchronously. @@ -112,7 +117,9 @@ async def execute_row_protected( ] return await asyncio.gather(*tasks) - return await _derive_from_rows_base(input, transform, callbacks, gather) + return await _derive_from_rows_base( + input, transform, callbacks, gather, progress_msg + ) ItemType = TypeVar("ItemType") @@ -126,13 +133,16 @@ async def _derive_from_rows_base( transform: Callable[[pd.Series], Awaitable[ItemType]], callbacks: WorkflowCallbacks, gather: GatherFn[ItemType], + progress_msg: str = "", ) -> list[ItemType | None]: """ Derive from rows asynchronously. This is useful for IO bound operations. """ - tick = progress_ticker(callbacks.progress, num_total=len(input)) + tick = progress_ticker( + callbacks.progress, num_total=len(input), description=progress_msg + ) errors: list[tuple[BaseException, str]] = [] async def execute(row: tuple[Any, pd.Series]) -> ItemType | None: @@ -153,7 +163,9 @@ async def execute(row: tuple[Any, pd.Series]) -> ItemType | None: tick.done() for error, stack in errors: - callbacks.error("parallel transformation error", error, stack) + logger.error( + "parallel transformation error", exc_info=error, extra={"stack": stack} + ) if len(errors) > 0: raise ParallelizationError(len(errors), errors[0][1]) diff --git a/graphrag/index/utils/tokens.py b/graphrag/index/utils/tokens.py index fcd996840f..6c48f24059 100644 --- a/graphrag/index/utils/tokens.py +++ b/graphrag/index/utils/tokens.py @@ -11,7 +11,7 @@ DEFAULT_ENCODING_NAME = defs.ENCODING_MODEL -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def num_tokens_from_string( @@ -23,7 +23,7 @@ def num_tokens_from_string( encoding = tiktoken.encoding_for_model(model) except KeyError: msg = f"Failed to get encoding for {model} when getting num_tokens_from_string. Fall back to default encoding {DEFAULT_ENCODING_NAME}" - log.warning(msg) + logger.warning(msg) encoding = tiktoken.get_encoding(DEFAULT_ENCODING_NAME) else: encoding = tiktoken.get_encoding(encoding_name or DEFAULT_ENCODING_NAME) diff --git a/graphrag/index/validate_config.py b/graphrag/index/validate_config.py index fc75494522..cf9fbec4aa 100644 --- a/graphrag/index/validate_config.py +++ b/graphrag/index/validate_config.py @@ -4,15 +4,17 @@ """A module containing validate_config_names definition.""" import asyncio +import logging import sys from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks from graphrag.config.models.graph_rag_config import GraphRagConfig from graphrag.language_model.manager import ModelManager -from graphrag.logger.print_progress import ProgressLogger +logger = logging.getLogger(__name__) -def validate_config_names(logger: ProgressLogger, parameters: GraphRagConfig) -> None: + +def validate_config_names(parameters: GraphRagConfig) -> None: """Validate config file for LLM deployment name typos.""" # Validate Chat LLM configs # TODO: Replace default_chat_model with a way to select the model @@ -28,7 +30,7 @@ def validate_config_names(logger: ProgressLogger, parameters: GraphRagConfig) -> try: asyncio.run(llm.achat("This is an LLM connectivity test. Say Hello World")) - logger.success("LLM Config Params Validated") + logger.info("LLM Config Params Validated") except Exception as e: # noqa: BLE001 logger.error(f"LLM configuration error detected. Exiting...\n{e}") # noqa sys.exit(1) @@ -48,7 +50,7 @@ def validate_config_names(logger: ProgressLogger, parameters: GraphRagConfig) -> try: asyncio.run(embed_llm.aembed_batch(["This is an LLM Embedding Test String"])) - logger.success("Embedding LLM Config Params Validated") + logger.info("Embedding LLM Config Params Validated") except Exception as e: # noqa: BLE001 logger.error(f"Embedding LLM configuration error detected. Exiting...\n{e}") # noqa sys.exit(1) diff --git a/graphrag/index/workflows/create_base_text_units.py b/graphrag/index/workflows/create_base_text_units.py index d25c9a9ff8..a8c45aa1bc 100644 --- a/graphrag/index/workflows/create_base_text_units.py +++ b/graphrag/index/workflows/create_base_text_units.py @@ -4,6 +4,7 @@ """A module containing run_workflow method definition.""" import json +import logging from typing import Any, cast import pandas as pd @@ -19,12 +20,15 @@ from graphrag.logger.progress import Progress from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform base text_units.""" + logger.info("Workflow started: create_base_text_units") documents = await load_table_from_storage("documents", context.output_storage) chunks = config.chunks @@ -43,6 +47,7 @@ async def run_workflow( await write_table_to_storage(output, "text_units", context.output_storage) + logger.info("Workflow completed: create_base_text_units") return WorkflowFunctionOutput(result=output) @@ -81,7 +86,7 @@ def create_base_text_units( ) aggregated.rename(columns={"text_with_ids": "texts"}, inplace=True) - def chunker(row: dict[str, Any]) -> Any: + def chunker(row: pd.Series) -> Any: line_delimiter = ".\n" metadata_str = "" metadata_tokens = 0 @@ -125,7 +130,19 @@ def chunker(row: dict[str, Any]) -> Any: row["chunks"] = chunked return row - aggregated = aggregated.apply(lambda row: chunker(row), axis=1) + # Track progress of row-wise apply operation + total_rows = len(aggregated) + logger.info("Starting chunking process for %d documents", total_rows) + + def chunker_with_logging(row: pd.Series, row_index: int) -> Any: + """Add logging to chunker execution.""" + result = chunker(row) + logger.info("chunker progress: %d/%d", row_index + 1, total_rows) + return result + + aggregated = aggregated.apply( + lambda row: chunker_with_logging(row, row.name), axis=1 + ) aggregated = cast("pd.DataFrame", aggregated[[*group_by_columns, "chunks"]]) aggregated = aggregated.explode("chunks") diff --git a/graphrag/index/workflows/create_communities.py b/graphrag/index/workflows/create_communities.py index b1096f6a30..c06d5f4b28 100644 --- a/graphrag/index/workflows/create_communities.py +++ b/graphrag/index/workflows/create_communities.py @@ -3,6 +3,7 @@ """A module containing run_workflow method definition.""" +import logging from datetime import datetime, timezone from typing import cast from uuid import uuid4 @@ -18,12 +19,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform final communities.""" + logger.info("Workflow started: create_communities") entities = await load_table_from_storage("entities", context.output_storage) relationships = await load_table_from_storage( "relationships", context.output_storage @@ -43,6 +47,7 @@ async def run_workflow( await write_table_to_storage(output, "communities", context.output_storage) + logger.info("Workflow completed: create_communities") return WorkflowFunctionOutput(result=output) diff --git a/graphrag/index/workflows/create_community_reports.py b/graphrag/index/workflows/create_community_reports.py index 15dc187c8d..9eb677f010 100644 --- a/graphrag/index/workflows/create_community_reports.py +++ b/graphrag/index/workflows/create_community_reports.py @@ -3,6 +3,8 @@ """A module containing run_workflow method definition.""" +import logging + import pandas as pd import graphrag.data_model.schemas as schemas @@ -32,12 +34,15 @@ write_table_to_storage, ) +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform community reports.""" + logger.info("Workflow started: create_community_reports") edges = await load_table_from_storage("relationships", context.output_storage) entities = await load_table_from_storage("entities", context.output_storage) communities = await load_table_from_storage("communities", context.output_storage) @@ -70,6 +75,7 @@ async def run_workflow( await write_table_to_storage(output, "community_reports", context.output_storage) + logger.info("Workflow completed: create_community_reports") return WorkflowFunctionOutput(result=output) diff --git a/graphrag/index/workflows/create_community_reports_text.py b/graphrag/index/workflows/create_community_reports_text.py index b584c6f5ae..6ab78bdb36 100644 --- a/graphrag/index/workflows/create_community_reports_text.py +++ b/graphrag/index/workflows/create_community_reports_text.py @@ -29,7 +29,7 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run_workflow( @@ -37,6 +37,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform community reports.""" + logger.info("Workflow started: create_community_reports_text") entities = await load_table_from_storage("entities", context.output_storage) communities = await load_table_from_storage("communities", context.output_storage) @@ -64,6 +65,7 @@ async def run_workflow( await write_table_to_storage(output, "community_reports", context.output_storage) + logger.info("Workflow completed: create_community_reports_text") return WorkflowFunctionOutput(result=output) diff --git a/graphrag/index/workflows/create_final_documents.py b/graphrag/index/workflows/create_final_documents.py index 0f0076604a..d043c67015 100644 --- a/graphrag/index/workflows/create_final_documents.py +++ b/graphrag/index/workflows/create_final_documents.py @@ -3,6 +3,8 @@ """A module containing run_workflow method definition.""" +import logging + import pandas as pd from graphrag.config.models.graph_rag_config import GraphRagConfig @@ -11,12 +13,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( _config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform final documents.""" + logger.info("Workflow started: create_final_documents") documents = await load_table_from_storage("documents", context.output_storage) text_units = await load_table_from_storage("text_units", context.output_storage) @@ -24,6 +29,7 @@ async def run_workflow( await write_table_to_storage(output, "documents", context.output_storage) + logger.info("Workflow completed: create_final_documents") return WorkflowFunctionOutput(result=output) diff --git a/graphrag/index/workflows/create_final_text_units.py b/graphrag/index/workflows/create_final_text_units.py index f1ae44eda4..a74c9d6020 100644 --- a/graphrag/index/workflows/create_final_text_units.py +++ b/graphrag/index/workflows/create_final_text_units.py @@ -3,6 +3,8 @@ """A module containing run_workflow method definition.""" +import logging + import pandas as pd from graphrag.config.models.graph_rag_config import GraphRagConfig @@ -15,12 +17,15 @@ write_table_to_storage, ) +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform the text units.""" + logger.info("Workflow started: create_final_text_units") text_units = await load_table_from_storage("text_units", context.output_storage) final_entities = await load_table_from_storage("entities", context.output_storage) final_relationships = await load_table_from_storage( @@ -43,6 +48,7 @@ async def run_workflow( await write_table_to_storage(output, "text_units", context.output_storage) + logger.info("Workflow completed: create_final_text_units") return WorkflowFunctionOutput(result=output) diff --git a/graphrag/index/workflows/extract_covariates.py b/graphrag/index/workflows/extract_covariates.py index c67668504c..266cec0ec3 100644 --- a/graphrag/index/workflows/extract_covariates.py +++ b/graphrag/index/workflows/extract_covariates.py @@ -3,6 +3,7 @@ """A module containing run_workflow method definition.""" +import logging from typing import Any from uuid import uuid4 @@ -20,12 +21,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to extract and format covariates.""" + logger.info("Workflow started: extract_covariates") output = None if config.extract_claims.enabled: text_units = await load_table_from_storage("text_units", context.output_storage) @@ -53,6 +57,7 @@ async def run_workflow( await write_table_to_storage(output, "covariates", context.output_storage) + logger.info("Workflow completed: extract_covariates") return WorkflowFunctionOutput(result=output) diff --git a/graphrag/index/workflows/extract_graph.py b/graphrag/index/workflows/extract_graph.py index c6d259de47..bed4d4185b 100644 --- a/graphrag/index/workflows/extract_graph.py +++ b/graphrag/index/workflows/extract_graph.py @@ -3,6 +3,7 @@ """A module containing run_workflow method definition.""" +import logging from typing import Any import pandas as pd @@ -21,12 +22,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to create the base entity graph.""" + logger.info("Workflow started: extract_graph") text_units = await load_table_from_storage("text_units", context.output_storage) extract_graph_llm_settings = config.get_language_model_config( @@ -66,6 +70,7 @@ async def run_workflow( raw_relationships, "raw_relationships", context.output_storage ) + logger.info("Workflow completed: extract_graph") return WorkflowFunctionOutput( result={ "entities": entities, @@ -101,14 +106,14 @@ async def extract_graph( if not _validate_data(extracted_entities): error_msg = "Entity Extraction failed. No entities detected during extraction." - callbacks.error(error_msg) + logger.error(error_msg) raise ValueError(error_msg) if not _validate_data(extracted_relationships): error_msg = ( "Entity Extraction failed. No relationships detected during extraction." ) - callbacks.error(error_msg) + logger.error(error_msg) raise ValueError(error_msg) # copy these as is before any summarization diff --git a/graphrag/index/workflows/extract_graph_nlp.py b/graphrag/index/workflows/extract_graph_nlp.py index 5c1d097289..0becdaa823 100644 --- a/graphrag/index/workflows/extract_graph_nlp.py +++ b/graphrag/index/workflows/extract_graph_nlp.py @@ -3,6 +3,8 @@ """A module containing run_workflow method definition.""" +import logging + import pandas as pd from graphrag.cache.pipeline_cache import PipelineCache @@ -16,12 +18,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to create the base entity graph.""" + logger.info("Workflow started: extract_graph_nlp") text_units = await load_table_from_storage("text_units", context.output_storage) entities, relationships = await extract_graph_nlp( @@ -33,6 +38,8 @@ async def run_workflow( await write_table_to_storage(entities, "entities", context.output_storage) await write_table_to_storage(relationships, "relationships", context.output_storage) + logger.info("Workflow completed: extract_graph_nlp") + return WorkflowFunctionOutput( result={ "entities": entities, diff --git a/graphrag/index/workflows/factory.py b/graphrag/index/workflows/factory.py index 6e86540d8a..585ecfa8a1 100644 --- a/graphrag/index/workflows/factory.py +++ b/graphrag/index/workflows/factory.py @@ -3,6 +3,7 @@ """Encapsulates pipeline construction and selection.""" +import logging from typing import ClassVar from graphrag.config.enums import IndexingMethod @@ -10,6 +11,8 @@ from graphrag.index.typing.pipeline import Pipeline from graphrag.index.typing.workflow import WorkflowFunction +logger = logging.getLogger(__name__) + class PipelineFactory: """A factory class for workflow pipelines.""" @@ -41,6 +44,7 @@ def create_pipeline( ) -> Pipeline: """Create a pipeline generator.""" workflows = config.workflows or cls.pipelines.get(method, []) + logger.info("Creating pipeline with workflows: %s", workflows) return Pipeline([(name, cls.workflows[name]) for name in workflows]) diff --git a/graphrag/index/workflows/finalize_graph.py b/graphrag/index/workflows/finalize_graph.py index 8e79bb3950..66827774f2 100644 --- a/graphrag/index/workflows/finalize_graph.py +++ b/graphrag/index/workflows/finalize_graph.py @@ -3,9 +3,10 @@ """A module containing run_workflow method definition.""" +import logging + import pandas as pd -from graphrag.callbacks.workflow_callbacks import WorkflowCallbacks from graphrag.config.models.embed_graph_config import EmbedGraphConfig from graphrag.config.models.graph_rag_config import GraphRagConfig from graphrag.index.operations.create_graph import create_graph @@ -16,12 +17,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to create the base entity graph.""" + logger.info("Workflow started: finalize_graph") entities = await load_table_from_storage("entities", context.output_storage) relationships = await load_table_from_storage( "relationships", context.output_storage @@ -30,7 +34,6 @@ async def run_workflow( final_entities, final_relationships = finalize_graph( entities, relationships, - callbacks=context.callbacks, embed_config=config.embed_graph, layout_enabled=config.umap.enabled, ) @@ -50,6 +53,7 @@ async def run_workflow( storage=context.output_storage, ) + logger.info("Workflow completed: finalize_graph") return WorkflowFunctionOutput( result={ "entities": entities, @@ -61,13 +65,12 @@ async def run_workflow( def finalize_graph( entities: pd.DataFrame, relationships: pd.DataFrame, - callbacks: WorkflowCallbacks, embed_config: EmbedGraphConfig | None = None, layout_enabled: bool = False, ) -> tuple[pd.DataFrame, pd.DataFrame]: """All the steps to finalize the entity and relationship formats.""" final_entities = finalize_entities( - entities, relationships, callbacks, embed_config, layout_enabled + entities, relationships, embed_config, layout_enabled ) final_relationships = finalize_relationships(relationships) return (final_entities, final_relationships) diff --git a/graphrag/index/workflows/generate_text_embeddings.py b/graphrag/index/workflows/generate_text_embeddings.py index c19fed962b..e56c0ed8cb 100644 --- a/graphrag/index/workflows/generate_text_embeddings.py +++ b/graphrag/index/workflows/generate_text_embeddings.py @@ -30,7 +30,7 @@ write_table_to_storage, ) -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run_workflow( @@ -38,6 +38,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to transform community reports.""" + logger.info("Workflow started: generate_text_embeddings") documents = None relationships = None text_units = None @@ -81,6 +82,7 @@ async def run_workflow( context.output_storage, ) + logger.info("Workflow completed: generate_text_embeddings") return WorkflowFunctionOutput(result=output) @@ -145,12 +147,12 @@ async def generate_text_embeddings( }, } - log.info("Creating embeddings") + logger.info("Creating embeddings") outputs = {} for field in embedded_fields: if embedding_param_map[field]["data"] is None: msg = f"Embedding {field} is specified but data table is not in storage. This may or may not be intentional - if you expect it to me here, please check for errors earlier in the logs." - log.warning(msg) + logger.warning(msg) else: outputs[field] = await _run_embeddings( name=field, diff --git a/graphrag/index/workflows/load_input_documents.py b/graphrag/index/workflows/load_input_documents.py index b3d4170360..33e14d0cb2 100644 --- a/graphrag/index/workflows/load_input_documents.py +++ b/graphrag/index/workflows/load_input_documents.py @@ -12,11 +12,10 @@ from graphrag.index.input.factory import create_input from graphrag.index.typing.context import PipelineRunContext from graphrag.index.typing.workflow import WorkflowFunctionOutput -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage from graphrag.utils.storage import write_table_to_storage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run_workflow( @@ -27,10 +26,9 @@ async def run_workflow( output = await load_input_documents( config.input, context.input_storage, - context.progress_logger, ) - log.info("Final # of rows loaded: %s", len(output)) + logger.info("Final # of rows loaded: %s", len(output)) context.stats.num_documents = len(output) await write_table_to_storage(output, "documents", context.output_storage) @@ -39,7 +37,7 @@ async def run_workflow( async def load_input_documents( - config: InputConfig, storage: PipelineStorage, progress_logger: ProgressLogger + config: InputConfig, storage: PipelineStorage ) -> pd.DataFrame: """Load and parse input documents into a standard format.""" - return await create_input(config, storage, progress_logger) + return await create_input(config, storage) diff --git a/graphrag/index/workflows/load_update_documents.py b/graphrag/index/workflows/load_update_documents.py index 18d1e1b90e..fbe48b6419 100644 --- a/graphrag/index/workflows/load_update_documents.py +++ b/graphrag/index/workflows/load_update_documents.py @@ -13,11 +13,10 @@ from graphrag.index.typing.context import PipelineRunContext from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.index.update.incremental_index import get_delta_docs -from graphrag.logger.base import ProgressLogger from graphrag.storage.pipeline_storage import PipelineStorage from graphrag.utils.storage import write_table_to_storage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def run_workflow( @@ -29,15 +28,13 @@ async def run_workflow( config.input, context.input_storage, context.previous_storage, - context.progress_logger, ) - log.info("Final # of update rows loaded: %s", len(output)) + logger.info("Final # of update rows loaded: %s", len(output)) context.stats.update_documents = len(output) if len(output) == 0: - log.warning("No new update documents found.") - context.progress_logger.warning("No new update documents found.") + logger.warning("No new update documents found.") return WorkflowFunctionOutput(result=None, stop=True) await write_table_to_storage(output, "documents", context.output_storage) @@ -49,10 +46,9 @@ async def load_update_documents( config: InputConfig, input_storage: PipelineStorage, previous_storage: PipelineStorage, - progress_logger: ProgressLogger, ) -> pd.DataFrame: """Load and parse update-only input documents into a standard format.""" - input_documents = await create_input(config, input_storage, progress_logger) + input_documents = await create_input(config, input_storage) # previous storage is the output of the previous run # we'll use this to diff the input from the prior delta_documents = await get_delta_docs(input_documents, previous_storage) diff --git a/graphrag/index/workflows/prune_graph.py b/graphrag/index/workflows/prune_graph.py index 52987a8df8..8bb48df7ee 100644 --- a/graphrag/index/workflows/prune_graph.py +++ b/graphrag/index/workflows/prune_graph.py @@ -3,6 +3,8 @@ """A module containing run_workflow method definition.""" +import logging + import pandas as pd from graphrag.config.models.graph_rag_config import GraphRagConfig @@ -14,12 +16,15 @@ from graphrag.index.typing.workflow import WorkflowFunctionOutput from graphrag.utils.storage import load_table_from_storage, write_table_to_storage +logger = logging.getLogger(__name__) + async def run_workflow( config: GraphRagConfig, context: PipelineRunContext, ) -> WorkflowFunctionOutput: """All the steps to create the base entity graph.""" + logger.info("Workflow started: prune_graph") entities = await load_table_from_storage("entities", context.output_storage) relationships = await load_table_from_storage( "relationships", context.output_storage @@ -36,6 +41,7 @@ async def run_workflow( pruned_relationships, "relationships", context.output_storage ) + logger.info("Workflow completed: prune_graph") return WorkflowFunctionOutput( result={ "entities": pruned_entities, diff --git a/graphrag/index/workflows/update_clean_state.py b/graphrag/index/workflows/update_clean_state.py index 7739595a41..3803be47dc 100644 --- a/graphrag/index/workflows/update_clean_state.py +++ b/graphrag/index/workflows/update_clean_state.py @@ -17,7 +17,7 @@ async def run_workflow( # noqa: RUF029 context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Clean the state after the update.""" - logger.info("Cleaning State") + logger.info("Workflow started: update_clean_state") keys_to_delete = [ key_name for key_name in context.state @@ -27,4 +27,5 @@ async def run_workflow( # noqa: RUF029 for key_name in keys_to_delete: del context.state[key_name] + logger.info("Workflow completed: update_clean_state") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_communities.py b/graphrag/index/workflows/update_communities.py index 14c8826b75..b7e3e6a343 100644 --- a/graphrag/index/workflows/update_communities.py +++ b/graphrag/index/workflows/update_communities.py @@ -21,7 +21,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the communities from a incremental index run.""" - logger.info("Updating Communities") + logger.info("Workflow started: update_communities") output_storage, previous_storage, delta_storage = get_update_storages( config, context.state["update_timestamp"] ) @@ -32,6 +32,7 @@ async def run_workflow( context.state["incremental_update_community_id_mapping"] = community_id_mapping + logger.info("Workflow completed: update_communities") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_community_reports.py b/graphrag/index/workflows/update_community_reports.py index 2dc0feb3a2..42576aca27 100644 --- a/graphrag/index/workflows/update_community_reports.py +++ b/graphrag/index/workflows/update_community_reports.py @@ -23,7 +23,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the community reports from a incremental index run.""" - logger.info("Updating Community Reports") + logger.info("Workflow started: update_community_reports") output_storage, previous_storage, delta_storage = get_update_storages( config, context.state["update_timestamp"] ) @@ -38,6 +38,7 @@ async def run_workflow( merged_community_reports ) + logger.info("Workflow completed: update_community_reports") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_covariates.py b/graphrag/index/workflows/update_covariates.py index 1239de144a..f0bf29a6ae 100644 --- a/graphrag/index/workflows/update_covariates.py +++ b/graphrag/index/workflows/update_covariates.py @@ -27,6 +27,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the covariates from a incremental index run.""" + logger.info("Workflow started: update_covariates") output_storage, previous_storage, delta_storage = get_update_storages( config, context.state["update_timestamp"] ) @@ -37,6 +38,7 @@ async def run_workflow( logger.info("Updating Covariates") await _update_covariates(previous_storage, delta_storage, output_storage) + logger.info("Workflow completed: update_covariates") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_entities_relationships.py b/graphrag/index/workflows/update_entities_relationships.py index 0702d62776..cd8ad82553 100644 --- a/graphrag/index/workflows/update_entities_relationships.py +++ b/graphrag/index/workflows/update_entities_relationships.py @@ -27,7 +27,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the entities and relationships from a incremental index run.""" - logger.info("Updating Entities and Relationships") + logger.info("Workflow started: update_entities_relationships") output_storage, previous_storage, delta_storage = get_update_storages( config, context.state["update_timestamp"] ) @@ -49,6 +49,7 @@ async def run_workflow( context.state["incremental_update_merged_relationships"] = merged_relationships_df context.state["incremental_update_entity_id_mapping"] = entity_id_mapping + logger.info("Workflow completed: update_entities_relationships") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_final_documents.py b/graphrag/index/workflows/update_final_documents.py index 485cb7b10f..b684beba94 100644 --- a/graphrag/index/workflows/update_final_documents.py +++ b/graphrag/index/workflows/update_final_documents.py @@ -19,7 +19,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the documents from a incremental index run.""" - logger.info("Updating Documents") + logger.info("Workflow started: update_final_documents") output_storage, previous_storage, delta_storage = get_update_storages( config, context.state["update_timestamp"] ) @@ -30,4 +30,5 @@ async def run_workflow( context.state["incremental_update_final_documents"] = final_documents + logger.info("Workflow completed: update_final_documents") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_text_embeddings.py b/graphrag/index/workflows/update_text_embeddings.py index ed57de86d1..11bce16d3e 100644 --- a/graphrag/index/workflows/update_text_embeddings.py +++ b/graphrag/index/workflows/update_text_embeddings.py @@ -21,7 +21,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the text embeddings from a incremental index run.""" - logger.info("Updating Text Embeddings") + logger.info("Workflow started: update_text_embeddings") output_storage, _, _ = get_update_storages( config, context.state["update_timestamp"] ) @@ -55,4 +55,5 @@ async def run_workflow( output_storage, ) + logger.info("Workflow completed: update_text_embeddings") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/index/workflows/update_text_units.py b/graphrag/index/workflows/update_text_units.py index 4b26b47b07..392533f16b 100644 --- a/graphrag/index/workflows/update_text_units.py +++ b/graphrag/index/workflows/update_text_units.py @@ -23,7 +23,7 @@ async def run_workflow( context: PipelineRunContext, ) -> WorkflowFunctionOutput: """Update the text units from a incremental index run.""" - logger.info("Updating Text Units") + logger.info("Workflow started: update_text_units") output_storage, previous_storage, delta_storage = get_update_storages( config, context.state["update_timestamp"] ) @@ -35,6 +35,7 @@ async def run_workflow( context.state["incremental_update_merged_text_units"] = merged_text_units + logger.info("Workflow completed: update_text_units") return WorkflowFunctionOutput(result=None) diff --git a/graphrag/language_model/manager.py b/graphrag/language_model/manager.py index ebcce8eb4e..22a09f00ae 100644 --- a/graphrag/language_model/manager.py +++ b/graphrag/language_model/manager.py @@ -11,6 +11,8 @@ from typing import TYPE_CHECKING, Any, ClassVar +from typing_extensions import Self + from graphrag.language_model.factory import ModelFactory if TYPE_CHECKING: @@ -22,11 +24,11 @@ class ModelManager: _instance: ClassVar[ModelManager | None] = None - def __new__(cls) -> ModelManager: # noqa: PYI034: False positive + def __new__(cls) -> Self: """Create a new instance of LLMManager if it does not exist.""" if cls._instance is None: cls._instance = super().__new__(cls) - return cls._instance + return cls._instance # type: ignore[return-value] def __init__(self) -> None: # Avoid reinitialization in the singleton. diff --git a/graphrag/language_model/providers/fnllm/utils.py b/graphrag/language_model/providers/fnllm/utils.py index b864cf43f8..b12b0e27b0 100644 --- a/graphrag/language_model/providers/fnllm/utils.py +++ b/graphrag/language_model/providers/fnllm/utils.py @@ -6,6 +6,7 @@ from __future__ import annotations import asyncio +import logging import threading from typing import TYPE_CHECKING, Any, TypeVar @@ -26,6 +27,8 @@ ) from graphrag.index.typing.error_handler import ErrorHandlerFn +logger = logging.getLogger(__name__) + def _create_cache(cache: PipelineCache | None, name: str) -> FNLLMCacheProvider | None: """Create an FNLLM cache from a pipeline cache.""" @@ -34,7 +37,7 @@ def _create_cache(cache: PipelineCache | None, name: str) -> FNLLMCacheProvider return FNLLMCacheProvider(cache).child(name) -def _create_error_handler(callbacks: WorkflowCallbacks) -> ErrorHandlerFn: +def _create_error_handler(callbacks: WorkflowCallbacks) -> ErrorHandlerFn: # noqa: ARG001 """Create an error handler from a WorkflowCallbacks.""" def on_error( @@ -42,7 +45,11 @@ def on_error( stack: str | None = None, details: dict | None = None, ) -> None: - callbacks.error("Error Invoking LLM", error, stack, details) + logger.error( + "Error Invoking LLM", + exc_info=error, + extra={"stack": stack, "details": details}, + ) return on_error diff --git a/graphrag/logger/base.py b/graphrag/logger/base.py deleted file mode 100644 index 73b5668552..0000000000 --- a/graphrag/logger/base.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Base classes for logging and progress reporting.""" - -from abc import ABC, abstractmethod -from typing import Any - -from graphrag.logger.progress import Progress - - -class StatusLogger(ABC): - """Provides a way to log status updates from the pipeline.""" - - @abstractmethod - def error(self, message: str, details: dict[str, Any] | None = None): - """Log an error.""" - - @abstractmethod - def warning(self, message: str, details: dict[str, Any] | None = None): - """Log a warning.""" - - @abstractmethod - def log(self, message: str, details: dict[str, Any] | None = None): - """Report a log.""" - - -class ProgressLogger(ABC): - """ - Abstract base class for progress loggers. - - This is used to report workflow processing progress via mechanisms like progress-bars. - """ - - @abstractmethod - def __call__(self, update: Progress): - """Update progress.""" - - @abstractmethod - def dispose(self): - """Dispose of the progress logger.""" - - @abstractmethod - def child(self, prefix: str, transient=True) -> "ProgressLogger": - """Create a child progress bar.""" - - @abstractmethod - def force_refresh(self) -> None: - """Force a refresh.""" - - @abstractmethod - def stop(self) -> None: - """Stop the progress logger.""" - - @abstractmethod - def error(self, message: str) -> None: - """Log an error.""" - - @abstractmethod - def warning(self, message: str) -> None: - """Log a warning.""" - - @abstractmethod - def info(self, message: str) -> None: - """Log information.""" - - @abstractmethod - def success(self, message: str) -> None: - """Log success.""" diff --git a/graphrag/callbacks/blob_workflow_callbacks.py b/graphrag/logger/blob_workflow_logger.py similarity index 65% rename from graphrag/callbacks/blob_workflow_callbacks.py rename to graphrag/logger/blob_workflow_logger.py index 04e033f0d6..ae4893c6e8 100644 --- a/graphrag/callbacks/blob_workflow_callbacks.py +++ b/graphrag/logger/blob_workflow_logger.py @@ -4,6 +4,7 @@ """A logger that emits updates from the indexing engine to a blob in Azure Storage.""" import json +import logging from datetime import datetime, timezone from pathlib import Path from typing import Any @@ -11,11 +12,9 @@ from azure.identity import DefaultAzureCredential from azure.storage.blob import BlobServiceClient -from graphrag.callbacks.noop_workflow_callbacks import NoopWorkflowCallbacks - -class BlobWorkflowCallbacks(NoopWorkflowCallbacks): - """A logger that writes to a blob storage account.""" +class BlobWorkflowLogger(logging.Handler): + """A logging handler that writes to a blob storage account.""" _blob_service_client: BlobServiceClient _container_name: str @@ -28,16 +27,21 @@ def __init__( blob_name: str = "", base_dir: str | None = None, storage_account_blob_url: str | None = None, + level: int = logging.NOTSET, ): - """Create a new instance of the BlobStorageReporter class.""" + """Create a new instance of the BlobWorkflowLogger class.""" + super().__init__(level) + if container_name is None: msg = "No container name provided for blob storage." raise ValueError(msg) if connection_string is None and storage_account_blob_url is None: msg = "No storage account blob url provided for blob storage." raise ValueError(msg) + self._connection_string = connection_string self._storage_account_blob_url = storage_account_blob_url + if self._connection_string: self._blob_service_client = BlobServiceClient.from_connection_string( self._connection_string @@ -65,7 +69,37 @@ def __init__( self._num_blocks = 0 # refresh block counter + def emit(self, record) -> None: + """Emit a log record to blob storage.""" + try: + # Create JSON structure based on record + log_data = { + "type": self._get_log_type(record.levelno), + "data": record.getMessage(), + } + + # Add additional fields if they exist + if hasattr(record, "details") and record.details: # type: ignore[reportAttributeAccessIssue] + log_data["details"] = record.details # type: ignore[reportAttributeAccessIssue] + if record.exc_info and record.exc_info[1]: + log_data["cause"] = str(record.exc_info[1]) + if hasattr(record, "stack") and record.stack: # type: ignore[reportAttributeAccessIssue] + log_data["stack"] = record.stack # type: ignore[reportAttributeAccessIssue] + + self._write_log(log_data) + except (OSError, ValueError): + self.handleError(record) + + def _get_log_type(self, level: int) -> str: + """Get log type string based on log level.""" + if level >= logging.ERROR: + return "error" + if level >= logging.WARNING: + return "warning" + return "log" + def _write_log(self, log: dict[str, Any]): + """Write log data to blob storage.""" # create a new file when block count hits close 25k if ( self._num_blocks >= self._max_block_count @@ -83,27 +117,3 @@ def _write_log(self, log: dict[str, Any]): # update the blob's block count self._num_blocks += 1 - - def error( - self, - message: str, - cause: BaseException | None = None, - stack: str | None = None, - details: dict | None = None, - ): - """Report an error.""" - self._write_log({ - "type": "error", - "data": message, - "cause": str(cause), - "stack": stack, - "details": details, - }) - - def warning(self, message: str, details: dict | None = None): - """Report a warning.""" - self._write_log({"type": "warning", "data": message, "details": details}) - - def log(self, message: str, details: dict | None = None): - """Report a generic log message.""" - self._write_log({"type": "log", "data": message, "details": details}) diff --git a/graphrag/logger/console.py b/graphrag/logger/console.py deleted file mode 100644 index 3388ba77b2..0000000000 --- a/graphrag/logger/console.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Console Log.""" - -from typing import Any - -from graphrag.logger.base import StatusLogger - - -class ConsoleReporter(StatusLogger): - """A logger that writes to a console.""" - - def error(self, message: str, details: dict[str, Any] | None = None): - """Log an error.""" - print(message, details) # noqa T201 - - def warning(self, message: str, details: dict[str, Any] | None = None): - """Log a warning.""" - _print_warning(message) - - def log(self, message: str, details: dict[str, Any] | None = None): - """Log a log.""" - print(message, details) # noqa T201 - - -def _print_warning(skk): - print(f"\033[93m {skk}\033[00m") # noqa T201 diff --git a/graphrag/logger/factory.py b/graphrag/logger/factory.py deleted file mode 100644 index ef394e2dd9..0000000000 --- a/graphrag/logger/factory.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Factory functions for creating loggers.""" - -from typing import ClassVar - -from graphrag.logger.base import ProgressLogger -from graphrag.logger.null_progress import NullProgressLogger -from graphrag.logger.print_progress import PrintProgressLogger -from graphrag.logger.rich_progress import RichProgressLogger -from graphrag.logger.types import LoggerType - - -class LoggerFactory: - """A factory class for loggers.""" - - logger_types: ClassVar[dict[str, type]] = {} - - @classmethod - def register(cls, logger_type: str, logger: type): - """Register a custom logger implementation.""" - cls.logger_types[logger_type] = logger - - @classmethod - def create_logger( - cls, logger_type: LoggerType | str, kwargs: dict | None = None - ) -> ProgressLogger: - """Create a logger based on the provided type.""" - if kwargs is None: - kwargs = {} - match logger_type: - case LoggerType.RICH: - return RichProgressLogger("GraphRAG Indexer ") - case LoggerType.PRINT: - return PrintProgressLogger("GraphRAG Indexer ") - case LoggerType.NONE: - return NullProgressLogger() - case _: - if logger_type in cls.logger_types: - return cls.logger_types[logger_type](**kwargs) - # default to null logger if no other logger is found - return NullProgressLogger() diff --git a/graphrag/logger/null_progress.py b/graphrag/logger/null_progress.py deleted file mode 100644 index ee4fef096d..0000000000 --- a/graphrag/logger/null_progress.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Null Progress Reporter.""" - -from graphrag.logger.base import Progress, ProgressLogger - - -class NullProgressLogger(ProgressLogger): - """A progress logger that does nothing.""" - - def __call__(self, update: Progress) -> None: - """Update progress.""" - - def dispose(self) -> None: - """Dispose of the progress logger.""" - - def child(self, prefix: str, transient: bool = True) -> ProgressLogger: - """Create a child progress bar.""" - return self - - def force_refresh(self) -> None: - """Force a refresh.""" - - def stop(self) -> None: - """Stop the progress logger.""" - - def error(self, message: str) -> None: - """Log an error.""" - - def warning(self, message: str) -> None: - """Log a warning.""" - - def info(self, message: str) -> None: - """Log information.""" - - def success(self, message: str) -> None: - """Log success.""" diff --git a/graphrag/logger/print_progress.py b/graphrag/logger/print_progress.py deleted file mode 100644 index 39514c0c19..0000000000 --- a/graphrag/logger/print_progress.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Print Progress Logger.""" - -from graphrag.logger.base import Progress, ProgressLogger - - -class PrintProgressLogger(ProgressLogger): - """A progress logger that prints progress to stdout.""" - - prefix: str - - def __init__(self, prefix: str): - """Create a new progress logger.""" - self.prefix = prefix - print(f"\n{self.prefix}", end="") # noqa T201 - - def __call__(self, update: Progress) -> None: - """Update progress.""" - print(".", end="") # noqa T201 - - def dispose(self) -> None: - """Dispose of the progress logger.""" - - def child(self, prefix: str, transient: bool = True) -> ProgressLogger: - """Create a child progress bar.""" - return PrintProgressLogger(prefix) - - def stop(self) -> None: - """Stop the progress logger.""" - - def force_refresh(self) -> None: - """Force a refresh.""" - - def error(self, message: str) -> None: - """Log an error.""" - print(f"\n{self.prefix}ERROR: {message}") # noqa T201 - - def warning(self, message: str) -> None: - """Log a warning.""" - print(f"\n{self.prefix}WARNING: {message}") # noqa T201 - - def info(self, message: str) -> None: - """Log information.""" - print(f"\n{self.prefix}INFO: {message}") # noqa T201 - - def success(self, message: str) -> None: - """Log success.""" - print(f"\n{self.prefix}SUCCESS: {message}") # noqa T201 diff --git a/graphrag/logger/progress.py b/graphrag/logger/progress.py index 536786100b..e96f93555e 100644 --- a/graphrag/logger/progress.py +++ b/graphrag/logger/progress.py @@ -1,13 +1,15 @@ # Copyright (c) 2024 Microsoft Corporation. # Licensed under the MIT License -"""Progress reporting types.""" +"""Progress Logging Utilities.""" +import logging from collections.abc import Callable, Iterable from dataclasses import dataclass from typing import TypeVar T = TypeVar("T") +logger = logging.getLogger(__name__) @dataclass @@ -24,7 +26,7 @@ class Progress: """Total number of items""" completed_items: int | None = None - """Number of items completed""" "" + """Number of items completed""" ProgressHandler = Callable[[Progress], None] @@ -35,11 +37,15 @@ class ProgressTicker: """A class that emits progress reports incrementally.""" _callback: ProgressHandler | None + _description: str _num_total: int _num_complete: int - def __init__(self, callback: ProgressHandler | None, num_total: int): + def __init__( + self, callback: ProgressHandler | None, num_total: int, description: str = "" + ): self._callback = callback + self._description = description self._num_total = num_total self._num_complete = 0 @@ -47,35 +53,47 @@ def __call__(self, num_ticks: int = 1) -> None: """Emit progress.""" self._num_complete += num_ticks if self._callback is not None: - self._callback( - Progress( - total_items=self._num_total, completed_items=self._num_complete - ) + p = Progress( + total_items=self._num_total, + completed_items=self._num_complete, + description=self._description, ) + if p.description: + logger.info( + "%s%s/%s", p.description, str(p.completed_items), str(p.total_items) + ) + self._callback(p) def done(self) -> None: """Mark the progress as done.""" if self._callback is not None: self._callback( - Progress(total_items=self._num_total, completed_items=self._num_total) + Progress( + total_items=self._num_total, + completed_items=self._num_total, + description=self._description, + ) ) -def progress_ticker(callback: ProgressHandler | None, num_total: int) -> ProgressTicker: +def progress_ticker( + callback: ProgressHandler | None, num_total: int, description: str = "" +) -> ProgressTicker: """Create a progress ticker.""" - return ProgressTicker(callback, num_total) + return ProgressTicker(callback, num_total, description=description) def progress_iterable( iterable: Iterable[T], progress: ProgressHandler | None, num_total: int | None = None, + description: str = "", ) -> Iterable[T]: """Wrap an iterable with a progress handler. Every time an item is yielded, the progress handler will be called with the current progress.""" if num_total is None: num_total = len(list(iterable)) - tick = ProgressTicker(progress, num_total) + tick = ProgressTicker(progress, num_total, description=description) for item in iterable: tick(1) diff --git a/graphrag/logger/rich_progress.py b/graphrag/logger/rich_progress.py deleted file mode 100644 index 818697a4f2..0000000000 --- a/graphrag/logger/rich_progress.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Rich-based progress logger for CLI use.""" - -# Print iterations progress -import asyncio - -from rich.console import Console, Group -from rich.live import Live -from rich.progress import Progress, TaskID, TimeElapsedColumn -from rich.spinner import Spinner -from rich.tree import Tree - -from graphrag.logger.base import ProgressLogger -from graphrag.logger.progress import Progress as GRProgress - - -# https://stackoverflow.com/a/34325723 -class RichProgressLogger(ProgressLogger): - """A rich-based progress logger for CLI use.""" - - _console: Console - _group: Group - _tree: Tree - _live: Live - _task: TaskID | None = None - _prefix: str - _transient: bool - _disposing: bool = False - _progressbar: Progress - _last_refresh: float = 0 - - def dispose(self) -> None: - """Dispose of the progress logger.""" - self._disposing = True - self._live.stop() - - @property - def console(self) -> Console: - """Get the console.""" - return self._console - - @property - def group(self) -> Group: - """Get the group.""" - return self._group - - @property - def tree(self) -> Tree: - """Get the tree.""" - return self._tree - - @property - def live(self) -> Live: - """Get the live.""" - return self._live - - def __init__( - self, - prefix: str, - parent: "RichProgressLogger | None" = None, - transient: bool = True, - ) -> None: - """Create a new rich-based progress logger.""" - self._prefix = prefix - - if parent is None: - console = Console() - group = Group(Spinner("dots", prefix), fit=True) - tree = Tree(group) - live = Live( - tree, console=console, refresh_per_second=1, vertical_overflow="crop" - ) - live.start() - - self._console = console - self._group = group - self._tree = tree - self._live = live - self._transient = False - else: - self._console = parent.console - self._group = parent.group - progress_columns = [*Progress.get_default_columns(), TimeElapsedColumn()] - self._progressbar = Progress( - *progress_columns, console=self._console, transient=transient - ) - - tree = Tree(prefix) - tree.add(self._progressbar) - tree.hide_root = True - - if parent is not None: - parent_tree = parent.tree - parent_tree.hide_root = False - parent_tree.add(tree) - - self._tree = tree - self._live = parent.live - self._transient = transient - - self.refresh() - - def refresh(self) -> None: - """Perform a debounced refresh.""" - now = asyncio.get_event_loop().time() - duration = now - self._last_refresh - if duration > 0.1: - self._last_refresh = now - self.force_refresh() - - def force_refresh(self) -> None: - """Force a refresh.""" - self.live.refresh() - - def stop(self) -> None: - """Stop the progress logger.""" - self._live.stop() - - def child(self, prefix: str, transient: bool = True) -> ProgressLogger: - """Create a child progress bar.""" - return RichProgressLogger(parent=self, prefix=prefix, transient=transient) - - def error(self, message: str) -> None: - """Log an error.""" - self._console.print(f"❌ [red]{message}[/red]") - - def warning(self, message: str) -> None: - """Log a warning.""" - self._console.print(f"⚠️ [yellow]{message}[/yellow]") - - def success(self, message: str) -> None: - """Log success.""" - self._console.print(f"🚀 [green]{message}[/green]") - - def info(self, message: str) -> None: - """Log information.""" - self._console.print(message) - - def __call__(self, progress_update: GRProgress) -> None: - """Update progress.""" - if self._disposing: - return - progressbar = self._progressbar - - if self._task is None: - self._task = progressbar.add_task(self._prefix) - - progress_description = "" - if progress_update.description is not None: - progress_description = f" - {progress_update.description}" - - completed = progress_update.completed_items or progress_update.percent - total = progress_update.total_items or 1 - progressbar.update( - self._task, - completed=completed, - total=total, - description=f"{self._prefix}{progress_description}", - ) - if completed == total and self._transient: - progressbar.update(self._task, visible=False) - - self.refresh() diff --git a/graphrag/logger/standard_logging.py b/graphrag/logger/standard_logging.py new file mode 100644 index 0000000000..3f6cc22405 --- /dev/null +++ b/graphrag/logger/standard_logging.py @@ -0,0 +1,153 @@ +# Copyright (c) 2024 Microsoft Corporation. +# Licensed under the MIT License + +"""Standard logging configuration for the graphrag package. + +This module provides a standardized way to configure Python's built-in +logging system for use within the graphrag package. + +Usage: + # Configuration should be done once at the start of your application: + from graphrag.logger.standard_logging import init_loggers + init_loggers(log_file="/path/to/app.log") + + # Then throughout your code: + import logging + logger = logging.getLogger(__name__) # Use standard logging + + # Use standard logging methods: + logger.debug("Debug message") + logger.info("Info message") + logger.warning("Warning message") + logger.error("Error message") + logger.critical("Critical error message") + +Notes +----- + The logging system is hierarchical. Loggers are organized in a tree structure, + with the root logger named 'graphrag'. All loggers created with names starting + with 'graphrag.' will be children of this root logger. This allows for consistent + configuration of all graphrag-related logs throughout the application. + + All progress logging now uses this standard logging system for consistency. +""" + +import logging +import sys +from pathlib import Path + +from graphrag.config.enums import ReportingType +from graphrag.config.models.graph_rag_config import GraphRagConfig +from graphrag.config.models.reporting_config import ReportingConfig + +LOG_FORMAT = "%(asctime)s.%(msecs)04d - %(levelname)s - %(name)s - %(message)s" +DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + + +def init_loggers( + config: GraphRagConfig | None = None, + root_dir: str | None = None, + verbose: bool = False, + log_file: str | Path | None = None, +) -> None: + """Initialize logging handlers for graphrag based on configuration. + + This function merges the functionality of configure_logging() and create_pipeline_logger() + to provide a unified way to set up logging for the graphrag package. + + Parameters + ---------- + config : GraphRagConfig | None, default=None + The GraphRAG configuration. If None, defaults to file-based reporting. + root_dir : str | None, default=None + The root directory for file-based logging. + verbose : bool, default=False + Whether to enable verbose (DEBUG) logging. + log_file : Optional[Union[str, Path]], default=None + Path to a specific log file. If provided, takes precedence over config. + """ + # import BlobWorkflowLogger here to avoid circular imports + from graphrag.logger.blob_workflow_logger import BlobWorkflowLogger + + # extract reporting config from GraphRagConfig if provided + reporting_config: ReportingConfig + if log_file: + # if log_file is provided directly, override config to use file-based logging + log_path = Path(log_file) + reporting_config = ReportingConfig( + type=ReportingType.file, + base_dir=str(log_path.parent), + ) + elif config is not None: + # use the reporting configuration from GraphRagConfig + reporting_config = config.reporting + else: + # default to file-based logging if no config provided + reporting_config = ReportingConfig(base_dir="logs", type=ReportingType.file) + + logger = logging.getLogger("graphrag") + log_level = logging.DEBUG if verbose else logging.INFO + logger.setLevel(log_level) + + # clear any existing handlers to avoid duplicate logs + if logger.hasHandlers(): + # Close file handlers properly before removing them + for handler in logger.handlers: + if isinstance(handler, logging.FileHandler): + handler.close() + logger.handlers.clear() + + # create formatter with custom format + formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt=DATE_FORMAT) + + init_console_logger(verbose) + + # add more handlers based on configuration + handler: logging.Handler + match reporting_config.type: + case ReportingType.file: + if log_file: + # use the specific log file provided + log_file_path = Path(log_file) + log_file_path.parent.mkdir(parents=True, exist_ok=True) + handler = logging.FileHandler(str(log_file_path), mode="a") + else: + # use the config-based file path + log_dir = Path(root_dir or "") / (reporting_config.base_dir or "") + log_dir.mkdir(parents=True, exist_ok=True) + log_file_path = log_dir / "logs.txt" + handler = logging.FileHandler(str(log_file_path), mode="a") + handler.setFormatter(formatter) + logger.addHandler(handler) + case ReportingType.blob: + handler = BlobWorkflowLogger( + reporting_config.connection_string, + reporting_config.container_name, + base_dir=reporting_config.base_dir, + storage_account_blob_url=reporting_config.storage_account_blob_url, + ) + logger.addHandler(handler) + case _: + logger.error("Unknown reporting type '%s'.", reporting_config.type) + + +def init_console_logger(verbose: bool = False) -> None: + """Initialize a console logger if not already present. + + This function sets up a logger that outputs log messages to STDOUT. + + Parameters + ---------- + verbose : bool, default=False + Whether to enable verbose (DEBUG) logging. + """ + logger = logging.getLogger("graphrag") + logger.setLevel(logging.DEBUG if verbose else logging.INFO) + has_console_handler = any( + isinstance(h, logging.StreamHandler) for h in logger.handlers + ) + if not has_console_handler: + console_handler = logging.StreamHandler(sys.stdout) + formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt=DATE_FORMAT) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) diff --git a/graphrag/logger/types.py b/graphrag/logger/types.py deleted file mode 100644 index 928211b972..0000000000 --- a/graphrag/logger/types.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2024 Microsoft Corporation. -# Licensed under the MIT License - -"""Logging types. - -This module defines the types of loggers that can be used. -""" - -from enum import Enum - - -# Note: Code in this module was not included in the factory module because it negatively impacts the CLI experience. -class LoggerType(str, Enum): - """The type of logger to use.""" - - RICH = "rich" - PRINT = "print" - NONE = "none" - - def __str__(self): - """Return a string representation of the enum value.""" - return self.value diff --git a/graphrag/prompt_tune/loader/input.py b/graphrag/prompt_tune/loader/input.py index 71f802d060..29010b05a8 100644 --- a/graphrag/prompt_tune/loader/input.py +++ b/graphrag/prompt_tune/loader/input.py @@ -3,6 +3,8 @@ """Input loading module.""" +import logging + import numpy as np import pandas as pd @@ -14,7 +16,6 @@ run as run_embed_text, ) from graphrag.index.workflows.create_base_text_units import create_base_text_units -from graphrag.logger.base import ProgressLogger from graphrag.prompt_tune.defaults import ( LIMIT, N_SUBSET_MAX, @@ -41,7 +42,7 @@ async def load_docs_in_chunks( config: GraphRagConfig, select_method: DocSelectionType, limit: int, - logger: ProgressLogger, + logger: logging.Logger, chunk_size: int, overlap: int, n_subset_max: int = N_SUBSET_MAX, @@ -52,7 +53,7 @@ async def load_docs_in_chunks( config.embed_text.model_id ) input_storage = create_storage_from_config(config.input.storage) - dataset = await create_input(config.input, input_storage, logger) + dataset = await create_input(config.input, input_storage) chunk_config = config.chunks chunks_df = create_base_text_units( documents=dataset, diff --git a/graphrag/query/context_builder/community_context.py b/graphrag/query/context_builder/community_context.py index ba506a0a9a..b527bd019b 100644 --- a/graphrag/query/context_builder/community_context.py +++ b/graphrag/query/context_builder/community_context.py @@ -14,7 +14,7 @@ from graphrag.data_model.entity import Entity from graphrag.query.llm.text_utils import num_tokens -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) NO_COMMUNITY_RECORDS_WARNING: str = ( "Warning: No community records added when building community context." @@ -88,7 +88,7 @@ def _report_context_text( ) ) if compute_community_weights: - log.info("Computing community weights...") + logger.debug("Computing community weights...") community_reports = _compute_community_weights( community_reports=community_reports, entities=entities, @@ -177,7 +177,7 @@ def _cut_batch() -> None: _cut_batch() if len(all_context_records) == 0: - log.warning(NO_COMMUNITY_RECORDS_WARNING) + logger.warning(NO_COMMUNITY_RECORDS_WARNING) return ([], {}) return all_context_text, { diff --git a/graphrag/query/context_builder/dynamic_community_selection.py b/graphrag/query/context_builder/dynamic_community_selection.py index 80fc562ae1..2763c64760 100644 --- a/graphrag/query/context_builder/dynamic_community_selection.py +++ b/graphrag/query/context_builder/dynamic_community_selection.py @@ -18,7 +18,7 @@ from graphrag.query.context_builder.rate_prompt import RATE_QUERY from graphrag.query.context_builder.rate_relevancy import rate_relevancy -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class DynamicCommunitySelection: @@ -109,7 +109,7 @@ async def select(self, query: str) -> tuple[list[CommunityReport], dict[str, Any communities_to_rate = [] for community, result in zip(queue, gather_results, strict=True): rating = result["rating"] - log.debug( + logger.debug( "dynamic community selection: community %s rating %s", community, rating, @@ -127,7 +127,7 @@ async def select(self, query: str) -> tuple[list[CommunityReport], dict[str, Any if child in self.reports: communities_to_rate.append(child) else: - log.debug( + logger.debug( "dynamic community selection: cannot find community %s in reports", child, ) @@ -142,7 +142,7 @@ async def select(self, query: str) -> tuple[list[CommunityReport], dict[str, Any and (str(level) in self.levels) and (level <= self.max_level) ): - log.info( + logger.debug( "dynamic community selection: no relevant community " "reports, adding all reports at level %s to rate.", level, @@ -155,7 +155,7 @@ async def select(self, query: str) -> tuple[list[CommunityReport], dict[str, Any ] end = time() - log.info( + logger.debug( "dynamic community selection (took: %ss)\n" "\trating distribution %s\n" "\t%s out of %s community reports are relevant\n" diff --git a/graphrag/query/context_builder/rate_relevancy.py b/graphrag/query/context_builder/rate_relevancy.py index b9d494f2a4..2e03559b8c 100644 --- a/graphrag/query/context_builder/rate_relevancy.py +++ b/graphrag/query/context_builder/rate_relevancy.py @@ -15,7 +15,7 @@ from graphrag.query.context_builder.rate_prompt import RATE_QUERY from graphrag.query.llm.text_utils import num_tokens, try_parse_json_object -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def rate_relevancy( @@ -60,7 +60,7 @@ async def rate_relevancy( except KeyError: # in case of json parsing error, default to rating 1 so the report is kept. # json parsing error should rarely happen. - log.info("Error parsing json response, defaulting to rating 1") + logger.warning("Error parsing json response, defaulting to rating 1") ratings.append(1) llm_calls += 1 prompt_tokens += num_tokens(messages[0]["content"], token_encoder) diff --git a/graphrag/query/indexer_adapters.py b/graphrag/query/indexer_adapters.py index b58ea36733..0c6e54a8af 100644 --- a/graphrag/query/indexer_adapters.py +++ b/graphrag/query/indexer_adapters.py @@ -30,7 +30,7 @@ ) from graphrag.vector_stores.base import BaseVectorStore -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def read_indexer_text_units(final_text_units: pd.DataFrame) -> list[TextUnit]: @@ -195,7 +195,7 @@ def read_indexer_communities( ~communities_df.community.isin(reports_df.community.unique()) ].community.to_list() if len(missing_reports): - log.warning("Missing reports for communities: %s", missing_reports) + logger.warning("Missing reports for communities: %s", missing_reports) communities_df = communities_df.loc[ communities_df.community.isin(reports_df.community.unique()) ] diff --git a/graphrag/query/llm/text_utils.py b/graphrag/query/llm/text_utils.py index 3266e9993a..8fbef6be44 100644 --- a/graphrag/query/llm/text_utils.py +++ b/graphrag/query/llm/text_utils.py @@ -14,7 +14,7 @@ import graphrag.config.defaults as defs -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) def num_tokens(text: str, token_encoder: tiktoken.Encoding | None = None) -> int: @@ -60,7 +60,7 @@ def try_parse_json_object(input: str, verbose: bool = True) -> tuple[str, dict]: result = json.loads(input) except json.JSONDecodeError: if verbose: - log.info("Warning: Error decoding faulty json, attempting repair") + logger.warning("Error decoding faulty json, attempting repair") if result: return input, result @@ -99,12 +99,12 @@ def try_parse_json_object(input: str, verbose: bool = True) -> tuple[str, dict]: result = json.loads(input) except json.JSONDecodeError: if verbose: - log.exception("error loading json, json=%s", input) + logger.exception("error loading json, json=%s", input) return input, {} else: if not isinstance(result, dict): if verbose: - log.exception("not expected dict type. type=%s:", type(result)) + logger.exception("not expected dict type. type=%s:", type(result)) return input, {} return input, result else: diff --git a/graphrag/query/question_gen/local_gen.py b/graphrag/query/question_gen/local_gen.py index 04ea517899..a5f2ef3aba 100644 --- a/graphrag/query/question_gen/local_gen.py +++ b/graphrag/query/question_gen/local_gen.py @@ -22,7 +22,7 @@ from graphrag.query.llm.text_utils import num_tokens from graphrag.query.question_gen.base import BaseQuestionGen, QuestionResult -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class LocalQuestionGen(BaseQuestionGen): @@ -88,7 +88,9 @@ async def agenerate( context_records = result.context_records else: context_records = {"context_data": context_data} - log.info("GENERATE QUESTION: %s. LAST QUESTION: %s", start_time, question_text) + logger.debug( + "GENERATE QUESTION: %s. LAST QUESTION: %s", start_time, question_text + ) system_prompt = "" try: system_prompt = self.system_prompt.format( @@ -120,7 +122,7 @@ async def agenerate( ) except Exception: - log.exception("Exception in generating question") + logger.exception("Exception in generating question") return QuestionResult( response=[], context_data=context_records, @@ -168,7 +170,7 @@ async def generate( context_records = result.context_records else: context_records = {"context_data": context_data} - log.info( + logger.debug( "GENERATE QUESTION: %s. QUESTION HISTORY: %s", start_time, question_text ) system_prompt = "" @@ -203,7 +205,7 @@ async def generate( ) except Exception: - log.exception("Exception in generating questions") + logger.exception("Exception in generating questions") return QuestionResult( response=[], context_data=context_records, diff --git a/graphrag/query/structured_search/basic_search/basic_context.py b/graphrag/query/structured_search/basic_search/basic_context.py index d08bdc2e73..cf15256e33 100644 --- a/graphrag/query/structured_search/basic_search/basic_context.py +++ b/graphrag/query/structured_search/basic_search/basic_context.py @@ -19,7 +19,7 @@ from graphrag.query.llm.text_utils import num_tokens from graphrag.vector_stores.base import BaseVectorStore -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class BasicSearchContext(BasicContextBuilder): @@ -84,7 +84,7 @@ def build_context( tokens = num_tokens(text, self.token_encoder) if current_tokens + tokens > max_context_tokens: msg = f"Reached token limit: {current_tokens + tokens}. Reverting to previous context state" - log.info(msg) + logger.warning(msg) break current_tokens += tokens diff --git a/graphrag/query/structured_search/basic_search/search.py b/graphrag/query/structured_search/basic_search/search.py index a5dca578d3..644e66ea02 100644 --- a/graphrag/query/structured_search/basic_search/search.py +++ b/graphrag/query/structured_search/basic_search/search.py @@ -20,7 +20,7 @@ from graphrag.query.llm.text_utils import num_tokens from graphrag.query.structured_search.base import BaseSearch, SearchResult -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) """ Implementation of a generic RAG algorithm (vector search on raw text chunks) """ @@ -73,7 +73,7 @@ async def search( prompt_tokens["build_context"] = context_result.prompt_tokens output_tokens["build_context"] = context_result.output_tokens - log.info("GENERATE ANSWER: %s. QUERY: %s", start_time, query) + logger.debug("GENERATE ANSWER: %s. QUERY: %s", start_time, query) try: search_prompt = self.system_prompt.format( context_data=context_result.context_chunks, @@ -114,7 +114,7 @@ async def search( ) except Exception: - log.exception("Exception in _asearch") + logger.exception("Exception in _asearch") return SearchResult( response="", context_data=context_result.context_records, @@ -141,7 +141,7 @@ async def stream_search( conversation_history=conversation_history, **self.context_builder_params, ) - log.info("GENERATE ANSWER: %s. QUERY: %s", start_time, query) + logger.debug("GENERATE ANSWER: %s. QUERY: %s", start_time, query) search_prompt = self.system_prompt.format( context_data=context_result.context_chunks, response_type=self.response_type ) diff --git a/graphrag/query/structured_search/drift_search/action.py b/graphrag/query/structured_search/drift_search/action.py index 7254eb33d0..8f1da3d721 100644 --- a/graphrag/query/structured_search/drift_search/action.py +++ b/graphrag/query/structured_search/drift_search/action.py @@ -9,7 +9,7 @@ from graphrag.query.llm.text_utils import try_parse_json_object -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class DriftAction: @@ -67,7 +67,7 @@ async def search(self, search_engine: Any, global_query: str, scorer: Any = None Updated action with search results. """ if self.is_complete: - log.warning("Action already complete. Skipping search.") + logger.warning("Action already complete. Skipping search.") return self search_result = await search_engine.search( @@ -83,7 +83,7 @@ async def search(self, search_engine: Any, global_query: str, scorer: Any = None self.metadata.update({"context_data": search_result.context_data}) if self.answer is None: - log.warning("No answer found for query: %s", self.query) + logger.warning("No answer found for query: %s", self.query) self.metadata["llm_calls"] += 1 self.metadata["prompt_tokens"] += search_result.prompt_tokens @@ -91,7 +91,7 @@ async def search(self, search_engine: Any, global_query: str, scorer: Any = None self.follow_ups = response.pop("follow_up_queries", []) if not self.follow_ups: - log.warning("No follow-up actions found for response: %s", response) + logger.warning("No follow-up actions found for response: %s", response) if scorer: self.compute_score(scorer) diff --git a/graphrag/query/structured_search/drift_search/drift_context.py b/graphrag/query/structured_search/drift_search/drift_context.py index 1013b995b9..cdda862e3d 100644 --- a/graphrag/query/structured_search/drift_search/drift_context.py +++ b/graphrag/query/structured_search/drift_search/drift_context.py @@ -30,7 +30,7 @@ ) from graphrag.vector_stores.base import BaseVectorStore -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class DRIFTSearchContextBuilder(DRIFTContextBuilder): diff --git a/graphrag/query/structured_search/drift_search/primer.py b/graphrag/query/structured_search/drift_search/primer.py index 66d86be88b..58dc148ace 100644 --- a/graphrag/query/structured_search/drift_search/primer.py +++ b/graphrag/query/structured_search/drift_search/primer.py @@ -22,7 +22,7 @@ from graphrag.query.llm.text_utils import num_tokens from graphrag.query.structured_search.base import SearchResult -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class PrimerQueryProcessor: @@ -78,7 +78,7 @@ async def expand_query(self, query: str) -> tuple[str, dict[str, int]]: "output_tokens": output_tokens, } if text == "": - log.warning("Failed to generate expansion for query: %s", query) + logger.warning("Failed to generate expansion for query: %s", query) return query, token_ct return text, token_ct @@ -94,7 +94,7 @@ async def __call__(self, query: str) -> tuple[list[float], dict[str, int]]: tuple[list[float], int]: List of embeddings for the expanded query and the token count. """ hyde_query, token_ct = await self.expand_query(query) - log.info("Expanded query: %s", hyde_query) + logger.debug("Expanded query: %s", hyde_query) return self.text_embedder.embed(hyde_query), token_ct diff --git a/graphrag/query/structured_search/drift_search/search.py b/graphrag/query/structured_search/drift_search/search.py index a452cf1d19..98b6bce75d 100644 --- a/graphrag/query/structured_search/drift_search/search.py +++ b/graphrag/query/structured_search/drift_search/search.py @@ -28,7 +28,7 @@ from graphrag.query.structured_search.drift_search.state import QueryState from graphrag.query.structured_search.local_search.search import LocalSearch -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class DRIFTSearch(BaseSearch[DRIFTSearchContextBuilder]): @@ -233,7 +233,7 @@ async def search( while epochs < self.context_builder.config.n_depth: actions = self.query_state.rank_incomplete_actions() if len(actions) == 0: - log.info("No more actions to take. Exiting DRIFT loop.") + logger.debug("No more actions to take. Exiting DRIFT loop.") break actions = actions[: self.context_builder.config.drift_k_followups] llm_call_offset += ( diff --git a/graphrag/query/structured_search/drift_search/state.py b/graphrag/query/structured_search/drift_search/state.py index c454158f1b..82453b3a4e 100644 --- a/graphrag/query/structured_search/drift_search/state.py +++ b/graphrag/query/structured_search/drift_search/state.py @@ -12,7 +12,7 @@ from graphrag.query.structured_search.drift_search.action import DriftAction -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class QueryState: @@ -39,13 +39,13 @@ def add_all_follow_ups( ): """Add all follow-up actions and links them to the given action.""" if len(follow_ups) == 0: - log.warning("No follow-up actions for action: %s", action.query) + logger.warning("No follow-up actions for action: %s", action.query) for follow_up in follow_ups: if isinstance(follow_up, str): follow_up = DriftAction(query=follow_up) elif not isinstance(follow_up, DriftAction): - log.warning( + logger.warning( "Follow-up action is not a string, found type: %s", type(follow_up) ) diff --git a/graphrag/query/structured_search/global_search/search.py b/graphrag/query/structured_search/global_search/search.py index daa7f55cf7..960fd0a50a 100644 --- a/graphrag/query/structured_search/global_search/search.py +++ b/graphrag/query/structured_search/global_search/search.py @@ -33,7 +33,7 @@ from graphrag.query.llm.text_utils import num_tokens, try_parse_json_object from graphrag.query.structured_search.base import BaseSearch, SearchResult -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) @dataclass(kw_only=True) @@ -231,12 +231,12 @@ async def _map_response_single_batch( json=True, ) search_response = model_response.output.content - log.info("Map response: %s", search_response) + logger.debug("Map response: %s", search_response) try: # parse search response json processed_response = self._parse_search_response(search_response) except ValueError: - log.warning( + logger.warning( "Warning: Error parsing search response json - skipping this batch" ) processed_response = [] @@ -252,7 +252,7 @@ async def _map_response_single_batch( ) except Exception: - log.exception("Exception in _map_response_single_batch") + logger.exception("Exception in _map_response_single_batch") return SearchResult( response=[{"answer": "", "score": 0}], context_data=context_data, @@ -329,7 +329,7 @@ async def _reduce_response( if len(filtered_key_points) == 0 and not self.allow_general_knowledge: # return no data answer if no key points are found - log.warning( + logger.warning( "Warning: All map responses have score 0 (i.e., no relevant information found from the dataset), returning a canned 'I do not know' answer. You can try enabling `allow_general_knowledge` to encourage the LLM to incorporate relevant general knowledge, at the risk of increasing hallucinations." ) return SearchResult( @@ -402,7 +402,7 @@ async def _reduce_response( output_tokens=num_tokens(search_response, self.token_encoder), ) except Exception: - log.exception("Exception in reduce_response") + logger.exception("Exception in reduce_response") return SearchResult( response="", context_data=text_data, @@ -445,7 +445,7 @@ async def _stream_reduce_response( if len(filtered_key_points) == 0 and not self.allow_general_knowledge: # return no data answer if no key points are found - log.warning( + logger.warning( "Warning: All map responses have score 0 (i.e., no relevant information found from the dataset), returning a canned 'I do not know' answer. You can try enabling `allow_general_knowledge` to encourage the LLM to incorporate relevant general knowledge, at the risk of increasing hallucinations." ) yield NO_DATA_ANSWER diff --git a/graphrag/query/structured_search/local_search/mixed_context.py b/graphrag/query/structured_search/local_search/mixed_context.py index 8883d009e7..fd9d495903 100644 --- a/graphrag/query/structured_search/local_search/mixed_context.py +++ b/graphrag/query/structured_search/local_search/mixed_context.py @@ -44,7 +44,7 @@ from graphrag.query.structured_search.base import LocalContextBuilder from graphrag.vector_stores.base import BaseVectorStore -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class LocalSearchMixedContext(LocalContextBuilder): @@ -446,7 +446,9 @@ def _build_local_context( current_context_data[covariate.lower()] = covariate_context_data if total_tokens > max_context_tokens: - log.info("Reached token limit - reverting to previous context state") + logger.warning( + "Reached token limit - reverting to previous context state" + ) break final_context = current_context diff --git a/graphrag/query/structured_search/local_search/search.py b/graphrag/query/structured_search/local_search/search.py index 3a02caaf44..8ff9013125 100644 --- a/graphrag/query/structured_search/local_search/search.py +++ b/graphrag/query/structured_search/local_search/search.py @@ -22,7 +22,7 @@ from graphrag.query.llm.text_utils import num_tokens from graphrag.query.structured_search.base import BaseSearch, SearchResult -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class LocalSearch(BaseSearch[LocalContextBuilder]): @@ -70,7 +70,7 @@ async def search( prompt_tokens["build_context"] = context_result.prompt_tokens output_tokens["build_context"] = context_result.output_tokens - log.info("GENERATE ANSWER: %s. QUERY: %s", start_time, query) + logger.debug("GENERATE ANSWER: %s. QUERY: %s", start_time, query) try: if "drift_query" in kwargs: drift_query = kwargs["drift_query"] @@ -120,7 +120,7 @@ async def search( ) except Exception: - log.exception("Exception in _asearch") + logger.exception("Exception in _asearch") return SearchResult( response="", context_data=context_result.context_records, @@ -144,7 +144,7 @@ async def stream_search( conversation_history=conversation_history, **self.context_builder_params, ) - log.info("GENERATE ANSWER: %s. QUERY: %s", start_time, query) + logger.debug("GENERATE ANSWER: %s. QUERY: %s", start_time, query) search_prompt = self.system_prompt.format( context_data=context_result.context_chunks, response_type=self.response_type ) diff --git a/graphrag/storage/blob_pipeline_storage.py b/graphrag/storage/blob_pipeline_storage.py index 04b971ca70..c6463b9e2a 100644 --- a/graphrag/storage/blob_pipeline_storage.py +++ b/graphrag/storage/blob_pipeline_storage.py @@ -12,14 +12,12 @@ from azure.identity import DefaultAzureCredential from azure.storage.blob import BlobServiceClient -from graphrag.logger.base import ProgressLogger -from graphrag.logger.progress import Progress from graphrag.storage.pipeline_storage import ( PipelineStorage, get_timestamp_formatted_with_local_tz, ) -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class BlobPipelineStorage(PipelineStorage): @@ -63,7 +61,7 @@ def __init__( if storage_account_blob_url else None ) - log.info( + logger.info( "creating blob storage at container=%s, path=%s", self._container_name, self._path_prefix, @@ -98,7 +96,6 @@ def find( self, file_pattern: re.Pattern[str], base_dir: str | None = None, - progress: ProgressLogger | None = None, file_filter: dict[str, Any] | None = None, max_count=-1, ) -> Iterator[tuple[str, dict[str, Any]]]: @@ -116,7 +113,7 @@ def find( """ base_dir = base_dir or "" - log.info( + logger.info( "search container %s for files matching %s", self._container_name, file_pattern.pattern, @@ -159,12 +156,14 @@ def item_filter(item: dict[str, Any]) -> bool: num_filtered += 1 else: num_filtered += 1 - if progress is not None: - progress( - _create_progress_status(num_loaded, num_filtered, num_total) - ) + logger.debug( + "Blobs loaded: %d, filtered: %d, total: %d", + num_loaded, + num_filtered, + num_total, + ) except Exception: - log.exception( + logger.exception( "Error finding blobs: base_dir=%s, file_pattern=%s, file_filter=%s", base_dir, file_pattern, @@ -187,7 +186,7 @@ async def get( coding = encoding or self._encoding blob_data = blob_data.decode(coding) except Exception: - log.exception("Error getting key %s", key) + logger.exception("Error getting key %s", key) return None else: return blob_data @@ -206,7 +205,7 @@ async def set(self, key: str, value: Any, encoding: str | None = None) -> None: coding = encoding or self._encoding blob_client.upload_blob(value.encode(coding), overwrite=True) except Exception: - log.exception("Error setting key %s: %s", key) + logger.exception("Error setting key %s: %s", key) def _set_df_json(self, key: str, dataframe: Any) -> None: """Set a json dataframe.""" @@ -305,7 +304,7 @@ async def get_creation_date(self, key: str) -> str: timestamp = blob_client.download_blob().properties.creation_time return get_timestamp_formatted_with_local_tz(timestamp) except Exception: - log.exception("Error getting key %s", key) + logger.exception("Error getting key %s", key) return "" @@ -315,7 +314,7 @@ def create_blob_storage(**kwargs: Any) -> PipelineStorage: storage_account_blob_url = kwargs.get("storage_account_blob_url") base_dir = kwargs.get("base_dir") container_name = kwargs["container_name"] - log.info("Creating blob storage at %s", container_name) + logger.info("Creating blob storage at %s", container_name) if container_name is None: msg = "No container name provided for blob storage." raise ValueError(msg) @@ -381,13 +380,3 @@ def validate_blob_container_name(container_name: str): ) return True - - -def _create_progress_status( - num_loaded: int, num_filtered: int, num_total: int -) -> Progress: - return Progress( - total_items=num_total, - completed_items=num_loaded + num_filtered, - description=f"{num_loaded} files loaded ({num_filtered} filtered)", - ) diff --git a/graphrag/storage/cosmosdb_pipeline_storage.py b/graphrag/storage/cosmosdb_pipeline_storage.py index 63d95d17d3..f41d8ab146 100644 --- a/graphrag/storage/cosmosdb_pipeline_storage.py +++ b/graphrag/storage/cosmosdb_pipeline_storage.py @@ -17,14 +17,13 @@ from azure.cosmos.partition_key import PartitionKey from azure.identity import DefaultAzureCredential -from graphrag.logger.base import ProgressLogger from graphrag.logger.progress import Progress from graphrag.storage.pipeline_storage import ( PipelineStorage, get_timestamp_formatted_with_local_tz, ) -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class CosmosDBPipelineStorage(PipelineStorage): @@ -72,7 +71,7 @@ def __init__( else None ) self._no_id_prefixes = [] - log.info( + logger.info( "creating cosmosdb storage with account: %s and database: %s and container: %s", self._cosmosdb_account_name, self._database_name, @@ -117,7 +116,6 @@ def find( self, file_pattern: re.Pattern[str], base_dir: str | None = None, - progress: ProgressLogger | None = None, file_filter: dict[str, Any] | None = None, max_count=-1, ) -> Iterator[tuple[str, dict[str, Any]]]: @@ -134,7 +132,7 @@ def find( An iterator of document IDs and their corresponding regex matches. """ base_dir = base_dir or "" - log.info( + logger.info( "search container %s for documents matching %s", self._container_name, file_pattern.pattern, @@ -184,12 +182,18 @@ def item_filter(item: dict[str, Any]) -> bool: num_filtered += 1 else: num_filtered += 1 - if progress is not None: - progress( - _create_progress_status(num_loaded, num_filtered, num_total) - ) + + progress_status = _create_progress_status( + num_loaded, num_filtered, num_total + ) + logger.debug( + "Progress: %s (%d/%d completed)", + progress_status.description, + progress_status.completed_items, + progress_status.total_items, + ) except Exception: - log.exception( + logger.exception( "An error occurred while searching for documents in Cosmos DB." ) @@ -226,7 +230,7 @@ async def get( item_body = item.get("body") return json.dumps(item_body) except Exception: - log.exception("Error reading item %s", key) + logger.exception("Error reading item %s", key) return None async def set(self, key: str, value: Any, encoding: str | None = None) -> None: @@ -246,7 +250,7 @@ async def set(self, key: str, value: Any, encoding: str | None = None) -> None: orient="records", lines=False, force_ascii=False ) if value_json is None: - log.exception("Error converting output %s to json", key) + logger.error("Error converting output %s to json", key) else: cosmosdb_item_list = json.loads(value_json) for index, cosmosdb_item in enumerate(cosmosdb_item_list): @@ -267,7 +271,7 @@ async def set(self, key: str, value: Any, encoding: str | None = None) -> None: } self._container_client.upsert_item(body=cosmosdb_item) except Exception: - log.exception("Error writing item %s", key) + logger.exception("Error writing item %s", key) async def has(self, key: str) -> bool: """Check if the contents of the given filename key exist in the cosmosdb storage.""" @@ -306,7 +310,7 @@ async def delete(self, key: str) -> None: except CosmosResourceNotFoundError: return except Exception: - log.exception("Error deleting item %s", key) + logger.exception("Error deleting item %s", key) async def clear(self) -> None: """Clear all contents from storage. @@ -340,7 +344,7 @@ async def get_creation_date(self, key: str) -> str: ) except Exception: - log.exception("Error getting key %s", key) + logger.exception("Error getting key %s", key) return "" @@ -348,7 +352,7 @@ async def get_creation_date(self, key: str) -> str: # once the new config system is in place and will enforce the correct types/existence of certain fields def create_cosmosdb_storage(**kwargs: Any) -> PipelineStorage: """Create a CosmosDB storage instance.""" - log.info("Creating cosmosdb storage") + logger.info("Creating cosmosdb storage") cosmosdb_account_url = kwargs.get("cosmosdb_account_url") connection_string = kwargs.get("connection_string") base_dir = kwargs["base_dir"] diff --git a/graphrag/storage/file_pipeline_storage.py b/graphrag/storage/file_pipeline_storage.py index 6c6bf95c53..d1ba479495 100644 --- a/graphrag/storage/file_pipeline_storage.py +++ b/graphrag/storage/file_pipeline_storage.py @@ -16,14 +16,12 @@ from aiofiles.os import remove from aiofiles.ospath import exists -from graphrag.logger.base import ProgressLogger -from graphrag.logger.progress import Progress from graphrag.storage.pipeline_storage import ( PipelineStorage, get_timestamp_formatted_with_local_tz, ) -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) class FilePipelineStorage(PipelineStorage): @@ -42,7 +40,6 @@ def find( self, file_pattern: re.Pattern[str], base_dir: str | None = None, - progress: ProgressLogger | None = None, file_filter: dict[str, Any] | None = None, max_count=-1, ) -> Iterator[tuple[str, dict[str, Any]]]: @@ -56,7 +53,9 @@ def item_filter(item: dict[str, Any]) -> bool: ) search_path = Path(self._root_dir) / (base_dir or "") - log.info("search %s for files matching %s", search_path, file_pattern.pattern) + logger.info( + "search %s for files matching %s", search_path, file_pattern.pattern + ) all_files = list(search_path.rglob("**/*")) num_loaded = 0 num_total = len(all_files) @@ -77,8 +76,12 @@ def item_filter(item: dict[str, Any]) -> bool: num_filtered += 1 else: num_filtered += 1 - if progress is not None: - progress(_create_progress_status(num_loaded, num_filtered, num_total)) + logger.debug( + "Files loaded: %d, filtered: %d, total: %d", + num_loaded, + num_filtered, + num_total, + ) async def get( self, key: str, as_bytes: bool | None = False, encoding: str | None = None @@ -169,15 +172,5 @@ def join_path(file_path: str, file_name: str) -> Path: def create_file_storage(**kwargs: Any) -> PipelineStorage: """Create a file based storage.""" base_dir = kwargs["base_dir"] - log.info("Creating file storage at %s", base_dir) + logger.info("Creating file storage at %s", base_dir) return FilePipelineStorage(root_dir=base_dir) - - -def _create_progress_status( - num_loaded: int, num_filtered: int, num_total: int -) -> Progress: - return Progress( - total_items=num_total, - completed_items=num_loaded + num_filtered, - description=f"{num_loaded} files loaded ({num_filtered} filtered)", - ) diff --git a/graphrag/storage/pipeline_storage.py b/graphrag/storage/pipeline_storage.py index a1c651fe49..ed117a577d 100644 --- a/graphrag/storage/pipeline_storage.py +++ b/graphrag/storage/pipeline_storage.py @@ -9,8 +9,6 @@ from datetime import datetime from typing import Any -from graphrag.logger.base import ProgressLogger - class PipelineStorage(metaclass=ABCMeta): """Provide a storage interface for the pipeline. This is where the pipeline will store its output data.""" @@ -20,7 +18,6 @@ def find( self, file_pattern: re.Pattern[str], base_dir: str | None = None, - progress: ProgressLogger | None = None, file_filter: dict[str, Any] | None = None, max_count=-1, ) -> Iterator[tuple[str, dict[str, Any]]]: diff --git a/graphrag/utils/api.py b/graphrag/utils/api.py index 2512fb0c14..484a279b1f 100644 --- a/graphrag/utils/api.py +++ b/graphrag/utils/api.py @@ -255,3 +255,10 @@ def create_cache_from_config(cache: CacheConfig, root_dir: str) -> PipelineCache root_dir=root_dir, kwargs=cache_config, ) + + +def truncate(text: str, max_length: int) -> str: + """Truncate a string to a maximum length.""" + if len(text) <= max_length: + return text + return text[:max_length] + "...[truncated]" diff --git a/graphrag/utils/storage.py b/graphrag/utils/storage.py index caf8003fc5..8534330a15 100644 --- a/graphrag/utils/storage.py +++ b/graphrag/utils/storage.py @@ -10,7 +10,7 @@ from graphrag.storage.pipeline_storage import PipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) async def load_table_from_storage(name: str, storage: PipelineStorage) -> pd.DataFrame: @@ -20,10 +20,10 @@ async def load_table_from_storage(name: str, storage: PipelineStorage) -> pd.Dat msg = f"Could not find {filename} in storage!" raise ValueError(msg) try: - log.info("reading table from storage: %s", filename) + logger.info("reading table from storage: %s", filename) return pd.read_parquet(BytesIO(await storage.get(filename, as_bytes=True))) except Exception: - log.exception("error loading table from storage: %s", filename) + logger.exception("error loading table from storage: %s", filename) raise diff --git a/poetry.lock b/poetry.lock index d857a5cb41..15d4a3b32f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "aiofiles" @@ -6,6 +6,7 @@ version = "24.1.0" description = "File support for asyncio." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}, {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}, @@ -17,6 +18,7 @@ version = "1.2.1" description = "asyncio rate limiter, a leaky bucket implementation" optional = false python-versions = "<4.0,>=3.8" +groups = ["main"] files = [ {file = "aiolimiter-1.2.1-py3-none-any.whl", hash = "sha256:d3f249e9059a20badcb56b61601a83556133655c11d1eb3dd3e04ff069e5f3c7"}, {file = "aiolimiter-1.2.1.tar.gz", hash = "sha256:e02a37ea1a855d9e832252a105420ad4d15011505512a1a1d814647451b5cca9"}, @@ -28,6 +30,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -39,6 +42,7 @@ version = "4.9.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, @@ -52,7 +56,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] +test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] trio = ["trio (>=0.26.1)"] [[package]] @@ -61,6 +65,7 @@ version = "2.13.0" description = "Powerful and Lightweight Python Tree Data Structure with various plugins" optional = false python-versions = "<4.0,>=3.9.2" +groups = ["main"] files = [ {file = "anytree-2.13.0-py3-none-any.whl", hash = "sha256:4cbcf10df36b1f1cba131b7e487ff3edafc9d6e932a3c70071b5b768bab901ff"}, {file = "anytree-2.13.0.tar.gz", hash = "sha256:c9d3aa6825fdd06af7ebb05b4ef291d2db63e62bb1f9b7d9b71354be9d362714"}, @@ -72,6 +77,8 @@ version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = ">=3.6" +groups = ["dev"] +markers = "platform_system == \"Darwin\"" files = [ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, @@ -79,30 +86,26 @@ files = [ [[package]] name = "argon2-cffi" -version = "23.1.0" +version = "25.1.0" description = "Argon2 for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, - {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, + {file = "argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741"}, + {file = "argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1"}, ] [package.dependencies] argon2-cffi-bindings = "*" -[package.extras] -dev = ["argon2-cffi[tests,typing]", "tox (>4)"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] -tests = ["hypothesis", "pytest"] -typing = ["mypy"] - [[package]] name = "argon2-cffi-bindings" version = "21.2.0" description = "Low-level CFFI bindings for Argon2" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, @@ -140,6 +143,7 @@ version = "1.3.0" description = "Better dates & times for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, @@ -159,6 +163,7 @@ version = "2.4.1" description = "Annotate AST trees with source code positions" optional = false python-versions = "*" +groups = ["main", "dev"] files = [ {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, @@ -168,8 +173,8 @@ files = [ six = ">=1.12.0" [package.extras] -astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] -test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] +astroid = ["astroid (>=1,<2) ; python_version < \"3\"", "astroid (>=2,<4) ; python_version >= \"3\""] +test = ["astroid (>=1,<2) ; python_version < \"3\"", "astroid (>=2,<4) ; python_version >= \"3\"", "pytest"] [[package]] name = "async-lru" @@ -177,6 +182,7 @@ version = "2.0.5" description = "Simple LRU cache for asyncio" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "async_lru-2.0.5-py3-none-any.whl", hash = "sha256:ab95404d8d2605310d345932697371a5f40def0487c03d6d0ad9138de52c9943"}, {file = "async_lru-2.0.5.tar.gz", hash = "sha256:481d52ccdd27275f42c43a928b4a50c3bfb2d67af4e78b170e3e0bb39c66e5bb"}, @@ -191,18 +197,19 @@ version = "25.3.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] -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-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -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"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "autograd" @@ -210,6 +217,7 @@ version = "1.8.0" description = "Efficiently computes derivatives of NumPy code." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "autograd-1.8.0-py3-none-any.whl", hash = "sha256:4ab9084294f814cf56c280adbe19612546a35574d67c574b04933c7d2ecb7d78"}, {file = "autograd-1.8.0.tar.gz", hash = "sha256:107374ded5b09fc8643ac925348c0369e7b0e73bbed9565ffd61b8fd04425683"}, @@ -228,6 +236,7 @@ version = "1.1.28" description = "Microsoft Azure Client Library for Python (Common)" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "azure-common-1.1.28.zip", hash = "sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3"}, {file = "azure_common-1.1.28-py2.py3-none-any.whl", hash = "sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad"}, @@ -235,13 +244,14 @@ files = [ [[package]] name = "azure-core" -version = "1.34.0" +version = "1.35.0" description = "Microsoft Azure Core Library for Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "azure_core-1.34.0-py3-none-any.whl", hash = "sha256:0615d3b756beccdb6624d1c0ae97284f38b78fb59a2a9839bf927c66fbbdddd6"}, - {file = "azure_core-1.34.0.tar.gz", hash = "sha256:bdb544989f246a0ad1c85d72eeb45f2f835afdcbc5b45e43f0dbde7461c81ece"}, + {file = "azure_core-1.35.0-py3-none-any.whl", hash = "sha256:8db78c72868a58f3de8991eb4d22c4d368fae226dac1002998d6c50437e7dad1"}, + {file = "azure_core-1.35.0.tar.gz", hash = "sha256:c0be528489485e9ede59b6971eb63c1eaacf83ef53001bfe3904e475e972be5c"}, ] [package.dependencies] @@ -259,6 +269,7 @@ version = "4.9.0" description = "Microsoft Azure Cosmos Client Library for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "azure_cosmos-4.9.0-py3-none-any.whl", hash = "sha256:3b60eaa01a16a857d0faf0cec304bac6fa8620a81bc268ce760339032ef617fe"}, {file = "azure_cosmos-4.9.0.tar.gz", hash = "sha256:c70db4cbf55b0ff261ed7bb8aa325a5dfa565d3c6eaa43d75d26ae5e2ad6d74f"}, @@ -274,6 +285,7 @@ version = "1.23.0" description = "Microsoft Azure Identity Library for Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "azure_identity-1.23.0-py3-none-any.whl", hash = "sha256:dbbeb64b8e5eaa81c44c565f264b519ff2de7ff0e02271c49f3cb492762a50b0"}, {file = "azure_identity-1.23.0.tar.gz", hash = "sha256:d9cdcad39adb49d4bb2953a217f62aec1f65bbb3c63c9076da2be2a47e53dde4"}, @@ -288,13 +300,14 @@ typing-extensions = ">=4.0.0" [[package]] name = "azure-search-documents" -version = "11.5.2" +version = "11.5.3" description = "Microsoft Azure Cognitive Search Client Library for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "azure_search_documents-11.5.2-py3-none-any.whl", hash = "sha256:c949d011008a4b0bcee3db91132741b4e4d50ddb3f7e2f48944d949d4b413b11"}, - {file = "azure_search_documents-11.5.2.tar.gz", hash = "sha256:98977dd1fa4978d3b7d8891a0856b3becb6f02cc07ff2e1ea40b9c7254ada315"}, + {file = "azure_search_documents-11.5.3-py3-none-any.whl", hash = "sha256:110617751c6c8bd50b1f0af2b00a478bd4fbaf4e2f0387e3454c26ec3eb433d6"}, + {file = "azure_search_documents-11.5.3.tar.gz", hash = "sha256:6931149ec0db90485d78648407f18ea4271420473c7cb646bf87790374439989"}, ] [package.dependencies] @@ -309,6 +322,7 @@ version = "12.25.1" description = "Microsoft Azure Blob Storage Client Library for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "azure_storage_blob-12.25.1-py3-none-any.whl", hash = "sha256:1f337aab12e918ec3f1b638baada97550673911c4ceed892acc8e4e891b74167"}, {file = "azure_storage_blob-12.25.1.tar.gz", hash = "sha256:4f294ddc9bc47909ac66b8934bd26b50d2000278b10ad82cc109764fdc6e0e3b"}, @@ -329,13 +343,14 @@ version = "2.17.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, ] [package.extras] -dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "backports-datetime-fromisoformat" @@ -343,6 +358,8 @@ version = "2.0.3" description = "Backport of Python 3.11's datetime.fromisoformat" optional = false python-versions = ">3" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "backports_datetime_fromisoformat-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f681f638f10588fa3c101ee9ae2b63d3734713202ddfcfb6ec6cea0778a29d4"}, {file = "backports_datetime_fromisoformat-2.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:cd681460e9142f1249408e5aee6d178c6d89b49e06d44913c8fdfb6defda8d1c"}, @@ -395,17 +412,19 @@ files = [ [[package]] name = "backrefs" -version = "5.8" +version = "5.9" description = "A wrapper around re and regex that adds additional back references." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "backrefs-5.8-py310-none-any.whl", hash = "sha256:c67f6638a34a5b8730812f5101376f9d41dc38c43f1fdc35cb54700f6ed4465d"}, - {file = "backrefs-5.8-py311-none-any.whl", hash = "sha256:2e1c15e4af0e12e45c8701bd5da0902d326b2e200cafcd25e49d9f06d44bb61b"}, - {file = "backrefs-5.8-py312-none-any.whl", hash = "sha256:bbef7169a33811080d67cdf1538c8289f76f0942ff971222a16034da88a73486"}, - {file = "backrefs-5.8-py313-none-any.whl", hash = "sha256:e3a63b073867dbefd0536425f43db618578528e3896fb77be7141328642a1585"}, - {file = "backrefs-5.8-py39-none-any.whl", hash = "sha256:a66851e4533fb5b371aa0628e1fee1af05135616b86140c9d787a2ffdf4b8fdc"}, - {file = "backrefs-5.8.tar.gz", hash = "sha256:2cab642a205ce966af3dd4b38ee36009b31fa9502a35fd61d59ccc116e40a6bd"}, + {file = "backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f"}, + {file = "backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf"}, + {file = "backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa"}, + {file = "backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b"}, + {file = "backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9"}, + {file = "backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60"}, + {file = "backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59"}, ] [package.extras] @@ -417,6 +436,7 @@ version = "0.18.5" description = "Unbearably fast runtime type checking in pure Python." optional = false python-versions = ">=3.8.0" +groups = ["main"] files = [ {file = "beartype-0.18.5-py3-none-any.whl", hash = "sha256:5301a14f2a9a5540fe47ec6d34d758e9cd8331d36c4760fc7a5499ab86310089"}, {file = "beartype-0.18.5.tar.gz", hash = "sha256:264ddc2f1da9ec94ff639141fbe33d22e12a9f75aa863b83b7046ffff1381927"}, @@ -424,9 +444,9 @@ files = [ [package.extras] all = ["typing-extensions (>=3.10.0.0)"] -dev = ["autoapi (>=0.9.0)", "coverage (>=5.5)", "equinox", "mypy (>=0.800)", "numpy", "pandera", "pydata-sphinx-theme (<=0.7.2)", "pytest (>=4.0.0)", "sphinx", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] +dev = ["autoapi (>=0.9.0)", "coverage (>=5.5)", "equinox", "mypy (>=0.800) ; platform_python_implementation != \"PyPy\"", "numpy ; sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "pandera", "pydata-sphinx-theme (<=0.7.2)", "pytest (>=4.0.0)", "sphinx (>=4.2.0,<6.0.0)", "sphinx ; python_version >= \"3.8.0\"", "sphinxext-opengraph (>=0.7.5)", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)"] -test-tox = ["equinox", "mypy (>=0.800)", "numpy", "pandera", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] +test-tox = ["equinox", "mypy (>=0.800) ; platform_python_implementation != \"PyPy\"", "numpy ; sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "pandera", "pytest (>=4.0.0)", "sphinx ; python_version >= \"3.8.0\"", "typing-extensions (>=3.10.0.0)"] test-tox-coverage = ["coverage (>=5.5)"] [[package]] @@ -435,6 +455,7 @@ version = "4.13.4" description = "Screen-scraping library" optional = false python-versions = ">=3.7.0" +groups = ["dev"] files = [ {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, @@ -457,6 +478,7 @@ version = "6.2.0" description = "An easy safelist-based HTML-sanitizing tool." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, @@ -475,6 +497,7 @@ version = "1.2.1" description = "The Blis BLAS-like linear algebra library, as a self-contained C-extension." optional = false python-versions = "<3.13,>=3.6" +groups = ["main"] files = [ {file = "blis-1.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112443b90698158ada38f71e74c079c3561e802554a51e9850d487c39db25de0"}, {file = "blis-1.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b9f8c4fbc303f47778d1fd47916cae785b6f3beaa2031502112a8c0aa5eb29f6"}, @@ -515,6 +538,7 @@ version = "2.0.10" description = "Super lightweight function registries for your library" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "catalogue-2.0.10-py3-none-any.whl", hash = "sha256:58c2de0020aa90f4a2da7dfad161bf7b3b054c86a5f09fcedc0b2b740c109a9f"}, {file = "catalogue-2.0.10.tar.gz", hash = "sha256:4f56daa940913d3f09d589c191c74e5a6d51762b3a9e37dd53b7437afd6cda15"}, @@ -522,13 +546,14 @@ files = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.7.9" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, - {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, + {file = "certifi-2025.7.9-py3-none-any.whl", hash = "sha256:d842783a14f8fdd646895ac26f719a061408834473cfc10203f6a575beb15d39"}, + {file = "certifi-2025.7.9.tar.gz", hash = "sha256:c1d2ec05395148ee10cf672ffc28cd37ea0ab0d99f9cc74c43e588cbd111b079"}, ] [[package]] @@ -537,6 +562,7 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -606,6 +632,7 @@ files = [ {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] +markers = {main = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = "*" @@ -616,6 +643,7 @@ version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, @@ -717,6 +745,7 @@ version = "8.2.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" +groups = ["main", "dev"] files = [ {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, @@ -731,6 +760,7 @@ version = "0.21.1" description = "pathlib-style classes for cloud storage services." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "cloudpathlib-0.21.1-py3-none-any.whl", hash = "sha256:bfe580ad72ec030472ec233cd7380701b2d3227da7b2898387bd170aa70c803c"}, {file = "cloudpathlib-0.21.1.tar.gz", hash = "sha256:f26a855abf34d98f267aafd15efdb2db3c9665913dbabe5fad079df92837a431"}, @@ -751,10 +781,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "sys_platform == \"win32\" or platform_system == \"Windows\""} [[package]] name = "comm" @@ -762,6 +794,7 @@ version = "0.2.2" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, @@ -779,6 +812,7 @@ version = "0.1.5" description = "The sweetest config system for Python" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "confection-0.1.5-py3-none-any.whl", hash = "sha256:e29d3c3f8eac06b3f77eb9dfb4bf2fc6bcc9622a98ca00a698e3d019c6430b14"}, {file = "confection-0.1.5.tar.gz", hash = "sha256:8e72dd3ca6bd4f48913cd220f10b8275978e740411654b6e8ca6d7008c590f0e"}, @@ -794,6 +828,7 @@ version = "1.3.2" description = "Python library for calculating contours of 2D quadrilateral grids" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934"}, {file = "contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989"}, @@ -866,140 +901,142 @@ test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist" [[package]] name = "coverage" -version = "7.8.2" +version = "7.9.2" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" -files = [ - {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, - {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, - {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, - {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, - {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, - {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, - {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, - {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, - {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, - {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, - {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, - {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, - {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, - {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, - {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, - {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, - {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, - {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, - {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, - {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, - {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, - {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, - {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, - {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, - {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, - {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, - {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, - {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, - {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, - {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, - {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, - {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, - {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, - {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, - {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, - {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, - {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, - {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, - {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, - {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, - {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, - {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, - {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, - {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, - {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, - {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, - {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, - {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, - {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, - {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, - {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, - {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, - {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, - {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, - {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, - {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, - {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, - {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, - {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, - {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, - {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, - {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, - {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, - {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, - {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, - {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, - {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, +groups = ["dev"] +files = [ + {file = "coverage-7.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66283a192a14a3854b2e7f3418d7db05cdf411012ab7ff5db98ff3b181e1f912"}, + {file = "coverage-7.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e01d138540ef34fcf35c1aa24d06c3de2a4cffa349e29a10056544f35cca15f"}, + {file = "coverage-7.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f22627c1fe2745ee98d3ab87679ca73a97e75ca75eb5faee48660d060875465f"}, + {file = "coverage-7.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b1c2d8363247b46bd51f393f86c94096e64a1cf6906803fa8d5a9d03784bdbf"}, + {file = "coverage-7.9.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10c882b114faf82dbd33e876d0cbd5e1d1ebc0d2a74ceef642c6152f3f4d547"}, + {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de3c0378bdf7066c3988d66cd5232d161e933b87103b014ab1b0b4676098fa45"}, + {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1e2f097eae0e5991e7623958a24ced3282676c93c013dde41399ff63e230fcf2"}, + {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28dc1f67e83a14e7079b6cea4d314bc8b24d1aed42d3582ff89c0295f09b181e"}, + {file = "coverage-7.9.2-cp310-cp310-win32.whl", hash = "sha256:bf7d773da6af9e10dbddacbf4e5cab13d06d0ed93561d44dae0188a42c65be7e"}, + {file = "coverage-7.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:0c0378ba787681ab1897f7c89b415bd56b0b2d9a47e5a3d8dc0ea55aac118d6c"}, + {file = "coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba"}, + {file = "coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa"}, + {file = "coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a"}, + {file = "coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc"}, + {file = "coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2"}, + {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c"}, + {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd"}, + {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74"}, + {file = "coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6"}, + {file = "coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7"}, + {file = "coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62"}, + {file = "coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0"}, + {file = "coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3"}, + {file = "coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1"}, + {file = "coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615"}, + {file = "coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b"}, + {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9"}, + {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f"}, + {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d"}, + {file = "coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355"}, + {file = "coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0"}, + {file = "coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b"}, + {file = "coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038"}, + {file = "coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d"}, + {file = "coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3"}, + {file = "coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14"}, + {file = "coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6"}, + {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b"}, + {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d"}, + {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868"}, + {file = "coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a"}, + {file = "coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b"}, + {file = "coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694"}, + {file = "coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5"}, + {file = "coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b"}, + {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3"}, + {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8"}, + {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46"}, + {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584"}, + {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e"}, + {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac"}, + {file = "coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926"}, + {file = "coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd"}, + {file = "coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb"}, + {file = "coverage-7.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddc39510ac922a5c4c27849b739f875d3e1d9e590d1e7b64c98dadf037a16cce"}, + {file = "coverage-7.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a535c0c7364acd55229749c2b3e5eebf141865de3a8f697076a3291985f02d30"}, + {file = "coverage-7.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df0f9ef28e0f20c767ccdccfc5ae5f83a6f4a2fbdfbcbcc8487a8a78771168c8"}, + {file = "coverage-7.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f3da12e0ccbcb348969221d29441ac714bbddc4d74e13923d3d5a7a0bebef7a"}, + {file = "coverage-7.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a17eaf46f56ae0f870f14a3cbc2e4632fe3771eab7f687eda1ee59b73d09fe4"}, + {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:669135a9d25df55d1ed56a11bf555f37c922cf08d80799d4f65d77d7d6123fcf"}, + {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d3a700304d01a627df9db4322dc082a0ce1e8fc74ac238e2af39ced4c083193"}, + {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:71ae8b53855644a0b1579d4041304ddc9995c7b21c8a1f16753c4d8903b4dfed"}, + {file = "coverage-7.9.2-cp39-cp39-win32.whl", hash = "sha256:dd7a57b33b5cf27acb491e890720af45db05589a80c1ffc798462a765be6d4d7"}, + {file = "coverage-7.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f65bb452e579d5540c8b37ec105dd54d8b9307b07bcaa186818c104ffda22441"}, + {file = "coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050"}, + {file = "coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4"}, + {file = "coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b"}, ] [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" -version = "45.0.3" +version = "45.0.5" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" -files = [ - {file = "cryptography-45.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:7573d9eebaeceeb55285205dbbb8753ac1e962af3d9640791d12b36864065e71"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d377dde61c5d67eb4311eace661c3efda46c62113ff56bf05e2d679e02aebb5b"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae1e637f527750811588e4582988932c222f8251f7b7ea93739acb624e1487f"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ca932e11218bcc9ef812aa497cdf669484870ecbcf2d99b765d6c27a86000942"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af3f92b1dc25621f5fad065288a44ac790c5798e986a34d393ab27d2b27fcff9"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f8f8f0b73b885ddd7f3d8c2b2234a7d3ba49002b0223f58cfde1bedd9563c56"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9cc80ce69032ffa528b5e16d217fa4d8d4bb7d6ba8659c1b4d74a1b0f4235fca"}, - {file = "cryptography-45.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c824c9281cb628015bfc3c59335163d4ca0540d49de4582d6c2637312907e4b1"}, - {file = "cryptography-45.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5833bb4355cb377ebd880457663a972cd044e7f49585aee39245c0d592904578"}, - {file = "cryptography-45.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bb5bf55dcb69f7067d80354d0a348368da907345a2c448b0babc4215ccd3497"}, - {file = "cryptography-45.0.3-cp311-abi3-win32.whl", hash = "sha256:3ad69eeb92a9de9421e1f6685e85a10fbcfb75c833b42cc9bc2ba9fb00da4710"}, - {file = "cryptography-45.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:97787952246a77d77934d41b62fb1b6f3581d83f71b44796a4158d93b8f5c490"}, - {file = "cryptography-45.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:c92519d242703b675ccefd0f0562eb45e74d438e001f8ab52d628e885751fb06"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5edcb90da1843df85292ef3a313513766a78fbbb83f584a5a58fb001a5a9d57"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38deed72285c7ed699864f964a3f4cf11ab3fb38e8d39cfcd96710cd2b5bb716"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5555365a50efe1f486eed6ac7062c33b97ccef409f5970a0b6f205a7cfab59c8"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e4253ed8f5948a3589b3caee7ad9a5bf218ffd16869c516535325fece163dcc"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cfd84777b4b6684955ce86156cfb5e08d75e80dc2585e10d69e47f014f0a5342"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:a2b56de3417fd5f48773ad8e91abaa700b678dc7fe1e0c757e1ae340779acf7b"}, - {file = "cryptography-45.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:57a6500d459e8035e813bd8b51b671977fb149a8c95ed814989da682314d0782"}, - {file = "cryptography-45.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f22af3c78abfbc7cbcdf2c55d23c3e022e1a462ee2481011d518c7fb9c9f3d65"}, - {file = "cryptography-45.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:232954730c362638544758a8160c4ee1b832dc011d2c41a306ad8f7cccc5bb0b"}, - {file = "cryptography-45.0.3-cp37-abi3-win32.whl", hash = "sha256:cb6ab89421bc90e0422aca911c69044c2912fc3debb19bb3c1bfe28ee3dff6ab"}, - {file = "cryptography-45.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:d54ae41e6bd70ea23707843021c778f151ca258081586f0cfa31d936ae43d1b2"}, - {file = "cryptography-45.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed43d396f42028c1f47b5fec012e9e12631266e3825e95c00e3cf94d472dac49"}, - {file = "cryptography-45.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:fed5aaca1750e46db870874c9c273cd5182a9e9deb16f06f7bdffdb5c2bde4b9"}, - {file = "cryptography-45.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:00094838ecc7c6594171e8c8a9166124c1197b074cfca23645cee573910d76bc"}, - {file = "cryptography-45.0.3-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:92d5f428c1a0439b2040435a1d6bc1b26ebf0af88b093c3628913dd464d13fa1"}, - {file = "cryptography-45.0.3-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:ec64ee375b5aaa354b2b273c921144a660a511f9df8785e6d1c942967106438e"}, - {file = "cryptography-45.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:71320fbefd05454ef2d457c481ba9a5b0e540f3753354fff6f780927c25d19b0"}, - {file = "cryptography-45.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:edd6d51869beb7f0d472e902ef231a9b7689508e83880ea16ca3311a00bf5ce7"}, - {file = "cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:555e5e2d3a53b4fabeca32835878b2818b3f23966a4efb0d566689777c5a12c8"}, - {file = "cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:25286aacb947286620a31f78f2ed1a32cded7be5d8b729ba3fb2c988457639e4"}, - {file = "cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:050ce5209d5072472971e6efbfc8ec5a8f9a841de5a4db0ebd9c2e392cb81972"}, - {file = "cryptography-45.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:dc10ec1e9f21f33420cc05214989544727e776286c1c16697178978327b95c9c"}, - {file = "cryptography-45.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:9eda14f049d7f09c2e8fb411dda17dd6b16a3c76a1de5e249188a32aeb92de19"}, - {file = "cryptography-45.0.3.tar.gz", hash = "sha256:ec21313dd335c51d7877baf2972569f40a4291b76a0ce51391523ae358d05899"}, +groups = ["main"] +files = [ + {file = "cryptography-45.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9"}, + {file = "cryptography-45.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27"}, + {file = "cryptography-45.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e"}, + {file = "cryptography-45.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174"}, + {file = "cryptography-45.0.5-cp311-abi3-win32.whl", hash = "sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9"}, + {file = "cryptography-45.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63"}, + {file = "cryptography-45.0.5-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42"}, + {file = "cryptography-45.0.5-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492"}, + {file = "cryptography-45.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0"}, + {file = "cryptography-45.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a"}, + {file = "cryptography-45.0.5-cp37-abi3-win32.whl", hash = "sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f"}, + {file = "cryptography-45.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97"}, + {file = "cryptography-45.0.5-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd"}, + {file = "cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097"}, + {file = "cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e"}, + {file = "cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30"}, + {file = "cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e"}, + {file = "cryptography-45.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d"}, + {file = "cryptography-45.0.5-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e"}, + {file = "cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6"}, + {file = "cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18"}, + {file = "cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463"}, + {file = "cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1"}, + {file = "cryptography-45.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f"}, + {file = "cryptography-45.0.5.tar.gz", hash = "sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a"}, ] [package.dependencies] cffi = {version = ">=1.14", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] +docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs ; python_full_version >= \"3.8.0\"", "sphinx-rtd-theme (>=3.0.0) ; python_full_version >= \"3.8.0\""] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_full_version >= \"3.8.0\""] +pep8test = ["check-sdist ; python_full_version >= \"3.8.0\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==45.0.3)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test = ["certifi (>=2024)", "cryptography-vectors (==45.0.5)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] test-randomorder = ["pytest-randomly"] [[package]] @@ -1008,6 +1045,7 @@ version = "0.12.1" description = "Composable style cycles" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, @@ -1023,6 +1061,7 @@ version = "2.0.11" description = "Manage calls to calloc/free through Cython" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "cymem-2.0.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1b4dd8f8c2475c7c9948eefa89c790d83134600858d8d43b90276efd8df3882e"}, {file = "cymem-2.0.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d46ba0d2e0f749195297d16f2286b55af7d7c084db2b853fdfccece2c000c5dc"}, @@ -1068,6 +1107,7 @@ version = "1.8.14" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "debugpy-1.8.14-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:93fee753097e85623cab1c0e6a68c76308cd9f13ffdf44127e6fab4fbf024339"}, {file = "debugpy-1.8.14-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d937d93ae4fa51cdc94d3e865f535f185d5f9748efb41d0d49e33bf3365bd79"}, @@ -1103,6 +1143,7 @@ version = "5.2.1" description = "Decorators for Humans" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, @@ -1114,6 +1155,7 @@ version = "0.7.1" description = "XML bomb protection for Python stdlib modules" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] files = [ {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, @@ -1125,6 +1167,7 @@ version = "2.1.0" description = "A library to handle automated deprecations" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, @@ -1139,6 +1182,7 @@ version = "0.21.2" description = "A command line utility to check for unused, missing and transitive dependencies in a Python project." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "deptry-0.21.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e3b9e0c5ee437240b65e61107b5777a12064f78f604bf9f181a96c9b56eb896d"}, {file = "deptry-0.21.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:d76bbf48bd62ecc44ca3d414769bd4b7956598d23d9ccb42fd359b831a31cab2"}, @@ -1171,6 +1215,7 @@ version = "0.12.2" description = "Python's missing debug print command, and more." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "devtools-0.12.2-py3-none-any.whl", hash = "sha256:c366e3de1df4cdd635f1ad8cbcd3af01a384d7abda71900e68d43b04eb6aaca7"}, {file = "devtools-0.12.2.tar.gz", hash = "sha256:efceab184cb35e3a11fa8e602cc4fadacaa2e859e920fc6f87bf130b69885507"}, @@ -1187,6 +1232,7 @@ version = "1.9.0" description = "Distro - an OS platform information API" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -1198,6 +1244,7 @@ version = "11.2.1" description = "simplified environment variable parsing" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "environs-11.2.1-py3-none-any.whl", hash = "sha256:9d2080cf25807a26fc0d4301e2d7b62c64fbf547540f21e3a30cc02bc5fbe948"}, {file = "environs-11.2.1.tar.gz", hash = "sha256:e068ae3174cef52ba4b95ead22e639056a02465f616e62323e04ae08e86a75a4"}, @@ -1218,6 +1265,8 @@ version = "1.3.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, @@ -1235,13 +1284,14 @@ version = "2.2.0" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, ] [package.extras] -tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich ; python_version >= \"3.11\""] [[package]] name = "fastjsonschema" @@ -1249,6 +1299,7 @@ version = "2.21.1" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667"}, {file = "fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4"}, @@ -1263,6 +1314,7 @@ version = "0.3.0" description = "A function-based LLM protocol and wrapper." optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "fnllm-0.3.0-py3-none-any.whl", hash = "sha256:75268656cfe51fc2265a62fb10f9eca3d4a29d14b6057f0287985b3b72fa53cf"}, {file = "fnllm-0.3.0.tar.gz", hash = "sha256:c69c42990d1c86a463365d2299bfe5a38a5b396a995c35876545977b7a122d40"}, @@ -1286,68 +1338,69 @@ openai = ["openai (>=1.35.12)", "tiktoken (>=0.7.0)"] [[package]] name = "fonttools" -version = "4.58.1" +version = "4.58.5" description = "Tools to manipulate font files" optional = false python-versions = ">=3.9" -files = [ - {file = "fonttools-4.58.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ebd423034ac4f74196c1ae29f8ed3b862f820345acbf35600af8596ebf62573"}, - {file = "fonttools-4.58.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9dc36f4b4044d95e6fb358da4c3e6a5c07c9b6f4c1e8c396e89bee3b65dae902"}, - {file = "fonttools-4.58.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc4b74d7bb84189fe264d56a544ac5c818f8f1e8141856746768691fe185b229"}, - {file = "fonttools-4.58.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa4fa41e9cb43f78881a5896d6e41b6a0ec54e9d68e7eaaff6d7a1769b17017"}, - {file = "fonttools-4.58.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91335202f19c9edc04f2f6a7d9bb269b0a435d7de771e3f33c3ea9f87f19c8d4"}, - {file = "fonttools-4.58.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6b0ec2171e811a0d9e467225dc06b0fac39a84b4704f263c2d538c3c67b99b2"}, - {file = "fonttools-4.58.1-cp310-cp310-win32.whl", hash = "sha256:a788983d522d02a9b457cc98aa60fc631dabae352fb3b30a56200890cd338ca0"}, - {file = "fonttools-4.58.1-cp310-cp310-win_amd64.whl", hash = "sha256:c8c848a2d5961d277b85ac339480cecea90599059f72a42047ced25431e8b72a"}, - {file = "fonttools-4.58.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9966e14729669bcfbb56f83b747a2397c4d97c6d4798cb2e2adc28f9388fa008"}, - {file = "fonttools-4.58.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64cc1647bbe83dea57f5496ec878ad19ccdba7185b0dd34955d3e6f03dc789e6"}, - {file = "fonttools-4.58.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464f790ce681d08d1583df0735776aa9cb1999594bf336ddd0bf962c17b629ac"}, - {file = "fonttools-4.58.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c53c6a720ee70cc25746d511ba88c45c95ec510fd258026ed209b0b9e3ba92f"}, - {file = "fonttools-4.58.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6823a633bbce29cf3033508ebb54a433c473fb9833eff7f936bfdc5204fd98d"}, - {file = "fonttools-4.58.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5701fe66a1408c1974d2f78c00f964f8aad17cccbc32bc041e1b81421f31f448"}, - {file = "fonttools-4.58.1-cp311-cp311-win32.whl", hash = "sha256:4cad2c74adf9ee31ae43be6b0b376fdb386d4d50c60979790e32c3548efec051"}, - {file = "fonttools-4.58.1-cp311-cp311-win_amd64.whl", hash = "sha256:7ade12485abccb0f6b6a6e2a88c50e587ff0e201e48e0153dd9b2e0ed67a2f38"}, - {file = "fonttools-4.58.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f56085a65769dc0100822c814069327541db9c3c4f21e599c6138f9dbda75e96"}, - {file = "fonttools-4.58.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:19c65a88e522c9f1be0c05d73541de20feada99d23d06e9b5354023cc3e517b0"}, - {file = "fonttools-4.58.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b01bb37006e97703300bfde7a73d1c7038574dd1df9d8d92ca99af151becf2ca"}, - {file = "fonttools-4.58.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d629dea240f0fc826d8bb14566e95c663214eece21b5932c9228d3e8907f55aa"}, - {file = "fonttools-4.58.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ef0b33ff35421a04a638e736823c2dee9d200cdd275cfdb43e875ca745150aae"}, - {file = "fonttools-4.58.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4db9399ee633855c718fe8bea5eecbdc5bf3fdbed2648e50f67f8946b943ed1c"}, - {file = "fonttools-4.58.1-cp312-cp312-win32.whl", hash = "sha256:5cf04c4f73d36b30ea1cff091a7a9e65f8d5b08345b950f82679034e9f7573f4"}, - {file = "fonttools-4.58.1-cp312-cp312-win_amd64.whl", hash = "sha256:4a3841b59c67fa1f739542b05211609c453cec5d11d21f863dd2652d5a81ec9b"}, - {file = "fonttools-4.58.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:68379d1599fc59569956a97eb7b07e0413f76142ac8513fa24c9f2c03970543a"}, - {file = "fonttools-4.58.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8631905657de4f9a7ae1e12186c1ed20ba4d6168c2d593b9e0bd2908061d341b"}, - {file = "fonttools-4.58.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2ecea7289061c2c71468723409a8dd6e70d1ecfce6bc7686e5a74b9ce9154fe"}, - {file = "fonttools-4.58.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b8860f8cd48b345bd1df1d7be650f600f69ee971ffe338c5bd5bcb6bdb3b92c"}, - {file = "fonttools-4.58.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7c9a0acdefcb8d7ccd7c59202056166c400e797047009ecb299b75ab950c2a9c"}, - {file = "fonttools-4.58.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1fac0be6be3e4309058e156948cb73196e5fd994268b89b5e3f5a26ee2b582"}, - {file = "fonttools-4.58.1-cp313-cp313-win32.whl", hash = "sha256:aed7f93a9a072f0ce6fb46aad9474824ac6dd9c7c38a72f8295dd14f2215950f"}, - {file = "fonttools-4.58.1-cp313-cp313-win_amd64.whl", hash = "sha256:b27d69c97c20c9bca807f7ae7fc7df459eb62994859ff6a2a489e420634deac3"}, - {file = "fonttools-4.58.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:927762f9fe39ea0a4d9116353251f409389a6b58fab58717d3c3377acfc23452"}, - {file = "fonttools-4.58.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:761ac80efcb7333c71760458c23f728d6fe2dff253b649faf52471fd7aebe584"}, - {file = "fonttools-4.58.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef910226f788a4e72aa0fc1c1657fb43fa62a4200b883edffdb1392b03fe86"}, - {file = "fonttools-4.58.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff2859ca2319454df8c26af6693269b21f2e9c0e46df126be916a4f6d85fc75"}, - {file = "fonttools-4.58.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:418927e888e1bcc976b4e190a562f110dc27b0b5cac18033286f805dc137fc66"}, - {file = "fonttools-4.58.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a907007a8b341e8e129d3994d34d1cc85bc8bf38b3a0be65eb14e4668f634a21"}, - {file = "fonttools-4.58.1-cp39-cp39-win32.whl", hash = "sha256:455cb6adc9f3419273925fadc51a6207046e147ce503797b29895ba6bdf85762"}, - {file = "fonttools-4.58.1-cp39-cp39-win_amd64.whl", hash = "sha256:2e64931258866df187bd597b4e9fff488f059a0bc230fbae434f0f112de3ce46"}, - {file = "fonttools-4.58.1-py3-none-any.whl", hash = "sha256:db88365d0962cd6f5bce54b190a4669aeed9c9941aa7bd60a5af084d8d9173d6"}, - {file = "fonttools-4.58.1.tar.gz", hash = "sha256:cbc8868e0a29c3e22628dfa1432adf7a104d86d1bc661cecc3e9173070b6ab2d"}, +groups = ["main"] +files = [ + {file = "fonttools-4.58.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d500d399aa4e92d969a0d21052696fa762385bb23c3e733703af4a195ad9f34c"}, + {file = "fonttools-4.58.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b00530b84f87792891874938bd42f47af2f7f4c2a1d70466e6eb7166577853ab"}, + {file = "fonttools-4.58.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5579fb3744dfec151b5c29b35857df83e01f06fe446e8c2ebaf1effd7e6cdce"}, + {file = "fonttools-4.58.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adf440deecfcc2390998e649156e3bdd0b615863228c484732dc06ac04f57385"}, + {file = "fonttools-4.58.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a81769fc4d473c808310c9ed91fbe01b67f615e3196fb9773e093939f59e6783"}, + {file = "fonttools-4.58.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0162a6a37b0ca70d8505311d541e291cd6cab54d1a986ae3d2686c56c0581e8f"}, + {file = "fonttools-4.58.5-cp310-cp310-win32.whl", hash = "sha256:1cde303422198fdc7f502dbdf1bf65306166cdb9446debd6c7fb826b4d66a530"}, + {file = "fonttools-4.58.5-cp310-cp310-win_amd64.whl", hash = "sha256:75cf8c2812c898dd3d70d62b2b768df4eeb524a83fb987a512ddb3863d6a8c54"}, + {file = "fonttools-4.58.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cda226253bf14c559bc5a17c570d46abd70315c9a687d91c0e01147f87736182"}, + {file = "fonttools-4.58.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:83a96e4a4e65efd6c098da549ec34f328f08963acd2d7bc910ceba01d2dc73e6"}, + {file = "fonttools-4.58.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d172b92dff59ef8929b4452d5a7b19b8e92081aa87bfb2d82b03b1ff14fc667"}, + {file = "fonttools-4.58.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0bfddfd09aafbbfb3bd98ae67415fbe51eccd614c17db0c8844fe724fbc5d43d"}, + {file = "fonttools-4.58.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfde5045f1bc92ad11b4b7551807564045a1b38cb037eb3c2bc4e737cd3a8d0f"}, + {file = "fonttools-4.58.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3515ac47a9a5ac025d2899d195198314023d89492340ba86e4ba79451f7518a8"}, + {file = "fonttools-4.58.5-cp311-cp311-win32.whl", hash = "sha256:9f7e2ab9c10b6811b4f12a0768661325a48e664ec0a0530232c1605896a598db"}, + {file = "fonttools-4.58.5-cp311-cp311-win_amd64.whl", hash = "sha256:126c16ec4a672c9cb5c1c255dc438d15436b470afc8e9cac25a2d39dd2dc26eb"}, + {file = "fonttools-4.58.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c3af3fefaafb570a03051a0d6899b8374dcf8e6a4560e42575843aef33bdbad6"}, + {file = "fonttools-4.58.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:688137789dbd44e8757ad77b49a771539d8069195ffa9a8bcf18176e90bbd86d"}, + {file = "fonttools-4.58.5-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af65836cf84cd7cb882d0b353bdc73643a497ce23b7414c26499bb8128ca1af"}, + {file = "fonttools-4.58.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2d79cfeb456bf438cb9fb87437634d4d6f228f27572ca5c5355e58472d5519d"}, + {file = "fonttools-4.58.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0feac9dda9a48a7a342a593f35d50a5cee2dbd27a03a4c4a5192834a4853b204"}, + {file = "fonttools-4.58.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36555230e168511e83ad8637232268649634b8dfff6ef58f46e1ebc057a041ad"}, + {file = "fonttools-4.58.5-cp312-cp312-win32.whl", hash = "sha256:26ec05319353842d127bd02516eacb25b97ca83966e40e9ad6fab85cab0576f4"}, + {file = "fonttools-4.58.5-cp312-cp312-win_amd64.whl", hash = "sha256:778a632e538f82c1920579c0c01566a8f83dc24470c96efbf2fbac698907f569"}, + {file = "fonttools-4.58.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f4b6f1360da13cecc88c0d60716145b31e1015fbe6a59e32f73a4404e2ea92cf"}, + {file = "fonttools-4.58.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a036822e915692aa2c03e2decc60f49a8190f8111b639c947a4f4e5774d0d7a"}, + {file = "fonttools-4.58.5-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6d7709fcf4577b0f294ee6327088884ca95046e1eccde87c53bbba4d5008541"}, + {file = "fonttools-4.58.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9b5099ca99b79d6d67162778b1b1616fc0e1de02c1a178248a0da8d78a33852"}, + {file = "fonttools-4.58.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3f2c05a8d82a4d15aebfdb3506e90793aea16e0302cec385134dd960647a36c0"}, + {file = "fonttools-4.58.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79f0c4b1cc63839b61deeac646d8dba46f8ed40332c2ac1b9997281462c2e4ba"}, + {file = "fonttools-4.58.5-cp313-cp313-win32.whl", hash = "sha256:a1a9a2c462760976882131cbab7d63407813413a2d32cd699e86a1ff22bf7aa5"}, + {file = "fonttools-4.58.5-cp313-cp313-win_amd64.whl", hash = "sha256:bca61b14031a4b7dc87e14bf6ca34c275f8e4b9f7a37bc2fe746b532a924cf30"}, + {file = "fonttools-4.58.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:082410bc40014db55be5457836043f0dd1e6b3817c7d11a0aeb44eaa862890af"}, + {file = "fonttools-4.58.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0b0983be58d8c8acb11161fdd3b43d64015cef8c3d65ad9289a252243b236128"}, + {file = "fonttools-4.58.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5a0e28fb6abc31ba45a2d11dc2fe826e5a074013d13b7b447b441e8236e5f1c"}, + {file = "fonttools-4.58.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d506652abc285934ee949a5f3a952c5d52a09257bc2ba44a92db3ec2804c76fe"}, + {file = "fonttools-4.58.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9e2d71676025dd74a21d682be36d4846aa03644c619f2c2d695a11a7262433f6"}, + {file = "fonttools-4.58.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb46a73759efc8a7eca40203843241cd3c79aa983ed7f7515548ed3d82073761"}, + {file = "fonttools-4.58.5-cp39-cp39-win32.whl", hash = "sha256:bf09f14d73a18c62eb9ad1cac98a37569241ba3cd5789cc578286c128cc29f7f"}, + {file = "fonttools-4.58.5-cp39-cp39-win_amd64.whl", hash = "sha256:8ddb7c0c3e91b187acc1bed31857376926569a18a348ac58d6a71eb8a6b22393"}, + {file = "fonttools-4.58.5-py3-none-any.whl", hash = "sha256:e48a487ed24d9b611c5c4b25db1e50e69e9854ca2670e39a3486ffcd98863ec4"}, + {file = "fonttools-4.58.5.tar.gz", hash = "sha256:b2a35b0a19f1837284b3a23dd64fd7761b8911d50911ecd2bdbaf5b2d1b5df9c"}, ] [package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "pycairo", "scipy"] +interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] lxml = ["lxml (>=4.0)"] pathops = ["skia-pathops (>=0.5.0)"] plot = ["matplotlib"] repacker = ["uharfbuzz (>=0.23.0)"] symfont = ["sympy"] -type1 = ["xattr"] +type1 = ["xattr ; sys_platform == \"darwin\""] ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=15.1.0)"] -woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] +unicode = ["unicodedata2 (>=15.1.0) ; python_version <= \"3.12\""] +woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] [[package]] name = "fqdn" @@ -1355,6 +1408,7 @@ version = "1.5.1" description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +groups = ["dev"] files = [ {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, @@ -1366,6 +1420,7 @@ version = "1.0.0" description = "Clean single-source support for Python 3 and 2" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["main"] files = [ {file = "future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216"}, {file = "future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05"}, @@ -1377,6 +1432,7 @@ version = "4.3.3" description = "Python framework for fast Vector Space Modelling" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "gensim-4.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4e72840adfbea35c5804fd559bc0cb6bc9f439926220a37d852b7ce76eb325c1"}, {file = "gensim-4.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4019263c9d9afae7c669f880c17e09461e77a71afce04ed4d79cf71a4cad2848"}, @@ -1423,6 +1479,7 @@ version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, @@ -1440,6 +1497,7 @@ version = "3.4.1" description = "A set of Python modules for graph statistics" optional = false python-versions = "<3.13,>=3.9" +groups = ["main"] files = [ {file = "graspologic-3.4.1-py3-none-any.whl", hash = "sha256:c6563e087eda599bad1de831d4b7321c0daa7a82f4e85a7d7737ff67e07cdda2"}, {file = "graspologic-3.4.1.tar.gz", hash = "sha256:7561f0b852a2bccd351bff77e8db07d9892f9dfa35a420fdec01690e4fdc8075"}, @@ -1469,6 +1527,7 @@ version = "1.2.5" description = "Python native companion module to the graspologic library" optional = false python-versions = "<3.14,>=3.8" +groups = ["main"] files = [ {file = "graspologic_native-1.2.5-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bf05f2e162ae2a2a8d6e8cfccbe3586d1faa0b808159ff950478348df557c61e"}, {file = "graspologic_native-1.2.5-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7fff06ed49c3875cf351bb09a92ae7cbc169ce92dcc4c3439e28e801f822ae"}, @@ -1483,6 +1542,7 @@ version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -1494,6 +1554,7 @@ version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -1515,6 +1576,7 @@ version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -1527,7 +1589,7 @@ httpcore = "==1.*" idna = "*" [package.extras] -brotli = ["brotli", "brotlicffi"] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -1539,6 +1601,7 @@ version = "0.4.0" description = "A comprehensive independence testing package" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "hyppo-0.4.0-py3-none-any.whl", hash = "sha256:4e75565b8deb601485cd7bc1b5c3f44e6ddf329136fc81e65d011f9b4e95132f"}, ] @@ -1556,6 +1619,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -1570,6 +1634,7 @@ version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -1581,6 +1646,7 @@ version = "6.29.5" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, @@ -1610,13 +1676,15 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "8.36.0" +version = "8.37.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ - {file = "ipython-8.36.0-py3-none-any.whl", hash = "sha256:12b913914d010dcffa2711505ec8be4bf0180742d97f1e5175e51f22086428c1"}, - {file = "ipython-8.36.0.tar.gz", hash = "sha256:24658e9fe5c5c819455043235ba59cfffded4a35936eefceceab6b192f7092ff"}, + {file = "ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2"}, + {file = "ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216"}, ] [package.dependencies] @@ -1635,7 +1703,7 @@ typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing_extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli ; python_version < \"3.11\"", "typing_extensions"] kernel = ["ipykernel"] matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] @@ -1646,12 +1714,63 @@ qtconsole = ["qtconsole"] test = ["packaging", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] +[[package]] +name = "ipython" +version = "9.4.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.11" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066"}, + {file = "ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +ipython-pygments-lexers = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt_toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack_data = "*" +traitlets = ">=5.13.0" +typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} + +[package.extras] +all = ["ipython[doc,matplotlib,test,test-extra]"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinx_toml (==0.0.4)", "typing_extensions"] +matplotlib = ["matplotlib"] +test = ["packaging", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipykernel", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "nbclient", "nbformat", "numpy (>=1.23)", "pandas", "trio"] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +description = "Defines a variety of Pygments lexers for highlighting IPython code." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c"}, + {file = "ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81"}, +] + +[package.dependencies] +pygments = "*" + [[package]] name = "ipywidgets" version = "8.1.7" description = "Jupyter interactive widgets" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "ipywidgets-8.1.7-py3-none-any.whl", hash = "sha256:764f2602d25471c213919b8a1997df04bef869251db4ca8efba1b76b1bd9f7bb"}, {file = "ipywidgets-8.1.7.tar.gz", hash = "sha256:15f1ac050b9ccbefd45dccfbb2ef6bed0029d8278682d569d71b8dd96bee0376"}, @@ -1673,6 +1792,7 @@ version = "0.7.2" description = "An ISO 8601 date/time/duration parser and formatter" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15"}, {file = "isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"}, @@ -1684,6 +1804,7 @@ version = "20.11.0" description = "Operations with ISO 8601 durations" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, @@ -1698,6 +1819,7 @@ version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, @@ -1717,6 +1839,7 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -1734,6 +1857,7 @@ version = "0.10.0" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "jiter-0.10.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cd2fb72b02478f06a900a5782de2ef47e0396b3e1f7d5aba30daeb1fce66f303"}, {file = "jiter-0.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32bb468e3af278f095d3fa5b90314728a6916d89ba3d0ffb726dd9bf7367285e"}, @@ -1820,6 +1944,7 @@ version = "1.5.1" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a"}, {file = "joblib-1.5.1.tar.gz", hash = "sha256:f4f86e351f39fe3d0d32a9f2c3d8af1ee4cec285aafcb27003dda5205576b444"}, @@ -1831,6 +1956,7 @@ version = "0.30.3" description = "A package to repair broken json strings" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "json_repair-0.30.3-py3-none-any.whl", hash = "sha256:63bb588162b0958ae93d85356ecbe54c06b8c33f8a4834f93fa2719ea669804e"}, {file = "json_repair-0.30.3.tar.gz", hash = "sha256:0ac56e7ae9253ee9c507a7e1a3a26799c9b0bbe5e2bec1b2cc5053e90d5b05e3"}, @@ -1842,13 +1968,14 @@ version = "0.12.0" description = "A Python implementation of the JSON5 data format." optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "json5-0.12.0-py3-none-any.whl", hash = "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db"}, {file = "json5-0.12.0.tar.gz", hash = "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a"}, ] [package.extras] -dev = ["build (==1.2.2.post1)", "coverage (==7.5.4)", "coverage (==7.8.0)", "mypy (==1.14.1)", "mypy (==1.15.0)", "pip (==25.0.1)", "pylint (==3.2.7)", "pylint (==3.3.6)", "ruff (==0.11.2)", "twine (==6.1.0)", "uv (==0.6.11)"] +dev = ["build (==1.2.2.post1)", "coverage (==7.5.4) ; python_version < \"3.9\"", "coverage (==7.8.0) ; python_version >= \"3.9\"", "mypy (==1.14.1) ; python_version < \"3.9\"", "mypy (==1.15.0) ; python_version >= \"3.9\"", "pip (==25.0.1)", "pylint (==3.2.7) ; python_version < \"3.9\"", "pylint (==3.3.6) ; python_version >= \"3.9\"", "ruff (==0.11.2)", "twine (==6.1.0)", "uv (==0.6.11)"] [[package]] name = "jsonpointer" @@ -1856,6 +1983,7 @@ version = "3.0.0" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, @@ -1867,6 +1995,7 @@ version = "4.24.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d"}, {file = "jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196"}, @@ -1896,6 +2025,7 @@ version = "2025.4.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af"}, {file = "jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608"}, @@ -1910,6 +2040,7 @@ version = "1.1.1" description = "Jupyter metapackage. Install all the Jupyter components in one go." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83"}, {file = "jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a"}, @@ -1929,6 +2060,7 @@ version = "8.6.3" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"}, {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"}, @@ -1943,7 +2075,7 @@ traitlets = ">=5.3" [package.extras] docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko ; sys_platform == \"win32\"", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] [[package]] name = "jupyter-console" @@ -1951,6 +2083,7 @@ version = "6.6.3" description = "Jupyter terminal console" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485"}, {file = "jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539"}, @@ -1975,6 +2108,7 @@ version = "5.8.1" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyter_core-5.8.1-py3-none-any.whl", hash = "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0"}, {file = "jupyter_core-5.8.1.tar.gz", hash = "sha256:0a5f9706f70e64786b75acba995988915ebd4601c8a52e534a40b51c95f59941"}, @@ -1995,6 +2129,7 @@ version = "0.12.0" description = "Jupyter Event System library" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb"}, {file = "jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b"}, @@ -2021,6 +2156,7 @@ version = "2.2.5" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyter-lsp-2.2.5.tar.gz", hash = "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001"}, {file = "jupyter_lsp-2.2.5-py3-none-any.whl", hash = "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da"}, @@ -2035,6 +2171,7 @@ version = "2.16.0" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "jupyter_server-2.16.0-py3-none-any.whl", hash = "sha256:3d8db5be3bc64403b1c65b400a1d7f4647a5ce743f3b20dbdefe8ddb7b55af9e"}, {file = "jupyter_server-2.16.0.tar.gz", hash = "sha256:65d4b44fdf2dcbbdfe0aa1ace4a842d4aaf746a2b7b168134d5aaed35621b7f6"}, @@ -2071,6 +2208,7 @@ version = "0.5.3" description = "A Jupyter Server Extension Providing Terminals." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyter_server_terminals-0.5.3-py3-none-any.whl", hash = "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa"}, {file = "jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269"}, @@ -2086,13 +2224,14 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.4.3" +version = "4.4.4" description = "JupyterLab computational environment" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "jupyterlab-4.4.3-py3-none-any.whl", hash = "sha256:164302f6d4b6c44773dfc38d585665a4db401a16e5296c37df5cba63904fbdea"}, - {file = "jupyterlab-4.4.3.tar.gz", hash = "sha256:a94c32fd7f8b93e82a49dc70a6ec45a5c18281ca2a7228d12765e4e210e5bca2"}, + {file = "jupyterlab-4.4.4-py3-none-any.whl", hash = "sha256:711611e4f59851152eb93316c3547c3ec6291f16bb455f1f4fa380d25637e0dd"}, + {file = "jupyterlab-4.4.4.tar.gz", hash = "sha256:163fee1ef702e0a057f75d2eed3ed1da8a986d59eb002cbeb6f0c2779e6cd153"}, ] [package.dependencies] @@ -2124,6 +2263,7 @@ version = "0.3.0" description = "Pygments theme using JupyterLab CSS variables" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, @@ -2135,6 +2275,7 @@ version = "2.27.3" description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "jupyterlab_server-2.27.3-py3-none-any.whl", hash = "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4"}, {file = "jupyterlab_server-2.27.3.tar.gz", hash = "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4"}, @@ -2160,6 +2301,7 @@ version = "3.0.15" description = "Jupyter interactive widgets for JupyterLab" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "jupyterlab_widgets-3.0.15-py3-none-any.whl", hash = "sha256:d59023d7d7ef71400d51e6fee9a88867f6e65e10a4201605d2d7f3e8f012a31c"}, {file = "jupyterlab_widgets-3.0.15.tar.gz", hash = "sha256:2920888a0c2922351a9202817957a68c07d99673504d6cd37345299e971bb08b"}, @@ -2167,13 +2309,14 @@ files = [ [[package]] name = "jupytext" -version = "1.17.1" +version = "1.17.2" description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "jupytext-1.17.1-py3-none-any.whl", hash = "sha256:99145b1e1fa96520c21ba157de7d354ffa4904724dcebdcd70b8413688a312de"}, - {file = "jupytext-1.17.1.tar.gz", hash = "sha256:c02fda8af76ffd6e064a04cf2d3cc8aae242b2f0e38c42b4cd80baf89c3325d3"}, + {file = "jupytext-1.17.2-py3-none-any.whl", hash = "sha256:4f85dc43bb6a24b75491c5c434001ad5ef563932f68f15dd3e1c8ce12a4a426b"}, + {file = "jupytext-1.17.2.tar.gz", hash = "sha256:772d92898ac1f2ded69106f897b34af48ce4a85c985fa043a378ff5a65455f02"}, ] [package.dependencies] @@ -2200,6 +2343,7 @@ version = "1.4.8" description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "kiwisolver-1.4.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88c6f252f6816a73b1f8c904f7bbe02fd67c09a69f7cb8a0eecdbf5ce78e63db"}, {file = "kiwisolver-1.4.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72941acb7b67138f35b879bbe85be0f6c6a70cab78fe3ef6db9c024d9223e5b"}, @@ -2289,6 +2433,7 @@ version = "0.17.0" description = "lancedb" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "lancedb-0.17.0-cp39-abi3-macosx_10_15_x86_64.whl", hash = "sha256:40aac1583edda390e51189c4e95bdfd4768d23705234e12a7b81957f1143df42"}, {file = "lancedb-0.17.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:895bed499dae61cac1dbfc40ad71a566e06ab5c8d538aa57873a0cba859f8a7a"}, @@ -2320,6 +2465,7 @@ version = "3.5.0" description = "Tools for labeling human languages with IETF language tags" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "langcodes-3.5.0-py3-none-any.whl", hash = "sha256:853c69d1a35e0e13da2f427bb68fb2fa4a8f4fb899e0c62ad8df8d073dcfed33"}, {file = "langcodes-3.5.0.tar.gz", hash = "sha256:1eef8168d07e51e131a2497ffecad4b663f6208e7c3ae3b8dc15c51734a6f801"}, @@ -2338,6 +2484,7 @@ version = "1.3.0" description = "Supplementary data about languages used by the langcodes module" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "language_data-1.3.0-py3-none-any.whl", hash = "sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf"}, {file = "language_data-1.3.0.tar.gz", hash = "sha256:7600ef8aa39555145d06c89f0c324bf7dab834ea0b0a439d8243762e3ebad7ec"}, @@ -2356,6 +2503,7 @@ version = "0.44.0" description = "lightweight wrapper around basic LLVM functionality" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "llvmlite-0.44.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:9fbadbfba8422123bab5535b293da1cf72f9f478a65645ecd73e781f962ca614"}, {file = "llvmlite-0.44.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cccf8eb28f24840f2689fb1a45f9c0f7e582dd24e088dcf96e424834af11f791"}, @@ -2386,6 +2534,7 @@ version = "1.2.1" description = "Static memory-efficient and fast Trie-like structures for Python." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "marisa_trie-1.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a2eb41d2f9114d8b7bd66772c237111e00d2bae2260824560eaa0a1e291ce9e8"}, {file = "marisa_trie-1.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e956e6a46f604b17d570901e66f5214fb6f658c21e5e7665deace236793cef6"}, @@ -2473,13 +2622,14 @@ test = ["hypothesis", "pytest", "readme-renderer"] [[package]] name = "markdown" -version = "3.8" +version = "3.8.2" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc"}, - {file = "markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"}, + {file = "markdown-3.8.2-py3-none-any.whl", hash = "sha256:5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24"}, + {file = "markdown-3.8.2.tar.gz", hash = "sha256:247b9a70dd12e27f67431ce62523e675b866d254f900c4fe75ce3dda62237c45"}, ] [package.extras] @@ -2492,6 +2642,7 @@ version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -2516,6 +2667,7 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -2586,6 +2738,7 @@ version = "4.0.0" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "marshmallow-4.0.0-py3-none-any.whl", hash = "sha256:e7b0528337e9990fd64950f8a6b3a1baabed09ad17a0dfb844d701151f92d203"}, {file = "marshmallow-4.0.0.tar.gz", hash = "sha256:3b6e80aac299a7935cfb97ed01d1854fb90b5079430969af92118ea1b12a8d55"}, @@ -2606,6 +2759,7 @@ version = "3.10.3" description = "Python plotting package" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "matplotlib-3.10.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:213fadd6348d106ca7db99e113f1bea1e65e383c3ba76e8556ba4a3054b65ae7"}, {file = "matplotlib-3.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3bec61cb8221f0ca6313889308326e7bb303d0d302c5cc9e523b2f2e6c73deb"}, @@ -2663,6 +2817,7 @@ version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, @@ -2677,6 +2832,7 @@ version = "0.4.2" description = "Collection of plugins for markdown-it-py" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, @@ -2696,6 +2852,7 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -2707,6 +2864,7 @@ version = "1.3.4" description = "A deep merge function for 🐍." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, @@ -2718,6 +2876,7 @@ version = "3.1.3" description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mistune-3.1.3-py3-none-any.whl", hash = "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9"}, {file = "mistune-3.1.3.tar.gz", hash = "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0"}, @@ -2732,6 +2891,7 @@ version = "1.6.1" description = "Project documentation with Markdown." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"}, {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"}, @@ -2754,7 +2914,7 @@ watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform_system == \"Windows\"", "ghp-import (==1.0)", "importlib-metadata (==4.4) ; python_version < \"3.10\"", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] [[package]] name = "mkdocs-exclude-search" @@ -2762,6 +2922,7 @@ version = "0.6.6" description = "A mkdocs plugin that lets you exclude selected files or sections from the search index." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mkdocs-exclude-search-0.6.6.tar.gz", hash = "sha256:3cdff1b9afdc1b227019cd1e124f401453235b92153d60c0e5e651a76be4f044"}, {file = "mkdocs_exclude_search-0.6.6-py3-none-any.whl", hash = "sha256:2b4b941d1689808db533fe4a6afba75ce76c9bab8b21d4e31efc05fd8c4e0a4f"}, @@ -2776,6 +2937,7 @@ version = "0.2.0" description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, @@ -2792,6 +2954,7 @@ version = "0.25.1" description = "Use Jupyter in mkdocs websites" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "mkdocs_jupyter-0.25.1-py3-none-any.whl", hash = "sha256:3f679a857609885d322880e72533ef5255561bbfdb13cfee2a1e92ef4d4ad8d8"}, {file = "mkdocs_jupyter-0.25.1.tar.gz", hash = "sha256:0e9272ff4947e0ec683c92423a4bfb42a26477c103ab1a6ab8277e2dcc8f7afe"}, @@ -2807,13 +2970,14 @@ pygments = ">2.12.0" [[package]] name = "mkdocs-material" -version = "9.6.14" +version = "9.6.15" description = "Documentation that simply works" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "mkdocs_material-9.6.14-py3-none-any.whl", hash = "sha256:3b9cee6d3688551bf7a8e8f41afda97a3c39a12f0325436d76c86706114b721b"}, - {file = "mkdocs_material-9.6.14.tar.gz", hash = "sha256:39d795e90dce6b531387c255bd07e866e027828b7346d3eba5ac3de265053754"}, + {file = "mkdocs_material-9.6.15-py3-none-any.whl", hash = "sha256:ac969c94d4fe5eb7c924b6d2f43d7db41159ea91553d18a9afc4780c34f2717a"}, + {file = "mkdocs_material-9.6.15.tar.gz", hash = "sha256:64adf8fa8dba1a17905b6aee1894a5aafd966d4aeb44a11088519b0f5ca4f1b5"}, ] [package.dependencies] @@ -2840,6 +3004,7 @@ version = "1.3.1" description = "Extension pack for Python Markdown and MkDocs Material." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, @@ -2851,6 +3016,7 @@ version = "0.0.3" description = "An MkDocs extension to generate documentation for Typer command line applications" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "mkdocs_typer-0.0.3-py3-none-any.whl", hash = "sha256:b2a9a44da590a7100114fde4de9123fedfea692d229379984db20ee3b3f12d7c"}, {file = "mkdocs_typer-0.0.3.tar.gz", hash = "sha256:4dd37f024190a82aaf0f6c984faafb15167d34eab7e29a6a85e61362423a4eb7"}, @@ -2866,6 +3032,7 @@ version = "1.32.3" description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "msal-1.32.3-py3-none-any.whl", hash = "sha256:b2798db57760b1961b142f027ffb7c8169536bf77316e99a0df5c4aaebb11569"}, {file = "msal-1.32.3.tar.gz", hash = "sha256:5eea038689c78a5a70ca8ecbe1245458b55a857bd096efb6989c69ba15985d35"}, @@ -2877,7 +3044,7 @@ PyJWT = {version = ">=1.0.0,<3", extras = ["crypto"]} requests = ">=2.0.0,<3" [package.extras] -broker = ["pymsalruntime (>=0.14,<0.18)", "pymsalruntime (>=0.17,<0.18)"] +broker = ["pymsalruntime (>=0.14,<0.18) ; python_version >= \"3.6\" and platform_system == \"Windows\"", "pymsalruntime (>=0.17,<0.18) ; python_version >= \"3.8\" and platform_system == \"Darwin\""] [[package]] name = "msal-extensions" @@ -2885,6 +3052,7 @@ version = "1.3.1" description = "Microsoft Authentication Library extensions (MSAL EX) provides a persistence API that can save your data on disk, encrypted on Windows, macOS and Linux. Concurrent data access will be coordinated by a file lock mechanism." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "msal_extensions-1.3.1-py3-none-any.whl", hash = "sha256:96d3de4d034504e969ac5e85bae8106c8373b5c6568e4c8fa7af2eca9dbe6bca"}, {file = "msal_extensions-1.3.1.tar.gz", hash = "sha256:c5b0fd10f65ef62b5f1d62f4251d51cbcaf003fcedae8c91b040a488614be1a4"}, @@ -2902,6 +3070,7 @@ version = "1.0.13" description = "Cython bindings for MurmurHash" optional = false python-versions = "<3.14,>=3.6" +groups = ["main"] files = [ {file = "murmurhash-1.0.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:136c7017e7d59ef16f065c2285bf5d30557ad8260adf47714c3c2802725e3e07"}, {file = "murmurhash-1.0.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d0292f6fcd99361157fafad5c86d508f367931b7699cce1e14747364596950cb"}, @@ -2947,6 +3116,7 @@ version = "0.10.2" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false python-versions = ">=3.9.0" +groups = ["dev"] files = [ {file = "nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d"}, {file = "nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193"}, @@ -2969,6 +3139,7 @@ version = "7.16.6" description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "nbconvert-7.16.6-py3-none-any.whl", hash = "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b"}, {file = "nbconvert-7.16.6.tar.gz", hash = "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582"}, @@ -3005,6 +3176,7 @@ version = "5.10.4" description = "The Jupyter Notebook format" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, @@ -3026,6 +3198,7 @@ version = "1.6.0" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, @@ -3037,6 +3210,8 @@ version = "3.4.2" description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = ">=3.10" +groups = ["main"] +markers = "python_version == \"3.10\"" files = [ {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, @@ -3050,12 +3225,35 @@ example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] +[[package]] +name = "networkx" +version = "3.5" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec"}, + {file = "networkx-3.5.tar.gz", hash = "sha256:d4c6f9cf81f52d69230866796b82afbccdec3db7ae4fbd1b65ea750feed50037"}, +] + +[package.extras] +default = ["matplotlib (>=3.8)", "numpy (>=1.25)", "pandas (>=2.0)", "scipy (>=1.11.2)"] +developer = ["mypy (>=1.15)", "pre-commit (>=4.1)"] +doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=10)", "pydata-sphinx-theme (>=0.16)", "sphinx (>=8.0)", "sphinx-gallery (>=0.18)", "texext (>=0.6.7)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=2.0.0)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"] +test-extras = ["pytest-mpl", "pytest-randomly"] + [[package]] name = "nltk" version = "3.9.1" description = "Natural Language Toolkit" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1"}, {file = "nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868"}, @@ -3081,6 +3279,7 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -3088,18 +3287,19 @@ files = [ [[package]] name = "notebook" -version = "7.4.3" +version = "7.4.4" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "notebook-7.4.3-py3-none-any.whl", hash = "sha256:9cdeee954e04101cadb195d90e2ab62b7c9286c1d4f858bf3bb54e40df16c0c3"}, - {file = "notebook-7.4.3.tar.gz", hash = "sha256:a1567481cd3853f2610ee0ecf5dfa12bb508e878ee8f92152c134ef7f0568a76"}, + {file = "notebook-7.4.4-py3-none-any.whl", hash = "sha256:32840f7f777b6bff79bb101159336e9b332bdbfba1495b8739e34d1d65cbc1c0"}, + {file = "notebook-7.4.4.tar.gz", hash = "sha256:392fd501e266f2fb3466c6fcd3331163a2184968cb5c5accf90292e01dfe528c"}, ] [package.dependencies] jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.4.3,<4.5" +jupyterlab = ">=4.4.4,<4.5" jupyterlab-server = ">=2.27.1,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -3107,7 +3307,7 @@ tornado = ">=6.2.0" [package.extras] dev = ["hatch", "pre-commit"] docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["importlib-resources (>=5.0)", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.27.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] +test = ["importlib-resources (>=5.0) ; python_version < \"3.10\"", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.27.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] [[package]] name = "notebook-shim" @@ -3115,6 +3315,7 @@ version = "0.2.4" description = "A shim layer for notebook traits and config" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, @@ -3132,6 +3333,7 @@ version = "0.61.2" description = "compiling Python code using LLVM" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "numba-0.61.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:cf9f9fc00d6eca0c23fc840817ce9f439b9f03c8f03d6246c0e7f0cb15b7162a"}, {file = "numba-0.61.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ea0247617edcb5dd61f6106a56255baab031acc4257bddaeddb3a1003b4ca3fd"}, @@ -3166,6 +3368,7 @@ version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, @@ -3207,13 +3410,14 @@ files = [ [[package]] name = "openai" -version = "1.82.1" +version = "1.93.3" description = "The official Python library for the openai API" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "openai-1.82.1-py3-none-any.whl", hash = "sha256:334eb5006edf59aa464c9e932b9d137468d810b2659e5daea9b3a8c39d052395"}, - {file = "openai-1.82.1.tar.gz", hash = "sha256:ffc529680018e0417acac85f926f92aa0bbcbc26e82e2621087303c66bc7f95d"}, + {file = "openai-1.93.3-py3-none-any.whl", hash = "sha256:41aaa7594c7d141b46eed0a58dcd75d20edcc809fdd2c931ecbb4957dc98a892"}, + {file = "openai-1.93.3.tar.gz", hash = "sha256:488b76399238c694af7e4e30c58170ea55e6f65038ab27dbe95b5077a00f8af8"}, ] [package.dependencies] @@ -3227,6 +3431,7 @@ tqdm = ">4" typing-extensions = ">=4.11,<5" [package.extras] +aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.6)"] datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] realtime = ["websockets (>=13,<16)"] voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"] @@ -3237,6 +3442,7 @@ version = "7.7.0" description = "A decorator to automatically detect mismatch when overriding a method." optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, @@ -3248,6 +3454,7 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -3259,6 +3466,7 @@ version = "0.5.7" description = "Divides large result sets into pages for easier browsing" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"}, {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"}, @@ -3270,53 +3478,54 @@ lint = ["black"] [[package]] name = "pandas" -version = "2.2.3" +version = "2.3.1" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" -files = [ - {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, - {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"}, - {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, - {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, - {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"}, - {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"}, - {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"}, - {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, +groups = ["main"] +files = [ + {file = "pandas-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22c2e866f7209ebc3a8f08d75766566aae02bcc91d196935a1d9e59c7b990ac9"}, + {file = "pandas-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3583d348546201aff730c8c47e49bc159833f971c2899d6097bce68b9112a4f1"}, + {file = "pandas-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f951fbb702dacd390561e0ea45cdd8ecfa7fb56935eb3dd78e306c19104b9b0"}, + {file = "pandas-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd05b72ec02ebfb993569b4931b2e16fbb4d6ad6ce80224a3ee838387d83a191"}, + {file = "pandas-2.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1b916a627919a247d865aed068eb65eb91a344b13f5b57ab9f610b7716c92de1"}, + {file = "pandas-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fe67dc676818c186d5a3d5425250e40f179c2a89145df477dd82945eaea89e97"}, + {file = "pandas-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:2eb789ae0274672acbd3c575b0598d213345660120a257b47b5dafdc618aec83"}, + {file = "pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b"}, + {file = "pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f"}, + {file = "pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85"}, + {file = "pandas-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d"}, + {file = "pandas-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678"}, + {file = "pandas-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299"}, + {file = "pandas-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab"}, + {file = "pandas-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:689968e841136f9e542020698ee1c4fbe9caa2ed2213ae2388dc7b81721510d3"}, + {file = "pandas-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:025e92411c16cbe5bb2a4abc99732a6b132f439b8aab23a59fa593eb00704232"}, + {file = "pandas-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b7ff55f31c4fcb3e316e8f7fa194566b286d6ac430afec0d461163312c5841e"}, + {file = "pandas-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dcb79bf373a47d2a40cf7232928eb7540155abbc460925c2c96d2d30b006eb4"}, + {file = "pandas-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8"}, + {file = "pandas-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679"}, + {file = "pandas-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8"}, + {file = "pandas-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22"}, + {file = "pandas-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a"}, + {file = "pandas-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928"}, + {file = "pandas-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9"}, + {file = "pandas-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12"}, + {file = "pandas-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb"}, + {file = "pandas-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956"}, + {file = "pandas-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a"}, + {file = "pandas-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9"}, + {file = "pandas-2.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275"}, + {file = "pandas-2.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab"}, + {file = "pandas-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96"}, + {file = "pandas-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444"}, + {file = "pandas-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4645f770f98d656f11c69e81aeb21c6fca076a44bed3dcbb9396a4311bc7f6d8"}, + {file = "pandas-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:342e59589cc454aaff7484d75b816a433350b3d7964d7847327edda4d532a2e3"}, + {file = "pandas-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d12f618d80379fde6af007f65f0c25bd3e40251dbd1636480dfffce2cf1e6da"}, + {file = "pandas-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd71c47a911da120d72ef173aeac0bf5241423f9bfea57320110a978457e069e"}, + {file = "pandas-2.3.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:09e3b1587f0f3b0913e21e8b32c3119174551deb4a4eba4a89bc7377947977e7"}, + {file = "pandas-2.3.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2323294c73ed50f612f67e2bf3ae45aea04dce5690778e08a09391897f35ff88"}, + {file = "pandas-2.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4b0de34dc8499c2db34000ef8baad684cfa4cbd836ecee05f323ebfba348c7d"}, + {file = "pandas-2.3.1.tar.gz", hash = "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2"}, ] [package.dependencies] @@ -3360,6 +3569,7 @@ version = "1.5.1" description = "Utilities for writing pandoc filters in python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, @@ -3371,6 +3581,7 @@ version = "0.8.4" description = "A Python Parser" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, @@ -3386,6 +3597,7 @@ version = "0.2.1" description = "Bring colors to your terminal." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, @@ -3397,6 +3609,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -3408,6 +3621,7 @@ version = "1.0.1" description = "A Python package for describing statistical models and for building design matrices." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "patsy-1.0.1-py2.py3-none-any.whl", hash = "sha256:751fb38f9e97e62312e921a1954b81e1bb2bcda4f5eeabaf94db251ee791509c"}, {file = "patsy-1.0.1.tar.gz", hash = "sha256:e786a9391eec818c054e359b737bbce692f051aee4c661f4141cc88fb459c0c4"}, @@ -3425,6 +3639,8 @@ version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" +groups = ["dev"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, @@ -3435,101 +3651,127 @@ ptyprocess = ">=0.5" [[package]] name = "pillow" -version = "11.2.1" +version = "11.3.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.9" -files = [ - {file = "pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047"}, - {file = "pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d"}, - {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97"}, - {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579"}, - {file = "pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d"}, - {file = "pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad"}, - {file = "pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2"}, - {file = "pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70"}, - {file = "pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788"}, - {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e"}, - {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e"}, - {file = "pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6"}, - {file = "pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193"}, - {file = "pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7"}, - {file = "pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f"}, - {file = "pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4"}, - {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443"}, - {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c"}, - {file = "pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3"}, - {file = "pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941"}, - {file = "pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb"}, - {file = "pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28"}, - {file = "pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155"}, - {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14"}, - {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b"}, - {file = "pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2"}, - {file = "pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691"}, - {file = "pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c"}, - {file = "pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22"}, - {file = "pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91"}, - {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751"}, - {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9"}, - {file = "pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd"}, - {file = "pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e"}, - {file = "pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681"}, - {file = "pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8"}, - {file = "pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb"}, - {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a"}, - {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36"}, - {file = "pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67"}, - {file = "pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1"}, - {file = "pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044"}, - {file = "pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6"}, +groups = ["main"] +files = [ + {file = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"}, + {file = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e"}, + {file = "pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6"}, + {file = "pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f"}, + {file = "pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94"}, + {file = "pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0"}, + {file = "pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac"}, + {file = "pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d"}, + {file = "pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149"}, + {file = "pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d"}, + {file = "pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b"}, + {file = "pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3"}, + {file = "pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51"}, + {file = "pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c"}, + {file = "pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788"}, + {file = "pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31"}, + {file = "pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a"}, + {file = "pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214"}, + {file = "pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635"}, + {file = "pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b"}, + {file = "pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12"}, + {file = "pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db"}, + {file = "pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d"}, + {file = "pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71"}, + {file = "pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada"}, + {file = "pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8"}, + {file = "pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"}, ] [package.extras] -docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] fpx = ["olefile"] mic = ["olefile"] test-arrow = ["pyarrow"] -tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"] -typing = ["typing-extensions"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] +typing = ["typing-extensions ; python_version < \"3.10\""] xmp = ["defusedxml"] [[package]] @@ -3538,6 +3780,7 @@ version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, @@ -3554,6 +3797,7 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -3569,6 +3813,7 @@ version = "0.31.1" description = "A task runner that works well with poetry." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "poethepoet-0.31.1-py3-none-any.whl", hash = "sha256:7fdfa0ac6074be9936723e7231b5bfaad2923e96c674a9857e81d326cf8ccdc2"}, {file = "poethepoet-0.31.1.tar.gz", hash = "sha256:d6b66074edf85daf115bb916eae0afd6387d19e1562e1c9ef7d61d5c585696aa"}, @@ -3588,6 +3833,7 @@ version = "0.9.5" description = "Python Optimal Transport Library" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "POT-0.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:34d766c38e65a69c087b01a854fe89fbd152c3e8af93da2227b6c40aed6d37b9"}, {file = "POT-0.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5407377256de11b6fdc94bbba9b50ea5a2301570905fc9014541cc8473806d9"}, @@ -3652,6 +3898,7 @@ version = "3.0.10" description = "Cython hash table that trusts the keys are pre-hashed" optional = false python-versions = "<3.14,>=3.6" +groups = ["main"] files = [ {file = "preshed-3.0.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:14593c32e6705fda0fd54684293ca079530418bb1fb036dcbaa6c0ef0f144b7d"}, {file = "preshed-3.0.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba1960a3996678aded882260133853e19e3a251d9f35a19c9d7d830c4238c4eb"}, @@ -3697,13 +3944,14 @@ murmurhash = ">=0.28.0,<1.1.0" [[package]] name = "prometheus-client" -version = "0.22.0" +version = "0.22.1" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "prometheus_client-0.22.0-py3-none-any.whl", hash = "sha256:c8951bbe64e62b96cd8e8f5d917279d1b9b91ab766793f33d4dce6c228558713"}, - {file = "prometheus_client-0.22.0.tar.gz", hash = "sha256:18da1d2241ac2d10c8d2110f13eedcd5c7c0c8af18c926e8731f04fc10cd575c"}, + {file = "prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094"}, + {file = "prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28"}, ] [package.extras] @@ -3715,6 +3963,7 @@ version = "3.0.51" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, @@ -3729,6 +3978,7 @@ version = "7.0.0" description = "Cross-platform lib for process and system monitoring in Python. NOTE: the syntax of this script MUST be kept compatible with Python 2.7." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25"}, {file = "psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da"}, @@ -3752,6 +4002,8 @@ version = "0.7.0" description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" +groups = ["dev"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\" or os_name != \"nt\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -3763,6 +4015,7 @@ version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, @@ -3777,6 +4030,7 @@ version = "20.0.0" description = "Python library for Apache Arrow" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7"}, {file = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4"}, @@ -3844,20 +4098,23 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] +markers = {main = "platform_python_implementation != \"PyPy\""} [[package]] name = "pydantic" -version = "2.11.5" +version = "2.11.7" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7"}, - {file = "pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a"}, + {file = "pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b"}, + {file = "pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db"}, ] [package.dependencies] @@ -3868,7 +4125,7 @@ typing-inspection = ">=0.4.0" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" @@ -3876,6 +4133,7 @@ version = "2.33.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, @@ -3983,13 +4241,14 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pygments" -version = "2.19.1" +version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, ] [package.extras] @@ -4001,6 +4260,7 @@ version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -4021,6 +4281,7 @@ version = "0.20.0" description = "python wrapper for Lance columnar format" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pylance-0.20.0-cp39-abi3-macosx_10_15_x86_64.whl", hash = "sha256:fbb640b00567ff79d23a5994c0f0bc97587fcf74ece6ca568e77c453f70801c5"}, {file = "pylance-0.20.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:c8e30f1b6429b843429fde8f3d6fb7e715153174161e3bcf29902e2d32ee471f"}, @@ -4039,19 +4300,20 @@ benchmarks = ["pytest-benchmark"] cuvs-cu11 = ["cuvs-cu11", "pylibraft-cu11"] cuvs-cu12 = ["cuvs-cu12", "pylibraft-cu12"] dev = ["ruff (==0.4.1)"] -ray = ["ray[data] (<2.38)"] +ray = ["ray[data] (<2.38) ; python_version < \"3.12\""] tests = ["boto3", "datasets", "duckdb", "ml-dtypes", "pandas", "pillow", "polars[pandas,pyarrow]", "pytest", "tensorflow", "tqdm"] torch = ["torch"] [[package]] name = "pymdown-extensions" -version = "10.15" +version = "10.16" description = "Extension pack for Python Markdown." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pymdown_extensions-10.15-py3-none-any.whl", hash = "sha256:46e99bb272612b0de3b7e7caf6da8dd5f4ca5212c0b273feb9304e236c484e5f"}, - {file = "pymdown_extensions-10.15.tar.gz", hash = "sha256:0e5994e32155f4b03504f939e501b981d306daf7ec2aa1cd2eb6bd300784f8f7"}, + {file = "pymdown_extensions-10.16-py3-none-any.whl", hash = "sha256:f5dd064a4db588cb2d95229fc4ee63a1b16cc8b4d0e6145c0899ed8723da1df2"}, + {file = "pymdown_extensions-10.16.tar.gz", hash = "sha256:71dac4fca63fabeffd3eb9038b756161a33ec6e8d230853d3cecf562155ab3de"}, ] [package.dependencies] @@ -4067,6 +4329,7 @@ version = "0.5.13" description = "Nearest Neighbor Descent" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pynndescent-0.5.13-py3-none-any.whl", hash = "sha256:69aabb8f394bc631b6ac475a1c7f3994c54adf3f51cd63b2730fefba5771b949"}, {file = "pynndescent-0.5.13.tar.gz", hash = "sha256:d74254c0ee0a1eeec84597d5fe89fedcf778593eeabe32c2f97412934a9800fb"}, @@ -4085,6 +4348,7 @@ version = "3.2.3" description = "pyparsing module - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, @@ -4095,13 +4359,14 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyright" -version = "1.1.401" +version = "1.1.403" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "pyright-1.1.401-py3-none-any.whl", hash = "sha256:6fde30492ba5b0d7667c16ecaf6c699fab8d7a1263f6a18549e0b00bf7724c06"}, - {file = "pyright-1.1.401.tar.gz", hash = "sha256:788a82b6611fa5e34a326a921d86d898768cddf59edde8e93e56087d277cc6f1"}, + {file = "pyright-1.1.403-py3-none-any.whl", hash = "sha256:c0eeca5aa76cbef3fcc271259bbd785753c7ad7bcac99a9162b4c4c7daed23b3"}, + {file = "pyright-1.1.403.tar.gz", hash = "sha256:3ab69b9f41c67fb5bbb4d7a36243256f0d549ed3608678d381d5f51863921104"}, ] [package.dependencies] @@ -4115,25 +4380,27 @@ nodejs = ["nodejs-wheel-binaries"] [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, - {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, + {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, + {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, ] [package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1" +packaging = ">=20" pluggy = ">=1.5,<2" +pygments = ">=2.7.2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" @@ -4141,6 +4408,7 @@ version = "0.24.0" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b"}, {file = "pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276"}, @@ -4159,6 +4427,7 @@ version = "0.5.2" description = "A py.test plugin that parses environment files before running tests" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "pytest-dotenv-0.5.2.tar.gz", hash = "sha256:2dc6c3ac6d8764c71c6d2804e902d0ff810fa19692e95fe138aefc9b1aa73732"}, {file = "pytest_dotenv-0.5.2-py3-none-any.whl", hash = "sha256:40a2cece120a213898afaa5407673f6bd924b1fa7eafce6bda0e8abffe2f710f"}, @@ -4174,6 +4443,7 @@ version = "2.4.0" description = "pytest plugin to abort hanging tests" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest_timeout-2.4.0-py3-none-any.whl", hash = "sha256:c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2"}, {file = "pytest_timeout-2.4.0.tar.gz", hash = "sha256:7e68e90b01f9eff71332b25001f85c75495fc4e3a836701876183c4bcfd0540a"}, @@ -4188,6 +4458,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -4198,13 +4469,14 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "1.1.0" +version = "1.1.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d"}, - {file = "python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5"}, + {file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"}, + {file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"}, ] [package.extras] @@ -4216,13 +4488,14 @@ version = "3.3.0" description = "JSON Log Formatter for the Python Logging Package" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7"}, {file = "python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84"}, ] [package.extras] -dev = ["backports.zoneinfo", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec", "mypy", "orjson", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] [[package]] name = "pytz" @@ -4230,6 +4503,7 @@ version = "2025.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, @@ -4241,6 +4515,8 @@ version = "310" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["dev"] +markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"" files = [ {file = "pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1"}, {file = "pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d"}, @@ -4266,6 +4542,8 @@ version = "2.0.15" description = "Pseudo terminal support for Windows from Python." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "os_name == \"nt\"" files = [ {file = "pywinpty-2.0.15-cp310-cp310-win_amd64.whl", hash = "sha256:8e7f5de756a615a38b96cd86fa3cd65f901ce54ce147a3179c45907fa11b4c4e"}, {file = "pywinpty-2.0.15-cp311-cp311-win_amd64.whl", hash = "sha256:9a6bcec2df2707aaa9d08b86071970ee32c5026e10bcc3cc5f6f391d85baf7ca"}, @@ -4282,6 +4560,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -4344,6 +4623,7 @@ version = "1.1" description = "A custom YAML tag for referencing environment variables in YAML files." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04"}, {file = "pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff"}, @@ -4354,104 +4634,91 @@ pyyaml = "*" [[package]] name = "pyzmq" -version = "26.4.0" +version = "27.0.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.8" -files = [ - {file = "pyzmq-26.4.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:0329bdf83e170ac133f44a233fc651f6ed66ef8e66693b5af7d54f45d1ef5918"}, - {file = "pyzmq-26.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:398a825d2dea96227cf6460ce0a174cf7657d6f6827807d4d1ae9d0f9ae64315"}, - {file = "pyzmq-26.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d52d62edc96787f5c1dfa6c6ccff9b581cfae5a70d94ec4c8da157656c73b5b"}, - {file = "pyzmq-26.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1410c3a3705db68d11eb2424d75894d41cff2f64d948ffe245dd97a9debfebf4"}, - {file = "pyzmq-26.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:7dacb06a9c83b007cc01e8e5277f94c95c453c5851aac5e83efe93e72226353f"}, - {file = "pyzmq-26.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6bab961c8c9b3a4dc94d26e9b2cdf84de9918931d01d6ff38c721a83ab3c0ef5"}, - {file = "pyzmq-26.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7a5c09413b924d96af2aa8b57e76b9b0058284d60e2fc3730ce0f979031d162a"}, - {file = "pyzmq-26.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7d489ac234d38e57f458fdbd12a996bfe990ac028feaf6f3c1e81ff766513d3b"}, - {file = "pyzmq-26.4.0-cp310-cp310-win32.whl", hash = "sha256:dea1c8db78fb1b4b7dc9f8e213d0af3fc8ecd2c51a1d5a3ca1cde1bda034a980"}, - {file = "pyzmq-26.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:fa59e1f5a224b5e04dc6c101d7186058efa68288c2d714aa12d27603ae93318b"}, - {file = "pyzmq-26.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:a651fe2f447672f4a815e22e74630b6b1ec3a1ab670c95e5e5e28dcd4e69bbb5"}, - {file = "pyzmq-26.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:bfcf82644c9b45ddd7cd2a041f3ff8dce4a0904429b74d73a439e8cab1bd9e54"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9bcae3979b2654d5289d3490742378b2f3ce804b0b5fd42036074e2bf35b030"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccdff8ac4246b6fb60dcf3982dfaeeff5dd04f36051fe0632748fc0aa0679c01"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4550af385b442dc2d55ab7717837812799d3674cb12f9a3aa897611839c18e9e"}, - {file = "pyzmq-26.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f7ffe9db1187a253fca95191854b3fda24696f086e8789d1d449308a34b88"}, - {file = "pyzmq-26.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3709c9ff7ba61589b7372923fd82b99a81932b592a5c7f1a24147c91da9a68d6"}, - {file = "pyzmq-26.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f8f3c30fb2d26ae5ce36b59768ba60fb72507ea9efc72f8f69fa088450cff1df"}, - {file = "pyzmq-26.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:382a4a48c8080e273427fc692037e3f7d2851959ffe40864f2db32646eeb3cef"}, - {file = "pyzmq-26.4.0-cp311-cp311-win32.whl", hash = "sha256:d56aad0517d4c09e3b4f15adebba8f6372c5102c27742a5bdbfc74a7dceb8fca"}, - {file = "pyzmq-26.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:963977ac8baed7058c1e126014f3fe58b3773f45c78cce7af5c26c09b6823896"}, - {file = "pyzmq-26.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0c8e8cadc81e44cc5088fcd53b9b3b4ce9344815f6c4a03aec653509296fae3"}, - {file = "pyzmq-26.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:5227cb8da4b6f68acfd48d20c588197fd67745c278827d5238c707daf579227b"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1c07a7fa7f7ba86554a2b1bef198c9fed570c08ee062fd2fd6a4dcacd45f905"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae775fa83f52f52de73183f7ef5395186f7105d5ed65b1ae65ba27cb1260de2b"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c760d0226ebd52f1e6b644a9e839b5db1e107a23f2fcd46ec0569a4fdd4e63"}, - {file = "pyzmq-26.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ef8c6ecc1d520debc147173eaa3765d53f06cd8dbe7bd377064cdbc53ab456f5"}, - {file = "pyzmq-26.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3150ef4084e163dec29ae667b10d96aad309b668fac6810c9e8c27cf543d6e0b"}, - {file = "pyzmq-26.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4448c9e55bf8329fa1dcedd32f661bf611214fa70c8e02fee4347bc589d39a84"}, - {file = "pyzmq-26.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e07dde3647afb084d985310d067a3efa6efad0621ee10826f2cb2f9a31b89d2f"}, - {file = "pyzmq-26.4.0-cp312-cp312-win32.whl", hash = "sha256:ba034a32ecf9af72adfa5ee383ad0fd4f4e38cdb62b13624278ef768fe5b5b44"}, - {file = "pyzmq-26.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:056a97aab4064f526ecb32f4343917a4022a5d9efb6b9df990ff72e1879e40be"}, - {file = "pyzmq-26.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f23c750e485ce1eb639dbd576d27d168595908aa2d60b149e2d9e34c9df40e0"}, - {file = "pyzmq-26.4.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:c43fac689880f5174d6fc864857d1247fe5cfa22b09ed058a344ca92bf5301e3"}, - {file = "pyzmq-26.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:902aca7eba477657c5fb81c808318460328758e8367ecdd1964b6330c73cae43"}, - {file = "pyzmq-26.4.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e48a830bfd152fe17fbdeaf99ac5271aa4122521bf0d275b6b24e52ef35eb6"}, - {file = "pyzmq-26.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31be2b6de98c824c06f5574331f805707c667dc8f60cb18580b7de078479891e"}, - {file = "pyzmq-26.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6332452034be001bbf3206ac59c0d2a7713de5f25bb38b06519fc6967b7cf771"}, - {file = "pyzmq-26.4.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:da8c0f5dd352136853e6a09b1b986ee5278dfddfebd30515e16eae425c872b30"}, - {file = "pyzmq-26.4.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f4ccc1a0a2c9806dda2a2dd118a3b7b681e448f3bb354056cad44a65169f6d86"}, - {file = "pyzmq-26.4.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1c0b5fceadbab461578daf8d1dcc918ebe7ddd2952f748cf30c7cf2de5d51101"}, - {file = "pyzmq-26.4.0-cp313-cp313-win32.whl", hash = "sha256:28e2b0ff5ba4b3dd11062d905682bad33385cfa3cc03e81abd7f0822263e6637"}, - {file = "pyzmq-26.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:23ecc9d241004c10e8b4f49d12ac064cd7000e1643343944a10df98e57bc544b"}, - {file = "pyzmq-26.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:1edb0385c7f025045d6e0f759d4d3afe43c17a3d898914ec6582e6f464203c08"}, - {file = "pyzmq-26.4.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:93a29e882b2ba1db86ba5dd5e88e18e0ac6b627026c5cfbec9983422011b82d4"}, - {file = "pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45684f276f57110bb89e4300c00f1233ca631f08f5f42528a5c408a79efc4a"}, - {file = "pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f72073e75260cb301aad4258ad6150fa7f57c719b3f498cb91e31df16784d89b"}, - {file = "pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be37e24b13026cfedd233bcbbccd8c0bcd2fdd186216094d095f60076201538d"}, - {file = "pyzmq-26.4.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:237b283044934d26f1eeff4075f751b05d2f3ed42a257fc44386d00df6a270cf"}, - {file = "pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:b30f862f6768b17040929a68432c8a8be77780317f45a353cb17e423127d250c"}, - {file = "pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:c80fcd3504232f13617c6ab501124d373e4895424e65de8b72042333316f64a8"}, - {file = "pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:26a2a7451606b87f67cdeca2c2789d86f605da08b4bd616b1a9981605ca3a364"}, - {file = "pyzmq-26.4.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:831cc53bf6068d46d942af52fa8b0b9d128fb39bcf1f80d468dc9a3ae1da5bfb"}, - {file = "pyzmq-26.4.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:51d18be6193c25bd229524cfac21e39887c8d5e0217b1857998dfbef57c070a4"}, - {file = "pyzmq-26.4.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:445c97854204119ae2232503585ebb4fa7517142f71092cb129e5ee547957a1f"}, - {file = "pyzmq-26.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:807b8f4ad3e6084412c0f3df0613269f552110fa6fb91743e3e306223dbf11a6"}, - {file = "pyzmq-26.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c01d109dd675ac47fa15c0a79d256878d898f90bc10589f808b62d021d2e653c"}, - {file = "pyzmq-26.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0a294026e28679a8dd64c922e59411cb586dad307661b4d8a5c49e7bbca37621"}, - {file = "pyzmq-26.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:22c8dd677274af8dfb1efd05006d6f68fb2f054b17066e308ae20cb3f61028cf"}, - {file = "pyzmq-26.4.0-cp38-cp38-win32.whl", hash = "sha256:14fc678b696bc42c14e2d7f86ac4e97889d5e6b94d366ebcb637a768d2ad01af"}, - {file = "pyzmq-26.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1ef0a536662bbbdc8525f7e2ef19e74123ec9c4578e0582ecd41aedc414a169"}, - {file = "pyzmq-26.4.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:a88643de8abd000ce99ca72056a1a2ae15881ee365ecb24dd1d9111e43d57842"}, - {file = "pyzmq-26.4.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a744ce209ecb557406fb928f3c8c55ce79b16c3eeb682da38ef5059a9af0848"}, - {file = "pyzmq-26.4.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9434540f333332224ecb02ee6278b6c6f11ea1266b48526e73c903119b2f420f"}, - {file = "pyzmq-26.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c6f0a23e55cd38d27d4c89add963294ea091ebcb104d7fdab0f093bc5abb1c"}, - {file = "pyzmq-26.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6145df55dc2309f6ef72d70576dcd5aabb0fd373311613fe85a5e547c722b780"}, - {file = "pyzmq-26.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2ea81823840ef8c56e5d2f9918e4d571236294fea4d1842b302aebffb9e40997"}, - {file = "pyzmq-26.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc2abc385dc37835445abe206524fbc0c9e3fce87631dfaa90918a1ba8f425eb"}, - {file = "pyzmq-26.4.0-cp39-cp39-win32.whl", hash = "sha256:41a2508fe7bed4c76b4cf55aacfb8733926f59d440d9ae2b81ee8220633b4d12"}, - {file = "pyzmq-26.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:d4000e8255d6cbce38982e5622ebb90823f3409b7ffe8aeae4337ef7d6d2612a"}, - {file = "pyzmq-26.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f6919d9c120488246bdc2a2f96662fa80d67b35bd6d66218f457e722b3ff64"}, - {file = "pyzmq-26.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:98d948288ce893a2edc5ec3c438fe8de2daa5bbbd6e2e865ec5f966e237084ba"}, - {file = "pyzmq-26.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9f34f5c9e0203ece706a1003f1492a56c06c0632d86cb77bcfe77b56aacf27b"}, - {file = "pyzmq-26.4.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80c9b48aef586ff8b698359ce22f9508937c799cc1d2c9c2f7c95996f2300c94"}, - {file = "pyzmq-26.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f2a5b74009fd50b53b26f65daff23e9853e79aa86e0aa08a53a7628d92d44a"}, - {file = "pyzmq-26.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:61c5f93d7622d84cb3092d7f6398ffc77654c346545313a3737e266fc11a3beb"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4478b14cb54a805088299c25a79f27eaf530564a7a4f72bf432a040042b554eb"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a28ac29c60e4ba84b5f58605ace8ad495414a724fe7aceb7cf06cd0598d04e1"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43b03c1ceea27c6520124f4fb2ba9c647409b9abdf9a62388117148a90419494"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7731abd23a782851426d4e37deb2057bf9410848a4459b5ede4fe89342e687a9"}, - {file = "pyzmq-26.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a222ad02fbe80166b0526c038776e8042cd4e5f0dec1489a006a1df47e9040e0"}, - {file = "pyzmq-26.4.0-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:91c3ffaea475ec8bb1a32d77ebc441dcdd13cd3c4c284a6672b92a0f5ade1917"}, - {file = "pyzmq-26.4.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d9a78a52668bf5c9e7b0da36aa5760a9fc3680144e1445d68e98df78a25082ed"}, - {file = "pyzmq-26.4.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b70cab356ff8c860118b89dc86cd910c73ce2127eb986dada4fbac399ef644cf"}, - {file = "pyzmq-26.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acae207d4387780838192326b32d373bb286da0b299e733860e96f80728eb0af"}, - {file = "pyzmq-26.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f928eafd15794aa4be75463d537348b35503c1e014c5b663f206504ec1a90fe4"}, - {file = "pyzmq-26.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:552b0d2e39987733e1e9e948a0ced6ff75e0ea39ab1a1db2fc36eb60fd8760db"}, - {file = "pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd670a8aa843f2ee637039bbd412e0d7294a5e588e1ecc9ad98b0cdc050259a4"}, - {file = "pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d367b7b775a0e1e54a59a2ba3ed4d5e0a31566af97cc9154e34262777dab95ed"}, - {file = "pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112af16c406e4a93df2caef49f884f4c2bb2b558b0b5577ef0b2465d15c1abc"}, - {file = "pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c76c298683f82669cab0b6da59071f55238c039738297c69f187a542c6d40099"}, - {file = "pyzmq-26.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:49b6ca2e625b46f499fb081aaf7819a177f41eeb555acb05758aa97f4f95d147"}, - {file = "pyzmq-26.4.0.tar.gz", hash = "sha256:4bd13f85f80962f91a651a7356fe0472791a5f7a92f227822b5acf44795c626d"}, +groups = ["dev"] +files = [ + {file = "pyzmq-27.0.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:b973ee650e8f442ce482c1d99ca7ab537c69098d53a3d046676a484fd710c87a"}, + {file = "pyzmq-27.0.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:661942bc7cd0223d569d808f2e5696d9cc120acc73bf3e88a1f1be7ab648a7e4"}, + {file = "pyzmq-27.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50360fb2a056ffd16e5f4177eee67f1dd1017332ea53fb095fe7b5bf29c70246"}, + {file = "pyzmq-27.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf209a6dc4b420ed32a7093642843cbf8703ed0a7d86c16c0b98af46762ebefb"}, + {file = "pyzmq-27.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c2dace4a7041cca2fba5357a2d7c97c5effdf52f63a1ef252cfa496875a3762d"}, + {file = "pyzmq-27.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:63af72b2955fc77caf0a77444baa2431fcabb4370219da38e1a9f8d12aaebe28"}, + {file = "pyzmq-27.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e8c4adce8e37e75c4215297d7745551b8dcfa5f728f23ce09bf4e678a9399413"}, + {file = "pyzmq-27.0.0-cp310-cp310-win32.whl", hash = "sha256:5d5ef4718ecab24f785794e0e7536436698b459bfbc19a1650ef55280119d93b"}, + {file = "pyzmq-27.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:e40609380480b3d12c30f841323f42451c755b8fece84235236f5fe5ffca8c1c"}, + {file = "pyzmq-27.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:6b0397b0be277b46762956f576e04dc06ced265759e8c2ff41a0ee1aa0064198"}, + {file = "pyzmq-27.0.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:21457825249b2a53834fa969c69713f8b5a79583689387a5e7aed880963ac564"}, + {file = "pyzmq-27.0.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1958947983fef513e6e98eff9cb487b60bf14f588dc0e6bf35fa13751d2c8251"}, + {file = "pyzmq-27.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0dc628b5493f9a8cd9844b8bee9732ef587ab00002157c9329e4fc0ef4d3afa"}, + {file = "pyzmq-27.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7bbe9e1ed2c8d3da736a15694d87c12493e54cc9dc9790796f0321794bbc91f"}, + {file = "pyzmq-27.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc1091f59143b471d19eb64f54bae4f54bcf2a466ffb66fe45d94d8d734eb495"}, + {file = "pyzmq-27.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7011ade88c8e535cf140f8d1a59428676fbbce7c6e54fefce58bf117aefb6667"}, + {file = "pyzmq-27.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c386339d7e3f064213aede5d03d054b237937fbca6dd2197ac8cf3b25a6b14e"}, + {file = "pyzmq-27.0.0-cp311-cp311-win32.whl", hash = "sha256:0546a720c1f407b2172cb04b6b094a78773491497e3644863cf5c96c42df8cff"}, + {file = "pyzmq-27.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:15f39d50bd6c9091c67315ceb878a4f531957b121d2a05ebd077eb35ddc5efed"}, + {file = "pyzmq-27.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c5817641eebb391a2268c27fecd4162448e03538387093cdbd8bf3510c316b38"}, + {file = "pyzmq-27.0.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:cbabc59dcfaac66655c040dfcb8118f133fb5dde185e5fc152628354c1598e52"}, + {file = "pyzmq-27.0.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cb0ac5179cba4b2f94f1aa208fbb77b62c4c9bf24dd446278b8b602cf85fcda3"}, + {file = "pyzmq-27.0.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53a48f0228eab6cbf69fde3aa3c03cbe04e50e623ef92ae395fce47ef8a76152"}, + {file = "pyzmq-27.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:111db5f395e09f7e775f759d598f43cb815fc58e0147623c4816486e1a39dc22"}, + {file = "pyzmq-27.0.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c8878011653dcdc27cc2c57e04ff96f0471e797f5c19ac3d7813a245bcb24371"}, + {file = "pyzmq-27.0.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:c0ed2c1f335ba55b5fdc964622254917d6b782311c50e138863eda409fbb3b6d"}, + {file = "pyzmq-27.0.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e918d70862d4cfd4b1c187310015646a14e1f5917922ab45b29f28f345eeb6be"}, + {file = "pyzmq-27.0.0-cp312-abi3-win32.whl", hash = "sha256:88b4e43cab04c3c0f0d55df3b1eef62df2b629a1a369b5289a58f6fa8b07c4f4"}, + {file = "pyzmq-27.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:dce4199bf5f648a902ce37e7b3afa286f305cd2ef7a8b6ec907470ccb6c8b371"}, + {file = "pyzmq-27.0.0-cp312-abi3-win_arm64.whl", hash = "sha256:56e46bbb85d52c1072b3f809cc1ce77251d560bc036d3a312b96db1afe76db2e"}, + {file = "pyzmq-27.0.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c36ad534c0c29b4afa088dc53543c525b23c0797e01b69fef59b1a9c0e38b688"}, + {file = "pyzmq-27.0.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:67855c14173aec36395d7777aaba3cc527b393821f30143fd20b98e1ff31fd38"}, + {file = "pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8617c7d43cd8ccdb62aebe984bfed77ca8f036e6c3e46dd3dddda64b10f0ab7a"}, + {file = "pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:67bfbcbd0a04c575e8103a6061d03e393d9f80ffdb9beb3189261e9e9bc5d5e9"}, + {file = "pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5cd11d46d7b7e5958121b3eaf4cd8638eff3a720ec527692132f05a57f14341d"}, + {file = "pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:b801c2e40c5aa6072c2f4876de8dccd100af6d9918d4d0d7aa54a1d982fd4f44"}, + {file = "pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20d5cb29e8c5f76a127c75b6e7a77e846bc4b655c373baa098c26a61b7ecd0ef"}, + {file = "pyzmq-27.0.0-cp313-cp313t-win32.whl", hash = "sha256:a20528da85c7ac7a19b7384e8c3f8fa707841fd85afc4ed56eda59d93e3d98ad"}, + {file = "pyzmq-27.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d8229f2efece6a660ee211d74d91dbc2a76b95544d46c74c615e491900dc107f"}, + {file = "pyzmq-27.0.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:f4162dbbd9c5c84fb930a36f290b08c93e35fce020d768a16fc8891a2f72bab8"}, + {file = "pyzmq-27.0.0-cp38-cp38-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e7d0a8d460fba526cc047333bdcbf172a159b8bd6be8c3eb63a416ff9ba1477"}, + {file = "pyzmq-27.0.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:29f44e3c26b9783816ba9ce274110435d8f5b19bbd82f7a6c7612bb1452a3597"}, + {file = "pyzmq-27.0.0-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e435540fa1da54667f0026cf1e8407fe6d8a11f1010b7f06b0b17214ebfcf5e"}, + {file = "pyzmq-27.0.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:51f5726de3532b8222e569990c8aa34664faa97038304644679a51d906e60c6e"}, + {file = "pyzmq-27.0.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:42c7555123679637c99205b1aa9e8f7d90fe29d4c243c719e347d4852545216c"}, + {file = "pyzmq-27.0.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a979b7cf9e33d86c4949df527a3018767e5f53bc3b02adf14d4d8db1db63ccc0"}, + {file = "pyzmq-27.0.0-cp38-cp38-win32.whl", hash = "sha256:26b72c5ae20bf59061c3570db835edb81d1e0706ff141747055591c4b41193f8"}, + {file = "pyzmq-27.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:55a0155b148fe0428285a30922f7213539aa84329a5ad828bca4bbbc665c70a4"}, + {file = "pyzmq-27.0.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:100f6e5052ba42b2533011d34a018a5ace34f8cac67cb03cfa37c8bdae0ca617"}, + {file = "pyzmq-27.0.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bf6c6b061efd00404b9750e2cfbd9507492c8d4b3721ded76cb03786131be2ed"}, + {file = "pyzmq-27.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee05728c0b0b2484a9fc20466fa776fffb65d95f7317a3419985b8c908563861"}, + {file = "pyzmq-27.0.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7cdf07fe0a557b131366f80727ec8ccc4b70d89f1e3f920d94a594d598d754f0"}, + {file = "pyzmq-27.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:90252fa2ff3a104219db1f5ced7032a7b5fc82d7c8d2fec2b9a3e6fd4e25576b"}, + {file = "pyzmq-27.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ea6d441c513bf18c578c73c323acf7b4184507fc244762193aa3a871333c9045"}, + {file = "pyzmq-27.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ae2b34bcfaae20c064948a4113bf8709eee89fd08317eb293ae4ebd69b4d9740"}, + {file = "pyzmq-27.0.0-cp39-cp39-win32.whl", hash = "sha256:5b10bd6f008937705cf6e7bf8b6ece5ca055991e3eb130bca8023e20b86aa9a3"}, + {file = "pyzmq-27.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:00387d12a8af4b24883895f7e6b9495dc20a66027b696536edac35cb988c38f3"}, + {file = "pyzmq-27.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:4c19d39c04c29a6619adfeb19e3735c421b3bfee082f320662f52e59c47202ba"}, + {file = "pyzmq-27.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:656c1866505a5735d0660b7da6d7147174bbf59d4975fc2b7f09f43c9bc25745"}, + {file = "pyzmq-27.0.0-pp310-pypy310_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74175b9e12779382432dd1d1f5960ebe7465d36649b98a06c6b26be24d173fab"}, + {file = "pyzmq-27.0.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8c6de908465697a8708e4d6843a1e884f567962fc61eb1706856545141d0cbb"}, + {file = "pyzmq-27.0.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c644aaacc01d0df5c7072826df45e67301f191c55f68d7b2916d83a9ddc1b551"}, + {file = "pyzmq-27.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:10f70c1d9a446a85013a36871a296007f6fe4232b530aa254baf9da3f8328bc0"}, + {file = "pyzmq-27.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd1dc59763effd1576f8368047c9c31468fce0af89d76b5067641137506792ae"}, + {file = "pyzmq-27.0.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:60e8cc82d968174650c1860d7b716366caab9973787a1c060cf8043130f7d0f7"}, + {file = "pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14fe7aaac86e4e93ea779a821967360c781d7ac5115b3f1a171ced77065a0174"}, + {file = "pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ad0562d4e6abb785be3e4dd68599c41be821b521da38c402bc9ab2a8e7ebc7e"}, + {file = "pyzmq-27.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:9df43a2459cd3a3563404c1456b2c4c69564daa7dbaf15724c09821a3329ce46"}, + {file = "pyzmq-27.0.0-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8c86ea8fe85e2eb0ffa00b53192c401477d5252f6dd1db2e2ed21c1c30d17e5e"}, + {file = "pyzmq-27.0.0-pp38-pypy38_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:c45fee3968834cd291a13da5fac128b696c9592a9493a0f7ce0b47fa03cc574d"}, + {file = "pyzmq-27.0.0-pp38-pypy38_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cae73bb6898c4e045fbed5024cb587e4110fddb66f6163bcab5f81f9d4b9c496"}, + {file = "pyzmq-27.0.0-pp38-pypy38_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26d542258c7a1f35a9cff3d887687d3235006134b0ac1c62a6fe1ad3ac10440e"}, + {file = "pyzmq-27.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:04cd50ef3b28e35ced65740fb9956a5b3f77a6ff32fcd887e3210433f437dd0f"}, + {file = "pyzmq-27.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:39ddd3ba0a641f01d8f13a3cfd4c4924eb58e660d8afe87e9061d6e8ca6f7ac3"}, + {file = "pyzmq-27.0.0-pp39-pypy39_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8ca7e6a0388dd9e1180b14728051068f4efe83e0d2de058b5ff92c63f399a73f"}, + {file = "pyzmq-27.0.0-pp39-pypy39_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2524c40891be6a3106885a3935d58452dd83eb7a5742a33cc780a1ad4c49dec0"}, + {file = "pyzmq-27.0.0-pp39-pypy39_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a56e3e5bd2d62a01744fd2f1ce21d760c7c65f030e9522738d75932a14ab62a"}, + {file = "pyzmq-27.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:096af9e133fec3a72108ddefba1e42985cb3639e9de52cfd336b6fc23aa083e9"}, + {file = "pyzmq-27.0.0.tar.gz", hash = "sha256:b1f08eeb9ce1510e6939b6e5dcd46a17765e2333daae78ecf4606808442e52cf"}, ] [package.dependencies] @@ -4463,6 +4730,7 @@ version = "0.36.2" description = "JSON Referencing + Python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, @@ -4479,6 +4747,7 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, @@ -4578,18 +4847,19 @@ files = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, + {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, + {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, ] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" +charset_normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" @@ -4603,6 +4873,7 @@ version = "0.13.0" description = "This is a small Python module for parsing Pip requirement files." optional = false python-versions = "<4.0,>=3.8" +groups = ["dev"] files = [ {file = "requirements_parser-0.13.0-py3-none-any.whl", hash = "sha256:2b3173faecf19ec5501971b7222d38f04cb45bb9d87d0ad629ca71e2e62ded14"}, {file = "requirements_parser-0.13.0.tar.gz", hash = "sha256:0843119ca2cb2331de4eb31b10d70462e39ace698fd660a915c247d2301a4418"}, @@ -4617,6 +4888,7 @@ version = "0.1.4" description = "A pure python RFC3339 validator" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] files = [ {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, @@ -4631,6 +4903,7 @@ version = "0.1.1" description = "Pure python rfc3986 validator" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] files = [ {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, @@ -4638,13 +4911,14 @@ files = [ [[package]] name = "rich" -version = "13.9.4" +version = "14.0.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" +groups = ["main", "dev"] files = [ - {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, - {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, + {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, + {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, ] [package.dependencies] @@ -4657,128 +4931,156 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.25.1" +version = "0.26.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" -files = [ - {file = "rpds_py-0.25.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9"}, - {file = "rpds_py-0.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2"}, - {file = "rpds_py-0.25.1-cp310-cp310-win32.whl", hash = "sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24"}, - {file = "rpds_py-0.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042"}, - {file = "rpds_py-0.25.1-cp311-cp311-win32.whl", hash = "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb"}, - {file = "rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728"}, - {file = "rpds_py-0.25.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559"}, - {file = "rpds_py-0.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd"}, - {file = "rpds_py-0.25.1-cp313-cp313-win32.whl", hash = "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31"}, - {file = "rpds_py-0.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500"}, - {file = "rpds_py-0.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5"}, - {file = "rpds_py-0.25.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129"}, - {file = "rpds_py-0.25.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66"}, - {file = "rpds_py-0.25.1-cp313-cp313t-win32.whl", hash = "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523"}, - {file = "rpds_py-0.25.1-cp313-cp313t-win_amd64.whl", hash = "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763"}, - {file = "rpds_py-0.25.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd"}, - {file = "rpds_py-0.25.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f"}, - {file = "rpds_py-0.25.1-cp39-cp39-win32.whl", hash = "sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449"}, - {file = "rpds_py-0.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793"}, - {file = "rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3"}, +groups = ["dev"] +files = [ + {file = "rpds_py-0.26.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37"}, + {file = "rpds_py-0.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19"}, + {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11"}, + {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f"}, + {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323"}, + {file = "rpds_py-0.26.0-cp310-cp310-win32.whl", hash = "sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45"}, + {file = "rpds_py-0.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84"}, + {file = "rpds_py-0.26.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed"}, + {file = "rpds_py-0.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3"}, + {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107"}, + {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a"}, + {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318"}, + {file = "rpds_py-0.26.0-cp311-cp311-win32.whl", hash = "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a"}, + {file = "rpds_py-0.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03"}, + {file = "rpds_py-0.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41"}, + {file = "rpds_py-0.26.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d"}, + {file = "rpds_py-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323"}, + {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158"}, + {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3"}, + {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2"}, + {file = "rpds_py-0.26.0-cp312-cp312-win32.whl", hash = "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44"}, + {file = "rpds_py-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c"}, + {file = "rpds_py-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8"}, + {file = "rpds_py-0.26.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d"}, + {file = "rpds_py-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1"}, + {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9"}, + {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9"}, + {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba"}, + {file = "rpds_py-0.26.0-cp313-cp313-win32.whl", hash = "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b"}, + {file = "rpds_py-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5"}, + {file = "rpds_py-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256"}, + {file = "rpds_py-0.26.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618"}, + {file = "rpds_py-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed"}, + {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632"}, + {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c"}, + {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0"}, + {file = "rpds_py-0.26.0-cp313-cp313t-win32.whl", hash = "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9"}, + {file = "rpds_py-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9"}, + {file = "rpds_py-0.26.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a"}, + {file = "rpds_py-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387"}, + {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af"}, + {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33"}, + {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953"}, + {file = "rpds_py-0.26.0-cp314-cp314-win32.whl", hash = "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9"}, + {file = "rpds_py-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37"}, + {file = "rpds_py-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867"}, + {file = "rpds_py-0.26.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da"}, + {file = "rpds_py-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b"}, + {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a"}, + {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170"}, + {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e"}, + {file = "rpds_py-0.26.0-cp314-cp314t-win32.whl", hash = "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f"}, + {file = "rpds_py-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7"}, + {file = "rpds_py-0.26.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226"}, + {file = "rpds_py-0.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284"}, + {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21"}, + {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292"}, + {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d"}, + {file = "rpds_py-0.26.0-cp39-cp39-win32.whl", hash = "sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51"}, + {file = "rpds_py-0.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11"}, + {file = "rpds_py-0.26.0.tar.gz", hash = "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0"}, ] [[package]] @@ -4787,6 +5089,7 @@ version = "0.8.6" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3"}, {file = "ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1"}, @@ -4810,57 +5113,53 @@ files = [ [[package]] name = "scikit-learn" -version = "1.6.1" +version = "1.7.0" description = "A set of python modules for machine learning and data mining" optional = false -python-versions = ">=3.9" -files = [ - {file = "scikit_learn-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d056391530ccd1e501056160e3c9673b4da4805eb67eb2bdf4e983e1f9c9204e"}, - {file = "scikit_learn-1.6.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:0c8d036eb937dbb568c6242fa598d551d88fb4399c0344d95c001980ec1c7d36"}, - {file = "scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8634c4bd21a2a813e0a7e3900464e6d593162a29dd35d25bdf0103b3fce60ed5"}, - {file = "scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:775da975a471c4f6f467725dff0ced5c7ac7bda5e9316b260225b48475279a1b"}, - {file = "scikit_learn-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:8a600c31592bd7dab31e1c61b9bbd6dea1b3433e67d264d17ce1017dbdce8002"}, - {file = "scikit_learn-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:72abc587c75234935e97d09aa4913a82f7b03ee0b74111dcc2881cba3c5a7b33"}, - {file = "scikit_learn-1.6.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b3b00cdc8f1317b5f33191df1386c0befd16625f49d979fe77a8d44cae82410d"}, - {file = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc4765af3386811c3ca21638f63b9cf5ecf66261cc4815c1db3f1e7dc7b79db2"}, - {file = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25fc636bdaf1cc2f4a124a116312d837148b5e10872147bdaf4887926b8c03d8"}, - {file = "scikit_learn-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:fa909b1a36e000a03c382aade0bd2063fd5680ff8b8e501660c0f59f021a6415"}, - {file = "scikit_learn-1.6.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:926f207c804104677af4857b2c609940b743d04c4c35ce0ddc8ff4f053cddc1b"}, - {file = "scikit_learn-1.6.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c2cae262064e6a9b77eee1c8e768fc46aa0b8338c6a8297b9b6759720ec0ff2"}, - {file = "scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1061b7c028a8663fb9a1a1baf9317b64a257fcb036dae5c8752b2abef31d136f"}, - {file = "scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e69fab4ebfc9c9b580a7a80111b43d214ab06250f8a7ef590a4edf72464dd86"}, - {file = "scikit_learn-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:70b1d7e85b1c96383f872a519b3375f92f14731e279a7b4c6cfd650cf5dffc52"}, - {file = "scikit_learn-1.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ffa1e9e25b3d93990e74a4be2c2fc61ee5af85811562f1288d5d055880c4322"}, - {file = "scikit_learn-1.6.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:dc5cf3d68c5a20ad6d571584c0750ec641cc46aeef1c1507be51300e6003a7e1"}, - {file = "scikit_learn-1.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c06beb2e839ecc641366000ca84f3cf6fa9faa1777e29cf0c04be6e4d096a348"}, - {file = "scikit_learn-1.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8ca8cb270fee8f1f76fa9bfd5c3507d60c6438bbee5687f81042e2bb98e5a97"}, - {file = "scikit_learn-1.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:7a1c43c8ec9fde528d664d947dc4c0789be4077a3647f232869f41d9bf50e0fb"}, - {file = "scikit_learn-1.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a17c1dea1d56dcda2fac315712f3651a1fea86565b64b48fa1bc090249cbf236"}, - {file = "scikit_learn-1.6.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6a7aa5f9908f0f28f4edaa6963c0a6183f1911e63a69aa03782f0d924c830a35"}, - {file = "scikit_learn-1.6.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0650e730afb87402baa88afbf31c07b84c98272622aaba002559b614600ca691"}, - {file = "scikit_learn-1.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:3f59fe08dc03ea158605170eb52b22a105f238a5d512c4470ddeca71feae8e5f"}, - {file = "scikit_learn-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6849dd3234e87f55dce1db34c89a810b489ead832aaf4d4550b7ea85628be6c1"}, - {file = "scikit_learn-1.6.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e7be3fa5d2eb9be7d77c3734ff1d599151bb523674be9b834e8da6abe132f44e"}, - {file = "scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44a17798172df1d3c1065e8fcf9019183f06c87609b49a124ebdf57ae6cb0107"}, - {file = "scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b7a3b86e411e4bce21186e1c180d792f3d99223dcfa3b4f597ecc92fa1a422"}, - {file = "scikit_learn-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7a73d457070e3318e32bdb3aa79a8d990474f19035464dfd8bede2883ab5dc3b"}, - {file = "scikit_learn-1.6.1.tar.gz", hash = "sha256:b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e"}, +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "scikit_learn-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9fe7f51435f49d97bd41d724bb3e11eeb939882af9c29c931a8002c357e8cdd5"}, + {file = "scikit_learn-1.7.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0c93294e1e1acbee2d029b1f2a064f26bd928b284938d51d412c22e0c977eb3"}, + {file = "scikit_learn-1.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf3755f25f145186ad8c403312f74fb90df82a4dfa1af19dc96ef35f57237a94"}, + {file = "scikit_learn-1.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2726c8787933add436fb66fb63ad18e8ef342dfb39bbbd19dc1e83e8f828a85a"}, + {file = "scikit_learn-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:e2539bb58886a531b6e86a510c0348afaadd25005604ad35966a85c2ec378800"}, + {file = "scikit_learn-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ef09b1615e1ad04dc0d0054ad50634514818a8eb3ee3dee99af3bffc0ef5007"}, + {file = "scikit_learn-1.7.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:7d7240c7b19edf6ed93403f43b0fcb0fe95b53bc0b17821f8fb88edab97085ef"}, + {file = "scikit_learn-1.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80bd3bd4e95381efc47073a720d4cbab485fc483966f1709f1fd559afac57ab8"}, + {file = "scikit_learn-1.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9dbe48d69aa38ecfc5a6cda6c5df5abef0c0ebdb2468e92437e2053f84abb8bc"}, + {file = "scikit_learn-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:8fa979313b2ffdfa049ed07252dc94038def3ecd49ea2a814db5401c07f1ecfa"}, + {file = "scikit_learn-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c2c7243d34aaede0efca7a5a96d67fddaebb4ad7e14a70991b9abee9dc5c0379"}, + {file = "scikit_learn-1.7.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:9f39f6a811bf3f15177b66c82cbe0d7b1ebad9f190737dcdef77cfca1ea3c19c"}, + {file = "scikit_learn-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63017a5f9a74963d24aac7590287149a8d0f1a0799bbe7173c0d8ba1523293c0"}, + {file = "scikit_learn-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b2f8a0b1e73e9a08b7cc498bb2aeab36cdc1f571f8ab2b35c6e5d1c7115d97d"}, + {file = "scikit_learn-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:34cc8d9d010d29fb2b7cbcd5ccc24ffdd80515f65fe9f1e4894ace36b267ce19"}, + {file = "scikit_learn-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5b7974f1f32bc586c90145df51130e02267e4b7e77cab76165c76cf43faca0d9"}, + {file = "scikit_learn-1.7.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:014e07a23fe02e65f9392898143c542a50b6001dbe89cb867e19688e468d049b"}, + {file = "scikit_learn-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e7ced20582d3a5516fb6f405fd1d254e1f5ce712bfef2589f51326af6346e8"}, + {file = "scikit_learn-1.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1babf2511e6ffd695da7a983b4e4d6de45dce39577b26b721610711081850906"}, + {file = "scikit_learn-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:5abd2acff939d5bd4701283f009b01496832d50ddafa83c90125a4e41c33e314"}, + {file = "scikit_learn-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e39d95a929b112047c25b775035c8c234c5ca67e681ce60d12413afb501129f7"}, + {file = "scikit_learn-1.7.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:0521cb460426c56fee7e07f9365b0f45ec8ca7b2d696534ac98bfb85e7ae4775"}, + {file = "scikit_learn-1.7.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:317ca9f83acbde2883bd6bb27116a741bfcb371369706b4f9973cf30e9a03b0d"}, + {file = "scikit_learn-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:126c09740a6f016e815ab985b21e3a0656835414521c81fc1a8da78b679bdb75"}, + {file = "scikit_learn-1.7.0.tar.gz", hash = "sha256:c01e869b15aec88e2cdb73d27f15bdbe03bce8e2fb43afbe77c45d399e73a5a3"}, ] [package.dependencies] joblib = ">=1.2.0" -numpy = ">=1.19.5" -scipy = ">=1.6.0" +numpy = ">=1.22.0" +scipy = ">=1.8.0" threadpoolctl = ">=3.1.0" [package.extras] -benchmark = ["matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "pandas (>=1.1.5)"] -build = ["cython (>=3.0.10)", "meson-python (>=0.16.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)"] -docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pydata-sphinx-theme (>=0.15.3)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=7.3.7)", "sphinx-copybutton (>=0.5.2)", "sphinx-design (>=0.5.0)", "sphinx-design (>=0.6.0)", "sphinx-gallery (>=0.17.1)", "sphinx-prompt (>=1.4.0)", "sphinx-remove-toctrees (>=1.0.0.post1)", "sphinxcontrib-sass (>=0.3.4)", "sphinxext-opengraph (>=0.9.1)", "towncrier (>=24.8.0)"] -examples = ["matplotlib (>=3.3.4)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)"] -install = ["joblib (>=1.2.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)", "threadpoolctl (>=3.1.0)"] -maintenance = ["conda-lock (==2.5.6)"] -tests = ["black (>=24.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.9)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.5.1)", "scikit-image (>=0.17.2)"] +benchmark = ["matplotlib (>=3.5.0)", "memory_profiler (>=0.57.0)", "pandas (>=1.4.0)"] +build = ["cython (>=3.0.10)", "meson-python (>=0.16.0)", "numpy (>=1.22.0)", "scipy (>=1.8.0)"] +docs = ["Pillow (>=8.4.0)", "matplotlib (>=3.5.0)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.4.0)", "plotly (>=5.14.0)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pydata-sphinx-theme (>=0.15.3)", "scikit-image (>=0.19.0)", "seaborn (>=0.9.0)", "sphinx (>=7.3.7)", "sphinx-copybutton (>=0.5.2)", "sphinx-design (>=0.5.0)", "sphinx-design (>=0.6.0)", "sphinx-gallery (>=0.17.1)", "sphinx-prompt (>=1.4.0)", "sphinx-remove-toctrees (>=1.0.0.post1)", "sphinxcontrib-sass (>=0.3.4)", "sphinxext-opengraph (>=0.9.1)", "towncrier (>=24.8.0)"] +examples = ["matplotlib (>=3.5.0)", "pandas (>=1.4.0)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.19.0)", "seaborn (>=0.9.0)"] +install = ["joblib (>=1.2.0)", "numpy (>=1.22.0)", "scipy (>=1.8.0)", "threadpoolctl (>=3.1.0)"] +maintenance = ["conda-lock (==3.0.1)"] +tests = ["matplotlib (>=3.5.0)", "mypy (>=1.15)", "numpydoc (>=1.2.0)", "pandas (>=1.4.0)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pyamg (>=4.2.1)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.11.7)", "scikit-image (>=0.19.0)"] [[package]] name = "scipy" @@ -4868,6 +5167,7 @@ version = "1.12.0" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, @@ -4910,6 +5210,7 @@ version = "0.13.2" description = "Statistical data visualization" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987"}, {file = "seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7"}, @@ -4931,6 +5232,7 @@ version = "2.0.6" description = "Manage properly semver in your repository" optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "semversioner-2.0.6-py2.py3-none-any.whl", hash = "sha256:b43cb76118a9cd7b5e122ec25703b93f8cf96cda445f8b881abac362ec2d03f3"}, {file = "semversioner-2.0.6.tar.gz", hash = "sha256:af7cf180c63601880e7de86cdc1fae0dd993339c5911769d9728c583b92af15c"}, @@ -4947,15 +5249,16 @@ version = "1.8.3" description = "Send file to trash natively under Mac OS X, Windows and Linux" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["dev"] files = [ {file = "Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9"}, {file = "Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf"}, ] [package.extras] -nativelib = ["pyobjc-framework-Cocoa", "pywin32"] -objc = ["pyobjc-framework-Cocoa"] -win32 = ["pywin32"] +nativelib = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\"", "pywin32 ; sys_platform == \"win32\""] +objc = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\""] +win32 = ["pywin32 ; sys_platform == \"win32\""] [[package]] name = "setuptools" @@ -4963,19 +5266,20 @@ version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] -core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] 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", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "shellingham" @@ -4983,6 +5287,7 @@ version = "1.5.4" description = "Tool to Detect Surrounding Shell" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, @@ -4994,6 +5299,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -5001,26 +5307,27 @@ files = [ [[package]] name = "smart-open" -version = "7.1.0" -description = "Utils for streaming large files (S3, HDFS, GCS, Azure Blob Storage, gzip, bz2...)" +version = "7.3.0.post1" +description = "Utils for streaming large files (S3, HDFS, GCS, SFTP, Azure Blob Storage, gzip, bz2, zst...)" optional = false -python-versions = "<4.0,>=3.7" +python-versions = "<4.0,>=3.8" +groups = ["main"] files = [ - {file = "smart_open-7.1.0-py3-none-any.whl", hash = "sha256:4b8489bb6058196258bafe901730c7db0dcf4f083f316e97269c66f45502055b"}, - {file = "smart_open-7.1.0.tar.gz", hash = "sha256:a4f09f84f0f6d3637c6543aca7b5487438877a21360e7368ccf1f704789752ba"}, + {file = "smart_open-7.3.0.post1-py3-none-any.whl", hash = "sha256:c73661a2c24bf045c1e04e08fffc585b59af023fe783d57896f590489db66fb4"}, + {file = "smart_open-7.3.0.post1.tar.gz", hash = "sha256:ce6a3d9bc1afbf6234ad13c010b77f8cd36d24636811e3c52c3b5160f5214d1e"}, ] [package.dependencies] wrapt = "*" [package.extras] -all = ["azure-common", "azure-core", "azure-storage-blob", "boto3", "google-cloud-storage (>=2.6.0)", "paramiko", "requests", "zstandard"] +all = ["smart_open[azure,gcs,http,s3,ssh,webhdfs,zst]"] azure = ["azure-common", "azure-core", "azure-storage-blob"] gcs = ["google-cloud-storage (>=2.6.0)"] http = ["requests"] s3 = ["boto3"] ssh = ["paramiko"] -test = ["awscli", "azure-common", "azure-core", "azure-storage-blob", "boto3", "google-cloud-storage (>=2.6.0)", "moto[server]", "numpy", "paramiko", "pyopenssl", "pytest", "pytest-benchmark", "pytest-rerunfailures", "requests", "responses", "zstandard"] +test = ["awscli", "moto[server]", "numpy", "pyopenssl", "pytest", "pytest-rerunfailures", "pytest_benchmark", "responses", "smart_open[all]"] webhdfs = ["requests"] zst = ["zstandard"] @@ -5030,6 +5337,7 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -5041,6 +5349,7 @@ version = "2.7" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, @@ -5052,6 +5361,7 @@ version = "3.8.7" description = "Industrial-strength Natural Language Processing (NLP) in Python" optional = false python-versions = "<3.14,>=3.9" +groups = ["main"] files = [ {file = "spacy-3.8.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6ec0368ce96cd775fb14906f04b771c912ea8393ba30f8b35f9c4dc47a420b8e"}, {file = "spacy-3.8.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5672f8a0fe7a3847e925544890be60015fbf48a60a838803425f82e849dd4f18"}, @@ -5145,6 +5455,7 @@ version = "3.0.12" description = "Legacy registered functions for spaCy backwards compatibility" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "spacy-legacy-3.0.12.tar.gz", hash = "sha256:b37d6e0c9b6e1d7ca1cf5bc7152ab64a4c4671f59c85adaf7a3fcb870357a774"}, {file = "spacy_legacy-3.0.12-py2.py3-none-any.whl", hash = "sha256:476e3bd0d05f8c339ed60f40986c07387c0a71479245d6d0f4298dbd52cda55f"}, @@ -5156,6 +5467,7 @@ version = "1.0.5" description = "Logging utilities for SpaCy" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "spacy-loggers-1.0.5.tar.gz", hash = "sha256:d60b0bdbf915a60e516cc2e653baeff946f0cfc461b452d11a4d5458c6fe5f24"}, {file = "spacy_loggers-1.0.5-py3-none-any.whl", hash = "sha256:196284c9c446cc0cdb944005384270d775fdeaf4f494d8e269466cfa497ef645"}, @@ -5167,6 +5479,7 @@ version = "2.5.1" description = "Modern high-performance serialization utilities for Python" optional = false python-versions = "<3.14,>=3.9" +groups = ["main"] files = [ {file = "srsly-2.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0cda6f65cc0dd1daf47e856b0d6c5d51db8a9343c5007723ca06903dcfe367d"}, {file = "srsly-2.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf643e6f45c266cfacea54997a1f9cfe0113fadac1ac21a1ec5b200cfe477ba0"}, @@ -5215,6 +5528,7 @@ version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, @@ -5230,41 +5544,42 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "statsmodels" -version = "0.14.4" +version = "0.14.5" description = "Statistical computations and models for Python" optional = false python-versions = ">=3.9" -files = [ - {file = "statsmodels-0.14.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7a62f1fc9086e4b7ee789a6f66b3c0fc82dd8de1edda1522d30901a0aa45e42b"}, - {file = "statsmodels-0.14.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:46ac7ddefac0c9b7b607eed1d47d11e26fe92a1bc1f4d9af48aeed4e21e87981"}, - {file = "statsmodels-0.14.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a337b731aa365d09bb0eab6da81446c04fde6c31976b1d8e3d3a911f0f1e07b"}, - {file = "statsmodels-0.14.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:631bb52159117c5da42ba94bd94859276b68cab25dc4cac86475bc24671143bc"}, - {file = "statsmodels-0.14.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3bb2e580d382545a65f298589809af29daeb15f9da2eb252af8f79693e618abc"}, - {file = "statsmodels-0.14.4-cp310-cp310-win_amd64.whl", hash = "sha256:9729642884147ee9db67b5a06a355890663d21f76ed608a56ac2ad98b94d201a"}, - {file = "statsmodels-0.14.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ed7e118e6e3e02d6723a079b8c97eaadeed943fa1f7f619f7148dfc7862670f"}, - {file = "statsmodels-0.14.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5f537f7d000de4a1708c63400755152b862cd4926bb81a86568e347c19c364b"}, - {file = "statsmodels-0.14.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa74aaa26eaa5012b0a01deeaa8a777595d0835d3d6c7175f2ac65435a7324d2"}, - {file = "statsmodels-0.14.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e332c2d9b806083d1797231280602340c5c913f90d4caa0213a6a54679ce9331"}, - {file = "statsmodels-0.14.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9c8fa28dfd75753d9cf62769ba1fecd7e73a0be187f35cc6f54076f98aa3f3f"}, - {file = "statsmodels-0.14.4-cp311-cp311-win_amd64.whl", hash = "sha256:a6087ecb0714f7c59eb24c22781491e6f1cfffb660b4740e167625ca4f052056"}, - {file = "statsmodels-0.14.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5221dba7424cf4f2561b22e9081de85f5bb871228581124a0d1b572708545199"}, - {file = "statsmodels-0.14.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:17672b30c6b98afe2b095591e32d1d66d4372f2651428e433f16a3667f19eabb"}, - {file = "statsmodels-0.14.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab5e6312213b8cfb9dca93dd46a0f4dccb856541f91d3306227c3d92f7659245"}, - {file = "statsmodels-0.14.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bbb150620b53133d6cd1c5d14c28a4f85701e6c781d9b689b53681effaa655f"}, - {file = "statsmodels-0.14.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb695c2025d122a101c2aca66d2b78813c321b60d3a7c86bb8ec4467bb53b0f9"}, - {file = "statsmodels-0.14.4-cp312-cp312-win_amd64.whl", hash = "sha256:7f7917a51766b4e074da283c507a25048ad29a18e527207883d73535e0dc6184"}, - {file = "statsmodels-0.14.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5a24f5d2c22852d807d2b42daf3a61740820b28d8381daaf59dcb7055bf1a79"}, - {file = "statsmodels-0.14.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df4f7864606fa843d7e7c0e6af288f034a2160dba14e6ccc09020a3cf67cb092"}, - {file = "statsmodels-0.14.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91341cbde9e8bea5fb419a76e09114e221567d03f34ca26e6d67ae2c27d8fe3c"}, - {file = "statsmodels-0.14.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1322286a7bfdde2790bf72d29698a1b76c20b8423a55bdcd0d457969d0041f72"}, - {file = "statsmodels-0.14.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e31b95ac603415887c9f0d344cb523889cf779bc52d68e27e2d23c358958fec7"}, - {file = "statsmodels-0.14.4-cp313-cp313-win_amd64.whl", hash = "sha256:81030108d27aecc7995cac05aa280cf8c6025f6a6119894eef648997936c2dd0"}, - {file = "statsmodels-0.14.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4793b01b7a5f5424f5a1dbcefc614c83c7608aa2b035f087538253007c339d5d"}, - {file = "statsmodels-0.14.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d330da34f59f1653c5193f9fe3a3a258977c880746db7f155fc33713ea858db5"}, - {file = "statsmodels-0.14.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e9ddefba1d4e1107c1f20f601b0581421ea3ad9fd75ce3c2ba6a76b6dc4682c"}, - {file = "statsmodels-0.14.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f43da7957e00190104c5dd0f661bfc6dfc68b87313e3f9c4dbd5e7d222e0aeb"}, - {file = "statsmodels-0.14.4-cp39-cp39-win_amd64.whl", hash = "sha256:8286f69a5e1d0e0b366ffed5691140c83d3efc75da6dbf34a3d06e88abfaaab6"}, - {file = "statsmodels-0.14.4.tar.gz", hash = "sha256:5d69e0f39060dc72c067f9bb6e8033b6dccdb0bae101d76a7ef0bcc94e898b67"}, +groups = ["main"] +files = [ + {file = "statsmodels-0.14.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9fc2b5cdc0c95cba894849651fec1fa1511d365e3eb72b0cc75caac44077cd48"}, + {file = "statsmodels-0.14.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b8d96b0bbaeabd3a557c35cc7249baa9cfbc6dd305c32a9f2cbdd7f46c037e7f"}, + {file = "statsmodels-0.14.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:145bc39b2cb201efb6c83cc3f2163c269e63b0d4809801853dec6f440bd3bc37"}, + {file = "statsmodels-0.14.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7c14fb2617bb819fb2532e1424e1da2b98a3419a80e95f33365a72d437d474e"}, + {file = "statsmodels-0.14.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1e9742d8a5ac38a3bfc4b7f4b0681903920f20cbbf466d72b1fd642033846108"}, + {file = "statsmodels-0.14.5-cp310-cp310-win_amd64.whl", hash = "sha256:1cab9e6fce97caf4239cdb2df375806937da5d0b7ba2699b13af33a07f438464"}, + {file = "statsmodels-0.14.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b7091a8442076c708c926de3603653a160955e80a2b6d931475b7bb8ddc02e5"}, + {file = "statsmodels-0.14.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:128872be8f3208f4446d91ea9e4261823902fc7997fee7e1a983eb62fd3b7c6e"}, + {file = "statsmodels-0.14.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ad5aee04ae7196c429df2174df232c057e478c5fa63193d01c8ec9aae04d31"}, + {file = "statsmodels-0.14.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f402fc793458dd6d96e099acb44cd1de1428565bf7ef3030878a8daff091f08a"}, + {file = "statsmodels-0.14.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:26c028832730aebfbfd4e7501694e1f9ad31ec8536e776716673f4e7afd4059a"}, + {file = "statsmodels-0.14.5-cp311-cp311-win_amd64.whl", hash = "sha256:ec56f771d9529cdc17ed2fb2a950d100b6e83a7c5372aae8ac5bb065c474b856"}, + {file = "statsmodels-0.14.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:37e7364a39f9aa3b51d15a208c2868b90aadb8412f868530f5cba9197cb00eaa"}, + {file = "statsmodels-0.14.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4263d7f4d0f1d5ac6eb4db22e1ee34264a14d634b9332c975c9d9109b6b46e12"}, + {file = "statsmodels-0.14.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86224f6e36f38486e471e75759d241fe2912d8bc25ab157d54ee074c6aedbf45"}, + {file = "statsmodels-0.14.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3dd760a6fa80cd5e0371685c697bb9c2c0e6e1f394d975e596a1e6d0bbb9372"}, + {file = "statsmodels-0.14.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6264fb00e02f858b86bd01ef2dc05055a71d4a0cc7551b9976b07b0f0e6cf24f"}, + {file = "statsmodels-0.14.5-cp312-cp312-win_amd64.whl", hash = "sha256:b2ed065bfbaf8bb214c7201656df840457c2c8c65e1689e3eb09dc7440f9c61c"}, + {file = "statsmodels-0.14.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:906263134dd1a640e55ecb01fda4a9be7b9e08558dba9e4c4943a486fdb0c9c8"}, + {file = "statsmodels-0.14.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9118f76344f77cffbb3a9cbcff8682b325be5eed54a4b3253e09da77a74263d3"}, + {file = "statsmodels-0.14.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9dc4ee159070557c9a6c000625d85f653de437772fe7086857cff68f501afe45"}, + {file = "statsmodels-0.14.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a085d47c8ef5387279a991633883d0e700de2b0acc812d7032d165888627bef"}, + {file = "statsmodels-0.14.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f866b2ebb2904b47c342d00def83c526ef2eb1df6a9a3c94ba5fe63d0005aec"}, + {file = "statsmodels-0.14.5-cp313-cp313-win_amd64.whl", hash = "sha256:2a06bca03b7a492f88c8106103ab75f1a5ced25de90103a89f3a287518017939"}, + {file = "statsmodels-0.14.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b23b8f646dd78ef5e8d775d879208f8dc0a73418b41c16acac37361ff9ab7738"}, + {file = "statsmodels-0.14.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e5e26b21d2920905764fb0860957d08b5ba2fae4466ef41b1f7c53ecf9fc7fa"}, + {file = "statsmodels-0.14.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a060c7e0841c549c8ce2825fd6687e6757e305d9c11c9a73f6c5a0ce849bb69"}, + {file = "statsmodels-0.14.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56da20def5350d676388213a330fd40ed15d0e8dd0bb1b92c0e4b0f2a65d3ad2"}, + {file = "statsmodels-0.14.5-cp39-cp39-win_amd64.whl", hash = "sha256:afb37ca1d70d99b5fd876e8574ea46372298ae0f0a8b17e4cf0a9afd2373ae62"}, + {file = "statsmodels-0.14.5.tar.gz", hash = "sha256:de260e58cccfd2ceddf835b55a357233d6ca853a1aa4f90f7553a52cc71c6ddf"}, ] [package.dependencies] @@ -5276,8 +5591,8 @@ scipy = ">=1.8,<1.9.2 || >1.9.2" [package.extras] build = ["cython (>=3.0.10)"] -develop = ["colorama", "cython (>=3.0.10)", "cython (>=3.0.10,<4)", "flake8", "isort", "joblib", "matplotlib (>=3)", "pytest (>=7.3.0,<8)", "pytest-cov", "pytest-randomly", "pytest-xdist", "pywinpty", "setuptools-scm[toml] (>=8.0,<9.0)"] -docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "numpydoc", "pandas-datareader", "sphinx"] +develop = ["colorama", "cython (>=3.0.10)", "cython (>=3.0.10,<4)", "flake8", "isort", "jinja2", "joblib", "matplotlib (>=3)", "pytest (>=7.3.0,<8)", "pytest-cov", "pytest-randomly", "pytest-xdist", "pywinpty ; os_name == \"nt\"", "setuptools_scm[toml] (>=8.0,<9.0)"] +docs = ["ipykernel", "jupyter_client", "matplotlib", "nbconvert", "nbformat", "numpydoc", "pandas-datareader", "sphinx"] [[package]] name = "tenacity" @@ -5285,6 +5600,7 @@ version = "9.1.2" description = "Retry code until it succeeds" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138"}, {file = "tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb"}, @@ -5300,6 +5616,7 @@ version = "0.18.1" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0"}, {file = "terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e"}, @@ -5321,6 +5638,7 @@ version = "0.18.0.post0" description = "Simple, Pythonic text processing. Sentiment analysis, part-of-speech tagging, noun phrase parsing, and more." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "textblob-0.18.0.post0-py3-none-any.whl", hash = "sha256:dd0c7ec4eb7b9346ec0a3f136a63eba13e0f59890d2a693d3d6aeb8371949dca"}, {file = "textblob-0.18.0.post0.tar.gz", hash = "sha256:8131c52c630bcdf61d04c359f939c98d5b836a01fba224d9e7ae22fc274e0ccb"}, @@ -5340,6 +5658,7 @@ version = "8.3.4" description = "A refreshing functional take on deep learning, compatible with your favorite libraries" optional = false python-versions = "<3.13,>=3.9" +groups = ["main"] files = [ {file = "thinc-8.3.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:916ea79a7c7462664be9435679b7769b4fc1ecea3886db6da6118e4eb5cc8c8b"}, {file = "thinc-8.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c985ce9cf82a611f4f348c721372d073537ca0e8b7bbb8bd865c1598ddd79d1"}, @@ -5410,6 +5729,7 @@ version = "3.6.0" description = "threadpoolctl" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb"}, {file = "threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e"}, @@ -5421,6 +5741,7 @@ version = "0.9.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "tiktoken-0.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:586c16358138b96ea804c034b8acf3f5d3f0258bd2bc3b0227af4af5d622e382"}, {file = "tiktoken-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9c59ccc528c6c5dd51820b3474402f69d9a9e1d656226848ad68a8d5b2e5108"}, @@ -5468,6 +5789,7 @@ version = "1.4.0" description = "A tiny CSS parser" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}, {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}, @@ -5486,6 +5808,8 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -5527,6 +5851,7 @@ version = "0.12.5" description = "Style preserving TOML library" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"}, {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"}, @@ -5538,6 +5863,7 @@ version = "6.5.1" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "tornado-6.5.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7"}, {file = "tornado-6.5.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6"}, @@ -5559,6 +5885,7 @@ version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -5580,6 +5907,7 @@ version = "5.14.3" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, @@ -5595,6 +5923,7 @@ version = "0.16.0" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "typer-0.16.0-py3-none-any.whl", hash = "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855"}, {file = "typer-0.16.0.tar.gz", hash = "sha256:af377ffaee1dbe37ae9440cb4e8f11686ea5ce4e9bae01b84ae7c63b87f1dd3b"}, @@ -5608,24 +5937,26 @@ typing-extensions = ">=3.7.4.3" [[package]] name = "types-python-dateutil" -version = "2.9.0.20250516" +version = "2.9.0.20250708" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93"}, - {file = "types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5"}, + {file = "types_python_dateutil-2.9.0.20250708-py3-none-any.whl", hash = "sha256:4d6d0cc1cc4d24a2dc3816024e502564094497b713f7befda4d5bc7a8e3fd21f"}, + {file = "types_python_dateutil-2.9.0.20250708.tar.gz", hash = "sha256:ccdbd75dab2d6c9696c350579f34cffe2c281e4c5f27a585b2a2438dd1d5c8ab"}, ] [[package]] name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" +version = "4.14.1" +description = "Backported and Experimental Type Hints for Python 3.9+" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, + {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"}, + {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"}, ] [[package]] @@ -5634,6 +5965,7 @@ version = "0.4.1" description = "Runtime typing introspection tools" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"}, {file = "typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28"}, @@ -5648,6 +5980,7 @@ version = "2025.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" +groups = ["main"] files = [ {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, @@ -5655,27 +5988,29 @@ files = [ [[package]] name = "umap-learn" -version = "0.5.7" +version = "0.5.9.post2" description = "Uniform Manifold Approximation and Projection" optional = false -python-versions = "*" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "umap-learn-0.5.7.tar.gz", hash = "sha256:b2a97973e4c6ffcebf241100a8de589a4c84126a832ab40f296c6d9fcc5eb19e"}, - {file = "umap_learn-0.5.7-py3-none-any.whl", hash = "sha256:6a7e0be2facfa365a5ed6588447102bdbef32a0ef449535c25c97ea7e680073c"}, + {file = "umap_learn-0.5.9.post2-py3-none-any.whl", hash = "sha256:fbe51166561e0e7fab00ef3d516ac2621243b8d15cf4bef9f656d701736b16a0"}, + {file = "umap_learn-0.5.9.post2.tar.gz", hash = "sha256:bdf60462d779bd074ce177a0714ced17e6d161285590fa487f3f9548dd3c31c9"}, ] [package.dependencies] numba = ">=0.51.2" -numpy = ">=1.17" +numpy = ">=1.23" pynndescent = ">=0.5" -scikit-learn = ">=0.22" +scikit-learn = ">=1.6" scipy = ">=1.3.1" tqdm = "*" [package.extras] parametric-umap = ["tensorflow (>=2.1)"] -plot = ["bokeh", "colorcet", "datashader", "holoviews", "matplotlib", "pandas", "scikit-image", "seaborn"] +plot = ["bokeh", "colorcet", "dask", "datashader", "holoviews", "matplotlib", "pandas", "scikit-image", "seaborn"] tbb = ["tbb (>=2019.0)"] +test = ["pytest"] [[package]] name = "update-toml" @@ -5683,6 +6018,7 @@ version = "0.2.1" description = "Update a toml value from a CLI" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "update_toml-0.2.1-py3-none-any.whl", hash = "sha256:90d5d9d2efbe2f273328ec78394912c33c0f741dc3b0ae744cfc4ddbe27051f7"}, {file = "update_toml-0.2.1.tar.gz", hash = "sha256:92870b2ef8591eeffa32df674d9b4c4fce59a428f65063e138dee253bdb5d372"}, @@ -5697,6 +6033,7 @@ version = "1.3.0" description = "RFC 6570 URI Template Processor" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, @@ -5707,17 +6044,18 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, - {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, + {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, + {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -5728,6 +6066,7 @@ version = "1.1.3" description = "A lightweight console printing and formatting toolkit" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "wasabi-1.1.3-py3-none-any.whl", hash = "sha256:f76e16e8f7e79f8c4c8be49b4024ac725713ab10cd7f19350ad18a8e3f71728c"}, {file = "wasabi-1.1.3.tar.gz", hash = "sha256:4bb3008f003809db0c3e28b4daf20906ea871a2bb43f9914197d540f4f2e0878"}, @@ -5742,6 +6081,7 @@ version = "6.0.0" description = "Filesystem events monitoring" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, @@ -5784,6 +6124,7 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -5795,6 +6136,7 @@ version = "0.4.1" description = "Weasel: A small and easy workflow system" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "weasel-0.4.1-py3-none-any.whl", hash = "sha256:24140a090ea1ac512a2b2f479cc64192fd1d527a7f3627671268d08ed5ac418c"}, {file = "weasel-0.4.1.tar.gz", hash = "sha256:aabc210f072e13f6744e5c3a28037f93702433405cd35673f7c6279147085aa9"}, @@ -5817,6 +6159,7 @@ version = "24.11.1" description = "A library for working with the color formats defined by HTML and CSS." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9"}, {file = "webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6"}, @@ -5828,6 +6171,7 @@ version = "0.5.1" description = "Character encoding aliases for legacy web content" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, @@ -5839,6 +6183,7 @@ version = "1.8.0" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, @@ -5855,6 +6200,7 @@ version = "4.0.14" description = "Jupyter interactive widgets for Jupyter Notebook" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "widgetsnbextension-4.0.14-py3-none-any.whl", hash = "sha256:4875a9eaf72fbf5079dc372a51a9f268fc38d46f767cbf85c43a36da5cb9b575"}, {file = "widgetsnbextension-4.0.14.tar.gz", hash = "sha256:a3629b04e3edb893212df862038c7232f62973373869db5084aed739b437b5af"}, @@ -5866,6 +6212,7 @@ version = "1.17.2" description = "Module for decorators, wrappers and monkey patching." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, @@ -5949,6 +6296,6 @@ files = [ ] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = ">=3.10,<3.13" -content-hash = "390be45312909e1849b6f88f2c70cb8eb97f9cbe111e7833c5035c96b8d3dd37" +content-hash = "375db7d2600918867968d227a911ecf812453403836e06f84e9dd05024673edb" diff --git a/pyproject.toml b/pyproject.toml index 61f126b9df..97ccde4d13 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,6 @@ pyyaml = "^6.0.2" python-dotenv = "^1.0.1" pydantic = "^2.10.3" -rich = "^13.9.4" devtools = "^0.12.2" typing-extensions = "^4.12.2" diff --git a/tests/integration/storage/test_file_pipeline_storage.py b/tests/integration/storage/test_file_pipeline_storage.py index 034df98609..be58476480 100644 --- a/tests/integration/storage/test_file_pipeline_storage.py +++ b/tests/integration/storage/test_file_pipeline_storage.py @@ -20,7 +20,6 @@ async def test_find(): storage.find( base_dir="tests/fixtures/text/input", file_pattern=re.compile(r".*\.txt$"), - progress=None, file_filter=None, ) ) diff --git a/tests/smoke/test_fixtures.py b/tests/smoke/test_fixtures.py index 094d135607..acb9012770 100644 --- a/tests/smoke/test_fixtures.py +++ b/tests/smoke/test_fixtures.py @@ -20,7 +20,7 @@ ) from graphrag.storage.blob_pipeline_storage import BlobPipelineStorage -log = logging.getLogger(__name__) +logger = logging.getLogger(__name__) debug = os.environ.get("DEBUG") is not None gh_pages = os.environ.get("GH_PAGES") is not None @@ -137,13 +137,11 @@ def __run_indexer( "--verbose" if debug else None, "--root", root.resolve().as_posix(), - "--logger", - "print", "--method", "standard", ] command = [arg for arg in command if arg] - log.info("running command ", " ".join(command)) + logger.info("running command ", " ".join(command)) completion = subprocess.run( command, env={**os.environ, "GRAPHRAG_INPUT_FILE_TYPE": input_file_type} ) @@ -218,7 +216,7 @@ def __run_query(self, root: Path, query_config: dict[str, str]): query_config["query"], ] - log.info("running command ", " ".join(command)) + logger.info("running command ", " ".join(command)) return subprocess.run(command, capture_output=True, text=True) @cleanup(skip=debug) diff --git a/tests/unit/indexing/operations/chunk_text/test_chunk_text.py b/tests/unit/indexing/operations/chunk_text/test_chunk_text.py index c013580705..7b6c54923f 100644 --- a/tests/unit/indexing/operations/chunk_text/test_chunk_text.py +++ b/tests/unit/indexing/operations/chunk_text/test_chunk_text.py @@ -160,7 +160,7 @@ def test_run_strategy_arr_tuple_same_doc(): @mock.patch("graphrag.index.operations.chunk_text.chunk_text.load_strategy") @mock.patch("graphrag.index.operations.chunk_text.chunk_text.run_strategy") -@mock.patch("graphrag.logger.progress.ProgressTicker") +@mock.patch("graphrag.index.operations.chunk_text.chunk_text.progress_ticker") def test_chunk_text(mock_progress_ticker, mock_run_strategy, mock_load_strategy): input_data = pd.DataFrame({"name": ["The Shining"]}) column = "name" @@ -169,6 +169,7 @@ def test_chunk_text(mock_progress_ticker, mock_run_strategy, mock_load_strategy) encoding_model = "model" strategy = ChunkStrategyType.sentence callbacks = Mock() + callbacks.progress = Mock() mock_load_strategy.return_value = Mock() mock_progress_ticker.return_value = Mock() @@ -176,5 +177,5 @@ def test_chunk_text(mock_progress_ticker, mock_run_strategy, mock_load_strategy) chunk_text(input_data, column, size, overlap, encoding_model, strategy, callbacks) mock_run_strategy.assert_called_with( - mock_load_strategy(), "The Shining", ANY, mock_progress_ticker() + mock_load_strategy(), "The Shining", ANY, mock_progress_ticker.return_value ) diff --git a/tests/unit/indexing/verbs/entities/extraction/strategies/graph_intelligence/test_gi_entity_extraction.py b/tests/unit/indexing/verbs/entities/extraction/strategies/graph_intelligence/test_gi_entity_extraction.py index a2e1f1b164..13e676e9fb 100644 --- a/tests/unit/indexing/verbs/entities/extraction/strategies/graph_intelligence/test_gi_entity_extraction.py +++ b/tests/unit/indexing/verbs/entities/extraction/strategies/graph_intelligence/test_gi_entity_extraction.py @@ -16,7 +16,6 @@ async def test_run_extract_graph_single_document_correct_entities_returned(self) results = await run_extract_graph( docs=[Document("test_text", "1")], entity_types=["person"], - callbacks=None, args={ "max_gleanings": 0, "summarize_descriptions": False, @@ -51,7 +50,6 @@ async def test_run_extract_graph_multiple_documents_correct_entities_returned( results = await run_extract_graph( docs=[Document("text_1", "1"), Document("text_2", "2")], entity_types=["person"], - callbacks=None, args={ "max_gleanings": 0, "summarize_descriptions": False, @@ -88,7 +86,6 @@ async def test_run_extract_graph_multiple_documents_correct_edges_returned(self) results = await run_extract_graph( docs=[Document("text_1", "1"), Document("text_2", "2")], entity_types=["person"], - callbacks=None, args={ "max_gleanings": 0, "summarize_descriptions": False, @@ -133,7 +130,6 @@ async def test_run_extract_graph_multiple_documents_correct_entity_source_ids_ma results = await run_extract_graph( docs=[Document("text_1", "1"), Document("text_2", "2")], entity_types=["person"], - callbacks=None, args={ "max_gleanings": 0, "summarize_descriptions": False, @@ -183,7 +179,6 @@ async def test_run_extract_graph_multiple_documents_correct_edge_source_ids_mapp results = await run_extract_graph( docs=[Document("text_1", "1"), Document("text_2", "2")], entity_types=["person"], - callbacks=None, args={ "max_gleanings": 0, "summarize_descriptions": False, diff --git a/tests/unit/logger/__init__.py b/tests/unit/logger/__init__.py new file mode 100644 index 0000000000..7493c4e8ad --- /dev/null +++ b/tests/unit/logger/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Microsoft Corporation. +# Licensed under the MIT License + +"""Tests for logger module.""" diff --git a/tests/unit/logger/test_standard_logging.py b/tests/unit/logger/test_standard_logging.py new file mode 100644 index 0000000000..191165652b --- /dev/null +++ b/tests/unit/logger/test_standard_logging.py @@ -0,0 +1,199 @@ +# Copyright (c) 2024 Microsoft Corporation. +# Licensed under the MIT License + +"""Tests for standard logging functionality.""" + +import logging +import tempfile +from pathlib import Path + +from graphrag.config.enums import ReportingType +from graphrag.config.models.reporting_config import ReportingConfig +from graphrag.logger.standard_logging import init_loggers +from tests.unit.config.utils import get_default_graphrag_config + + +def test_standard_logging(): + """Test that standard logging works.""" + logger = logging.getLogger("graphrag.test") + assert logger.name == "graphrag.test" + + +def test_file_logging(): + """Test that logging to a file works.""" + with tempfile.TemporaryDirectory() as temp_dir: + log_file = Path(temp_dir) / "test.log" + + # configure logging to file using init_loggers + init_loggers(log_file=log_file) + + # get a logger and log some messages + logger = logging.getLogger("graphrag.test") + test_message = "Test file logging message" + logger.info(test_message) + + # check that the log file exists and contains our message + assert log_file.exists() + with open(log_file) as f: + content = f.read() + assert test_message in content + + # close all file handlers to ensure proper cleanup on Windows + graphrag_logger = logging.getLogger("graphrag") + for handler in graphrag_logger.handlers[:]: + if isinstance(handler, logging.FileHandler): + handler.close() + graphrag_logger.removeHandler(handler) + + +def test_logger_hierarchy(): + """Test that logger hierarchy works correctly.""" + # reset logging to default state using init_loggers + init_loggers() + + root_logger = logging.getLogger("graphrag") + child_logger = logging.getLogger("graphrag.child") + + # setting level on root should affect children + root_logger.setLevel(logging.ERROR) + assert child_logger.getEffectiveLevel() == logging.ERROR + + # clean up after test + root_logger.handlers.clear() + + +def test_init_loggers_console_enabled(): + """Test that init_loggers works with console handler.""" + init_loggers() + + logger = logging.getLogger("graphrag") + + # should have both a console handler and a file handler (default config) + console_handlers = [ + h + for h in logger.handlers + if isinstance(h, logging.StreamHandler) + and not isinstance(h, logging.FileHandler) + ] + file_handlers = [h for h in logger.handlers if isinstance(h, logging.FileHandler)] + assert len(console_handlers) > 0 + assert len(file_handlers) > 0 # Due to default file config + + # clean up + for handler in logger.handlers[:]: + if isinstance(handler, logging.FileHandler): + handler.close() + logger.handlers.clear() + + +def test_init_loggers_default_config(): + """Test that init_loggers uses default file config when none provided.""" + with tempfile.TemporaryDirectory() as temp_dir: + # call init_loggers with no config (should default to file logging) + init_loggers(root_dir=temp_dir) + + logger = logging.getLogger("graphrag") + + # Should have a file handler due to default config + file_handlers = [ + h for h in logger.handlers if isinstance(h, logging.FileHandler) + ] + assert len(file_handlers) > 0 + + # test that logging works + test_message = "Test default config message" + logger.info(test_message) + + # check that the log file was created with default structure + log_file = Path(temp_dir) / "logs" / "logs.txt" + assert log_file.exists() + + with open(log_file) as f: + content = f.read() + assert test_message in content + + # clean up + for handler in logger.handlers[:]: + if isinstance(handler, logging.FileHandler): + handler.close() + logger.handlers.clear() + + +def test_init_loggers_file_config(): + """Test that init_loggers works with file configuration.""" + with tempfile.TemporaryDirectory() as temp_dir: + config = get_default_graphrag_config(root_dir=temp_dir) + config.reporting = ReportingConfig(type=ReportingType.file, base_dir="logs") + + # call init_loggers with file config + init_loggers(config=config, root_dir=temp_dir) + + logger = logging.getLogger("graphrag") + + # should have a file handler + file_handlers = [ + h for h in logger.handlers if isinstance(h, logging.FileHandler) + ] + assert len(file_handlers) > 0 + + # test that logging works + test_message = "Test init_loggers file message" + logger.info(test_message) + + # check that the log file was created + log_file = Path(temp_dir) / "logs" / "logs.txt" + assert log_file.exists() + + with open(log_file) as f: + content = f.read() + assert test_message in content + + # clean up + for handler in logger.handlers[:]: + if isinstance(handler, logging.FileHandler): + handler.close() + logger.handlers.clear() + + +def test_init_loggers_console_config(): + """Test that init_loggers works with console configuration.""" + config = get_default_graphrag_config() + + # call init_loggers with config + init_loggers(config=config) + + logger = logging.getLogger("graphrag") + + # should have a console handler from the config + console_handlers = [ + h + for h in logger.handlers + if isinstance(h, logging.StreamHandler) + and not isinstance(h, logging.FileHandler) + ] + assert len(console_handlers) > 0 + + # clean up + logger.handlers.clear() + + +def test_init_loggers_both_console(): + """Test that init_loggers doesn't duplicate console handlers.""" + config = get_default_graphrag_config() + + # call init_loggers with config + init_loggers(config=config) + + logger = logging.getLogger("graphrag") + + # should have only one console handler (no duplicates) + console_handlers = [ + h + for h in logger.handlers + if isinstance(h, logging.StreamHandler) + and not isinstance(h, logging.FileHandler) + ] + assert len(console_handlers) == 1 + + # clean up + logger.handlers.clear()