diff --git a/.github/workflows/document.yaml b/.github/workflows/document.yaml new file mode 100644 index 0000000..bccc46d --- /dev/null +++ b/.github/workflows/document.yaml @@ -0,0 +1,66 @@ +name: document + +on: + workflow_dispatch: + push: + branches: + - main + - develop + paths: + - 'docs/**' + pull_request: + branches: + - main + - develop + paths: + - 'docs/**' + +concurrency: + group: 'pages' + cancel-in-progress: true + +permissions: + contents: write + pull-requests: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + + - name: Cache virtual environment + id: cached-virtualenv + uses: actions/cache@v4 + with: + path: .venv + key: ${{ runner.os }}-venv-${{ hashFiles('**/poetry.lock') }} + + - name: Install dependencies + if: steps.cached-virtualenv.outputs.cache-hit != 'true' + run: | + python -m venv .venv + source .venv/bin/activate + pip install --upgrade pip + pip install poetry + poetry install + + - name: Build documentation + run: | + source .venv/bin/activate + sphinx-apidoc -f -o ./docs/source ./adf_core_python + cd docs + make html + ls build/html + + - name: Deploy documentation + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/build/html diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..b9913b1 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +source/adf_core_python.* diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..f9d0012 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,8 @@ +# sphinx-documentation + +## Generate documentation + +```bash +sphinx-apidoc -f -o ./docs/source ./adf_core_python +sphinx-build -M html ./docs/source ./docs/build -a +``` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..747ffb7 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/.gitkeep b/docs/source/_static/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..d0b0168 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,40 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import os +import sys + +sys.path.insert(0, os.path.abspath("../../")) + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = "adf-core-python" +copyright = "2024, Haruki Uehara, Yuki Shimada" +author = "Haruki Uehara, Yuki Shimada" +release = "0.1.0" + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx.ext.autosummary", + "sphinx_copybutton", + "myst_parser", + "sphinxcontrib.mermaid", +] + +templates_path = ["_templates"] +exclude_patterns = [] + +language = "ja" + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "sphinx_book_theme" +html_static_path = ["_static"] diff --git a/docs/source/hands-on/clustering.md b/docs/source/hands-on/clustering.md new file mode 100644 index 0000000..5c24b98 --- /dev/null +++ b/docs/source/hands-on/clustering.md @@ -0,0 +1,299 @@ +# クラスタリングモジュール + +## クラスタリングモジュールの目的 + +複数のエージェントを動かす場合は、それらのエージェントにどのように協調させるかが重要になります。RRSでは多くのチームが、エージェントに各々の担当地域を持たせ役割分担をおこなう協調を取り入れています(他の手段による協調も取り入れています)。担当地域を割り振るためには、地図上のオブジェクトをいくつかのグループに分ける必要があります。このようなグループ分けをしてそれらを管理する場合には、クラスタリングモジュールと呼ばれるモジュールを用います。 + +本資料では、多くの世界大会参加チームが使用しているアルゴリズムを用いたクラスタリングモジュールの実装をおこないます。 + +## 開発するクラスタリングモジュールの概要 + +本資料で開発するモジュールは下の画像のように、 + +1. k-means++アルゴリズムによって地図上のオブジェクトをエージェント数分の区画に分けます。 +1. Hungarianアルゴリズムによってそれらの区画とエージェントを (間の距離の総和が最も小さくなるように)1対1で結びつけます。 + +![クラスタリングの画像](./../images/clustering_image.jpg) + +## クラスタリングモジュールの実装 + +```{note} +以降の作業では、カレントディレクトリがプロジェクトのルートディレクトリであることを前提としています。 +``` + +まず、クラスタリングモジュールを記述するためのファイルを作成します。 + +```bash +mkdir -p src//module/algorithm +touch src//module/algorithm/k_means_pp_clustering.py +``` + +次に、クラスタリングモジュールの実装を行います。 以下のコードを `k_means_pp_clustering.py` に記述してください。 + +```python +import numpy as np +from adf_core_python.core.agent.develop.develop_data import DevelopData +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo, ScenarioInfoKeys +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.agent.module.module_manager import ModuleManager +from adf_core_python.core.component.module.algorithm.clustering import Clustering +from adf_core_python.core.logger.logger import get_logger +from rcrs_core.connection.URN import Entity as EntityURN +from rcrs_core.entities.ambulanceCenter import AmbulanceCentre +from rcrs_core.entities.building import Building +from rcrs_core.entities.entity import Entity +from rcrs_core.entities.fireStation import FireStation +from rcrs_core.entities.gasStation import GasStation +from rcrs_core.entities.hydrant import Hydrant +from rcrs_core.entities.policeOffice import PoliceOffice +from rcrs_core.entities.refuge import Refuge +from rcrs_core.entities.road import Road +from rcrs_core.worldmodel.entityID import EntityID +from scipy.optimize import linear_sum_assignment +from sklearn.cluster import KMeans + +# クラスタリングのシード値 +SEED = 42 + + +class KMeansPPClustering(Clustering): + def __init__( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + module_manager: ModuleManager, + develop_data: DevelopData, + ) -> None: + super().__init__( + agent_info, world_info, scenario_info, module_manager, develop_data + ) + self._logger = get_logger(f"{self.__class__.__name__}") + + # クラスター数の設定 + self._cluster_number: int = 1 + match agent_info.get_myself().get_urn(): + case EntityURN.AMBULANCE_TEAM: + self._cluster_number = scenario_info.get_value( + ScenarioInfoKeys.SCENARIO_AGENTS_AT, + 1, + ) + case EntityURN.POLICE_FORCE: + self._cluster_number = scenario_info.get_value( + ScenarioInfoKeys.SCENARIO_AGENTS_PF, + 1, + ) + case EntityURN.FIRE_BRIGADE: + self._cluster_number = scenario_info.get_value( + ScenarioInfoKeys.SCENARIO_AGENTS_FB, + 1, + ) + + # 自分と同じクラスのエージェントのリストを取得 + self._agents: list[Entity] = world_info.get_entities_of_types( + [ + agent_info.get_myself().__class__, + ] + ) + + # クラスタリング結果を保持する変数 + self._cluster_entities: list[list[Entity]] = [] + + # クラスタリング対象のエンティティのリストを取得 + self._entities: list[Entity] = world_info.get_entities_of_types( + [ + AmbulanceCentre, + FireStation, + GasStation, + Hydrant, + PoliceOffice, + Refuge, + Road, + Building, + ] + ) + + def calculate(self) -> Clustering: + return self + + def get_cluster_number(self) -> int: + """ + クラスター数を取得する + + Returns + ------- + int + クラスター数 + """ + return self._cluster_number + + def get_cluster_index(self, entity_id: EntityID) -> int: + """ + エージェントに割り当てられたクラスターのインデックスを取得する + + Parameters + ---------- + entity_id : EntityID + エージェントのID + + Returns + ------- + int + クラスターのインデックス + """ + return self._agent_cluster_indices.get(entity_id, 0) + + def get_cluster_entities(self, cluster_index: int) -> list[Entity]: + """ + クラスターのエンティティのリストを取得する + + Parameters + ---------- + cluster_index : int + クラスターのインデックス + + Returns + ------- + list[Entity] + クラスターのエンティティのリスト + """ + if cluster_index >= len(self._cluster_entities): + return [] + return self._cluster_entities[cluster_index] + + def get_cluster_entity_ids(self, cluster_index: int) -> list[EntityID]: + """ + クラスターのエンティティのIDのリストを取得する + + Parameters + ---------- + cluster_index : int + クラスターのインデックス + + Returns + ------- + list[EntityID] + クラスターのエンティティのIDのリスト + """ + if cluster_index >= len(self._cluster_entities): + return [] + return [entity.get_id() for entity in self._cluster_entities[cluster_index]] + + def prepare(self) -> Clustering: + """ + エージェントの起動時に一回のみ実行される処理 + """ + super().prepare() + if self.get_count_prepare() > 1: + return self + + # クラスタリングを実行 + kmeans_pp = self._perform_kmeans_pp(self._entities, self._cluster_number) + + # クラスタリング結果を保持 + self._cluster_entities = [[] for _ in range(self._cluster_number)] + for entity, cluster_index in zip(self._entities, kmeans_pp.labels_): + self._cluster_entities[cluster_index].append(entity) + + # エージェントとクラスターのエンティティの距離を計算し、最も全体の合計の距離が短くなるようにエージェントとクラスターを対応付ける + agent_cluster_indices = self._agent_cluster_assignment( + self._agents, kmeans_pp.cluster_centers_ + ) + + # エージェントとクラスターの対応付け結果を保持 + self._agent_cluster_indices = { + entity.get_id(): cluster_index + for entity, cluster_index in zip(self._agents, agent_cluster_indices) + } + + # デバッグ用のログ出力 + self._logger.info( + f"Clustered entities: {[[entity.get_id().get_value() for entity in cluster] for cluster in self._cluster_entities]}" + ) + + self._logger.info( + f"Agent cluster indices: {[([self._world_info.get_entity(entity_id).get_x(), self._world_info.get_entity(entity_id).get_y()], int(cluster_index)) for entity_id, cluster_index in self._agent_cluster_indices.items()]}" + ) + + return self + + def _perform_kmeans_pp(self, entities: list[Entity], n_clusters: int = 1) -> KMeans: + """ + K-means++法によるクラスタリングを実行する + + Parameters + ---------- + entities : list[Entity] + クラスタリング対象のエンティティのリスト + + n_clusters : int, optional + クラスター数, by default 1 + + Returns + ------- + KMeans + クラスタリング結果 + """ + entity_positions: np.ndarray = np.array( + [ + [entity.get_x(), entity.get_y()] + for entity in entities + if entity.get_x() is not None and entity.get_y() is not None + ] + ) + + entity_positions = entity_positions.reshape(-1, 2) + kmeans_pp = KMeans( + n_clusters=n_clusters, + init="k-means++", + random_state=SEED, + ) + kmeans_pp.fit(entity_positions) + return kmeans_pp + + def _agent_cluster_assignment( + self, agents: list[Entity], cluster_positions: np.ndarray + ) -> np.ndarray: + """ + エージェントとクラスターの対応付けを行う + + Parameters + ---------- + agents : list[Entity] + エージェントのリスト + + cluster_positions : np.ndarray + クラスターの位置のリスト + + Returns + ------- + np.ndarray + エージェントとクラスターの対応付け結果 + """ + agent_positions = np.array( + [ + [agent.get_x(), agent.get_y()] + for agent in agents + if agent.get_x() is not None and agent.get_y() is not None + ] + ) + + agent_positions = agent_positions.reshape(-1, 2) + cost_matrix = np.linalg.norm( + agent_positions[:, np.newaxis] - cluster_positions, axis=2 + ) + _, col_ind = linear_sum_assignment(cost_matrix) + return col_ind +``` + +次に、作成したモジュールを登録します。`config/module.yaml` を以下のように編集してください。 + +```yaml +SampleSearch: + PathPlanning: adf_core_python.implement.module.algorithm.a_star_path_planning.AStarPathPlanning + Clustering: src.test-agent.module.algorithm.k_means_pp_clustering.KMeansPPClustering + +SampleHumanDetector: + Clustering: src.test-agent.module.algorithm.k_means_pp_clustering.KMeansPPClustering +``` diff --git a/docs/source/hands-on/search.md b/docs/source/hands-on/search.md new file mode 100644 index 0000000..cc48fce --- /dev/null +++ b/docs/source/hands-on/search.md @@ -0,0 +1,173 @@ +# サーチモジュール + +## サーチモジュールの概要 + +今回開発するモジュールは、`KMeansPPClustering` モジュールを用いた情報探索対象決定 (`Search`) モジュールです。 クラスタリングモジュールによってエージェント間で担当地域の分割をおこない、 担当地域内からランダムに探索対象として選択します。 + +## サーチモジュールの実装の準備 + +```{note} +以降の作業では、カレントディレクトリがプロジェクトのルートディレクトリであることを前提としています。 +``` + +まず、サーチモジュールを記述するためのファイルを作成します。 + +```bash +mkdir -p src//module/search +touch src//module/complex/k_means_pp_search.py +``` + +次に、サーチモジュールの実装を行います。 以下のコードを `k_means_pp_search.py` に記述してください。 +これが今回実装するサーチモジュールの雛形になります。 + +```python +import random +from typing import Optional, cast + +from rcrs_core.entities.building import Building +from rcrs_core.entities.entity import Entity +from rcrs_core.entities.refuge import Refuge +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.communication.message_manager import MessageManager +from adf_core_python.core.agent.develop.develop_data import DevelopData +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.agent.module.module_manager import ModuleManager +from adf_core_python.core.component.module.algorithm.clustering import Clustering +from adf_core_python.core.component.module.algorithm.path_planning import PathPlanning +from adf_core_python.core.component.module.complex.search import Search +from adf_core_python.core.logger.logger import get_agent_logger + + +class KMeansPPSearch(Search): + def __init__( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + module_manager: ModuleManager, + develop_data: DevelopData, + ) -> None: + super().__init__( + agent_info, world_info, scenario_info, module_manager, develop_data + ) + self._result: Optional[EntityID] = None + self._logger = get_agent_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}", + self._agent_info, + ) + + def calculate(self) -> Search: + return self + + def get_target_entity_id(self) -> Optional[EntityID]: + return self._result +``` + +## モジュールの登録 + +次に、作成したモジュールを登録します。 +以下のように`config/module.yaml`の該当箇所を変更してください + +```yaml +DefaultTacticsAmbulanceTeam: + Search: src..module.complex.k_means_pp_search.KMeansPPSearch + +DefaultTacticsFireBrigade: + Search: src..module.complex.k_means_pp_search.KMeansPPSearch + +DefaultTacticsPoliceForce: + Search: src..module.complex.k_means_pp_search.KMeansPPSearch +``` + +## モジュールの実装 + +まず、`KMeansPPClustering` モジュールを呼び出せるようにします。 + +以下のコードを`config/module.yaml`に追記してください。 + +```yaml +KMeansPPSearch: + Clustering: src..module.algorithm.k_means_pp_clustering.KMeansPPClustering +``` + +次に、`KMeansPPSearch` モジュールで `KMeansPPClustering` モジュールを呼び出せるようにします。 + +以下のコードを `k_means_pp_search.py` に追記してください。 + +```python +class KMeansPPSearch(Search): + def __init__( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + module_manager: ModuleManager, + develop_data: DevelopData, + ) -> None: + super().__init__( + agent_info, world_info, scenario_info, module_manager, develop_data + ) + self._result: Optional[EntityID] = None + + self._logger = get_agent_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}", + self._agent_info, + ) + + self._clustering: Clustering = cast( + Clustering, + module_manager.get_module( + "KMeansPPSearch.Clustering", + "adf_core_python.implement.module.algorithm.k_means_clustering.KMeansClustering", + ), + ) + + self.register_sub_module(self._clustering) +``` + +そして、`calculate` メソッドでクラスタリングモジュールを呼び出し、探索対象を決定します。 + +```python + def calculate(self) -> Search: + # 自エージェントのエンティティIDを取得 + me: EntityID = self._agent_info.get_entity_id() + # 自エージェントが所属するクラスターのインデックスを取得 + allocated_cluster_index: int = self._clustering.get_cluster_index(me) + # クラスター内のエンティティIDを取得 + cluster_entity_ids: list[EntityID] = self._clustering.get_cluster_entity_ids( + allocated_cluster_index + ) + # 乱数で選択 + index = random.randint(0, len(cluster_entity_ids) - 1) + # 選択したエンティティIDを結果として設定 + self._result = cluster_entity_ids[index] + + return self +``` + +以上で、`KMeansPPClustering` モジュールを用いた `KMeansPPSearch` モジュールの実装が完了しました。 + +実行すると、各エージェントが担当地域内からランダムに探索対象を選択し、探索を行います。 + +## モジュールの改善 + +`KMeansPPSearch` モジュールは、クラスタリングモジュールを用いて担当地域内からランダムに探索対象を選択しています。 +そのため、以下のような問題があります。 + +- 探索対象がステップごとに変わってしまう + - 目標にたどり着く前に探索対象が変わってしまうため、なかなか目標にたどり着けない + - 色んなところにランダムに探索対象を選択することで、効率的な探索ができない +- すでに探索したエンティティを再度探索対象として選択してしまうため、効率的な探索ができない + +などの問題があります。 + +## 課題 + +`KMeansPPSearch` モジュールを改善し、より効率的な探索を行うモジュールを実装して見てください。 + +### 探索対象がステップごとに変わってしまう問題 + +### すでに探索したエンティティを再度探索対象として選択してしまう問題 diff --git a/docs/source/images/agent_control.jpg b/docs/source/images/agent_control.jpg new file mode 100644 index 0000000..a641c8d Binary files /dev/null and b/docs/source/images/agent_control.jpg differ diff --git a/docs/source/images/agent_flow.png b/docs/source/images/agent_flow.png new file mode 100644 index 0000000..fb5720f Binary files /dev/null and b/docs/source/images/agent_flow.png differ diff --git a/docs/source/images/clustering_image.jpg b/docs/source/images/clustering_image.jpg new file mode 100644 index 0000000..6fb37eb Binary files /dev/null and b/docs/source/images/clustering_image.jpg differ diff --git a/docs/source/images/entity.png b/docs/source/images/entity.png new file mode 100644 index 0000000..503c34c Binary files /dev/null and b/docs/source/images/entity.png differ diff --git a/docs/source/images/human_detector_flow.png b/docs/source/images/human_detector_flow.png new file mode 100644 index 0000000..13856ce Binary files /dev/null and b/docs/source/images/human_detector_flow.png differ diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..5779f93 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,69 @@ +.. adf-core-python documentation master file, created by + sphinx-quickstart on Mon Oct 14 00:15:07 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +adf-core-pythonのドキュメント +============================== + +.. warning:: + + 現在このパッケージは開発中です。破壊的な変更が行われる可能性があります。 + +.. warning:: + + パッケージとしてまだ公開していないので、pip でインストールすることはできません。 + + +.. contents:: 目次 + :depth: 2 + :local: + +特徴 +---- + +- **モジュール単位での開発**: モジュール単位でエージェント開発を行い、モジュールの入れ替えが容易です。 +- **モジュールの再利用**: 他のエージェントで使用されているモジュールを再利用することができます。 +- **エージェントの開発に集中**: シミュレーションサーバーとの通信やログ出力などの共通処理をライブラリが提供します。 + +はじめに +-------- + +ADF Core Python を始めるには、インストール手順に従い、このドキュメントに記載されている例を参照してください。 + +.. toctree:: + :maxdepth: 1 + :caption: チュートリアル: + + tutorial/environment/environment + tutorial/install/install + tutorial/agent/agent + tutorial/agent/agent_control + tutorial/config/config + tutorial/module/module + +.. toctree:: + :maxdepth: 1 + :caption: ハンズオン: + + hands-on/clustering + hands-on/search + +.. toctree:: + :maxdepth: 1 + :caption: クイックスタート: + + quickstart/quickstart + +.. automodule:: adf_core_python + :members: + :undoc-members: + :show-inheritance: + + +パッケージの詳細 +--------------------- + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/modules.rst b/docs/source/modules.rst new file mode 100644 index 0000000..d0160b5 --- /dev/null +++ b/docs/source/modules.rst @@ -0,0 +1,7 @@ +adf_core_python +=============== + +.. toctree:: + :maxdepth: 4 + + adf_core_python diff --git a/docs/source/quickstart/quickstart.md b/docs/source/quickstart/quickstart.md new file mode 100644 index 0000000..4142999 --- /dev/null +++ b/docs/source/quickstart/quickstart.md @@ -0,0 +1,62 @@ +# クイックスタート + +## 前提条件 + +インストールする前に、以下の前提条件を確認してください: + +- Python 3.12 以上 +- pip + +## パッケージのインストール + +パッケージをインストールするには、次のコマンドを実行します: + +```bash +pip install adf_core_python +``` + +## 新規エージェントの作成 + +新規エージェントを作成するには、次のコマンドを実行します: + +```bash +adf-core-python +``` + +実行すると、下記のような対話形式のプロンプトが表示されます: + +```bash +Your agent team name: my-agent +Creating a new agent team with name: my-agent +``` + +入力後、下記のようなエージェントのテンプレートがカレントディレクトリに作成されます。 + +```bash +. +├── config +│ ├── development.json +│ ├── launcher.yaml +│ └── module.yaml +├── main.py +└── src + └── my-agent + ├── __init__.py + └── module + ├── __init__.py + └── complex + ├── __init__.py + ├── sample_human_detector.py + ├── sample_road_detector.py + └── sample_search.py +``` + +## エージェントを実行する + +エージェントを実行するには、シミュレーションサーバーを起動し、次のコマンドを実行します: + +```bash +python main.py +``` + +エージェントの実行が開始され、シミュレーションサーバーとの通信が開始されます。 diff --git a/docs/source/tutorial/agent/agent.md b/docs/source/tutorial/agent/agent.md new file mode 100644 index 0000000..1beb851 --- /dev/null +++ b/docs/source/tutorial/agent/agent.md @@ -0,0 +1,63 @@ +# エージェントの作成 + +このセクションでは、`adf-core-python` ライブラリの使用方法の概要を提供します。 + +## 新規エージェントの作成 + +新規エージェントを作成するには、次のコマンドを実行します: + +```bash +adf-core-python +``` + +実行すると、下記のような対話形式のプロンプトが表示されます: + +```bash +Your agent team name: my-agent +Creating a new agent team with name: my-agent +``` + +入力後、下記のようなエージェントのテンプレートがカレントディレクトリに作成されます。 + +```bash +. +└── my-agent + ├── config + │ ├── development.json + │ ├── launcher.yaml + │ └── module.yaml + ├── main.py + └── src + └── my-agent + ├── __init__.py + └── module + ├── __init__.py + └── complex + ├── __init__.py + ├── sample_human_detector.py + ├── sample_road_detector.py + └── sample_search.py +``` + +## シミュレーションを実行する + +シミュレーションサーバーを以下のコマンドで起動します: + +```bash +cd WORKING_DIR/rcrs-server/scripts +./start-comprun.sh -m ../maps/test/map -c ../maps/test/config +``` + +その後、エージェントを起動します: + +```bash +cd WORKING_DIR/my-agent +python main.py +``` + +エージェントが正常に起動すると、シミュレーションサーバーに接続され、エージェントがシミュレーションに参加し、エージェントが動き出します。 +途中で止めたい場合は、それぞれのコマンドラインで `Ctrl + C` を押してください。 + +```{warning} +シミュレーションサーバーを停止させたあとは、プロセスが残ってしまう場合があるので`./kill.sh` を実行してください。 +``` diff --git a/docs/source/tutorial/agent/agent_control.md b/docs/source/tutorial/agent/agent_control.md new file mode 100644 index 0000000..afc3457 --- /dev/null +++ b/docs/source/tutorial/agent/agent_control.md @@ -0,0 +1,315 @@ +# エージェントの制御 + +このセクションでは、エージェントの制御用のプログラムを作成する方法について説明します。 + +## エージェントの制御について + +RRSの災害救助エージェントは3種類あり、種類毎にそれぞれ異なるプログラムを書く必要があります。しかし、初めから全てのプログラムを書くことは困難です。ここではまず初めに、消防隊エージェントを操作するプログラムの一部を書いてみましょう。 + +```{note} +エージェントを操作するプログラムは、エージェントの種類毎に同一です。 プログラムは各エージェントに配られ、そのエージェントのみの操作を担います。 消防隊エージェントを操作するプログラムを書けば、それがすべての消防隊エージェント上でそれぞれ動作します。 +``` + +![消防隊エージェント](./../../images/agent_control.jpg) + +## エージェントの動作フロー + +エージェントの動作を決めているのはTacticsというプログラムです。 + +消防隊の思考ルーチンは下の図の通りにおおよそおこなわれます。 消防隊の動作としては、まず救助対象の市民を捜索し(`Human Detector`)、見つかった市民を救助します(`Action Rescue`)。 救助対象の市民が見つからない場合は、探索場所を変更して市民を捜索するため、次の捜索場所を決定して(`Search`)移動します(`Action Ext move`)。 なお、エージェントは1ステップ内で、移動と救助活動を同時におこなうことが出来ません。つまり、ステップごとに更新される自身の周辺情報を確認して、動作の対象と動作内容を決定していくということになります。 これらそれぞれの機能が、モジュールと呼ばれるプログラムとして分割して表現されています。 + +今回はこの中で、救助(掘り起こし)対象を決定する `Human Detector` モジュールを開発します。 + +![消防隊エージェントの動作フロー](./../../images/agent_flow.png) + +## `Human Detector` モジュールの実装の準備 + +まず、`Human Detector` モジュールを記述するためのファイルを作成します。 + +```bash +cd WORKING_DIR/ +touch src//module/complex/fire_brigade_human_detector.py +``` + +次に、`Human Detector` モジュールの雛形の実装を行います。 以下のコードを`fire_brigade_human_detector.py` に記述してください。 + +```python +from typing import Optional + +from rcrs_core.worldmodel.entityID import EntityID + +from adf_core_python.core.agent.develop.develop_data import DevelopData +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.agent.module.module_manager import ModuleManager +from adf_core_python.core.component.module.complex.human_detector import HumanDetector +from adf_core_python.core.logger.logger import get_agent_logger + + +class FireBrigadeHumanDetector(HumanDetector): + def __init__( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + module_manager: ModuleManager, + develop_data: DevelopData, + ) -> None: + super().__init__( + agent_info, world_info, scenario_info, module_manager, develop_data + ) + # 計算結果を格納する変数 + self._result: Optional[EntityID] = None + # ロガーの取得 + self._logger = get_agent_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}", + self._agent_info, + ) + + def calculate(self) -> HumanDetector: + """ + 行動対象を決定する + + Returns + ------- + HumanDetector: 自身のインスタンス + """ + self._logger.info("Calculate FireBrigadeHumanDetector") + return self + + def get_target_entity_id(self) -> Optional[EntityID]: + """ + 行動対象のEntityIDを取得する + + Returns + ------- + Optional[EntityID]: 行動対象のEntityID + """ + return self._result +``` + +## モジュールの登録 + +次に、作成したモジュールを登録します。 + +`WORKING_DIR//config/module.yaml` ファイルを開き、以下の部分を + +```yaml +DefaultTacticsFireBrigade: + HumanDetector: src..module.complex.sample_human_detector.SampleHumanDetector +``` + +以下のように変更してください。 + +```yaml +DefaultTacticsFireBrigade: + HumanDetector: src..module.complex.fire_brigade_human_detector.FireBrigadeHumanDetector +``` + +シミュレーションサーバーを起動し、エージェントを実行してみましょう。 + +```bash +cd WORKING_DIR/ +python main.py +``` + +標準出力に `Calculate FireBrigadeHumanDetector` と表示されれば成功です。 + +## `Human Detector` モジュールの設計 + +救助対象選択プログラムの中身を書き、消防隊エージェントが救助活動をおこなえるように修正します。 + +消防隊エージェントの救助対象を最も簡単に選択する方法は、埋没している市民の中で最も自身に近い市民を選択する方法です。 今回は、この方法を採用した消防隊エージェントの行動対象決定モジュールを書いてみましょう。 + +埋没している市民の中で最も自身に近い市民を救助対象として選択する方法は、フローチャートで表すと下図のようになります。 + +![救助対象選択フローチャート](./../../images/human_detector_flow.png) + +このフローチャート中の各処理を、次小節で紹介する各クラス・メソッド等で置き換えたものを、`fire_brigade_human_detector.py` に記述していくことで、救助対象選択プログラムを完成させます。 + +## `Human Detector` モジュールの実装で使用するクラス・メソッド + +### Entity + +`Entity` クラスは、エンティティの基底クラスです。 このクラスは、エンティティの基本情報を保持します。 + +RRS上のエンティティは下図のように `Entity` を継承したクラスで表現されています。 赤枠で囲まれたクラスは、クラスの意味がそのままRRSの直接的な構成要素を表しています。 + +例: Road クラスのインスタンスの中には、 Hydrant クラスを継承してない通常の道路を表すものも存在しています。 + +![エンティティの継承関係](./../../images/entity.png) + +### EntityID + +`EntityID` クラスは、全てのエージェント/オブジェクトを一意に識別するためのID(識別子)を表すクラスです。 RRSではエージェントとオブジェクトをまとめて、エンティティと呼んでいます。 + +### Civilian + +`Civilian` クラスは、市民を表すクラスです。このクラスからは、エージェントの位置や負傷の進行状況を取得することができます。 + +- `entity` が市民であるかどうかを判定する + +```python +isinstance(entity, Civilian) +``` + +- エンティティIDを取得する + +```python +entity.get_id() +``` + +- 市民が生きているかどうかを判定する + +```python +hp: Optional[int] = entity.get_hp() +if hp is None or hp <= 0: + return False +``` + +- 市民が埋まっているかどうかを判定する + +```python +buriedness: Optional[int] = entity.get_buriedness() +if buriedness is None or buriedness <= 0: + return False +``` + +### WorldInfo + +`WorldInfo` クラスは、エージェントが把握している情報とそれに関する操作をおこなうメソッドをもったクラスです。 エージェントはこのクラスのインスタンスを通して、他のエージェントやオブジェクトの状態を確認します。 + +モジュール内では、`WorldInfo` クラスのインスタンスを `self._world_info` として保持しています。 + +- エンティティIDからエンティティを取得する + +```python +self._world_info.get_entity(entity_id) +``` + +- 指定したクラスのエンティティを全て取得する + +```python +self._world_info.get_entities_by_type([Building, Road]) +``` + +- エージェントの位置から指定したエンティティまでの距離を取得する + +```python +self._world_info.get_distance(me, civilian.get_id()) +``` + +[詳細はこちら](../../adf_core_python.core.agent.info.rst) + +### AgentInfo + +`AgentInfo` クラスは、エージェント自身の情報とそれに関する操作をおこなうメソッドをもったクラスです。 エージェントはこのクラスのインスタンスを通して、エージェント自身の状態を取得します。 + +モジュール内では、`AgentInfo` クラスのインスタンスを `self._agent_info` として保持しています。 + +- 自分自身のエンティティIDを取得する + +```python +self._agent_info.get_entity_id() +``` + +[詳細はこちら](../../adf_core_python.core.agent.info.rst) + +## `Human Detector` モジュールの実装 + +`Human Detector` モジュールの実装を行います。 +以下のコードを`fire_brigade_human_detector.py` に記述してください。 + +```python +from typing import Optional + +from rcrs_core.worldmodel.entityID import EntityID +from rcrs_core.entities.civilian import Civilian +from rcrs_core.entities.entity import Entity + +from adf_core_python.core.agent.develop.develop_data import DevelopData +from adf_core_python.core.agent.info.agent_info import AgentInfo +from adf_core_python.core.agent.info.scenario_info import ScenarioInfo +from adf_core_python.core.agent.info.world_info import WorldInfo +from adf_core_python.core.agent.module.module_manager import ModuleManager +from adf_core_python.core.component.module.complex.human_detector import HumanDetector +from adf_core_python.core.logger.logger import get_agent_logger + + +class SampleHumanDetector(HumanDetector): + def __init__( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + module_manager: ModuleManager, + develop_data: DevelopData, + ) -> None: + super().__init__( + agent_info, world_info, scenario_info, module_manager, develop_data + ) + # 計算結果を格納する変数 + self._result: Optional[EntityID] = None + # ロガーの取得 + self._logger = get_agent_logger( + f"{self.__class__.__module__}.{self.__class__.__qualname__}", + self._agent_info, + ) + + def calculate(self) -> HumanDetector: + """ + 行動対象を決定する + + Returns + ------- + HumanDetector: 自身のインスタンス + """ + me: EntityID = self._agent_info.get_entity_id() + civilians: list[Entity] = self._world_info.get_entities_of_types( + [ + Civilian, + ] + ) + + nearest_civilian: Optional[EntityID] = None + nearest_distance: Optional[float] = None + for civilian in civilians: + if not isinstance(civilian, Civilian): + continue + + if civilian.get_hp() <= 0: + continue + + if civilian.get_buriedness() <= 0: + continue + + distance: float = self._world_info.get_distance(me, civilian.get_id()) + + if nearest_distance is None or distance < nearest_distance: + nearest_civilian = civilian.get_id() + nearest_distance = distance + + self._result = nearest_civilian + + return self + + def get_target_entity_id(self) -> Optional[EntityID]: + """ + 行動対象のEntityIDを取得する + + Returns + ------- + Optional[EntityID]: 行動対象のEntityID + """ + return self._result +``` + +シミュレーションサーバーを起動し、エージェントを実行してみましょう。 + +```bash +cd WORKING_DIR/ +python main.py +``` + +埋没している市民を消防隊エージェントが救出できるようになっていれば成功です。 diff --git a/docs/source/tutorial/config/config.md b/docs/source/tutorial/config/config.md new file mode 100644 index 0000000..3257086 --- /dev/null +++ b/docs/source/tutorial/config/config.md @@ -0,0 +1,31 @@ +# コンフィグについて + +## コンフィグについての説明 + +```bash +. +└── + └── config + ├── development.json + ├── launcher.yaml + └── module.yaml +``` + +`config` ディレクトリには、エージェントの設定ファイルが格納されています。 + +### launcher.yaml + +`launcher.yaml` は、エージェントの起動時に読み込まれる設定ファイルです。 +シミュレーションサーバーの指定や読み込むモジュールが記述されたファイルの指定などが記述されています。 + +### module.yaml + +`module.yaml` は、エージェントが読み込むモジュールの設定ファイルです。 +読み込むモジュールのパスなどが記述されています。 +パスを指定する際は、プロジェクトの`main.py`からの相対パスで指定してください。 + +### development.json + +`development.json` は、開発時に使用する設定ファイルです。 +エージェントの開発時に外部から値を取得する際に使用します。 +そのため、競技時には使用することができません。 diff --git a/docs/source/tutorial/environment/environment.md b/docs/source/tutorial/environment/environment.md new file mode 100644 index 0000000..ec566ec --- /dev/null +++ b/docs/source/tutorial/environment/environment.md @@ -0,0 +1,38 @@ +# 環境構築 + +## 必要なもの + +- Git +- Python 3.12 以上 +- OpenJDK 17 + +[Windowsでの必要なもののインストール方法](./windows/install.md) + +## シミュレーションサーバーのインストール + +```{note} +WORKING_DIR は任意のディレクトリを指定してください。 +``` + +```bash +cd WORKING_DIR +git clone https://github.com/roborescue/rcrs-server.git +cd rcrs-server +./gradlew completeBuild +``` + +ビルドした際に以下のようなメッセージが表示されたら成功です。 + +```bash +BUILD SUCCESSFUL in ... +``` + +## シュミレーションサーバーの動作確認 + +```bash +cd WORKING_DIR/rcrs-server/scripts +./start-comprun.sh -m ../maps/test/map -c ../maps/test/config +``` + +何個かのウィンドウが表示されたら成功です。 +コマンドラインで `Ctrl + C` を押すとシミュレーションサーバーが終了します。 diff --git a/docs/source/tutorial/environment/windows/install.md b/docs/source/tutorial/environment/windows/install.md new file mode 100644 index 0000000..ce36a29 --- /dev/null +++ b/docs/source/tutorial/environment/windows/install.md @@ -0,0 +1,20 @@ +# Windowsでの環境構築 + +## 1. Gitのインストール + +1. [Git for Windows](https://gitforwindows.org/)の公式サイトにアクセスします。 +2. ダウンロードページから最新のバージョンをダウンロードします。 +3. ダウンロードしたファイルを開き、インストールを開始します。 + +## 2. Pythonのインストール + +1. [Python](https://www.python.org/downloads/)の公式サイトにアクセスします。 +2. ダウンロードページから最新のバージョンをダウンロードします。 +3. ダウンロードしたファイルを開き、インストールを開始します。 +4. インストール時に「Add python.exe to PATH」にチェックを入れてください。 + +## 3. OpenJDKのインストール + +1. [OpenJDK](https://jdk.java.net/archive/)の公式サイトにアクセスします。 +2. ダウンロードページから17.0.2のバージョンをダウンロードします。 +3. ダウンロードしたファイルを開き、インストールを開始します。 diff --git a/docs/source/tutorial/install/install.md b/docs/source/tutorial/install/install.md new file mode 100644 index 0000000..c27a88f --- /dev/null +++ b/docs/source/tutorial/install/install.md @@ -0,0 +1,28 @@ +# インストール + +このセクションでは、パッケージのインストール方法について説明します。 + +## 前提条件 + +インストールする前に、以下の前提条件を確認してください: + +- Python 3.12 以上 +- pip + +## パッケージのインストール + +パッケージをインストールするには、次のコマンドを実行します: + +```bash +pip install adf_core_python +``` + +## インストールの確認 + +インストールを確認するには、次のコマンドを実行します: + +```bash +python -c "import adf_core_python; print(adf_core_python.__version__)" +``` + +パッケージが正しくインストールされている場合、パッケージのバージョン番号が表示されます。 diff --git a/docs/source/tutorial/module/module.md b/docs/source/tutorial/module/module.md new file mode 100644 index 0000000..ce8c9de --- /dev/null +++ b/docs/source/tutorial/module/module.md @@ -0,0 +1,88 @@ +# モジュールについて + +## モジュールの指定方法 + +モジュールを指定するには、module.yamlにモジュールの名前とパスを記述します。 + +例えば、以下のように記述します: + +```yaml +SampleSearch: + PathPlanning: src.my-agent.module.complex.sample_search.SampleSearch + Clustering: src.my-agent.module.complex.sample_search.SampleClustering +``` + +この場合、`SampleSearch` というモジュールで使用される、`PathPlanning` と `Clustering` というモジュールを指定しています。 + +## モジュールの読み込み方法 + +モジュール内で、他のモジュールを読み込む場合は、次のように記述します: + +```python +from adf_core_python.core.agent.module.module_manager import ModuleManager + +class SampleSearch(Search): + def __init__( + self, + agent_info: AgentInfo, + world_info: WorldInfo, + scenario_info: ScenarioInfo, + module_manager: ModuleManager, + develop_data: DevelopData, + ) -> None: + super().__init__( + agent_info, world_info, scenario_info, module_manager, develop_data + ) + + # クラスタリングモジュールの取得 + self._clustering: Clustering = cast( + # モジュールの型を指定 + Clustering, + # モジュールの取得 + module_manager.get_module( + # モジュールの名前 + "DefaultSearch.Clustering", + # 上記のモジュールの名前が指定されていない場合のデフォルトのモジュールのパス + "adf_core_python.implement.module.algorithm.k_means_clustering.KMeansClustering", + ), + ) + + # パスプランニングモジュールの取得 + self._path_planning: PathPlanning = cast( + # モジュールの型を指定 + PathPlanning, + # モジュールの取得 + module_manager.get_module( + # モジュールの名前 + "DefaultSearch.PathPlanning", + # 上記のモジュールの名前が指定されていない場合のデフォルトのモジュールのパス + "adf_core_python.implement.module.algorithm.a_star_path_planning.AStarPathPlanning", + ), + ) + + # モジュールの登録(これをしないと、モジュール内のシュミレーション環境の情報が更新されません) + self.register_sub_module(self._clustering) + self.register_sub_module(self._path_planning) +``` + +## モジュールの種類について + +adf-core-pythonでは、以下のモジュールが提供されています。 + +| クラス | 役割 | +| -------------------- | -------------------------------------------------------------------------- | +| TacticsFireBrigade | 消防隊用のモジュール呼び出し (競技では変更不可) | +| TacticsPoliceForce | 土木隊用のモジュール呼び出し (競技では変更不可) | +| TacticsAmbulanceTeam | 救急隊用のモジュール呼び出し (競技では変更不可) | +| BuildingDetector | 消防隊の活動対象の選択 | +| RoadDetector | 土木隊の活動対象の選択 | +| HumanDetector | 救急隊の活動対象の選択 | +| Search | 情報探索に向けた活動対象の選択 | +| PathPlanning | 経路探索 | +| DynamicClustering | シミュレーションの進行によってクラスタが変化するクラスタリング | +| StaticClustering | シミュレーション開始時にクラスタが定まるクラスタリング | +| ExtAction | 活動対象決定後のエージェントの動作決定 | +| MessageCoordinator | 通信でメッセージ(情報)を送信する経路である、チャンネルへのメッセージの分配 | +| ChannelSubscriber | 通信によってメッセージを受け取るチャンネルの選択 | + +自分で上記の役割以外のモジュールを作成する際は、`AbstractModule` を継承してください。 diff --git a/poetry.lock b/poetry.lock index d30279b..357088b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,69 @@ # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +[[package]] +name = "accessible-pygments" +version = "0.0.5" +description = "A collection of accessible pygments styles" +optional = false +python-versions = ">=3.9" +files = [ + {file = "accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7"}, + {file = "accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872"}, +] + +[package.dependencies] +pygments = ">=1.5" + +[package.extras] +dev = ["pillow", "pkginfo (>=1.10)", "playwright", "pre-commit", "setuptools", "twine (>=5.0)"] +tests = ["hypothesis", "pytest"] + +[[package]] +name = "alabaster" +version = "1.0.0" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.10" +files = [ + {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, + {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, +] + +[[package]] +name = "babel" +version = "2.16.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + [[package]] name = "bitarray" version = "3.0.0" @@ -146,6 +210,131 @@ files = [ {file = "bitarray-3.0.0.tar.gz", hash = "sha256:a2083dc20f0d828a7cdf7a16b20dae56aab0f43dc4f347a3b3039f6577992b03"}, ] +[[package]] +name = "certifi" +version = "2024.8.30" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +] + [[package]] name = "click" version = "8.1.7" @@ -171,6 +360,42 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "docutils" +version = "0.21.2" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.9" +files = [ + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, +] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -182,6 +407,23 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + [[package]] name = "joblib" version = "1.4.2" @@ -193,6 +435,130 @@ files = [ {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, ] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +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"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "markupsafe" +version = "3.0.2" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.9" +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"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.4.2" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +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"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0.0,<4.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "mslex" version = "1.3.0" @@ -267,6 +633,32 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "myst-parser" +version = "4.0.0" +description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +optional = false +python-versions = ">=3.10" +files = [ + {file = "myst_parser-4.0.0-py3-none-any.whl", hash = "sha256:b9317997552424448c6096c2558872fdb6f81d3ecb3a40ce84a7518798f3f28d"}, + {file = "myst_parser-4.0.0.tar.gz", hash = "sha256:851c9dfb44e36e56d15d05e72f02b80da21a9e0d07cba96baf5e2d476bb91531"}, +] + +[package.dependencies] +docutils = ">=0.19,<0.22" +jinja2 = "*" +markdown-it-py = ">=3.0,<4.0" +mdit-py-plugins = ">=0.4.1,<1.0" +pyyaml = "*" +sphinx = ">=7,<9" + +[package.extras] +code-style = ["pre-commit (>=3.0,<4.0)"] +linkify = ["linkify-it-py (>=2.0,<3.0)"] +rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] + [[package]] name = "numpy" version = "2.1.3" @@ -379,31 +771,74 @@ files = [ [[package]] name = "psutil" -version = "5.9.8" +version = "6.1.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, - {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, - {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, - {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, - {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, - {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, - {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, - {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, - {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, - {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, + {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, + {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"}, + {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"}, + {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"}, + {file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"}, + {file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"}, + {file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"}, + {file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"}, + {file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"}, + {file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"}, + {file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"}, + {file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"}, + {file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"}, + {file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"}, +] + +[package.extras] +dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"] +test = ["pytest", "pytest-xdist", "setuptools"] + +[[package]] +name = "pydata-sphinx-theme" +version = "0.16.0" +description = "Bootstrap-based Sphinx theme from the PyData community" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pydata_sphinx_theme-0.16.0-py3-none-any.whl", hash = "sha256:18c810ee4e67e05281e371e156c1fb5bb0fa1f2747240461b225272f7d8d57d8"}, + {file = "pydata_sphinx_theme-0.16.0.tar.gz", hash = "sha256:721dd26e05fa8b992d66ef545536e6cbe0110afb9865820a08894af1ad6f7707"}, ] +[package.dependencies] +accessible-pygments = "*" +Babel = "*" +beautifulsoup4 = "*" +docutils = "!=0.17.0" +pygments = ">=2.7" +sphinx = ">=6.1" +typing-extensions = "*" + [package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] +a11y = ["pytest-playwright"] +dev = ["pandoc", "pre-commit", "pydata-sphinx-theme[doc,test]", "pyyaml", "sphinx-theme-builder[cli]", "tox"] +doc = ["ablog (>=0.11.8)", "colorama", "graphviz", "ipykernel", "ipyleaflet", "ipywidgets", "jupyter_sphinx", "jupyterlite-sphinx", "linkify-it-py", "matplotlib", "myst-parser", "nbsphinx", "numpy", "numpydoc", "pandas", "plotly", "rich", "sphinx-autoapi (>=3.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-favicon (>=1.0.1)", "sphinx-sitemap", "sphinx-togglebutton", "sphinxcontrib-youtube (>=1.4.1)", "sphinxext-rediraffe", "xarray"] +i18n = ["Babel", "jinja2"] +test = ["pytest", "pytest-cov", "pytest-regressions", "sphinx[test]"] + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" @@ -506,6 +941,27 @@ url = "https://github.com/adf-python/rcrs-core-python" reference = "HEAD" resolved_reference = "aa661b19c98f82d8d648317f386c2f9d2c26a8fc" +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + [[package]] name = "rtree" version = "1.3.0" @@ -704,6 +1160,212 @@ numpy = ">=1.14,<3" docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] test = ["pytest", "pytest-cov"] +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "soupsieve" +version = "2.6" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, + {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, +] + +[[package]] +name = "sphinx" +version = "8.1.3" +description = "Python documentation generator" +optional = false +python-versions = ">=3.10" +files = [ + {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, + {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, +] + +[package.dependencies] +alabaster = ">=0.7.14" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" +imagesize = ">=1.3" +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" +sphinxcontrib-applehelp = ">=1.0.7" +sphinxcontrib-devhelp = ">=1.0.6" +sphinxcontrib-htmlhelp = ">=2.0.6" +sphinxcontrib-jsmath = ">=1.0.1" +sphinxcontrib-qthelp = ">=1.0.6" +sphinxcontrib-serializinghtml = ">=1.1.9" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=6.0)", "mypy (==1.11.1)", "pyright (==1.1.384)", "pytest (>=6.0)", "ruff (==0.6.9)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.18.0.20240506)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241005)", "types-requests (==2.32.0.20240914)", "types-urllib3 (==1.26.25.14)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] + +[[package]] +name = "sphinx-book-theme" +version = "1.1.3" +description = "A clean book theme for scientific explanations and documentation with Sphinx" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx_book_theme-1.1.3-py3-none-any.whl", hash = "sha256:a554a9a7ac3881979a87a2b10f633aa2a5706e72218a10f71be38b3c9e831ae9"}, + {file = "sphinx_book_theme-1.1.3.tar.gz", hash = "sha256:1f25483b1846cb3d353a6bc61b3b45b031f4acf845665d7da90e01ae0aef5b4d"}, +] + +[package.dependencies] +pydata-sphinx-theme = ">=0.15.2" +sphinx = ">=5" + +[package.extras] +code-style = ["pre-commit"] +doc = ["ablog", "folium", "ipywidgets", "matplotlib", "myst-nb", "nbclient", "numpy", "numpydoc", "pandas", "plotly", "sphinx-copybutton", "sphinx-design", "sphinx-examples", "sphinx-tabs", "sphinx-thebe", "sphinx-togglebutton", "sphinxcontrib-bibtex", "sphinxcontrib-youtube", "sphinxext-opengraph"] +test = ["beautifulsoup4", "coverage", "defusedxml", "myst-nb", "pytest", "pytest-cov", "pytest-regressions", "sphinx_thebe"] + +[[package]] +name = "sphinx-copybutton" +version = "0.5.2" +description = "Add a copy button to each of your code cells." +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, + {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, +] + +[package.dependencies] +sphinx = ">=1.8" + +[package.extras] +code-style = ["pre-commit (==2.12.1)"] +rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, + {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, + {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, + {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-mermaid" +version = "1.0.0" +description = "Mermaid diagrams in yours Sphinx powered docs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib_mermaid-1.0.0-py3-none-any.whl", hash = "sha256:60b72710ea02087f212028feb09711225fbc2e343a10d34822fe787510e1caa3"}, + {file = "sphinxcontrib_mermaid-1.0.0.tar.gz", hash = "sha256:2e8ab67d3e1e2816663f9347d026a8dee4a858acdd4ad32dd1c808893db88146"}, +] + +[package.dependencies] +pyyaml = "*" +sphinx = "*" + +[package.extras] +test = ["defusedxml", "myst-parser", "pytest", "ruff", "sphinx"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, + {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["defusedxml (>=0.7.1)", "pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, + {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + [[package]] name = "structlog" version = "24.4.0" @@ -723,19 +1385,19 @@ typing = ["mypy (>=1.4)", "rich", "twisted"] [[package]] name = "taskipy" -version = "1.14.0" +version = "1.14.1" description = "tasks runner for python projects" optional = false python-versions = "<4.0,>=3.6" files = [ - {file = "taskipy-1.14.0-py3-none-any.whl", hash = "sha256:29040d9a8038170602feb71792bdef5203720ed30f595304aee843625892452b"}, - {file = "taskipy-1.14.0.tar.gz", hash = "sha256:5d9631c29980481d59858f0a100ed3200cf7468ca8c0540ef19388586485532d"}, + {file = "taskipy-1.14.1-py3-none-any.whl", hash = "sha256:6e361520f29a0fd2159848e953599f9c75b1d0b047461e4965069caeb94908f1"}, + {file = "taskipy-1.14.1.tar.gz", hash = "sha256:410fbcf89692dfd4b9f39c2b49e1750b0a7b81affd0e2d7ea8c35f9d6a4774ed"}, ] [package.dependencies] colorama = ">=0.4.4,<0.5.0" mslex = {version = ">=1.1.0,<2.0.0", markers = "sys_platform == \"win32\""} -psutil = ">=5.7.2,<6.0.0" +psutil = ">=5.7.2,<7" tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version >= \"3.7\" and python_version < \"4.0\""} [[package]] @@ -793,7 +1455,24 @@ files = [ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] +[[package]] +name = "urllib3" +version = "2.2.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "62d5fde0d4a35f29aa7f21a31f5c1f4679c7a576c0f57c0363ec0b0cd6dc9e91" +content-hash = "29d6b40d3dcb183f4218df24f042f514858d0b01517ecc2956beca72bc4e598e" diff --git a/pyproject.toml b/pyproject.toml index 71f60d0..0a60a76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,11 @@ taskipy = "^1.12.2" mypy = "^1.9.0" types-protobuf = "^4.25.0.20240410" ruff = "^0.4.4" +sphinx = "^8.1.3" +myst-parser = "^4.0.0" +sphinx-book-theme = "^1.1.3" +sphinx-copybutton = "^0.5.2" +sphinxcontrib-mermaid = "^1.0.0" [build-system] requires = ["poetry-core"] @@ -72,6 +77,7 @@ exclude = [ "site-packages", "venv", "pb2", + "docs", ] # Same as Black. @@ -130,3 +136,4 @@ disallow_untyped_defs = true # 関数定義の引数/戻り値に型アノテ no_implicit_optional = true # デフォルト引数に None を取る場合型アノテーションに Optional 必須 check_untyped_defs = true # 型注釈がない関数やメソッドに対して型チェックを行う warn_redundant_casts = true # 冗長なキャストに警告 +exclude = ["docs/*"] diff --git a/pyrightconfig.json b/pyrightconfig.json index 8c19fca..972999c 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -1,4 +1,4 @@ { "typeCheckingMode": "standard", - "exclude": [".venv", ".git"] + "include": ["adf_core_python"] }