From d67bd7e1acb71b32f9fdd13ad55ff1734c2a131d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= <147368808+philip-paul-mueller@users.noreply.github.com> Date: Wed, 29 Jan 2025 13:49:33 +0100 Subject: [PATCH 01/13] fix[dace]: Fixed a bug in `gt_make_transients_persistent()` (#1831) Make a transient persistent essentially makes it a global, it is thus shared among different iterations of a Map. Consider the following: ```c++ #pragma omp parallel for for(int k = 0; k != N; ++k) { double b = foo(k); bar(b); }; ``` In the above code each iteration has its own local copy of `b` that is not shared with other threads. If `b` would be declared persistent, the code essentially becomes ```c++ double* b = new double; #pragma omp parallel for for(int k = 0; k != N; ++k) { *b = foo(k); bar(*b); }; ``` i.e. now `b` is shared among the different threads and we have a data race. To avoid this situation we have to ensure that there is no data race and we do this by requiring that a data descriptor that should be turned into a persistent one, can not have an AccessNode inside a scope other than the top scope. Note that this restriction is stronger than necessary and could be relaxed, but it might be very difficult to figuring out if in a particular case it is possible or not. --- .../runners/dace/transformations/utils.py | 10 +++ .../test_make_transients_persistent.py | 74 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_make_transients_persistent.py diff --git a/src/gt4py/next/program_processors/runners/dace/transformations/utils.py b/src/gt4py/next/program_processors/runners/dace/transformations/utils.py index 87308061e7..3cc2dadd89 100644 --- a/src/gt4py/next/program_processors/runners/dace/transformations/utils.py +++ b/src/gt4py/next/program_processors/runners/dace/transformations/utils.py @@ -50,6 +50,7 @@ def gt_make_transients_persistent( not_modify_lifetime: set[str] = set() for state in nsdfg.states(): + scope_dict = state.scope_dict() for dnode in state.data_nodes(): if dnode.data in not_modify_lifetime: continue @@ -70,6 +71,15 @@ def gt_make_transients_persistent( not_modify_lifetime.add(dnode.data) continue + # If the data is referenced inside a scope, such as a map, it might be possible + # that it is only used inside that scope. If we would make it persistent, then + # it would essentially be allocated outside and be shared among the different + # map iterations. So we can not make it persistent. + # The downside is, that we might have to perform dynamic allocation. + if scope_dict[dnode] is not None: + not_modify_lifetime.add(dnode.data) + continue + try: # The symbols describing the total size must be a subset of the # free symbols of the SDFG (symbols passed as argument). diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_make_transients_persistent.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_make_transients_persistent.py new file mode 100644 index 0000000000..d8cf8e33f8 --- /dev/null +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_make_transients_persistent.py @@ -0,0 +1,74 @@ +# GT4Py - GridTools Framework +# +# Copyright (c) 2014-2024, ETH Zurich +# All rights reserved. +# +# Please, refer to the LICENSE file in the root directory. +# SPDX-License-Identifier: BSD-3-Clause + +import pytest + +dace = pytest.importorskip("dace") +from dace.sdfg import nodes as dace_nodes + +from gt4py.next.program_processors.runners.dace import ( + transformations as gtx_transformations, +) + +from . import util + +import dace + + +def _make_transients_persistent_inner_access_sdfg() -> tuple[dace.SDFG, dace.SDFGState]: + sdfg = dace.SDFG(util.unique_name("transients_persistent_inner_access_sdfg")) + state = sdfg.add_state(is_start_block=True) + + for name in "abc": + sdfg.add_array( + name, + shape=(10,), + dtype=dace.float64, + transient=False, + ) + sdfg.arrays["b"].transient = True + + me: dace_nodes.MapEntry + mx: dace_nodes.MapExit + me, mx = state.add_map("comp", ndrange={"__i0": "0:10"}) + a, b, c = (state.add_access(name) for name in "abc") + tsklt: dace_nodes.Tasklet = state.add_tasklet( + "tsklt", + inputs={"__in"}, + code="__out = __in + 1.0", + outputs={"__out"}, + ) + + me.add_in_connector("IN_A") + state.add_edge(a, None, me, "IN_A", dace.Memlet("a[0:10]")) + + me.add_out_connector("OUT_A") + state.add_edge(me, "OUT_A", b, None, dace.Memlet("a[__i0] -> [__i0]")) + + state.add_edge(b, None, tsklt, "__in", dace.Memlet("b[__i0]")) + + mx.add_in_connector("IN_C") + state.add_edge(tsklt, "__out", mx, "IN_C", dace.Memlet("c[__i0]")) + + mx.add_out_connector("OUT_C") + state.add_edge(mx, "OUT_C", c, None, dace.Memlet("c[0:10]")) + sdfg.validate() + return sdfg, state + + +def test_make_transients_persistent_inner_access(): + sdfg, state = _make_transients_persistent_inner_access_sdfg() + assert sdfg.arrays["b"].lifetime is dace.dtypes.AllocationLifetime.Scope + + # Because `b`, the only transient, is used inside a map scope, it is not selected, + # although in this situation it would be possible. + change_report: dict[int, set[str]] = gtx_transformations.gt_make_transients_persistent( + sdfg, device=dace.DeviceType.CPU + ) + assert len(change_report) == 1 + assert change_report[sdfg.cfg_id] == set() From ac47ca691aa32deefe925b8d82246b3a56b38cee Mon Sep 17 00:00:00 2001 From: edopao Date: Wed, 29 Jan 2025 14:38:37 +0100 Subject: [PATCH 02/13] fix[next][dace]: handle if-expression as non-exclusive in field view (#1824) The implementation of scan field operator introduced a bug in the lowering of if-statements to SDFG. The scan requires extended lowering support for iterator view, therefore #1790 introduced the lowering of local-if with exclusive branch execution. However, attention was not paid to enable the exclusive behavior of if-expressions only in iterator view, that is only in the scope of scan field operators. Regular field operators should instead lower if-expressions to a tasklet, because the field view behavior is that of a local select. --- .../runners/dace/gtir_dataflow.py | 91 ++++++++++++++++++- .../runners/dace/gtir_scan_translator.py | 7 +- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py b/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py index e00e363ac4..a34828afcb 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py @@ -332,6 +332,7 @@ class LambdaToDataflow(eve.NodeVisitor): sdfg: dace.SDFG state: dace.SDFGState subgraph_builder: gtir_sdfg.DataflowBuilder + scan_carry_symbol: Optional[gtir.Sym] input_edges: list[DataflowInputEdge] = dataclasses.field(default_factory=lambda: []) symbol_map: dict[ str, @@ -693,7 +694,7 @@ def _visit_if_branch( # visit each branch of the if-statement as if it was a Lambda node lambda_node = gtir.Lambda(params=lambda_params, expr=expr) input_edges, output_tree = translate_lambda_to_dataflow( - if_sdfg, if_branch_state, self.subgraph_builder, lambda_node, args=lambda_args + if_sdfg, if_branch_state, self.subgraph_builder, lambda_node, lambda_args ) for data_node in if_branch_state.data_nodes(): @@ -736,7 +737,12 @@ def _visit_if(self, node: gtir.FunCall) -> ValueExpr | tuple[ValueExpr | tuple[A """ Lowers an if-expression with exclusive branch execution into a nested SDFG, in which each branch is lowered into a dataflow in a separate state and - the if-condition is represented as the inter-state edge condtion. + the if-condition is represented as the inter-state edge condition. + + Exclusive branch execution for local if expressions is meant to be used + in iterator view. Iterator view is required ONLY inside scan field operators. + For regular field operators, the fieldview behavior of if-expressions + corresponds to a local select, therefore it should be lowered to a tasklet. """ def write_output_of_nested_sdfg_to_temporary(inner_value: ValueExpr) -> ValueExpr: @@ -1633,13 +1639,87 @@ def _visit_tuple_get( tuple_fields = self.visit(node.args[1]) return tuple_fields[index] + def requires_exclusive_if(self, node: gtir.FunCall) -> bool: + """ + The meaning of `if_` builtin function is unclear in GTIR. + In some context, it corresponds to a ternary operator where, depending on + the condition result, only one branch or the other should be executed, + because one of them is invalid. The typical case is the use of `if_` to + decide whether it is possible or not to access a shifted iterator, for + example when the condition expression calls `can_deref`. + The ternary operator is also used in iterator view, where the field arguments + are not necessarily both defined on the entire output domain (this behavior + should not appear in field view, because there the user code should use + `concat_where` instead of `where` for such cases). It is difficult to catch + such behavior, because it would require to know the exact domain of all + fields, which is not known at compile time. However, the iterator view + behavior should only appear inside scan field operators. + A different usage of `if_` expressions is selecting one argument value or + the other, where both arguments are defined on the output domain, therefore + always valid. + In order to simplify the SDFG and facilitate the optimization stage, we + try to avoid the ternary operator form when not needed. The reason is that + exclusive branch execution is represented in the SDFG as a conditional + state transition, which prevents fusion. + """ + assert cpm.is_call_to(node, "if_") + assert len(node.args) == 3 + + condition_vars = ( + eve.walk_values(node.args[0]) + .if_isinstance(gtir.SymRef) + .map(lambda node: str(node.id)) + .filter(lambda x: x in self.symbol_map) + .to_set() + ) + + # first, check if any argument contains shift expressions that depend on the condition variables + for arg in node.args[1:3]: + shift_nodes = ( + eve.walk_values(arg).filter(lambda node: cpm.is_applied_shift(node)).to_set() + ) + for shift_node in shift_nodes: + shift_vars = ( + eve.walk_values(shift_node) + .if_isinstance(gtir.SymRef) + .map(lambda node: str(node.id)) + .filter(lambda x: x in self.symbol_map) + .to_set() + ) + # require exclusive branch execution if any shift expression one of + # the if branches accesses a variable used in the condition expression + depend_vars = condition_vars.intersection(shift_vars) + if len(depend_vars) != 0: + return True + + # secondly, check whether the `if_` branches access different sets of fields + # and this happens inside a scan field operator + if self.scan_carry_symbol is not None: + # the `if_` node is inside a scan stencil expression + scan_carry_var = str(self.scan_carry_symbol.id) + if scan_carry_var in condition_vars: + br1_vars, br2_vars = ( + eve.walk_values(arg) + .if_isinstance(gtir.SymRef) + .map(lambda node: str(node.id)) + .filter(lambda x: isinstance(self.symbol_map.get(x, None), MemletExpr)) + .to_set() + for arg in node.args[1:3] + ) + if br1_vars != br2_vars: + # the two branches of the `if_` expression access different sets of fields, + # depending on the scan carry value + return True + + return False + def visit_FunCall( self, node: gtir.FunCall ) -> IteratorExpr | DataExpr | tuple[IteratorExpr | DataExpr | tuple[Any, ...], ...]: if cpm.is_call_to(node, "deref"): return self._visit_deref(node) - elif cpm.is_call_to(node, "if_"): + elif cpm.is_call_to(node, "if_") and self.requires_exclusive_if(node): return self._visit_if(node) elif cpm.is_call_to(node, "neighbors"): @@ -1776,6 +1856,7 @@ def translate_lambda_to_dataflow( | ValueExpr | tuple[IteratorExpr | MemletExpr | ValueExpr | tuple[Any, ...], ...] ], + scan_carry_symbol: Optional[gtir.Sym] = None, ) -> tuple[ list[DataflowInputEdge], tuple[DataflowOutputEdge | tuple[Any, ...], ...], @@ -1794,13 +1875,15 @@ def translate_lambda_to_dataflow( sdfg_builder: Helper class to build the dataflow inside the given SDFG. node: Lambda node to visit. args: Arguments passed to lambda node. + scan_carry_symbol: When set, the lowering of `if_` expression will consider + using the ternary operator form with exclusive branch execution. Returns: A tuple of two elements: - List of connections for data inputs to the dataflow. - Tree representation of output data connections. """ - taskgen = LambdaToDataflow(sdfg, state, sdfg_builder) + taskgen = LambdaToDataflow(sdfg, state, sdfg_builder, scan_carry_symbol) lambda_output = taskgen.visit_let(node, args) if isinstance(lambda_output, DataflowOutputEdge): diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py b/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py index d3d8e101a7..ec88cd8f84 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py @@ -417,7 +417,12 @@ def init_scan_carry(sym: gtir.Sym) -> None: # stil inside the 'compute' state, generate the dataflow representing the stencil # to be applied on the horizontal domain lambda_input_edges, lambda_result = gtir_dataflow.translate_lambda_to_dataflow( - nsdfg, compute_state, lambda_translator, lambda_node, args=stencil_args + nsdfg, + compute_state, + lambda_translator, + lambda_node, + stencil_args, + scan_carry_symbol=scan_carry_symbol, ) # connect the dataflow input directly to the source data nodes, without passing through a map node; # the reason is that the map for horizontal domain is outside the scan loop region From f732f08020e0786fe955231eb8794c83c5778d00 Mon Sep 17 00:00:00 2001 From: edopao Date: Wed, 29 Jan 2025 15:51:52 +0100 Subject: [PATCH 03/13] refactor[next][daxce]: cleanup get_sdfg_args() parameter list (#1834) Remove unnecessary `kwargs` from parameter list of `get_sdfg_args()`. --- .../runners/dace/sdfg_callable.py | 14 +++++++++++--- .../runners/dace/workflow/decoration.py | 1 - 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py b/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py index ecd23619e5..7f221a5a41 100644 --- a/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py +++ b/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py @@ -129,15 +129,23 @@ def get_sdfg_args( *args: Any, check_args: bool = False, on_gpu: bool = False, - **kwargs: Any, ) -> dict[str, Any]: """Extracts the arguments needed to call the SDFG. - This function can handle the same arguments that are passed to dace runner. + This function can handle the arguments that are passed to the dace runner + and that end up in the decoration stage of the dace backend workflow. Args: sdfg: The SDFG for which we want to get the arguments. - offset_provider: Offset provider. + offset_provider: The offset provider. + args: The list of arguments passed to the dace runner. + check_args: If True, return only the arguments that are expected + according to the SDFG signature. + on_gpu: If True, this method ensures that the arrays for the + connectivity tables are allocated in GPU memory. + + Returns: + A dictionary of keyword arguments to be passed in the SDFG call. """ dace_args = _get_args(sdfg, args) diff --git a/src/gt4py/next/program_processors/runners/dace/workflow/decoration.py b/src/gt4py/next/program_processors/runners/dace/workflow/decoration.py index 2ee99f5fa4..9648ac9e04 100644 --- a/src/gt4py/next/program_processors/runners/dace/workflow/decoration.py +++ b/src/gt4py/next/program_processors/runners/dace/workflow/decoration.py @@ -86,7 +86,6 @@ def decorated_program( *flat_args, check_args=False, on_gpu=on_gpu, - use_field_canonical_representation=use_field_canonical_representation, ) with dace.config.temporary_config(): From c228f224e4a416d8b224d3bcfad0eda92755ff88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Gonz=C3=A1lez=20Paredes?= Date: Wed, 29 Jan 2025 15:53:00 +0100 Subject: [PATCH 04/13] build: update infrastructure to use the uv tool (#1813) Modernize development infrastructure to use newer python tools. The `uv` (https://docs.astral.sh/uv/) tool is used as project management tool, `nox` (https://nox.thea.codes/) replaces `tox` as the project test runner, custom scripts and `cog` snippets are replaced by a central `dev-tasks.py` tool with multiple commands. Additionally, documentation and CI workflows are updated accordingly and some tests which were not properly executed properly are fixed. Other related tasks to enhance the development infrastructure which could be done after this PR is merged are being tracked in issue #1829 --- .github/workflows/code-quality.yml | 18 +- .github/workflows/daily-ci.yml | 126 +- .github/workflows/test-cartesian-fallback.yml | 6 +- .github/workflows/test-cartesian.yml | 43 +- .github/workflows/test-eve-fallback.yml | 10 +- .github/workflows/test-eve.yml | 51 +- .github/workflows/test-examples.yml | 44 + .github/workflows/test-next-fallback.yml | 5 +- .github/workflows/test-next.yml | 60 +- .github/workflows/test-notebooks.yml | 42 - .github/workflows/test-storage-fallback.yml | 11 +- .github/workflows/test-storage.yml | 52 +- .pre-commit-config.yaml | 95 +- .python-version | 1 + CONTRIBUTING.md | 26 +- LICENSE.txt => LICENSE | 0 README.md | 86 +- ci/base.Dockerfile | 2 +- ci/cscs-ci.yml | 19 +- constraints.txt | 178 - dev-tasks.py | 97 + docs/development/tools/ci-infrastructure.md | 2 +- docs/development/tools/requirements.md | 27 - min-extra-requirements-test.txt | 110 - min-requirements-test.txt | 104 - noxfile.py | 251 ++ pyproject.toml | 122 +- requirements-dev.in | 36 - requirements-dev.txt | 178 - tach.toml | 4 +- .../multi_feature_tests/test_dace_parsing.py | 2 +- tests/conftest.py | 50 + tests/next_tests/definitions.py | 11 +- .../feature_tests/dace/__init__.py | 4 + .../feature_tests/dace/test_orchestration.py | 7 +- .../feature_tests/dace/test_program.py | 13 +- .../iterator_tests/test_extractors.py | 56 +- .../ffront_tests/test_ffront_fvm_nabla.py | 21 +- .../runners_tests/dace_tests/__init__.py | 3 +- .../runners_tests/dace_tests/test_dace.py | 2 - .../dace_tests/test_gtir_to_sdfg.py | 2 - .../transformation_tests/__init__.py | 3 +- .../transformation_tests/conftest.py | 2 +- .../test_distributed_buffer_relocator.py | 9 +- .../transformation_tests/test_gpu_utils.py | 2 +- .../test_loop_blocking.py | 2 +- .../transformation_tests/test_map_fusion.py | 2 +- .../transformation_tests/test_map_order.py | 8 +- .../test_serial_map_promoter.py | 2 +- tox.ini | 190 - uv.lock | 3345 +++++++++++++++++ 51 files changed, 4181 insertions(+), 1361 deletions(-) create mode 100644 .github/workflows/test-examples.yml delete mode 100644 .github/workflows/test-notebooks.yml create mode 100644 .python-version rename LICENSE.txt => LICENSE (100%) delete mode 100644 constraints.txt create mode 100755 dev-tasks.py delete mode 100644 docs/development/tools/requirements.md delete mode 100644 min-extra-requirements-test.txt delete mode 100644 min-requirements-test.txt create mode 100644 noxfile.py delete mode 100644 requirements-dev.in delete mode 100644 requirements-dev.txt delete mode 100644 tox.ini create mode 100644 uv.lock diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index d54fea9269..10bb537e3e 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -13,13 +13,17 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.10" - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - uses: pre-commit/action@v3.0.1 + python-version-file: ".python-version" + + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: "Run pre-commit" + uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/daily-ci.yml b/.github/workflows/daily-ci.yml index 28512a18ac..a2a52ce1ff 100644 --- a/.github/workflows/daily-ci.yml +++ b/.github/workflows/daily-ci.yml @@ -5,7 +5,8 @@ on: - cron: '0 4 * * *' workflow_dispatch: - ## COMMENTED OUT: only for testing CI action changes + ## COMMENTED OUT: only for testing CI action changes. + ## It only works for PRs to `main` branch from branches in the upstream gt4py repo. # pull_request: # branches: # - main @@ -15,106 +16,87 @@ jobs: daily-ci: strategy: matrix: + # dependencies-strategy -> The strategy that `uv lock` should use to select + # between the different compatible versions for a given package requirement + # [arg: --resolution, env: UV_RESOLUTION=] + dependencies-strategy: ["lowest-direct", "highest"] + gt4py-module: ["cartesian", "eve", "next", "storage"] + os: ["ubuntu-latest"] #, "macos-latest"] python-version: ["3.10", "3.11"] - tox-module-factor: ["cartesian", "eve", "next", "storage"] - os: ["ubuntu-latest"] - requirements-file: ["requirements-dev.txt", "min-requirements-test.txt", "min-extra-requirements-test.txt"] fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - name: Install C++ libraries if: ${{ matrix.os == 'macos-latest' }} shell: bash - run: | - brew install boost + run: brew install boost + - name: Install C++ libraries if: ${{ matrix.os == 'ubuntu-latest' }} shell: bash - run: | - sudo apt install libboost-dev - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + run: sudo apt install libboost-dev + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: + enable-cache: true + cache-dependency-glob: "uv.lock" python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - name: Install tox - run: | - python -m pip install -c ./constraints.txt pip setuptools wheel tox - python -m pip list - - name: Update requirements - run: | - pyversion=${{ matrix.python-version }} - pyversion_no_dot=${pyversion//./} - tox run -e requirements-py${pyversion_no_dot} - # TODO(egparedes): add notification for dependencies updates - # - name: Check for updated requirements - # id: update-requirements - # continue-on-error: true - # if: ${{ matrix.python-version == '3.8' && matrix.tox-module-factor == 'cartesian' }} - # shell: bash - # run: | - # if diff -q constraints.txt CURRENT-constraints.txt; then - # echo "REQS_DIFF=''" >> $GITHUB_OUTPUT - # else - # diff --changed-group-format='%<' --unchanged-group-format='' constraints.txt CURRENT-constraints.txt | tr '\n' ' ' > constraints.txt.diff - # echo "REQS_DIFF='$(cat constraints.txt.diff)'" >> $GITHUB_OUTPUT - # fi - # echo "REQS_DIFF_TEST="FOOOOOOOO" >> $GITHUB_OUTPUT - # - name: Notify updated requirements (if any) - # if: ${{ steps.update-requirements.outputs.REQS_DIFF }} - # env: - # SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - # uses: slackapi/slack-github-action@v1.23.0 - # with: - # channel-id: ${{ vars.SLACK_BOT_CHANNEL }} - # payload: | - # { - # "text": "TEXT", - # "blocks": [ - # { - # "type": "section", - # "text": { - # "type": "plain_text", - # "text": "@channel: AA/${{ steps.update-requirements.outputs.REQS_DIFF }}/BB/ ${{ steps.update-requirements.outputs.REQS_DIFF_TEST }} /CC" - # } - # }, - # { - # "type": "section", - # "text": { - # "type": "mrkdwn", - # "text": "@channel: AA/${{ steps.update-requirements.outputs.REQS_DIFF }}/BB/ ${{ steps.update-requirements.outputs.REQS_DIFF_TEST }} /CC" - # } - # } - # ] - # } - - name: Run tests + + - name: Run CPU tests for '${{ matrix.gt4py-module }}' with '${{ matrix.dependencies-strategy }}' resolution strategy env: NUM_PROCESSES: auto - ENV_REQUIREMENTS_FILE: ${{ matrix.requirements-file }} - run: | - tox run --skip-missing-interpreters -m test-${{ matrix.tox-module-factor }}-cpu + UV_RESOLUTION: ${{ matrix.dependencies-strategy }} + run: uv run nox -s 'test_${{ matrix.gt4py-module }}-${{ matrix.python-version }}' -t 'cpu' + - name: Notify slack if: ${{ failure() }} env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} uses: slackapi/slack-github-action@v1.23.0 with: - channel-id: ${{ vars.SLACK_BOT_CHANNEL }} + channel-id: ${{ vars.SLACK_BOT_CHANNEL }} # Use SLACK_BOT_CHANNEL_TEST for testing + payload: | + { + "text": "Failed tests for ${{ github.workflow }} (dependencies-strategy=${{ matrix.dependencies-strategy }}, python=${{ matrix.python-version }}, component=${{ matrix.gt4py-module }}) [https://github.com/GridTools/gt4py/actions/runs/${{ github.run_id }}].", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Failed tests: " + } + } + ] + } + + weekly-reminder: + runs-on: ubuntu-latest + steps: + - id: get_day_of_the_week + name: Get day of the week + run: echo "day_of_week=$(date +'%u')" >> $GITHUB_OUTPUT + + - name: Weekly notification + if: ${{ env.DAY_OF_WEEK == 1 }} + env: + DAY_OF_WEEK: ${{ steps.get_day_of_the_week.outputs.day_of_week }} + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + uses: slackapi/slack-github-action@v1.23.0 + with: + channel-id: ${{ vars.SLACK_BOT_CHANNEL }} # Use SLACK_BOT_CHANNEL_TEST for testing payload: | { - "text": "${{ github.workflow }}: `test-${{ matrix.tox-module-factor }}-cpu (python${{ matrix.python-version }})`>: *Failed tests!*", + "text": "Weekly reminder to check the latest runs of the GT4Py Daily CI workflow at the GitHub Actions dashboard [https://github.com/GridTools/gt4py/actions/workflows/daily-ci.yml].", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", - "text": ": *Failed tests!*" + "text": "Weekly reminder to check the latest runs of the workflow at the GitHub Actions dashboard." } } ] diff --git a/.github/workflows/test-cartesian-fallback.yml b/.github/workflows/test-cartesian-fallback.yml index 8061ca56b9..a846af2e7b 100644 --- a/.github/workflows/test-cartesian-fallback.yml +++ b/.github/workflows/test-cartesian-fallback.yml @@ -13,11 +13,11 @@ on: jobs: test-cartesian: - runs-on: ubuntu-latest strategy: matrix: + codegen-factor: [internal, dace] + os: ["ubuntu-latest"] python-version: ["3.10", "3.11"] - tox-factor: [internal, dace] - + runs-on: ${{ matrix.os }} steps: - run: 'echo "No build required"' diff --git a/.github/workflows/test-cartesian.yml b/.github/workflows/test-cartesian.yml index 4b5a790f4d..ea6b7940a3 100644 --- a/.github/workflows/test-cartesian.yml +++ b/.github/workflows/test-cartesian.yml @@ -7,7 +7,7 @@ on: pull_request: branches: - main - paths-ignore: # Skip if only gt4py.next and irrelevant doc files have been updated + paths-ignore: # Skip when only gt4py.next or doc files have been updated - "src/gt4py/next/**" - "tests/next_tests/**" - "examples/**" @@ -20,35 +20,36 @@ concurrency: jobs: test-cartesian: - runs-on: ubuntu-latest strategy: matrix: + codegen-factor: [internal, dace] + os: ["ubuntu-latest"] python-version: ["3.10", "3.11"] - tox-factor: [internal, dace] + fail-fast: false + + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - name: Install C++ libraries + if: ${{ matrix.os == 'macos-latest' }} shell: bash - run: | - sudo apt install libboost-dev - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + run: brew install boost + + - name: Install C++ libraries + if: ${{ matrix.os == 'ubuntu-latest' }} + shell: bash + run: sudo apt install libboost-dev + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: + enable-cache: true + cache-dependency-glob: "uv.lock" python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - name: Install python dependencies - run: | - python -m pip install -c ./constraints.txt pip setuptools wheel - python -m pip install -r ./requirements-dev.txt - - name: Test with tox + + - name: Run CPU 'cartesian' tests with nox env: NUM_PROCESSES: auto shell: bash - run: | - pyversion=${{ matrix.python-version }} - pyversion_no_dot=${pyversion//./} - tox run -e cartesian-py${pyversion_no_dot}-${{ matrix.tox-factor }}-cpu + run: uv run nox -s 'test_cartesian-${{ matrix.python-version }}(${{ matrix.codegen-factor }}, cpu)' diff --git a/.github/workflows/test-eve-fallback.yml b/.github/workflows/test-eve-fallback.yml index 78f6136888..f3dbb58acf 100644 --- a/.github/workflows/test-eve-fallback.yml +++ b/.github/workflows/test-eve-fallback.yml @@ -1,15 +1,17 @@ name: "Fallback: Test Eve" on: + push: + branches: + - main pull_request: branches: - main paths-ignore: # Inverse of corresponding workflow - "src/gt4py/eve/**" - "tests/eve_tests/**" - - "workflows/**" - - "*.cfg" - - "*.ini" + - ".github/workflows/**" + - "*.lock" - "*.toml" - "*.yml" @@ -17,8 +19,8 @@ jobs: test-eve: strategy: matrix: - python-version: ["3.10", "3.11"] os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/test-eve.yml b/.github/workflows/test-eve.yml index 9d48d50c03..aad3971ad0 100644 --- a/.github/workflows/test-eve.yml +++ b/.github/workflows/test-eve.yml @@ -10,9 +10,8 @@ on: paths: # Run when gt4py.eve files (or package settings) are changed - "src/gt4py/eve/**" - "tests/eve_tests/**" - - "workflows/**" - - "*.cfg" - - "*.ini" + - ".github/workflows/**" + - "*.lock" - "*.toml" - "*.yml" @@ -20,51 +19,23 @@ jobs: test-eve: strategy: matrix: - python-version: ["3.10", "3.11"] os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: + enable-cache: true + cache-dependency-glob: "uv.lock" python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - name: Install python dependencies - run: | - python -m pip install -c ./constraints.txt pip setuptools wheel - python -m pip install -r ./requirements-dev.txt - - name: Run tox tests + + - name: Run 'eve' tests with nox env: NUM_PROCESSES: auto shell: bash - run: | - pyversion=${{ matrix.python-version }} - pyversion_no_dot=${pyversion//./} - tox run -e eve-py${pyversion_no_dot} - # mv coverage.json coverage-py${{ matrix.python-version }}-${{ matrix.os }}.json - # - name: Upload coverage.json artifact - # uses: actions/upload-artifact@v4 - # with: - # name: coverage-py${{ matrix.python-version }}-${{ matrix.os }} - # path: coverage-py${{ matrix.python-version }}-${{ matrix.os }}.json - # - name: Gather info - # run: | - # echo ${{ github.ref_type }} >> info.txt - # echo ${{ github.ref }} >> info.txt - # echo ${{ github.sha }} >> info.txt - # echo ${{ github.event.number }} >> info.txt - # echo ${{ github.event.pull_request.head.ref }} >> info.txt - # echo ${{ github.event.pull_request.head.sha }} >> info.txt - # echo ${{ github.run_id }} >> info.txt - # - name: Upload info artifact - # uses: actions/upload-artifact@v4 - # with: - # name: info-py${{ matrix.python-version }}-${{ matrix.os }} - # path: info.txt + run: uv run nox -s test_eve-${{ matrix.python-version }} diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml new file mode 100644 index 0000000000..836af45dd1 --- /dev/null +++ b/.github/workflows/test-examples.yml @@ -0,0 +1,44 @@ +name: "Test examples in documentation" + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test-notebooks: + strategy: + matrix: + os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] + fail-fast: false + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Install C++ libraries + if: ${{ matrix.os == 'macos-latest' }} + shell: bash + run: brew install boost + + - name: Install C++ libraries + if: ${{ matrix.os == 'ubuntu-latest' }} + shell: bash + run: sudo apt install libboost-dev + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + cache-dependency-glob: "uv.lock" + python-version: ${{ matrix.python-version }} + + - name: Run 'docs' nox session + env: + NUM_PROCESSES: auto + shell: bash + run: uv run nox -s 'test_examples-${{ matrix.python-version }}' diff --git a/.github/workflows/test-next-fallback.yml b/.github/workflows/test-next-fallback.yml index 16a0cf0df3..ef8be3df5f 100644 --- a/.github/workflows/test-next-fallback.yml +++ b/.github/workflows/test-next-fallback.yml @@ -15,9 +15,10 @@ jobs: test-next: strategy: matrix: - python-version: ["3.10", "3.11"] - tox-factor: ["nomesh", "atlas"] + codegen-factor: [internal, dace] + mesh-factor: [nomesh, atlas] os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/test-next.yml b/.github/workflows/test-next.yml index 1928370202..068377c6c7 100644 --- a/.github/workflows/test-next.yml +++ b/.github/workflows/test-next.yml @@ -7,7 +7,7 @@ on: pull_request: branches: - main - paths-ignore: # Skip if only gt4py.cartesian and irrelevant doc files have been updated + paths-ignore: # Skip when only gt4py.cartesian or doc files have been updated - "src/gt4py/cartesian/**" - "tests/cartesian_tests/**" - "examples/**" @@ -18,63 +18,35 @@ jobs: test-next: strategy: matrix: - python-version: ["3.10", "3.11"] - tox-factor: ["nomesh", "atlas"] + codegen-factor: [internal, dace] + mesh-factor: [nomesh, atlas] os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - name: Install C++ libraries if: ${{ matrix.os == 'macos-latest' }} shell: bash - run: | - brew install boost + run: brew install boost + - name: Install C++ libraries if: ${{ matrix.os == 'ubuntu-latest' }} shell: bash - run: | - sudo apt install libboost-dev - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + run: sudo apt install libboost-dev + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: + enable-cache: true + cache-dependency-glob: "uv.lock" python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - name: Install python dependencies - shell: bash - run: | - python -m pip install -c ./constraints.txt pip setuptools wheel - python -m pip install -r ./requirements-dev.txt - - name: Run tox tests + + - name: Run CPU 'next' tests with nox env: NUM_PROCESSES: auto shell: bash - run: | - pyversion=${{ matrix.python-version }} - pyversion_no_dot=${pyversion//./} - tox run -e next-py${pyversion_no_dot}-${{ matrix.tox-factor }}-cpu - # mv coverage.json coverage-py${{ matrix.python-version }}-${{ matrix.os }}-${{ matrix.tox-env-factor }}-cpu.json - # - name: Upload coverage.json artifact - # uses: actions/upload-artifact@v4 - # with: - # name: coverage-py${{ matrix.python-version }}-${{ matrix.os }}-${{ matrix.tox-env-factor }}-cpu - # path: coverage-py${{ matrix.python-version }}-${{ matrix.os }}-${{ matrix.tox-env-factor }}-cpu.json - # - name: Gather info - # run: | - # echo ${{ github.ref_type }} >> info.txt - # echo ${{ github.ref }} >> info.txt - # echo ${{ github.sha }} >> info.txt - # echo ${{ github.event.number }} >> info.txt - # echo ${{ github.event.pull_request.head.ref }} >> info.txt - # echo ${{ github.event.pull_request.head.sha }} >> info.txt - # echo ${{ github.run_id }} >> info.txt - # - name: Upload info artifact - # uses: actions/upload-artifact@v4 - # with: - # name: info-py${{ matrix.python-version }}-${{ matrix.os }}-${{ matrix.tox-env-factor }}-cpu - # path: info.txt + run: uv run nox -s 'test_next-${{ matrix.python-version }}(${{ matrix.codegen-factor }}, cpu, ${{ matrix.mesh-factor }})' diff --git a/.github/workflows/test-notebooks.yml b/.github/workflows/test-notebooks.yml deleted file mode 100644 index ae45cb154d..0000000000 --- a/.github/workflows/test-notebooks.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: "Test Jupyter Notebooks" - -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - test-notebooks: - strategy: - matrix: - python-version: ["3.10", "3.11"] - os: ["ubuntu-latest"] - fail-fast: false - - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - name: Install python dependencies - run: | - python -m pip install -c ./constraints.txt pip setuptools wheel - python -m pip install -r ./requirements-dev.txt - - name: Run tox tests - env: - NUM_PROCESSES: auto - shell: bash - run: | - pyversion=${{ matrix.python-version }} - pyversion_no_dot=${pyversion//./} - tox run -e notebooks-py${pyversion_no_dot} diff --git a/.github/workflows/test-storage-fallback.yml b/.github/workflows/test-storage-fallback.yml index 46a4442520..c913529a1c 100644 --- a/.github/workflows/test-storage-fallback.yml +++ b/.github/workflows/test-storage-fallback.yml @@ -1,6 +1,9 @@ name: "Fallback: Test Storage (CPU)" on: + push: + branches: + - main pull_request: branches: - main @@ -8,9 +11,8 @@ on: - "src/gt4py/storage/**" - "src/gt4py/cartesian/backend/**" # For DaCe storages - "tests/storage_tests/**" - - "workflows/**" - - "*.cfg" - - "*.ini" + - ".github/workflows/**" + - "*.lock" - "*.toml" - "*.yml" @@ -18,9 +20,8 @@ jobs: test-storage: strategy: matrix: - python-version: ["3.10", "3.11"] - tox-factor: [internal, dace] os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/test-storage.yml b/.github/workflows/test-storage.yml index 3748ac193e..b2bb09dfcc 100644 --- a/.github/workflows/test-storage.yml +++ b/.github/workflows/test-storage.yml @@ -11,9 +11,8 @@ on: - "src/gt4py/storage/**" - "src/gt4py/cartesian/backend/**" # For DaCe storages - "tests/storage_tests/**" - - "workflows/**" - - "*.cfg" - - "*.ini" + - ".github/workflows/**" + - "*.lock" - "*.toml" - "*.yml" @@ -21,52 +20,23 @@ jobs: test-storage: strategy: matrix: - python-version: ["3.10", "3.11"] - tox-factor: [internal, dace] os: ["ubuntu-latest"] + python-version: ["3.10", "3.11"] fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: + enable-cache: true + cache-dependency-glob: "uv.lock" python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: | - **/pyproject.toml - **/constraints.txt - **/requirements-dev.txt - - name: Install python dependencies - run: | - python -m pip install -c ./constraints.txt pip setuptools wheel - python -m pip install -r ./requirements-dev.txt - - name: Run tox tests + + - name: Run CPU 'storage' tests with nox env: NUM_PROCESSES: auto shell: bash - run: | - pyversion=${{ matrix.python-version }} - pyversion_no_dot=${pyversion//./} - tox run -e storage-py${pyversion_no_dot}-${{ matrix.tox-factor }}-cpu - # mv coverage.json coverage-py${{ matrix.python-version }}-${{ matrix.os }}.json - # - name: Upload coverage.json artifact - # uses: actions/upload-artifact@v4 - # with: - # name: coverage-py${{ matrix.python-version }}-${{ matrix.os }} - # path: coverage-py${{ matrix.python-version }}-${{ matrix.os }}.json - # - name: Gather info - # run: | - # echo ${{ github.ref_type }} >> info.txt - # echo ${{ github.ref }} >> info.txt - # echo ${{ github.sha }} >> info.txt - # echo ${{ github.event.number }} >> info.txt - # echo ${{ github.event.pull_request.head.ref }} >> info.txt - # echo ${{ github.event.pull_request.head.sha }} >> info.txt - # echo ${{ github.run_id }} >> info.txt - # - name: Upload info artifact - # uses: actions/upload-artifact@v4 - # with: - # name: info-py${{ matrix.python-version }}-${{ matrix.os }} - # path: info.txt + run: uv run nox -s 'test_storage-${{ matrix.python-version }}(cpu)' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 051781ea49..4222224cc4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,23 @@ -# ----------------------------------------------------------------------- -# This file contains 'cog' snippets (https://nedbatchelder.com/code/cog/) -# to keep version numbers in sync with 'constraints.txt' -# ----------------------------------------------------------------------- - default_language_version: python: python3.10 +minimum_pre_commit_version: 3.8.0 repos: # - repo: meta # hooks: # - id: check-hooks-apply # - id: check-useless-excludes + +- repo: https://github.com/astral-sh/uv-pre-commit + # uv version. + rev: 0.5.10 + hooks: + - id: uv-lock + - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks rev: v2.6.0 hooks: - id: pretty-format-ini args: [--autofix] - exclude: tox.ini - id: pretty-format-toml args: [--autofix] exclude: tach.toml @@ -45,86 +47,25 @@ repos: - id: check-yaml - repo: https://github.com/astral-sh/ruff-pre-commit - ##[[[cog - ## import re - ## version = re.search('ruff==([0-9\.]*)', open("constraints.txt").read())[1] - ## print(f"rev: v{version}") - ##]]] rev: v0.8.6 - ##[[[end]]] hooks: - # Run the linter. - # TODO: include tests here - id: ruff - files: ^src/ + files: ^src/ # TODO(egparedes): also add the `tests` folder here args: [--fix] - # Run the formatter. - id: ruff-format - repo: https://github.com/gauge-sh/tach-pre-commit - rev: v0.10.7 + rev: v0.23.0 hooks: - id: tach -- repo: https://github.com/pre-commit/mirrors-mypy - ##[[[cog - ## import re - ## version = re.search('mypy==([0-9\.]*)', open("constraints.txt").read())[1] - ## print(f"#========= FROM constraints.txt: v{version} =========") - ##]]] - #========= FROM constraints.txt: v1.14.1 ========= - ##[[[end]]] - rev: v1.14.1 # MUST match version ^^^^ in constraints.txt (if the mirror is up-to-date) +- repo: local hooks: - id: mypy - additional_dependencies: # versions from constraints.txt - ##[[[cog - ## import re, sys - ## if sys.version_info >= (3, 11): - ## import tomllib - ## else: - ## import tomli as tomllib - ## constraints = open("constraints.txt").read() - ## project = tomllib.loads(open("pyproject.toml").read()) - ## packages = [re.match('^([\w-][\w\d-]*)', r)[1] for r in project["project"]["dependencies"] if r.strip()] - ## for pkg in packages: - ## print(f"- {pkg}==" + str(re.search(f'\n{pkg}==([0-9\.]*)', constraints)[1])) - ##]]] - - attrs==24.3.0 - - black==24.10.0 - - boltons==24.1.0 - - cached-property==2.0.1 - - click==8.1.8 - - cmake==3.31.2 - - cytoolz==1.0.1 - - deepdiff==8.1.1 - - devtools==0.12.2 - - diskcache==5.6.3 - - factory-boy==3.3.1 - - filelock==3.16.1 - - frozendict==2.4.6 - - gridtools-cpp==2.3.8 - - jinja2==3.1.5 - - lark==1.2.2 - - mako==1.3.8 - - nanobind==2.4.0 - - ninja==1.11.1.3 - - numpy==1.26.4 - - packaging==24.2 - - pybind11==2.13.6 - - setuptools==75.8.0 - - tabulate==0.9.0 - - typing-extensions==4.12.2 - - xxhash==3.0.0 - ##[[[end]]] - - types-tabulate - - types-typed-ast - args: [--no-install-types] - exclude: | - (?x)^( - setup.py | - build/.* | - ci/.* | - docs/.* | - tests/.* - )$ + name: mypy static type checker + entry: uv run mypy --no-install-types src/ + language: system + types_or: [python, pyi] + pass_filenames: false + require_serial: true + stages: [pre-commit] diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000..c8cfe39591 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 15e139a53e..e0ef75d31e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,7 +55,7 @@ Ready to start contributing? We use a [fork and pull request](https://www.atlass 3. Follow instructions in the [README.md](README.md) file to set up an environment for local development. For example: ```bash - $ tox --devenv .venv + $ uv sync --extra all $ source .venv/bin/activate ``` @@ -67,11 +67,11 @@ Ready to start contributing? We use a [fork and pull request](https://www.atlass Now you can make your changes locally. Make sure you follow the project code style documented in [CODING_GUIDELINES.md](CODING_GUIDELINES.md). -5. When you're done making changes, check that your code complies with the project code style and other quality assurance (QA) practices using `pre-commit`. Additionally, make sure that unit and regression tests pass for all supported Python versions by running `tox`: +5. When you're done making changes, check that your code complies with the project code style and other quality assurance (QA) practices using `pre-commit`. Additionally, make sure that unit and regression tests pass for all supported Python versions by running `nox`: ```bash $ pre-commit run - $ tox + $ nox ``` Read [Testing](#testing) section below for further details. @@ -143,21 +143,21 @@ pytest -v -l -s tests/ Check `pytest` documentation (`pytest --help`) for all the options to select and execute tests. -We recommended you to use `tox` for most development-related tasks, like running the complete test suite in different environments. `tox` runs the package installation script in properly isolated environments to run tests (or other tasks) in a reproducible way. A simple way to start with tox could be: +We recommended you to use `nox` for running the test suite in different environments. `nox` runs the package installation script in properly isolated environments to run tests in a reproducible way. A simple way to start with `nox` would be: ```bash # List all the available task environments -tox list +nox list # Run a specific task environment -tox run -e cartesian-py38-internal-cpu +nox -e cartesian-py38-internal-cpu ``` -Check `tox` documentation (`tox --help`) for the complete reference. +Check `nox` documentation (`nox --help`) for the complete reference. +Additionally, `nox` is configured to generate HTML test coverage reports in `tests/_reports/coverage_html/` at the end. --> ## Pull Requests (PRs) and Merge Guidelines @@ -175,27 +175,29 @@ Before submitting a pull request, check that it meets the following criteria: As mentioned above, we use several tools to help us write high-quality code. New tools could be added in the future, especially if they do not add a large overhead to our workflow and they bring extra benefits to keep our codebase in shape. The most important ones which we currently rely on are: -- [ruff][ruff] for style enforcement and code linting. +- [nox][nox] for testing and task automation with different environments. - [pre-commit][pre-commit] for automating the execution of QA tools. - [pytest][pytest] for writing readable tests, extended with: - [Coverage.py][coverage] and [pytest-cov][pytest-cov] for test coverage reports. - [pytest-xdist][pytest-xdist] for running tests in parallel. -- [tox][tox] for testing and task automation with different environments. +- [ruff][ruff] for style enforcement and code linting. - [sphinx][sphinx] for generating documentation, extended with: - [sphinx-autodoc][sphinx-autodoc] and [sphinx-napoleon][sphinx-napoleon] for extracting API documentation from docstrings. - [jupytext][jupytext] for writing new user documentation with code examples. +- [uv][uv] for managing dependencies and environments. [conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/#summary [coverage]: https://coverage.readthedocs.io/ -[ruff]: https://astral.sh/ruff [jupytext]: https://jupytext.readthedocs.io/ +[nox]: https://nox.thea.codes/en/stable/ [pre-commit]: https://pre-commit.com/ [pytest]: https://docs.pytest.org/ [pytest-cov]: https://pypi.org/project/pytest-cov/ [pytest-xdist]: https://pytest-xdist.readthedocs.io/en/latest/ +[ruff]: https://astral.sh/ruff [sphinx]: https://www.sphinx-doc.org [sphinx-autodoc]: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html [sphinx-napoleon]: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/index.html -[tox]: https://tox.wiki/en/latest/ +[uv]: https://docs.astral.sh/uv/ diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/README.md b/README.md index 07e0e1cdee..f778c4f54b 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ ![test-eve](https://github.com/GridTools/gt4py/actions/workflows/test-eve.yml/badge.svg?branch=main) ![qa](https://github.com/GridTools/gt4py/actions/workflows/code-quality.yml/badge.svg?branch=main) +[![uv](https://img.shields.io/badge/-uv-261230.svg?logo=uv)](https://github.com/astral-sh/uv) +[![Nox](https://img.shields.io/badge/%F0%9F%A6%8A-Nox-D85E00.svg)](https://github.com/wntrblm/nox) + # GT4Py: GridTools for Python GT4Py is a Python library for generating high performance implementations of stencil kernels from a high-level definition using regular Python functions. GT4Py is part of the GridTools framework, a set of libraries and utilities to develop performance portable applications in the area of weather and climate modeling. @@ -36,18 +39,18 @@ The following backends are supported: ## 🚜 Installation -GT4Py can be installed as a regular Python package using `pip` (or any other PEP-517 frontend). As usual, we strongly recommended to create a new virtual environment to work on this project. +GT4Py can be installed as a regular Python package using [uv](https://docs.astral.sh/uv/), [pip](https://pip.pypa.io/en/stable/) or any other PEP-517 compatible frontend. We strongly recommended to use`uv` to create and manage virtual environments for your own projects. The performance backends also require the [Boost](https://www.boost.org) library, a dependency of [GridTools C++](https://github.com/GridTools/gridtools), which needs to be installed by the user. ## ⚙ Configuration -If GridTools or Boost are not found in the compiler's standard include path, or a custom version is desired, then a couple configuration environment variables will allow the compiler to use them: +To explicitly set the [GridTools-C++](https://gridtools.github.io/gridtools) or [Boost](https://www.boost.org) versions used by the code generation backends, the following environment variables can be used: - `GT_INCLUDE_PATH`: Path to the GridTools installation. - `BOOST_ROOT`: Path to a boost installation. -Other commonly used environment variables are: +Other useful available environment variables are: - `CUDA_ARCH`: Set the compute capability of the NVIDIA GPU if it is not detected automatically by `cupy`. - `CXX`: Set the C++ compiler. @@ -56,67 +59,68 @@ Other commonly used environment variables are: More options and details are available in [`config.py`](https://github.com/GridTools/gt4py/blob/main/src/gt4py/cartesian/config.py). -## 📖 Documentation +## 🛠 Development Instructions -GT4Py uses Sphinx documentation. To build the documentation install the dependencies in `requirements-dev.txt` +Follow the installation instructions below to initialize a development virtual environment containing an _editable_ installation of the GT4Py package. Make sure you read the [CONTRIBUTING.md](CONTRIBUTING.md) and [CODING_GUIDELINES.md](CODING_GUIDELINES.md) documents before you start working on the project. -```bash -pip install -r ./gt4py/requirements-dev.txt -``` +### Development Environment Installation using `uv` -and then build the docs with +GT4Py uses the [`uv`](https://docs.astral.sh/uv/) project manager for the development workflow. `uv` is a versatile tool that consolidates functionality usually distributed across different applications into subcommands. -```bash -cd gt4py/docs/user/cartesian -make html # run 'make help' for a list of targets -``` +- The `uv pip` subcommand provides a _fast_ Python package manager, emulating [`pip`](https://pip.pypa.io/en/stable/). +- The `uv export | lock | sync` subcommands manage dependency versions in a manner similar to the [`pip-tools`](https://pip-tools.readthedocs.io/en/stable/) command suite. +- The `uv init | add | remove | build | publish | ...` subcommands facilitate project development workflows, akin to [`hatch`](https://hatch.pypa.io/latest/). +- The `uv tool` subcommand serves as a runner for Python applications in isolation, similar to [`pipx`](https://pipx.pypa.io/stable/). +- The `uv python` subcommands manage different Python installations and versions, much like [`pyenv`](https://github.com/pyenv/pyenv). -## 🛠 Development Instructions +`uv` can be installed in various ways (see its [installation instructions](https://docs.astral.sh/uv/getting-started/installation/)), with the recommended method being the standalone installer: -Follow the installation instructions below to initialize a development virtual environment containing an _editable_ installation of the GT4Py package. Make sure you read the [CONTRIBUTING.md](CONTRIBUTING.md) and [CODING_GUIDELINES.md](CODING_GUIDELINES.md) documents before you start working on the project. - -### Recommended Installation using `tox` +```bash +$ curl -LsSf https://astral.sh/uv/install.sh | sh +``` -If [tox](https://tox.wiki/en/latest/) is already installed in your system (`tox` is available in PyPI and many other package managers), the easiest way to create a virtual environment ready for development is: +Once `uv` is installed in your system, it is enough to clone this repository and let `uv` handling the installation of the development environment. ```bash # Clone the repository git clone https://github.com/gridtools/gt4py.git cd gt4py -# Create the development environment in any location (usually `.venv`) -# selecting one of the following templates: -# dev-py310 -> base environment -# dev-py310-atlas -> base environment + atlas4py bindings -tox devenv -e dev-py310 .venv +# Let uv create the development environment at `.venv`. +# The `--extra all` option tells uv to install all the optional +# dependencies of gt4py, and thus it is not strictly necessary. +# Note that if no dependency groups are provided as an option, +# uv uses `--group dev` by default so the development dependencies +# are installed. +uv sync --extra all -# Finally, activate the environment +# Finally, activate the virtual environment and start writing code! source .venv/bin/activate ``` -### Manual Installation +The newly created _venv_ is a standard Python virtual environment preconfigured with all necessary runtime and development dependencies. Additionally, the `gt4py` package is installed in editable mode, allowing for seamless development and testing. To install new packages in this environment, use the `uv pip` subcommand which emulates the `pip` interface and is generally much faster than the original `pip` tool (which is also available within the venv although its use is discouraged). -Alternatively, a development environment can be created from scratch installing the frozen dependencies packages : +The `pyproject.toml` file contains both the definition of the `gt4py` Python distribution package and the settings of the development tools used in this project, most notably `uv`, `ruff`, and `mypy`. It also contains _dependency groups_ (see [PEP 735](https://peps.python.org/pep-0735/) for further reference) with the development requirements listed in different groups (`build`, `docs`, `lint`, `test`, `typing`, ...) and collected together in the general `dev` group, which gets installed by default by `uv` as mentioned above. -```bash -# Clone the repository -git clone https://github.com/gridtools/gt4py.git -cd gt4py +### Development Tasks (`dev-tasks.py`) -# Create a (Python 3.10) virtual environment (usually at `.venv`) -python3.10 -m venv .venv +Recurrent development tasks like bumping versions of used development tools or required third party dependencies have been collected as different subcommands in the [`dev-tasks.py`](./dev-tasks.py) script. Read the tool help for a brief description of every task and always use this tool to update the versions and sync the version configuration accross different files (e.g. `pyproject.toml` and `.pre-commit-config.yaml`). -# Activate the virtual environment and update basic packages -source .venv/bin/activate -pip install --upgrade wheel setuptools pip +## 📖 Documentation + +GT4Py uses the Sphinx tool for the documentation. To build browseable HTML documentation, install the required tools provided in the `docs` dependency group: -# Install the required development tools -pip install -r requirements-dev.txt -# Install GT4Py project in editable mode -pip install -e . +```bash +uv install --group docs --extra all # or --group dev +``` + +(Note that most likely these tools are already installed in your development environment, since the `docs` group is included in the `dev` group, which installed by default by `uv sync` if no dependency groups are specified.) + +Once the requirements are already installed, then build the docs using: -# Optionally, install atlas4py bindings directly from the repo -# pip install git+https://github.com/GridTools/atlas4py#egg=atlas4py +```bash +cd gt4py/docs/user/cartesian +make html # run 'make help' for a list of targets ``` ## ⚖️ License diff --git a/ci/base.Dockerfile b/ci/base.Dockerfile index ea7c4722c7..1ad9aefa03 100644 --- a/ci/base.Dockerfile +++ b/ci/base.Dockerfile @@ -57,4 +57,4 @@ ENV PATH="/root/.pyenv/shims:${PATH}" ARG CUPY_PACKAGE=cupy-cuda12x ARG CUPY_VERSION=13.3.0 -RUN pip install --upgrade pip setuptools wheel tox ${CUPY_PACKAGE}==${CUPY_VERSION} +RUN pip install --upgrade pip setuptools wheel uv nox ${CUPY_PACKAGE}==${CUPY_VERSION} diff --git a/ci/cscs-ci.yml b/ci/cscs-ci.yml index b5ea07b787..05955913ba 100644 --- a/ci/cscs-ci.yml +++ b/ci/cscs-ci.yml @@ -4,7 +4,6 @@ include: .py311: &py311 PYVERSION_PREFIX: py311 PYVERSION: 3.11.9 - .py310: &py310 PYVERSION_PREFIX: py310 PYVERSION: 3.10.9 @@ -111,13 +110,14 @@ build_py310_image_aarch64: image: $CSCS_REGISTRY_PATH/public/$ARCH/gt4py/gt4py-ci:$CI_COMMIT_SHA-$PYVERSION script: - cd /gt4py.src - - python -c "import cupy" - - tox run -e $SUBPACKAGE-$PYVERSION_PREFIX$VARIANT$SUBVARIANT + - NOX_SESSION_ARGS="${VARIANT:+($VARIANT}${SUBVARIANT:+, $SUBVARIANT}${DETAIL:+, $DETAIL}${VARIANT:+)}" + - nox -e "test_$SUBPACKAGE-${PYVERSION:0:4}$NOX_SESSION_ARGS" variables: CRAY_CUDA_MPS: 1 SLURM_JOB_NUM_NODES: 1 SLURM_TIMELIMIT: 15 NUM_PROCESSES: auto + PYENV_VERSION: $PYVERSION VIRTUALENV_SYSTEM_SITE_PACKAGES: 1 # .test_helper_x86_64: # extends: [.container-runner-daint-gpu, .test_helper] @@ -134,13 +134,16 @@ build_py310_image_aarch64: extends: [.container-runner-daint-gh200, .test_helper] parallel: matrix: - - SUBPACKAGE: [cartesian, storage] - VARIANT: [-internal, -dace] - SUBVARIANT: [-cuda12x, -cpu] + - SUBPACKAGE: [cartesian] + VARIANT: ['internal', 'dace'] + SUBVARIANT: ['cuda12', 'cpu'] - SUBPACKAGE: eve - SUBPACKAGE: next - VARIANT: [-nomesh, -atlas] - SUBVARIANT: [-cuda12x, -cpu] + VARIANT: ['internal', 'dace'] + SUBVARIANT: ['cuda12', 'cpu'] + DETAIL: ['nomesh', 'atlas'] + - SUBPACKAGE: [storage] + VARIANT: ['cuda12', 'cpu'] variables: # Grace-Hopper gpu architecture is not enabled by default in CUDA build CUDAARCHS: "90" diff --git a/constraints.txt b/constraints.txt deleted file mode 100644 index 8b3e5e697f..0000000000 --- a/constraints.txt +++ /dev/null @@ -1,178 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# "tox run -e requirements-base" -# -aenum==3.1.15 # via dace -alabaster==1.0.0 # via sphinx -annotated-types==0.7.0 # via pydantic -asttokens==2.4.1 # via devtools, stack-data -astunparse==1.6.3 # via dace -attrs==24.3.0 # via gt4py (pyproject.toml), hypothesis, jsonschema, referencing -babel==2.16.0 # via sphinx -black==24.10.0 # via gt4py (pyproject.toml) -boltons==24.1.0 # via gt4py (pyproject.toml) -bracex==2.5.post1 # via wcmatch -build==1.2.2.post1 # via pip-tools -bump-my-version==0.29.0 # via -r requirements-dev.in -cached-property==2.0.1 # via gt4py (pyproject.toml) -cachetools==5.5.0 # via tox -certifi==2024.12.14 # via requests -cfgv==3.4.0 # via pre-commit -chardet==5.2.0 # via tox -charset-normalizer==3.4.1 # via requests -clang-format==19.1.6 # via -r requirements-dev.in, gt4py (pyproject.toml) -click==8.1.8 # via black, bump-my-version, gt4py (pyproject.toml), pip-tools, rich-click -cmake==3.31.2 # via gt4py (pyproject.toml) -cogapp==3.4.1 # via -r requirements-dev.in -colorama==0.4.6 # via tox -comm==0.2.2 # via ipykernel -contourpy==1.3.1 # via matplotlib -coverage==7.6.10 # via -r requirements-dev.in, pytest-cov -cycler==0.12.1 # via matplotlib -cytoolz==1.0.1 # via gt4py (pyproject.toml) -dace==1.0.0 # via gt4py (pyproject.toml) -darglint==1.8.1 # via -r requirements-dev.in -debugpy==1.8.11 # via ipykernel -decorator==5.1.1 # via ipython -deepdiff==8.1.1 # via gt4py (pyproject.toml) -devtools==0.12.2 # via gt4py (pyproject.toml) -dill==0.3.9 # via dace -diskcache==5.6.3 # via gt4py (pyproject.toml) -distlib==0.3.9 # via virtualenv -docutils==0.21.2 # via sphinx, sphinx-rtd-theme -exceptiongroup==1.2.2 # via hypothesis, ipython, pytest -execnet==2.1.1 # via pytest-cache, pytest-xdist -executing==2.1.0 # via devtools, stack-data -factory-boy==3.3.1 # via gt4py (pyproject.toml), pytest-factoryboy -faker==33.3.0 # via factory-boy -fastjsonschema==2.21.1 # via nbformat -filelock==3.16.1 # via gt4py (pyproject.toml), tox, virtualenv -fonttools==4.55.3 # via matplotlib -fparser==0.2.0 # via dace -frozendict==2.4.6 # via gt4py (pyproject.toml) -gitdb==4.0.12 # via gitpython -gitpython==3.1.44 # via tach -gridtools-cpp==2.3.8 # via gt4py (pyproject.toml) -hypothesis==6.123.11 # via -r requirements-dev.in, gt4py (pyproject.toml) -identify==2.6.5 # via pre-commit -idna==3.10 # via requests -imagesize==1.4.1 # via sphinx -inflection==0.5.1 # via pytest-factoryboy -iniconfig==2.0.0 # via pytest -ipykernel==6.29.5 # via nbmake -ipython==8.31.0 # via ipykernel -jax==0.4.38 # via gt4py (pyproject.toml) -jaxlib==0.4.38 # via jax -jedi==0.19.2 # via ipython -jinja2==3.1.5 # via gt4py (pyproject.toml), sphinx -jsonschema==4.23.0 # via nbformat -jsonschema-specifications==2024.10.1 # via jsonschema -jupyter-client==8.6.3 # via ipykernel, nbclient -jupyter-core==5.7.2 # via ipykernel, jupyter-client, nbclient, nbformat -jupytext==1.16.6 # via -r requirements-dev.in -kiwisolver==1.4.8 # via matplotlib -lark==1.2.2 # via gt4py (pyproject.toml) -mako==1.3.8 # via gt4py (pyproject.toml) -markdown-it-py==3.0.0 # via jupytext, mdit-py-plugins, rich -markupsafe==3.0.2 # via jinja2, mako -matplotlib==3.10.0 # via -r requirements-dev.in -matplotlib-inline==0.1.7 # via ipykernel, ipython -mdit-py-plugins==0.4.2 # via jupytext -mdurl==0.1.2 # via markdown-it-py -ml-dtypes==0.5.1 # via jax, jaxlib -mpmath==1.3.0 # via sympy -mypy==1.14.1 # via -r requirements-dev.in -mypy-extensions==1.0.0 # via black, mypy -nanobind==2.4.0 # via gt4py (pyproject.toml) -nbclient==0.10.2 # via nbmake -nbformat==5.10.4 # via jupytext, nbclient, nbmake -nbmake==1.5.5 # via -r requirements-dev.in -nest-asyncio==1.6.0 # via ipykernel -networkx==3.4.2 # via dace, tach -ninja==1.11.1.3 # via gt4py (pyproject.toml) -nodeenv==1.9.1 # via pre-commit -numpy==1.26.4 # via contourpy, dace, gt4py (pyproject.toml), jax, jaxlib, matplotlib, ml-dtypes, scipy -opt-einsum==3.4.0 # via jax -orderly-set==5.2.3 # via deepdiff -packaging==24.2 # via black, build, dace, gt4py (pyproject.toml), ipykernel, jupytext, matplotlib, pipdeptree, pyproject-api, pytest, pytest-factoryboy, setuptools-scm, sphinx, tox -parso==0.8.4 # via jedi -pathspec==0.12.1 # via black -pexpect==4.9.0 # via ipython -pillow==11.1.0 # via matplotlib -pip-tools==7.4.1 # via -r requirements-dev.in -pipdeptree==2.24.0 # via -r requirements-dev.in -platformdirs==4.3.6 # via black, jupyter-core, tox, virtualenv -pluggy==1.5.0 # via pytest, tox -ply==3.11 # via dace -pre-commit==4.0.1 # via -r requirements-dev.in -prompt-toolkit==3.0.48 # via ipython, questionary, tach -psutil==6.1.1 # via -r requirements-dev.in, ipykernel, pytest-xdist -ptyprocess==0.7.0 # via pexpect -pure-eval==0.2.3 # via stack-data -pybind11==2.13.6 # via gt4py (pyproject.toml) -pydantic==2.10.4 # via bump-my-version, pydantic-settings -pydantic-core==2.27.2 # via pydantic -pydantic-settings==2.7.1 # via bump-my-version -pydot==3.0.4 # via tach -pygments==2.19.1 # via -r requirements-dev.in, devtools, ipython, nbmake, rich, sphinx -pyparsing==3.2.1 # via matplotlib, pydot -pyproject-api==1.8.0 # via tox -pyproject-hooks==1.2.0 # via build, pip-tools -pytest==8.3.4 # via -r requirements-dev.in, gt4py (pyproject.toml), nbmake, pytest-cache, pytest-cov, pytest-custom-exit-code, pytest-factoryboy, pytest-instafail, pytest-xdist -pytest-cache==1.0 # via -r requirements-dev.in -pytest-cov==6.0.0 # via -r requirements-dev.in -pytest-custom-exit-code==0.3.0 # via -r requirements-dev.in -pytest-factoryboy==2.7.0 # via -r requirements-dev.in -pytest-instafail==0.5.0 # via -r requirements-dev.in -pytest-xdist==3.6.1 # via -r requirements-dev.in -python-dateutil==2.9.0.post0 # via faker, jupyter-client, matplotlib -python-dotenv==1.0.1 # via pydantic-settings -pyyaml==6.0.2 # via dace, jupytext, pre-commit, tach -pyzmq==26.2.0 # via ipykernel, jupyter-client -questionary==2.1.0 # via bump-my-version -referencing==0.35.1 # via jsonschema, jsonschema-specifications -requests==2.32.3 # via sphinx -rich==13.9.4 # via bump-my-version, rich-click, tach -rich-click==1.8.5 # via bump-my-version -rpds-py==0.22.3 # via jsonschema, referencing -ruff==0.8.6 # via -r requirements-dev.in -scipy==1.15.0 # via gt4py (pyproject.toml), jax, jaxlib -setuptools-scm==8.1.0 # via fparser -six==1.17.0 # via asttokens, astunparse, python-dateutil -smmap==5.0.2 # via gitdb -snowballstemmer==2.2.0 # via sphinx -sortedcontainers==2.4.0 # via hypothesis -sphinx==8.1.3 # via -r requirements-dev.in, sphinx-rtd-theme, sphinxcontrib-jquery -sphinx-rtd-theme==3.0.2 # via -r requirements-dev.in -sphinxcontrib-applehelp==2.0.0 # via sphinx -sphinxcontrib-devhelp==2.0.0 # via sphinx -sphinxcontrib-htmlhelp==2.1.0 # via sphinx -sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme -sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==2.0.0 # via sphinx -sphinxcontrib-serializinghtml==2.0.0 # via sphinx -stack-data==0.6.3 # via ipython -sympy==1.13.3 # via dace -tabulate==0.9.0 # via gt4py (pyproject.toml) -tach==0.19.5 # via -r requirements-dev.in -tomli==2.2.1 ; python_version < "3.11" # via -r requirements-dev.in, black, build, coverage, jupytext, mypy, pip-tools, pyproject-api, pytest, setuptools-scm, sphinx, tach, tox -tomli-w==1.1.0 # via tach -tomlkit==0.13.2 # via bump-my-version -toolz==1.0.0 # via cytoolz -tornado==6.4.2 # via ipykernel, jupyter-client -tox==4.23.2 # via -r requirements-dev.in -traitlets==5.14.3 # via comm, ipykernel, ipython, jupyter-client, jupyter-core, matplotlib-inline, nbclient, nbformat -types-tabulate==0.9.0.20241207 # via -r requirements-dev.in -typing-extensions==4.12.2 # via black, faker, gt4py (pyproject.toml), ipython, mypy, pydantic, pydantic-core, pytest-factoryboy, rich, rich-click, tox -urllib3==2.3.0 # via requests -virtualenv==20.28.1 # via pre-commit, tox -wcmatch==10.0 # via bump-my-version -wcwidth==0.2.13 # via prompt-toolkit -wheel==0.45.1 # via astunparse, pip-tools -xxhash==3.0.0 # via gt4py (pyproject.toml) - -# The following packages are considered to be unsafe in a requirements file: -pip==24.3.1 # via pip-tools, pipdeptree -setuptools==75.8.0 # via gt4py (pyproject.toml), pip-tools, setuptools-scm diff --git a/dev-tasks.py b/dev-tasks.py new file mode 100755 index 0000000000..437d107807 --- /dev/null +++ b/dev-tasks.py @@ -0,0 +1,97 @@ +#! /usr/bin/env -S uv run -q +# +# GT4Py - GridTools Framework +# +# Copyright (c) 2014-2024, ETH Zurich +# All rights reserved. +# +# Please, refer to the LICENSE file in the root directory. +# SPDX-License-Identifier: BSD-3-Clause +# +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "typer>=0.12.3", +# ] +# [tool.uv] +# exclude-newer = "2025-01-31T00:00:00Z" +# /// + + +"""Script for running recurrent development tasks.""" + +from __future__ import annotations + +import pathlib +import subprocess +from typing import Final + +import typer + +ROOT_DIR: Final = pathlib.Path(__file__).parent + + +# -- Helpers -- +def gather_versions() -> dict[str, str]: + with subprocess.Popen( + [*"uv export --frozen --no-hashes --project".split(), ROOT_DIR], stdout=subprocess.PIPE + ) as proc: + return dict( + line.split("==") + for line in proc.stdout.read().decode().splitlines() + if not any(line.startswith(c) for c in ["-", "#"]) + ) + + +# -- CLI -- +app = typer.Typer(no_args_is_help=True) + + +@app.command() +def sync_precommit() -> None: + """Sync versions of tools used in pre-commit hooks with the project versions.""" + versions = gather_versions() + # Update ruff version in pre-commit config + subprocess.run( + f"""uvx -q --from 'yamlpath' yaml-set --mustexist --change='repos[.repo%https://github.com/astral-sh/ruff-pre-commit].rev' --value='v{versions["ruff"]}' .pre-commit-config.yaml""", + cwd=ROOT_DIR, + shell=True, + check=True, + ) + + # Update tach version in pre-commit config + subprocess.run( + f"""uvx -q --from 'yamlpath' yaml-set --mustexist --change='repos[.repo%https://github.com/gauge-sh/tach-pre-commit].rev' --value='v{versions["tach"]}' .pre-commit-config.yaml""", + cwd=ROOT_DIR, + shell=True, + check=True, + ) + + # Format yaml files + subprocess.run( + f"uv run --project {ROOT_DIR} pre-commit run pretty-format-yaml --all-files", shell=True + ) + + +@app.command() +def update_precommit() -> None: + """Update and sync pre-commit hooks with the latest compatible versions.""" + subprocess.run(f"uv run --project {ROOT_DIR} pre-commit autoupdate", shell=True) + sync_precommit() + + +@app.command() +def update_versions() -> None: + """Update all project dependencies to their latest compatible versions.""" + subprocess.run("uv lock --upgrade", cwd=ROOT_DIR, shell=True, check=True) + + +@app.command() +def update_all() -> None: + """Update all project dependencies and pre-commit hooks.""" + update_versions() + update_precommit() + + +if __name__ == "__main__": + app() diff --git a/docs/development/tools/ci-infrastructure.md b/docs/development/tools/ci-infrastructure.md index 242bea50bd..e76cb7d608 100644 --- a/docs/development/tools/ci-infrastructure.md +++ b/docs/development/tools/ci-infrastructure.md @@ -1,6 +1,6 @@ # CI infrastructure -Any test job that runs on CI is encoded in automation tools like **tox** and **pre-commit** and can be run locally instead. +Any test job that runs on CI is encoded in automation tools like **nox** and **pre-commit** and can be run locally instead. ## GitHub Workflows diff --git a/docs/development/tools/requirements.md b/docs/development/tools/requirements.md deleted file mode 100644 index 010f317493..0000000000 --- a/docs/development/tools/requirements.md +++ /dev/null @@ -1,27 +0,0 @@ -# Requirements - -The specification of required third-party packages is scattered and partially duplicated across several configuration files used by several tools. Keeping all package requirements in sync manually is challenging and error-prone. Therefore, in this project we use [pip-tools](https://pip-tools.readthedocs.io/en/latest/) and the [cog](https://nedbatchelder.com/code/cog/) file generation tool to avoid inconsistencies. - -The following files in this repository contain information about required third-party packages: - -- `pyproject.toml`: GT4Py [package configuration](https://peps.python.org/pep-0621/) used by the build backend (`setuptools`). Install dependencies are specified in the _project.dependencies_ and _project.optional-dependencies_ tables. -- `requirements-dev.in`: [requirements file](https://pip.pypa.io/en/stable/reference/requirements-file-format/) used by **pip**. It contains a list of packages required only for the development of GT4Py. -- `requirements-dev.txt`: requirements file used by **pip**. It contains a completely frozen list of all packages required for installing and developing GT4Py. It is used by **pip** and **tox** to initialize the standard development and testing environments. It is automatically generated automatically from `requirements-dev.in` by **pip-compile**, when running the **tox** environment to update requirements. -- `constraints.txt`: [constraints file](https://pip.pypa.io/en/stable/user_guide/#constraints-files) used by **pip** and **tox** to initialize a subset of the standard development environment making sure that if other packages are installed, transitive dependencies are taken from the frozen package list. It is generated automatically from `requirements-dev.in` using **pip-compile**. -- `min-requirements-test.txt`: requirements file used by **pip**. It contains the minimum list of requirements to run GT4Py tests with the oldest compatible versions of all dependencies. It is generated automatically from `pyproject.toml` using **cog**. -- `min-extra-requirements-test.txt`: requirements file used by **pip**. It contains the minimum list of requirements to run GT4Py tests with the oldest compatible versions of all dependencies, additionally including all GT4Py extras. It is generated automatically from `pyproject.toml` using **cog**. -- `.pre-commit-config.yaml`: **pre-commit** configuration with settings for many linting and formatting tools. Part of its content is generated automatically from `pyproject.toml` using **cog**. - -The expected workflow to update GT4Py requirements is as follows: - -1. For changes in the GT4Py package dependencies, update the relevant table in `pyproject.toml`. When adding new tables to the _project.optional-dependencies_ section, make sure to add the new table as a dependency of the `all-` extra tables when possible. - -2. For changes in the development tools, update the `requirements-dev.in` file. Note that required project packages already appearing in `pyproject.toml` should not be duplicated here. - -3. Run the **tox** _requirements-base_ environment to update all files automatically with **pip-compile** and **cog**. Note that **pip-compile** will most likely update the versions of some unrelated tools if new versions are available in PyPI. - - ```bash - tox r -e requirements-base - ``` - -4. Check that the **mypy** mirror used by **pre-commit** (https://github.com/pre-commit/mirrors-mypy) in `.pre-commit-config.yaml` supports the same version as in `constraints.txt`, and manually update the `rev` version number. diff --git a/min-extra-requirements-test.txt b/min-extra-requirements-test.txt deleted file mode 100644 index a4924cc09c..0000000000 --- a/min-extra-requirements-test.txt +++ /dev/null @@ -1,110 +0,0 @@ -# -# Generated automatically by cog from pyproject.toml and requirements-dev.in -# Run: -# tox r -e requirements-common -# - -##[[[cog -## import copy, sys -## from packaging import requirements as reqs, specifiers as specs -## if sys.version_info >= (3, 11): -## import tomllib -## else: -## import tomli as tomllib -## -## def make_min_req(r: reqs.Requirement) -> reqs.Requirement: -## for s in r.specifier: -## if (ss := str(s)).startswith(">"): -## assert ss.startswith(">="), f"'{r!s}' requires a '>=' constraint" -## min_spec = specs.SpecifierSet(f"=={ss[2:]}") -## break -## min_r = copy.deepcopy(r) -## min_r.specifier = min_spec -## return min_r -## -## project = tomllib.loads(open("pyproject.toml").read()) -## all_cpu_extra = project["project"]["optional-dependencies"]["all-cpu"] -## assert len(all_cpu_extra) == 1 and all_cpu_extra[0].startswith("gt4py[") -## opt_req_versions = { -## reqs.Requirement(r).name: reqs.Requirement(r) -## for e in reqs.Requirement(all_cpu_extra[0]).extras -## for r in project["project"]["optional-dependencies"][e] -## } -## requirements = [ -## reqs.Requirement(rr) -## for r in (project["project"]["dependencies"] + open("requirements-dev.in").readlines()) -## if (rr := (r[: r.find("#")] if "#" in r else r)) -## ] -## processed = set() -## result = [] -## for r in requirements: -## assert r.name not in processed -## processed.add(r.name) -## if not r.specifier: -## assert r.name in opt_req_versions, f"Missing contraints for '{r.name}'" -## r = opt_req_versions[r.name] -## result.append(str(make_min_req(r))) -## for r_name, r in opt_req_versions.items(): -## if r_name not in processed: -## result.append(str(make_min_req(r))) -## print("\n".join(sorted(result))) -##]]] -attrs==21.3 -black==22.3 -boltons==20.1 -bump-my-version==0.12.0 -cached-property==1.5.1 -clang-format==9.0 -click==8.0.0 -cmake==3.22 -cogapp==3.3 -coverage[toml]==5.0 -cytoolz==0.12.1 -dace==1.0.0 -darglint==1.6 -deepdiff==5.6.0 -devtools==0.6 -diskcache==5.6.3 -factory-boy==3.3.0 -filelock==3.16.1 -frozendict==2.3 -gridtools-cpp==2.3.8 -hypothesis==6.0.0 -jax[cpu]==0.4.18 -jinja2==3.0.0 -jupytext==1.14 -lark==1.1.2 -mako==1.1 -matplotlib==3.3 -mypy==1.0 -nanobind==1.4.0 -nbmake==1.4.6 -ninja==1.10 -numpy==1.23.3 -packaging==20.0 -pip-tools==6.10 -pipdeptree==2.3 -pre-commit==2.17 -psutil==5.0 -pybind11==2.10.1 -pygments==2.7.3 -pytest-cache==1.0 -pytest-cov==2.8 -pytest-custom-exit-code==0.3.0 -pytest-factoryboy==2.0.3 -pytest-instafail==0.5.0 -pytest-xdist[psutil]==2.4 -pytest==7.0 -ruff==0.2.0 -scipy==1.9.2 -setuptools==65.5.0 -sphinx==4.4 -sphinx_rtd_theme==1.0 -tabulate==0.8.10 -tach==0.10.7 -tomli==2.0.1; python_version < "3.11" -tox==3.2.0 -types-tabulate==0.8.10 -typing-extensions==4.10.0 -xxhash==1.4.4 -##[[[end]]] diff --git a/min-requirements-test.txt b/min-requirements-test.txt deleted file mode 100644 index 4b24385410..0000000000 --- a/min-requirements-test.txt +++ /dev/null @@ -1,104 +0,0 @@ -# -# Generated automatically by cog from pyproject.toml and requirements-dev.in -# Run: -# tox r -e requirements-common -# - -##[[[cog -## import copy, sys -## from packaging import requirements as reqs, specifiers as specs -## if sys.version_info >= (3, 11): -## import tomllib -## else: -## import tomli as tomllib -## -## def make_min_req(r: reqs.Requirement) -> reqs.Requirement: -## for s in r.specifier: -## if (ss := str(s)).startswith(">"): -## assert ss.startswith(">="), f"'{r!s}' requires a '>=' constraint" -## min_spec = specs.SpecifierSet(f"=={ss[2:]}") -## break -## min_r = copy.deepcopy(r) -## min_r.specifier = min_spec -## return min_r -## -## project = tomllib.loads(open("pyproject.toml").read()) -## all_cpu_extra = project["project"]["optional-dependencies"]["all-cpu"] -## assert len(all_cpu_extra) == 1 and all_cpu_extra[0].startswith("gt4py[") -## opt_req_versions = { -## reqs.Requirement(r).name: reqs.Requirement(r) -## for e in reqs.Requirement(all_cpu_extra[0]).extras -## for r in project["project"]["optional-dependencies"][e] -## } -## requirements = [ -## reqs.Requirement(rr) -## for r in (project["project"]["dependencies"] + open("requirements-dev.in").readlines()) -## if (rr := (r[: r.find("#")] if "#" in r else r)) -## ] -## processed = set() -## result = [] -## for r in requirements: -## assert r.name not in processed -## processed.add(r.name) -## if not r.specifier: -## assert r.name in opt_req_versions, f"Missing contraints for '{r.name}'" -## r = opt_req_versions[r.name] -## result.append(str(make_min_req(r))) -## print("\n".join(sorted(result))) -##]]] -attrs==21.3 -black==22.3 -boltons==20.1 -bump-my-version==0.12.0 -cached-property==1.5.1 -clang-format==9.0 -click==8.0.0 -cmake==3.22 -cogapp==3.3 -coverage[toml]==5.0 -cytoolz==0.12.1 -darglint==1.6 -deepdiff==5.6.0 -devtools==0.6 -diskcache==5.6.3 -factory-boy==3.3.0 -filelock==3.16.1 -frozendict==2.3 -gridtools-cpp==2.3.8 -hypothesis==6.0.0 -jinja2==3.0.0 -jupytext==1.14 -lark==1.1.2 -mako==1.1 -matplotlib==3.3 -mypy==1.0 -nanobind==1.4.0 -nbmake==1.4.6 -ninja==1.10 -numpy==1.23.3 -packaging==20.0 -pip-tools==6.10 -pipdeptree==2.3 -pre-commit==2.17 -psutil==5.0 -pybind11==2.10.1 -pygments==2.7.3 -pytest-cache==1.0 -pytest-cov==2.8 -pytest-custom-exit-code==0.3.0 -pytest-factoryboy==2.0.3 -pytest-instafail==0.5.0 -pytest-xdist[psutil]==2.4 -pytest==7.0 -ruff==0.2.0 -setuptools==65.5.0 -sphinx==4.4 -sphinx_rtd_theme==1.0 -tabulate==0.8.10 -tach==0.10.7 -tomli==2.0.1; python_version < "3.11" -tox==3.2.0 -types-tabulate==0.8.10 -typing-extensions==4.10.0 -xxhash==1.4.4 -##[[[end]]] diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000000..0b150c0db7 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,251 @@ +# GT4Py - GridTools Framework +# +# Copyright (c) 2014-2024, ETH Zurich +# All rights reserved. +# +# Please, refer to the LICENSE file in the root directory. +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +import os +import pathlib +import types +from collections.abc import Sequence +from typing import Final, Literal, TypeAlias + +import nox + +#: This should just be `pytest.ExitCode.NO_TESTS_COLLECTED` but `pytest` +#: is not guaranteed to be available in the venv where `nox` is running. +NO_TESTS_COLLECTED_EXIT_CODE: Final = 5 + +# -- nox configuration -- +nox.options.default_venv_backend = "uv" +nox.options.sessions = [ + "test_cartesian-3.10(internal, cpu)", + "test_cartesian-3.10(dace, cpu)", + "test_cartesian-3.11(internal, cpu)", + "test_cartesian-3.11(dace, cpu)", + "test_eve-3.10", + "test_eve-3.11", + "test_next-3.10(internal, cpu, nomesh)", + "test_next-3.10(dace, cpu, nomesh)", + "test_next-3.11(internal, cpu, nomesh)", + "test_next-3.11(dace, cpu, nomesh)", + "test_storage-3.10(cpu)", + "test_storage-3.11(cpu)", +] + +# -- Parameter sets -- +DeviceOption: TypeAlias = Literal["cpu", "cuda11", "cuda12", "rocm4_3", "rocm5_0"] +DeviceNoxParam: Final = types.SimpleNamespace( + **{device: nox.param(device, id=device, tags=[device]) for device in DeviceOption.__args__} +) +DeviceTestSettings: Final[dict[str, dict[str, Sequence]]] = { + "cpu": {"extras": [], "markers": ["not requires_gpu"]}, + **{ + device: {"extras": [device], "markers": ["requires_gpu"]} + for device in ["cuda11", "cuda12", "rocm4_3", "rocm5_0"] + }, +} + +CodeGenOption: TypeAlias = Literal["internal", "dace"] +CodeGenNoxParam: Final = types.SimpleNamespace( + **{ + codegen: nox.param(codegen, id=codegen, tags=[codegen]) + for codegen in CodeGenOption.__args__ + } +) +CodeGenTestSettings: Final[dict[str, dict[str, Sequence]]] = { + "internal": {"extras": [], "markers": ["not requires_dace"]}, + "dace": {"extras": ["dace"], "markers": ["requires_dace"]}, +} + + +# -- nox sessions -- +@nox.session(python=["3.10", "3.11"], tags=["cartesian"]) +@nox.parametrize("device", [DeviceNoxParam.cpu, DeviceNoxParam.cuda12]) +@nox.parametrize("codegen", [CodeGenNoxParam.internal, CodeGenNoxParam.dace]) +def test_cartesian( + session: nox.Session, + codegen: CodeGenOption, + device: DeviceOption, +) -> None: + """Run selected 'gt4py.cartesian' tests.""" + + codegen_settings = CodeGenTestSettings[codegen] + device_settings = DeviceTestSettings[device] + + _install_session_venv( + session, + extras=["performance", "testing", *codegen_settings["extras"], *device_settings["extras"]], + groups=["test"], + ) + + num_processes = session.env.get("NUM_PROCESSES", "auto") + markers = " and ".join(codegen_settings["markers"] + device_settings["markers"]) + + session.run( + *f"pytest --cache-clear -sv -n {num_processes}".split(), + *("-m", f"{markers}"), + str(pathlib.Path("tests") / "cartesian_tests"), + *session.posargs, + ) + session.run( + *"pytest --doctest-modules --doctest-ignore-import-errors -sv".split(), + str(pathlib.Path("src") / "gt4py" / "cartesian"), + ) + + +@nox.session(python=["3.10", "3.11"]) +def test_examples(session: nox.Session) -> None: + """Run and test documentation workflows.""" + + _install_session_venv(session, extras=["testing"], groups=["docs", "test"]) + + session.run(*"jupytext docs/user/next/QuickstartGuide.md --to .ipynb".split()) + session.run(*"jupytext docs/user/next/advanced/*.md --to .ipynb".split()) + + num_processes = session.env.get("NUM_PROCESSES", "auto") + for notebook, extra_args in [ + ("docs/user/next/workshop/slides", None), + ("docs/user/next/workshop/exercises", ["-k", "solutions"]), + ("docs/user/next/QuickstartGuide.ipynb", None), + ("docs/user/next/advanced", None), + ("examples", (None)), + ]: + session.run( + *f"pytest --nbmake {notebook} -sv -n {num_processes}".split(), + *(extra_args or []), + ) + + +@nox.session(python=["3.10", "3.11"], tags=["cartesian", "next", "cpu"]) +def test_eve(session: nox.Session) -> None: + """Run 'gt4py.eve' tests.""" + + _install_session_venv(session, groups=["test"]) + + num_processes = session.env.get("NUM_PROCESSES", "auto") + + session.run( + *f"pytest --cache-clear -sv -n {num_processes}".split(), + str(pathlib.Path("tests") / "eve_tests"), + *session.posargs, + ) + session.run( + *"pytest --doctest-modules -sv".split(), + str(pathlib.Path("src") / "gt4py" / "eve"), + ) + + +@nox.session(python=["3.10", "3.11"], tags=["next"]) +@nox.parametrize( + "meshlib", + [ + nox.param("nomesh", id="nomesh", tags=["nomesh"]), + nox.param("atlas", id="atlas", tags=["atlas"]), + ], +) +@nox.parametrize("device", [DeviceNoxParam.cpu, DeviceNoxParam.cuda12]) +@nox.parametrize("codegen", [CodeGenNoxParam.internal, CodeGenNoxParam.dace]) +def test_next( + session: nox.Session, + codegen: CodeGenOption, + device: DeviceOption, + meshlib: Literal["nomesh", "atlas"], +) -> None: + """Run selected 'gt4py.next' tests.""" + + codegen_settings = CodeGenTestSettings[codegen] + device_settings = DeviceTestSettings[device] + groups: list[str] = ["test"] + mesh_markers: list[str] = [] + + match meshlib: + case "nomesh": + mesh_markers.append("not requires_atlas") + case "atlas": + mesh_markers.append("requires_atlas") + groups.append("frameworks") + + _install_session_venv( + session, + extras=["performance", "testing", *codegen_settings["extras"], *device_settings["extras"]], + groups=groups, + ) + + num_processes = session.env.get("NUM_PROCESSES", "auto") + markers = " and ".join(codegen_settings["markers"] + device_settings["markers"] + mesh_markers) + + session.run( + *f"pytest --cache-clear -sv -n {num_processes}".split(), + *("-m", f"{markers}"), + str(pathlib.Path("tests") / "next_tests"), + *session.posargs, + success_codes=[0, NO_TESTS_COLLECTED_EXIT_CODE], + ) + session.run( + *"pytest --doctest-modules --doctest-ignore-import-errors -sv".split(), + str(pathlib.Path("src") / "gt4py" / "next"), + success_codes=[0, NO_TESTS_COLLECTED_EXIT_CODE], + ) + + +@nox.session(python=["3.10", "3.11"], tags=["cartesian", "next"]) +@nox.parametrize("device", [DeviceNoxParam.cpu, DeviceNoxParam.cuda12]) +def test_storage( + session: nox.Session, + device: DeviceOption, +) -> None: + """Run selected 'gt4py.storage' tests.""" + + device_settings = DeviceTestSettings[device] + + _install_session_venv( + session, extras=["performance", "testing", *device_settings["extras"]], groups=["test"] + ) + + num_processes = session.env.get("NUM_PROCESSES", "auto") + markers = " and ".join(device_settings["markers"]) + + session.run( + *f"pytest --cache-clear -sv -n {num_processes}".split(), + *("-m", f"{markers}"), + str(pathlib.Path("tests") / "storage_tests"), + *session.posargs, + ) + session.run( + *"pytest --doctest-modules -sv".split(), + str(pathlib.Path("src") / "gt4py" / "storage"), + success_codes=[0, NO_TESTS_COLLECTED_EXIT_CODE], + ) + + +# -- utils -- +def _install_session_venv( + session: nox.Session, + *args: str | Sequence[str], + extras: Sequence[str] = (), + groups: Sequence[str] = (), +) -> None: + """Install session packages using uv.""" + session.run_install( + "uv", + "sync", + *("--python", session.python), + "--no-dev", + *(f"--extra={e}" for e in extras), + *(f"--group={g}" for g in groups), + env={key: value for key, value in os.environ.items()} + | {"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, + ) + for item in args: + session.run_install( + "uv", + "pip", + "install", + *((item,) if isinstance(item, str) else item), + env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, + ) diff --git a/pyproject.toml b/pyproject.toml index 979dfbbd02..91c2ba0323 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,68 @@ +# -- Build system requirements (PEP 518) -- + [build-system] build-backend = 'setuptools.build_meta' -requires = ['setuptools>=65.5.0', 'wheel>=0.33.6', 'cython>=0.29.13'] +requires = ['setuptools>=70.0.0', 'wheel>=0.33.6', 'cython>=3.0.0'] + +# -- Dependency groups -- +[dependency-groups] +build = [ + 'bump-my-version>=0.16.0', + 'cython>=3.0.0', + 'pip>=22.1.1', + 'setuptools>=70.0.0', + 'wheel>=0.33.6' +] +dev = [ + {include-group = 'build'}, + {include-group = 'docs'}, + {include-group = 'frameworks'}, + {include-group = 'lint'}, + {include-group = 'test'}, + {include-group = 'typing'} +] +docs = [ + 'esbonio>=0.16.0', + 'jupytext>=1.14', + 'matplotlib>=3.3', + 'myst-parser>=4.0.0', + 'pygments>=2.7.3', + 'sphinx>=7.3.7', + 'sphinx-rtd-theme>=3.0.1', + 'sphinx-toolbox>=3.8.1' +] +frameworks = [ + # 3rd party frameworks with some interoperability with gt4py + 'atlas4py>=0.35' +] +lint = [ + 'pre-commit>=4.0.1', + 'ruff>=0.8.0', + 'tach>=0.16.0' +] +test = [ + 'coverage[toml]>=7.5.0', + 'hypothesis>=6.0.0', + 'nbmake>=1.4.6', + 'nox>=2024.10.9', + 'pytest>=8.0.1', + 'pytest-benchmark>=5.0.0', + 'pytest-cache>=1.0', + 'pytest-cov>=5.0.0', + 'pytest-factoryboy>=2.6.1', + 'pytest-instafail>=0.5.0', + 'pytest-xdist[psutil]>=3.5.0' +] +typing = [ + 'mypy[faster-cache]>=1.13.0', + 'types-tabulate>=0.8.10', + 'types-PyYAML>=6.0.10', + 'types-decorator>=5.1.8', + 'types-docutils>=0.21.0', + 'types-pytz>=2024.2.0' +] -# ---- Project description ---- -# -- Standard options (PEP 621) -- +# -- Standard project description options (PEP 621) -- [project] authors = [{name = 'ETH Zurich', email = 'gridtools@cscs.ch'}] classifiers = [ @@ -44,9 +103,10 @@ dependencies = [ 'numpy>=1.23.3', 'packaging>=20.0', 'pybind11>=2.10.1', - 'setuptools>=65.5.0', + 'setuptools>=70.0.0', 'tabulate>=0.8.10', - 'typing-extensions>=4.10.0', + 'toolz>=0.12.1', + 'typing-extensions>=4.11.0', 'xxhash>=1.4.4,<3.1.0' ] description = 'Python library for generating high-performance implementations of stencil kernels for weather and climate modeling from a domain-specific language (DSL)' @@ -60,27 +120,25 @@ keywords = [ 'portable', 'hpc' ] -license = {file = 'LICENSE.txt'} +license = {text = 'BSD-3 License'} # TODO: waiting for PEP 639 being implemented by setuptools (https://github.com/codecov/codecov-cli/issues/605) name = 'gt4py' readme = 'README.md' -requires-python = '>=3.10' +requires-python = '>=3.10, <3.12' [project.optional-dependencies] -# Bundles -all-cpu = ['gt4py[dace,formatting,jax-cpu,performance,testing]'] -all-cuda11 = ['gt4py[cuda11,dace,formatting,jax-cuda11,performance,testing]'] -all-cuda12 = ['gt4py[cuda12,dace,formatting,jax-cuda12,performance,testing]'] -# Other extras +# bundles +all = ['gt4py[dace,formatting,jax,performance,testing]'] +# device-specific extras cuda11 = ['cupy-cuda11x>=12.0'] cuda12 = ['cupy-cuda12x>=12.0'] +# features dace = ['dace>=1.0.0,<1.1.0'] # v1.x will contain breaking changes, see https://github.com/spcl/dace/milestone/4 formatting = ['clang-format>=9.0'] -gpu = ['cupy>=12.0'] -jax-cpu = ['jax[cpu]>=0.4.18'] -jax-cuda11 = ['jax[cuda11_pip]>=0.4.18'] -jax-cuda12 = ['jax[cuda12_pip]>=0.4.18'] +jax = ['jax>=0.4.26'] +jax-cuda12 = ['jax[cuda12_local]>=0.4.26', 'gt4py[cuda12]'] performance = ['scipy>=1.9.2'] -rocm-43 = ['cupy-rocm-4-3'] +rocm4_3 = ['cupy-rocm-4-3>=13.3.0'] +rocm5_0 = ['cupy-rocm-5-0>=13.3.0'] testing = ['hypothesis>=6.0.0', 'pytest>=7.0'] [project.scripts] @@ -89,7 +147,7 @@ gtpyc = 'gt4py.cartesian.cli:gtpyc' [project.urls] Documentation = 'https://gridtools.github.io/gt4py' Homepage = 'https://gridtools.github.io/' -Source = 'https://github.com/GridTools/gt4py' +Repository = 'https://github.com/GridTools/gt4py' # ---- Other tools ---- # -- bump-my-version -- @@ -97,7 +155,7 @@ Source = 'https://github.com/GridTools/gt4py' allow_dirty = false commit = false commit_args = '' -current_version = "1.0.4" +current_version = '1.0.4' ignore_missing_version = false message = 'Bump version: {current_version} → {new_version}' parse = '(?P\d+)\.(?P\d+)(\.(?P\d+))?' @@ -111,7 +169,7 @@ tag_message = 'Bump version: {current_version} → {new_version}' tag_name = 'v{new_version}' [[tool.bumpversion.files]] -filename = "src/gt4py/__about__.py" +filename = 'src/gt4py/__about__.py' # -- coverage -- [tool.coverage] @@ -120,7 +178,7 @@ filename = "src/gt4py/__about__.py" directory = 'tests/_reports/coverage_html' [tool.coverage.paths] -source = ['src/', '.tox/py*/lib/python3.*/site-packages/'] +source = ['src/', '.nox/py*/lib/python3.*/site-packages/'] [tool.coverage.report] # Regexes for lines to exclude from consideration @@ -303,6 +361,9 @@ select = ['E', 'F', 'I', 'B', 'A', 'T10', 'ERA', 'NPY', 'RUF'] typing-modules = ['gt4py.eve.extended_typing'] unfixable = [] +[tool.ruff.lint.flake8-builtins] +builtins-allowed-modules = ['builtins'] + [tool.ruff.lint.isort] combine-as-imports = true # force-wrap-aliases = true @@ -368,3 +429,22 @@ version = {attr = 'gt4py.__about__.__version__'} [tool.setuptools.packages] find = {namespaces = false, where = ['src']} + +# -- uv: packages & workspace -- +[tool.uv] +conflicts = [ + [ + {extra = 'cuda11'}, + {extra = 'jax-cuda12'}, + {extra = 'rocm4_3'}, + {extra = 'rocm5_0'} + ] +] + +[[tool.uv.index]] +explicit = true +name = 'test.pypi' +url = 'https://test.pypi.org/simple/' + +[tool.uv.sources] +atlas4py = {index = "test.pypi"} diff --git a/requirements-dev.in b/requirements-dev.in deleted file mode 100644 index 1697051d25..0000000000 --- a/requirements-dev.in +++ /dev/null @@ -1,36 +0,0 @@ -# -# Constraints should specify the minimum required version (>=). -# -# Packages also required in the extra `gt4py['all-cpu']` configuration -# should be added here without constraints, so they will use the -# constraints defined in `pyproject.toml`. -# -bump-my-version>=0.12.0 -clang-format>=9.0 -cogapp>=3.3 -coverage[toml]>=5.0 -darglint>=1.6 -hypothesis # constraints in gt4py['testing'] -jupytext>=1.14 -mypy>=1.0 -matplotlib>=3.3 -nbmake>=1.4.6 -pipdeptree>=2.3 -pip-tools>=6.10 -pre-commit>=2.17 -psutil>=5.0 -pygments>=2.7.3 -pytest # constraints in gt4py['testing'] -pytest-cache>=1.0 -pytest-cov>=2.8 -pytest-custom-exit-code>=0.3.0 -pytest-factoryboy>=2.0.3 -pytest-xdist[psutil]>=2.4 -pytest-instafail>=0.5.0 -ruff>=0.2.0 -sphinx>=4.4 -sphinx_rtd_theme>=1.0 -tach>=0.10.7 -tomli>=2.0.1;python_version<'3.11' -tox>=3.2.0 -types-tabulate>=0.8.10 diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 463b1bc6ac..0000000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,178 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# "tox run -e requirements-base" -# -aenum==3.1.15 # via -c constraints.txt, dace -alabaster==1.0.0 # via -c constraints.txt, sphinx -annotated-types==0.7.0 # via -c constraints.txt, pydantic -asttokens==2.4.1 # via -c constraints.txt, devtools, stack-data -astunparse==1.6.3 # via -c constraints.txt, dace -attrs==24.3.0 # via -c constraints.txt, gt4py (pyproject.toml), hypothesis, jsonschema, referencing -babel==2.16.0 # via -c constraints.txt, sphinx -black==24.10.0 # via -c constraints.txt, gt4py (pyproject.toml) -boltons==24.1.0 # via -c constraints.txt, gt4py (pyproject.toml) -bracex==2.5.post1 # via -c constraints.txt, wcmatch -build==1.2.2.post1 # via -c constraints.txt, pip-tools -bump-my-version==0.29.0 # via -c constraints.txt, -r requirements-dev.in -cached-property==2.0.1 # via -c constraints.txt, gt4py (pyproject.toml) -cachetools==5.5.0 # via -c constraints.txt, tox -certifi==2024.12.14 # via -c constraints.txt, requests -cfgv==3.4.0 # via -c constraints.txt, pre-commit -chardet==5.2.0 # via -c constraints.txt, tox -charset-normalizer==3.4.1 # via -c constraints.txt, requests -clang-format==19.1.6 # via -c constraints.txt, -r requirements-dev.in, gt4py (pyproject.toml) -click==8.1.8 # via -c constraints.txt, black, bump-my-version, gt4py (pyproject.toml), pip-tools, rich-click -cmake==3.31.2 # via -c constraints.txt, gt4py (pyproject.toml) -cogapp==3.4.1 # via -c constraints.txt, -r requirements-dev.in -colorama==0.4.6 # via -c constraints.txt, tox -comm==0.2.2 # via -c constraints.txt, ipykernel -contourpy==1.3.1 # via -c constraints.txt, matplotlib -coverage[toml]==7.6.10 # via -c constraints.txt, -r requirements-dev.in, pytest-cov -cycler==0.12.1 # via -c constraints.txt, matplotlib -cytoolz==1.0.1 # via -c constraints.txt, gt4py (pyproject.toml) -dace==1.0.0 # via -c constraints.txt, gt4py (pyproject.toml) -darglint==1.8.1 # via -c constraints.txt, -r requirements-dev.in -debugpy==1.8.11 # via -c constraints.txt, ipykernel -decorator==5.1.1 # via -c constraints.txt, ipython -deepdiff==8.1.1 # via -c constraints.txt, gt4py (pyproject.toml) -devtools==0.12.2 # via -c constraints.txt, gt4py (pyproject.toml) -dill==0.3.9 # via -c constraints.txt, dace -diskcache==5.6.3 # via -c constraints.txt, gt4py (pyproject.toml) -distlib==0.3.9 # via -c constraints.txt, virtualenv -docutils==0.21.2 # via -c constraints.txt, sphinx, sphinx-rtd-theme -exceptiongroup==1.2.2 # via -c constraints.txt, hypothesis, ipython, pytest -execnet==2.1.1 # via -c constraints.txt, pytest-cache, pytest-xdist -executing==2.1.0 # via -c constraints.txt, devtools, stack-data -factory-boy==3.3.1 # via -c constraints.txt, gt4py (pyproject.toml), pytest-factoryboy -faker==33.3.0 # via -c constraints.txt, factory-boy -fastjsonschema==2.21.1 # via -c constraints.txt, nbformat -filelock==3.16.1 # via -c constraints.txt, gt4py (pyproject.toml), tox, virtualenv -fonttools==4.55.3 # via -c constraints.txt, matplotlib -fparser==0.2.0 # via -c constraints.txt, dace -frozendict==2.4.6 # via -c constraints.txt, gt4py (pyproject.toml) -gitdb==4.0.12 # via -c constraints.txt, gitpython -gitpython==3.1.44 # via -c constraints.txt, tach -gridtools-cpp==2.3.8 # via -c constraints.txt, gt4py (pyproject.toml) -hypothesis==6.123.11 # via -c constraints.txt, -r requirements-dev.in, gt4py (pyproject.toml) -identify==2.6.5 # via -c constraints.txt, pre-commit -idna==3.10 # via -c constraints.txt, requests -imagesize==1.4.1 # via -c constraints.txt, sphinx -inflection==0.5.1 # via -c constraints.txt, pytest-factoryboy -iniconfig==2.0.0 # via -c constraints.txt, pytest -ipykernel==6.29.5 # via -c constraints.txt, nbmake -ipython==8.31.0 # via -c constraints.txt, ipykernel -jax[cpu]==0.4.38 # via -c constraints.txt, gt4py (pyproject.toml) -jaxlib==0.4.38 # via -c constraints.txt, jax -jedi==0.19.2 # via -c constraints.txt, ipython -jinja2==3.1.5 # via -c constraints.txt, gt4py (pyproject.toml), sphinx -jsonschema==4.23.0 # via -c constraints.txt, nbformat -jsonschema-specifications==2024.10.1 # via -c constraints.txt, jsonschema -jupyter-client==8.6.3 # via -c constraints.txt, ipykernel, nbclient -jupyter-core==5.7.2 # via -c constraints.txt, ipykernel, jupyter-client, nbclient, nbformat -jupytext==1.16.6 # via -c constraints.txt, -r requirements-dev.in -kiwisolver==1.4.8 # via -c constraints.txt, matplotlib -lark==1.2.2 # via -c constraints.txt, gt4py (pyproject.toml) -mako==1.3.8 # via -c constraints.txt, gt4py (pyproject.toml) -markdown-it-py==3.0.0 # via -c constraints.txt, jupytext, mdit-py-plugins, rich -markupsafe==3.0.2 # via -c constraints.txt, jinja2, mako -matplotlib==3.10.0 # via -c constraints.txt, -r requirements-dev.in -matplotlib-inline==0.1.7 # via -c constraints.txt, ipykernel, ipython -mdit-py-plugins==0.4.2 # via -c constraints.txt, jupytext -mdurl==0.1.2 # via -c constraints.txt, markdown-it-py -ml-dtypes==0.5.1 # via -c constraints.txt, jax, jaxlib -mpmath==1.3.0 # via -c constraints.txt, sympy -mypy==1.14.1 # via -c constraints.txt, -r requirements-dev.in -mypy-extensions==1.0.0 # via -c constraints.txt, black, mypy -nanobind==2.4.0 # via -c constraints.txt, gt4py (pyproject.toml) -nbclient==0.10.2 # via -c constraints.txt, nbmake -nbformat==5.10.4 # via -c constraints.txt, jupytext, nbclient, nbmake -nbmake==1.5.5 # via -c constraints.txt, -r requirements-dev.in -nest-asyncio==1.6.0 # via -c constraints.txt, ipykernel -networkx==3.4.2 # via -c constraints.txt, dace, tach -ninja==1.11.1.3 # via -c constraints.txt, gt4py (pyproject.toml) -nodeenv==1.9.1 # via -c constraints.txt, pre-commit -numpy==1.26.4 # via -c constraints.txt, contourpy, dace, gt4py (pyproject.toml), jax, jaxlib, matplotlib, ml-dtypes, scipy -opt-einsum==3.4.0 # via -c constraints.txt, jax -orderly-set==5.2.3 # via -c constraints.txt, deepdiff -packaging==24.2 # via -c constraints.txt, black, build, dace, gt4py (pyproject.toml), ipykernel, jupytext, matplotlib, pipdeptree, pyproject-api, pytest, pytest-factoryboy, setuptools-scm, sphinx, tox -parso==0.8.4 # via -c constraints.txt, jedi -pathspec==0.12.1 # via -c constraints.txt, black -pexpect==4.9.0 # via -c constraints.txt, ipython -pillow==11.1.0 # via -c constraints.txt, matplotlib -pip-tools==7.4.1 # via -c constraints.txt, -r requirements-dev.in -pipdeptree==2.24.0 # via -c constraints.txt, -r requirements-dev.in -platformdirs==4.3.6 # via -c constraints.txt, black, jupyter-core, tox, virtualenv -pluggy==1.5.0 # via -c constraints.txt, pytest, tox -ply==3.11 # via -c constraints.txt, dace -pre-commit==4.0.1 # via -c constraints.txt, -r requirements-dev.in -prompt-toolkit==3.0.48 # via -c constraints.txt, ipython, questionary, tach -psutil==6.1.1 # via -c constraints.txt, -r requirements-dev.in, ipykernel, pytest-xdist -ptyprocess==0.7.0 # via -c constraints.txt, pexpect -pure-eval==0.2.3 # via -c constraints.txt, stack-data -pybind11==2.13.6 # via -c constraints.txt, gt4py (pyproject.toml) -pydantic==2.10.4 # via -c constraints.txt, bump-my-version, pydantic-settings -pydantic-core==2.27.2 # via -c constraints.txt, pydantic -pydantic-settings==2.7.1 # via -c constraints.txt, bump-my-version -pydot==3.0.4 # via -c constraints.txt, tach -pygments==2.19.1 # via -c constraints.txt, -r requirements-dev.in, devtools, ipython, nbmake, rich, sphinx -pyparsing==3.2.1 # via -c constraints.txt, matplotlib, pydot -pyproject-api==1.8.0 # via -c constraints.txt, tox -pyproject-hooks==1.2.0 # via -c constraints.txt, build, pip-tools -pytest==8.3.4 # via -c constraints.txt, -r requirements-dev.in, gt4py (pyproject.toml), nbmake, pytest-cache, pytest-cov, pytest-custom-exit-code, pytest-factoryboy, pytest-instafail, pytest-xdist -pytest-cache==1.0 # via -c constraints.txt, -r requirements-dev.in -pytest-cov==6.0.0 # via -c constraints.txt, -r requirements-dev.in -pytest-custom-exit-code==0.3.0 # via -c constraints.txt, -r requirements-dev.in -pytest-factoryboy==2.7.0 # via -c constraints.txt, -r requirements-dev.in -pytest-instafail==0.5.0 # via -c constraints.txt, -r requirements-dev.in -pytest-xdist[psutil]==3.6.1 # via -c constraints.txt, -r requirements-dev.in -python-dateutil==2.9.0.post0 # via -c constraints.txt, faker, jupyter-client, matplotlib -python-dotenv==1.0.1 # via -c constraints.txt, pydantic-settings -pyyaml==6.0.2 # via -c constraints.txt, dace, jupytext, pre-commit, tach -pyzmq==26.2.0 # via -c constraints.txt, ipykernel, jupyter-client -questionary==2.1.0 # via -c constraints.txt, bump-my-version -referencing==0.35.1 # via -c constraints.txt, jsonschema, jsonschema-specifications -requests==2.32.3 # via -c constraints.txt, sphinx -rich==13.9.4 # via -c constraints.txt, bump-my-version, rich-click, tach -rich-click==1.8.5 # via -c constraints.txt, bump-my-version -rpds-py==0.22.3 # via -c constraints.txt, jsonschema, referencing -ruff==0.8.6 # via -c constraints.txt, -r requirements-dev.in -scipy==1.15.0 # via -c constraints.txt, jax, jaxlib -setuptools-scm==8.1.0 # via -c constraints.txt, fparser -six==1.17.0 # via -c constraints.txt, asttokens, astunparse, python-dateutil -smmap==5.0.2 # via -c constraints.txt, gitdb -snowballstemmer==2.2.0 # via -c constraints.txt, sphinx -sortedcontainers==2.4.0 # via -c constraints.txt, hypothesis -sphinx==8.1.3 # via -c constraints.txt, -r requirements-dev.in, sphinx-rtd-theme, sphinxcontrib-jquery -sphinx-rtd-theme==3.0.2 # via -c constraints.txt, -r requirements-dev.in -sphinxcontrib-applehelp==2.0.0 # via -c constraints.txt, sphinx -sphinxcontrib-devhelp==2.0.0 # via -c constraints.txt, sphinx -sphinxcontrib-htmlhelp==2.1.0 # via -c constraints.txt, sphinx -sphinxcontrib-jquery==4.1 # via -c constraints.txt, sphinx-rtd-theme -sphinxcontrib-jsmath==1.0.1 # via -c constraints.txt, sphinx -sphinxcontrib-qthelp==2.0.0 # via -c constraints.txt, sphinx -sphinxcontrib-serializinghtml==2.0.0 # via -c constraints.txt, sphinx -stack-data==0.6.3 # via -c constraints.txt, ipython -sympy==1.13.3 # via -c constraints.txt, dace -tabulate==0.9.0 # via -c constraints.txt, gt4py (pyproject.toml) -tach==0.19.5 # via -c constraints.txt, -r requirements-dev.in -tomli==2.2.1 ; python_version < "3.11" # via -c constraints.txt, -r requirements-dev.in, black, build, coverage, jupytext, mypy, pip-tools, pyproject-api, pytest, setuptools-scm, sphinx, tach, tox -tomli-w==1.1.0 # via -c constraints.txt, tach -tomlkit==0.13.2 # via -c constraints.txt, bump-my-version -toolz==1.0.0 # via -c constraints.txt, cytoolz -tornado==6.4.2 # via -c constraints.txt, ipykernel, jupyter-client -tox==4.23.2 # via -c constraints.txt, -r requirements-dev.in -traitlets==5.14.3 # via -c constraints.txt, comm, ipykernel, ipython, jupyter-client, jupyter-core, matplotlib-inline, nbclient, nbformat -types-tabulate==0.9.0.20241207 # via -c constraints.txt, -r requirements-dev.in -typing-extensions==4.12.2 # via -c constraints.txt, black, faker, gt4py (pyproject.toml), ipython, mypy, pydantic, pydantic-core, pytest-factoryboy, rich, rich-click, tox -urllib3==2.3.0 # via -c constraints.txt, requests -virtualenv==20.28.1 # via -c constraints.txt, pre-commit, tox -wcmatch==10.0 # via -c constraints.txt, bump-my-version -wcwidth==0.2.13 # via -c constraints.txt, prompt-toolkit -wheel==0.45.1 # via -c constraints.txt, astunparse, pip-tools -xxhash==3.0.0 # via -c constraints.txt, gt4py (pyproject.toml) - -# The following packages are considered to be unsafe in a requirements file: -pip==24.3.1 # via -c constraints.txt, pip-tools, pipdeptree -setuptools==75.8.0 # via -c constraints.txt, gt4py (pyproject.toml), pip-tools, setuptools-scm diff --git a/tach.toml b/tach.toml index 7861ed1fe6..d23b5fb14d 100644 --- a/tach.toml +++ b/tach.toml @@ -3,7 +3,9 @@ source_roots = [ "src", ] exact = true -forbid_circular_dependencies = true +# forbid_circular_dependencies = true +# TODO(egparedes): try to solve the circular dependencies between +# gt4py.cartesian and gt4py.storage [[modules]] path = "gt4py._core" diff --git a/tests/cartesian_tests/integration_tests/multi_feature_tests/test_dace_parsing.py b/tests/cartesian_tests/integration_tests/multi_feature_tests/test_dace_parsing.py index 9fafc27c85..16a1860d9d 100644 --- a/tests/cartesian_tests/integration_tests/multi_feature_tests/test_dace_parsing.py +++ b/tests/cartesian_tests/integration_tests/multi_feature_tests/test_dace_parsing.py @@ -29,7 +29,7 @@ ) -pytestmark = pytest.mark.usefixtures("dace_env") +pytestmark = [pytest.mark.requires_dace, pytest.mark.usefixtures("dace_env")] @pytest.fixture(scope="module") diff --git a/tests/conftest.py b/tests/conftest.py index 285ccda2b0..1bf73651a2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,5 +8,55 @@ """Global configuration of pytest for collecting and running tests.""" +import collections.abc +import functools +import sys +import types +from typing import Final + +import pytest + + # Ignore hidden folders and disabled tests collect_ignore_glob = [".*", "_disabled*"] + +# Custom module attribute to store package-level marks +_PKG_MARKS_ATTR_NAME: Final = "package_pytestmarks" + + +@functools.cache +def _get_pkg_marks(module_name: str) -> list[pytest.Mark | str]: + """Collect markers in the `package_pytestmarks` module attribute (and recursively from its parents).""" + module = sys.modules[module_name] + pkg_markers = getattr(module, _PKG_MARKS_ATTR_NAME, []) + assert isinstance( + pkg_markers, collections.abc.Sequence + ), f"'{_PKG_MARKS_ATTR_NAME}' content must be a sequence of marks" + + if (parent := module_name.rsplit(".", 1)[0]) != module_name: + pkg_markers += _get_pkg_marks(parent) + + return pkg_markers + + +def pytest_collection_modifyitems( + session: pytest.Session, config: pytest.Config, items: list[pytest.Item] +) -> None: + """Pytest hook to modify the collected test items. + + See: https://docs.pytest.org/en/stable/reference/reference.html#pytest.hookspec.pytest_collection_modifyitems + """ + for item in items: + # Visit the chain of parents of the current test item in reverse order, + # until we get to the module object where the test function (or class) + # has been defined. At that point, process the custom package-level marks + # attribute if present, and move to the next collected item in the list. + for node in item.listchain()[-2::-1]: + if not (obj := getattr(node, "obj", None)): + break + if not isinstance(obj, types.ModuleType): + continue + + module_name = obj.__name__ + for marker in _get_pkg_marks(module_name): + item.add_marker(marker) diff --git a/tests/next_tests/definitions.py b/tests/next_tests/definitions.py index 6ffbc667bb..522250cafc 100644 --- a/tests/next_tests/definitions.py +++ b/tests/next_tests/definitions.py @@ -11,6 +11,7 @@ import dataclasses import enum import importlib +from typing import Final import pytest @@ -53,11 +54,17 @@ class ProgramBackendId(_PythonObjectIdMixin, str, enum.Enum): @dataclasses.dataclass(frozen=True) class EmbeddedDummyBackend: + name: str allocator: next_allocators.FieldBufferAllocatorProtocol + executor: Final = None -numpy_execution = EmbeddedDummyBackend(next_allocators.StandardCPUFieldBufferAllocator()) -cupy_execution = EmbeddedDummyBackend(next_allocators.StandardGPUFieldBufferAllocator()) +numpy_execution = EmbeddedDummyBackend( + "EmbeddedNumPy", next_allocators.StandardCPUFieldBufferAllocator() +) +cupy_execution = EmbeddedDummyBackend( + "EmbeddedCuPy", next_allocators.StandardGPUFieldBufferAllocator() +) class EmbeddedIds(_PythonObjectIdMixin, str, enum.Enum): diff --git a/tests/next_tests/integration_tests/feature_tests/dace/__init__.py b/tests/next_tests/integration_tests/feature_tests/dace/__init__.py index abf4c3e24c..7a9cb1ece5 100644 --- a/tests/next_tests/integration_tests/feature_tests/dace/__init__.py +++ b/tests/next_tests/integration_tests/feature_tests/dace/__init__.py @@ -6,3 +6,7 @@ # Please, refer to the LICENSE file in the root directory. # SPDX-License-Identifier: BSD-3-Clause +import pytest + +#: Attribute defining package-level marks used by a custom pytest hook. +package_pytestmarks = [pytest.mark.requires_dace] diff --git a/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py b/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py index 22af788845..8fe0634302 100644 --- a/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py +++ b/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py @@ -30,12 +30,7 @@ ) -try: - import dace -except ImportError: - dace: Optional[ModuleType] = None # type:ignore[no-redef] - -pytestmark = pytest.mark.requires_dace +dace = pytest.importorskip("dace") def test_sdfgConvertible_laplap(cartesian_case): # noqa: F811 diff --git a/tests/next_tests/integration_tests/feature_tests/dace/test_program.py b/tests/next_tests/integration_tests/feature_tests/dace/test_program.py index 2a7a3710a9..4edaf9f85f 100644 --- a/tests/next_tests/integration_tests/feature_tests/dace/test_program.py +++ b/tests/next_tests/integration_tests/feature_tests/dace/test_program.py @@ -23,18 +23,9 @@ ) -try: - import dace +dace = pytest.importorskip("dace") - from gt4py.next.program_processors.runners import dace as dace_backends -except ImportError: - from types import ModuleType - from typing import Optional - - from gt4py.next import backend as next_backend - - dace: Optional[ModuleType] = None - dace_backends: Optional[ModuleType] = None +from gt4py.next.program_processors.runners import dace as dace_backends @pytest.fixture( diff --git a/tests/next_tests/integration_tests/feature_tests/iterator_tests/test_extractors.py b/tests/next_tests/integration_tests/feature_tests/iterator_tests/test_extractors.py index 7358ab3d8f..2356e9c781 100644 --- a/tests/next_tests/integration_tests/feature_tests/iterator_tests/test_extractors.py +++ b/tests/next_tests/integration_tests/feature_tests/iterator_tests/test_extractors.py @@ -6,15 +6,15 @@ # Please, refer to the LICENSE file in the root directory. # SPDX-License-Identifier: BSD-3-Clause +from __future__ import annotations + import typing import pytest from gt4py import next as gtx -from gt4py.next import common from gt4py.next.iterator.transforms import extractors -from next_tests.integration_tests import cases from next_tests.integration_tests.feature_tests.ffront_tests.ffront_test_utils import ( IDim, JDim, @@ -22,53 +22,14 @@ ) -if typing.TYPE_CHECKING: - from types import ModuleType - from typing import Optional - -try: - import dace - - from gt4py.next.program_processors.runners.dace import run_dace_cpu -except ImportError: - from gt4py.next import backend as next_backend - - dace: Optional[ModuleType] = None - run_dace_cpu: Optional[next_backend.Backend] = None - - -@pytest.fixture(params=[pytest.param(run_dace_cpu, marks=pytest.mark.requires_dace), gtx.gtfn_cpu]) -def gtir_dace_backend(request): - yield request.param - - -@pytest.fixture -def cartesian(request, gtir_dace_backend): - if gtir_dace_backend is None: - yield None - - yield cases.Case( - backend=gtir_dace_backend, - offset_provider={ - "Ioff": IDim, - "Joff": JDim, - "Koff": KDim, - }, - default_sizes={IDim: 10, JDim: 10, KDim: 10}, - grid_type=common.GridType.CARTESIAN, - allocator=gtir_dace_backend.allocator, - ) - - -@pytest.mark.skipif(dace is None, reason="DaCe not found") -def test_input_names_extractor_cartesian(cartesian): - @gtx.field_operator(backend=cartesian.backend) +def test_input_names_extractor_cartesian(): + @gtx.field_operator def testee_op( a: gtx.Field[[IDim, JDim, KDim], gtx.int], ) -> gtx.Field[[IDim, JDim, KDim], gtx.int]: return a - @gtx.program(backend=cartesian.backend) + @gtx.program def testee( a: gtx.Field[[IDim, JDim, KDim], gtx.int], b: gtx.Field[[IDim, JDim, KDim], gtx.int], @@ -81,15 +42,14 @@ def testee( assert input_field_names == {"a", "b"} -@pytest.mark.skipif(dace is None, reason="DaCe not found") -def test_output_names_extractor(cartesian): - @gtx.field_operator(backend=cartesian.backend) +def test_output_names_extractor(): + @gtx.field_operator def testee_op( a: gtx.Field[[IDim, JDim, KDim], gtx.int], ) -> gtx.Field[[IDim, JDim, KDim], gtx.int]: return a - @gtx.program(backend=cartesian.backend) + @gtx.program def testee( a: gtx.Field[[IDim, JDim, KDim], gtx.int], b: gtx.Field[[IDim, JDim, KDim], gtx.int], diff --git a/tests/next_tests/integration_tests/multi_feature_tests/ffront_tests/test_ffront_fvm_nabla.py b/tests/next_tests/integration_tests/multi_feature_tests/ffront_tests/test_ffront_fvm_nabla.py index 6c6ca7e4bc..da354be7ea 100644 --- a/tests/next_tests/integration_tests/multi_feature_tests/ffront_tests/test_ffront_fvm_nabla.py +++ b/tests/next_tests/integration_tests/multi_feature_tests/ffront_tests/test_ffront_fvm_nabla.py @@ -13,6 +13,7 @@ pytest.importorskip("atlas4py") +import gt4py._core.definitions as core_defs from gt4py import next as gtx from gt4py.next import allocators, neighbor_sum from gt4py.next.iterator import atlas_utils @@ -62,12 +63,15 @@ def pnabla( return compute_pnabla(pp, S_M[0], sign, vol), compute_pnabla(pp, S_M[1], sign, vol) +@pytest.mark.requires_atlas def test_ffront_compute_zavgS(exec_alloc_descriptor): - _, allocator = exec_alloc_descriptor.executor, exec_alloc_descriptor.allocator + # TODO(havogt): fix nabla setup to work with GPU + if exec_alloc_descriptor.allocator.device_type != core_defs.DeviceType.CPU: + pytest.skip("This test is only supported on CPU devices yet") - setup = nabla_setup(allocator=allocator) + setup = nabla_setup(allocator=exec_alloc_descriptor.allocator) - zavgS = gtx.zeros({Edge: setup.edges_size}, allocator=allocator) + zavgS = gtx.zeros({Edge: setup.edges_size}, allocator=exec_alloc_descriptor.allocator) compute_zavgS.with_backend( None if exec_alloc_descriptor.executor is None else exec_alloc_descriptor @@ -82,13 +86,16 @@ def test_ffront_compute_zavgS(exec_alloc_descriptor): assert_close(388241977.58389181, np.max(zavgS.asnumpy())) +@pytest.mark.requires_atlas def test_ffront_nabla(exec_alloc_descriptor): - _, allocator = exec_alloc_descriptor.executor, exec_alloc_descriptor.allocator + # TODO(havogt): fix nabla setup to work with GPU + if exec_alloc_descriptor.allocator.device_type != core_defs.DeviceType.CPU: + pytest.skip("This test is only supported on CPU devices yet") - setup = nabla_setup(allocator=allocator) + setup = nabla_setup(allocator=exec_alloc_descriptor.allocator) - pnabla_MXX = gtx.zeros({Vertex: setup.nodes_size}, allocator=allocator) - pnabla_MYY = gtx.zeros({Vertex: setup.nodes_size}, allocator=allocator) + pnabla_MXX = gtx.zeros({Vertex: setup.nodes_size}, allocator=exec_alloc_descriptor.allocator) + pnabla_MYY = gtx.zeros({Vertex: setup.nodes_size}, allocator=exec_alloc_descriptor.allocator) pnabla.with_backend(None if exec_alloc_descriptor.executor is None else exec_alloc_descriptor)( setup.input_field, diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/__init__.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/__init__.py index 9fa07e46e9..1cdf0f0591 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/__init__.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/__init__.py @@ -9,4 +9,5 @@ import pytest -pytestmark = pytest.mark.requires_dace +#: Attribute defining package-level marks used by a custom pytest hook. +package_pytestmarks = [pytest.mark.requires_dace] diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace.py index 62d88d9f0a..ca4a1e0f1f 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace.py @@ -27,8 +27,6 @@ mesh_descriptor, ) -from . import pytestmark - dace = pytest.importorskip("dace") diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py index bfde179e33..7431ad2b4a 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py @@ -34,8 +34,6 @@ skip_value_mesh, ) -from . import pytestmark - dace_backend = pytest.importorskip("gt4py.next.program_processors.runners.dace") diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/__init__.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/__init__.py index 6c3b1060b6..a576665ee3 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/__init__.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/__init__.py @@ -9,4 +9,5 @@ import pytest -pytestmark = [pytest.mark.requires_dace, pytest.mark.usefixtures("set_dace_settings")] +#: Attribute defining package-level marks used by a custom pytest hook. +package_pytestmarks = [pytest.mark.usefixtures("common_dace_config")] diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/conftest.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/conftest.py index 0eb0bf39c2..c3455c37cc 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/conftest.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/conftest.py @@ -12,7 +12,7 @@ @pytest.fixture(autouse=True) -def set_dace_settings() -> Generator[None, None, None]: +def common_dace_config() -> Generator[None, None, None]: """Sets the common DaCe settings for the tests. The function will modify the following settings: diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_distributed_buffer_relocator.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_distributed_buffer_relocator.py index 9241bae4bf..ae3624ce13 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_distributed_buffer_relocator.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_distributed_buffer_relocator.py @@ -6,9 +6,13 @@ # Please, refer to the LICENSE file in the root directory. # SPDX-License-Identifier: BSD-3-Clause +from __future__ import annotations + import pytest import numpy as np +dace = pytest.importorskip("dace") + from gt4py.next.program_processors.runners.dace import ( transformations as gtx_transformations, ) @@ -16,11 +20,6 @@ from . import util -# dace = pytest.importorskip("dace") -from dace.sdfg import nodes as dace_nodes -import dace - - def _mk_distributed_buffer_sdfg() -> tuple[dace.SDFG, dace.SDFGState, dace.SDFGState]: sdfg = dace.SDFG(util.unique_name("distributed_buffer_sdfg")) diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_gpu_utils.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_gpu_utils.py index cdc66d4ffd..350fa807a1 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_gpu_utils.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_gpu_utils.py @@ -18,7 +18,7 @@ gpu_utils as gtx_dace_fieldview_gpu_utils, ) -from . import pytestmark + from . import util diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_loop_blocking.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_loop_blocking.py index a08cf12a5a..4d7a8156d7 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_loop_blocking.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_loop_blocking.py @@ -20,7 +20,7 @@ transformations as gtx_transformations, ) -from . import pytestmark + from . import util diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_fusion.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_fusion.py index 516a70b579..cd4ad77787 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_fusion.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_fusion.py @@ -21,7 +21,7 @@ transformations as gtx_transformations, ) -from . import pytestmark + from . import util diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_order.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_order.py index 762040e20d..d82127f6f3 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_order.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_map_order.py @@ -6,9 +6,13 @@ # Please, refer to the LICENSE file in the root directory. # SPDX-License-Identifier: BSD-3-Clause +from __future__ import annotations + import pytest import numpy as np +dace = pytest.importorskip("dace") + from gt4py.next.program_processors.runners.dace import ( transformations as gtx_transformations, ) @@ -16,10 +20,6 @@ from . import util -dace = pytest.importorskip("dace") -from dace.sdfg import nodes as dace_nodes - - def _perform_reorder_test( sdfg: dace.SDFG, leading_dim: list[str], diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_serial_map_promoter.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_serial_map_promoter.py index fa7c7255e3..3bd0ed2dc3 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_serial_map_promoter.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/transformation_tests/test_serial_map_promoter.py @@ -16,7 +16,7 @@ transformations as gtx_transformations, ) -from . import pytestmark + from . import util diff --git a/tox.ini b/tox.ini deleted file mode 100644 index e7bfd4a3e4..0000000000 --- a/tox.ini +++ /dev/null @@ -1,190 +0,0 @@ -[tox] -requires = - tox>=4.2 - virtualenv>20.2 -envlist = - cartesian-py{310}-{internal,dace}-{cpu} - eve-py{310} - next-py{310}-{nomesh,atlas}-{cpu} - storage-py{310}-{internal,dace}-{cpu} - # docs -labels = - test-cartesian-cpu = cartesian-internal-py310-cpu, cartesian-py311-internal-cpu, cartesian-py310-dace-cpu, cartesian-py311-dace-cpu - test-eve-cpu = eve-py310, eve-py311 - test-next-cpu = next-py310-nomesh-cpu, next-py311-nomesh-cpu, next-py310-atlas-cpu, next-py311-atlas-cpu - test-storage-cpu = storage-py310-internal-cpu, storage-py311-internal-cpu, storage-py310-dace-cpu, storage-py311-dace-cpu - test-cpu = cartesian-py310-internal-cpu, cartesian-py311-internal-cpu, cartesian-py310-dace-cpu, cartesian-py311-dace-cpu, \ - eve-py310, eve-py311, \ - next-py310-nomesh-cpu, next-py311-nomesh-cpu, next-py310-atlas-cpu, next-py311-atlas-cpu, \ - storage-py310-internal-cpu, storage-py311-internal-cpu, storage-py310-dace-cpu, storage-py311-dace-cpu - -[testenv] -deps = -r {tox_root}{/}{env:ENV_REQUIREMENTS_FILE:requirements-dev.txt} -constrain_package_deps = true -use_frozen_constraints = true -extras = - testing - formatting - dace: dace - cuda: cuda - cuda11x: cuda11x - cuda12x: cuda12x -package = wheel -wheel_build_env = .pkg -pass_env = CUDAARCHS, NUM_PROCESSES, GT4PY_* -set_env = - PYTEST_ADDOPTS = --color=auto --instafail - PYTHONWARNINGS = {env:PYTHONWARNINGS:ignore:Support for `[tool.setuptools]` in `pyproject.toml` is still *beta*:UserWarning,ignore:Field View Program:UserWarning} - -# -- Primary tests -- -[testenv:cartesian-py{310,311}-{internal,dace}-{cpu,cuda,cuda11x,cuda12x}] -description = Run 'gt4py.cartesian' tests -pass_env = {[testenv]pass_env}, BOOST_ROOT, BOOST_HOME, CUDA_HOME, CUDA_PATH, CXX, CC, OPENMP_CPPFLAGS, OPENMP_LDFLAGS, PIP_USER, PYTHONUSERBASE -allowlist_externals = - make - gcc - g++ - ldd - rm -commands = - python -m pytest --cache-clear -v -n {env:NUM_PROCESSES:1} -m "\ - internal: not requires_dace \ - dace: requires_dace \ - cpu: and not requires_gpu \ - {cuda,cuda11x,cuda12x}: and requires_gpu \ - " {posargs} tests{/}cartesian_tests - python -m pytest --doctest-modules --doctest-ignore-import-errors src{/}gt4py{/}cartesian -# commands_pre = -# rm -Rf tests/_reports/coverage* -# commands_post = -# coverage json --rcfile=setup.cfg -# coverage html --rcfile=setup.cfg --show-contexts - -[testenv:eve-py{310,311}] -description = Run 'gt4py.eve' tests -commands = - python -m pytest --cache-clear -v -n {env:NUM_PROCESSES:1} {posargs} tests{/}eve_tests - python -m pytest --doctest-modules src{/}gt4py{/}eve - -[testenv:next-py{310,311}-{nomesh,atlas}-{cpu,cuda,cuda11x,cuda12x}] -description = Run 'gt4py.next' tests -pass_env = {[testenv]pass_env}, BOOST_ROOT, BOOST_HOME, CUDA_HOME, CUDA_PATH -deps = - -r {tox_root}{/}requirements-dev.txt - atlas: atlas4py -set_env = - {[testenv]set_env} - PIP_EXTRA_INDEX_URL = {env:PIP_EXTRA_INDEX_URL:https://test.pypi.org/simple/} -commands = - python -m pytest --suppress-no-test-exit-code --cache-clear -v -n {env:NUM_PROCESSES:1} -m "\ - nomesh: not requires_atlas \ - atlas: requires_atlas \ - cpu: and not requires_gpu \ - {cuda,cuda11x,cuda12x}: and requires_gpu \ - " {posargs} tests{/}next_tests - pytest --doctest-modules src{/}gt4py{/}next - -[testenv:storage-py{310,311}-{internal,dace}-{cpu,cuda,cuda11x,cuda12x}] -description = Run 'gt4py.storage' tests -commands = - python -m pytest --cache-clear -v -n {env:NUM_PROCESSES:1} -m "\ - cpu: not requires_gpu \ - {cuda,cuda11x,cuda12x}: requires_gpu \ - " {posargs} tests{/}storage_tests - # pytest doctest-modules {posargs} src{/}gt4py{/}storage - -# -- Secondary tests -- -[testenv:notebooks-py{310,311}] -description = Run notebooks -commands_pre = - jupytext docs/user/next/QuickstartGuide.md --to .ipynb - jupytext docs/user/next/advanced/*.md --to .ipynb -commands = - python -m pytest --nbmake docs/user/next/workshop/slides -v -n {env:NUM_PROCESSES:1} - python -m pytest --nbmake docs/user/next/workshop/exercises -k 'solutions' -v -n {env:NUM_PROCESSES:1} - python -m pytest --nbmake docs/user/next/QuickstartGuide.ipynb -v -n {env:NUM_PROCESSES:1} - python -m pytest --nbmake docs/user/next/advanced -v -n {env:NUM_PROCESSES:1} - python -m pytest --nbmake examples -v -n {env:NUM_PROCESSES:1} - -# -- Other artefacts -- -[testenv:dev-py{310,311}{-atlas,}] -description = Initialize development environment for gt4py -deps = - -r {tox_root}{/}requirements-dev.txt - atlas: atlas4py -package = editable-legacy # => use_develop = True -set_env = - {[testenv]set_env} - PIP_EXTRA_INDEX_URL = {env:PIP_EXTRA_INDEX_URL:https://test.pypi.org/simple/} - -# [testenv:diagrams] -# install_command = echo {packages} -# skip_install = true -# allowlist_externals = -# /bin/bash -# make -# gcc -# g++ -# ldd -# rm -# plantuml -# git -# echo -# changedir = docs/development/ADRs -# commands = -# plantuml ./*.md -tsvg -o _static -# git add _static -# commands_post = - -[testenv:requirements-{base,py310,py311}] -description = - base: Update pinned development requirements - py310: Update requirements for testing a specific python version - py311: Update requirements for testing a specific python version -base_python = - base: py310 - py310: py310 - py311: py311 -deps = - cogapp>=3.3 - packaging>=20.0 - pip-tools>=6.10 -package = skip -set_env = - CUSTOM_COMPILE_COMMAND = "tox run -e requirements-base" -allowlist_externals = - mv -commands = - -mv constraints.txt constraints.txt.old - -mv requirements-dev.txt requirements-dev.old - # Run cog to update requirements files from pyproject - cog -r -P min-requirements-test.txt min-extra-requirements-test.txt - # Generate constraints file removing extras - # (extras are not supported by pip in constraints files) - pip-compile -r --resolver=backtracking \ - --annotation-style line \ - --build-isolation \ - --strip-extras \ - --allow-unsafe \ - --extra dace \ - --extra formatting \ - --extra jax-cpu \ - --extra performance \ - --extra testing \ - -o constraints.txt \ - pyproject.toml requirements-dev.in - # Generate actual requirements file - # (compiling from scratch again to print actual package sources) - pip-compile --resolver=backtracking \ - --annotation-style line \ - --build-isolation \ - --allow-unsafe \ - --extra dace \ - --extra formatting \ - --extra jax-cpu \ - --extra testing \ - -c constraints.txt \ - -o requirements-dev.txt \ - pyproject.toml requirements-dev.in - # Run cog to update .pre-commit-config.yaml with new versions - base: cog -r -P .pre-commit-config.yaml diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000000..1d050717af --- /dev/null +++ b/uv.lock @@ -0,0 +1,3345 @@ +version = 1 +requires-python = ">=3.10, <3.12" +resolution-markers = [ + "python_full_version < '3.11'", + "python_full_version >= '3.11'", +] +conflicts = [[ + { package = "gt4py", extra = "cuda11" }, + { package = "gt4py", extra = "jax-cuda12" }, + { package = "gt4py", extra = "rocm4-3" }, + { package = "gt4py", extra = "rocm5-0" }, +]] + +[[package]] +name = "aenum" +version = "3.1.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/f8/33e75863394f42e429bb553e05fda7c59763f0fd6848de847a25b3fbccf6/aenum-3.1.15.tar.gz", hash = "sha256:8cbd76cd18c4f870ff39b24284d3ea028fbe8731a58df3aa581e434c575b9559", size = 134730 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/fa/ca0c66b388624ba9dbbf35aab3a9f326bfdf5e56a7237fe8f1b600da6864/aenum-3.1.15-py3-none-any.whl", hash = "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288", size = 137633 }, +] + +[[package]] +name = "alabaster" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929 }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, +] + +[[package]] +name = "apeye" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "apeye-core" }, + { name = "domdf-python-tools" }, + { name = "platformdirs" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/cc65e31843d7bfda8313a9dc0c77a21e8580b782adca53c7cb3e511fe023/apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36", size = 99219 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/7b/2d63664777b3e831ac1b1d8df5bbf0b7c8bee48e57115896080890527b1b/apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e", size = 107989 }, +] + +[[package]] +name = "apeye-core" +version = "1.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "domdf-python-tools" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/4c/4f108cfd06923bd897bf992a6ecb6fb122646ee7af94d7f9a64abd071d4c/apeye_core-1.1.5.tar.gz", hash = "sha256:5de72ed3d00cc9b20fea55e54b7ab8f5ef8500eb33a5368bc162a5585e238a55", size = 96511 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/9f/fa9971d2a0c6fef64c87ba362a493a4f230eff4ea8dfb9f4c7cbdf71892e/apeye_core-1.1.5-py3-none-any.whl", hash = "sha256:dc27a93f8c9e246b3b238c5ea51edf6115ab2618ef029b9f2d9a190ec8228fbf", size = 99286 }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321 }, +] + +[[package]] +name = "argcomplete" +version = "3.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/be/6c23d80cb966fb8f83fb1ebfb988351ae6b0554d0c3a613ee4531c026597/argcomplete-3.5.3.tar.gz", hash = "sha256:c12bf50eded8aebb298c7b7da7a5ff3ee24dffd9f5281867dfe1424b58c55392", size = 72999 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/08/2a4db06ec3d203124c967fc89295e85a202e5cbbcdc08fd6a64b65217d1e/argcomplete-3.5.3-py3-none-any.whl", hash = "sha256:2ab2c4a215c59fd6caaff41a869480a23e8f6a5f910b266c1808037f4e375b61", size = 43569 }, +] + +[[package]] +name = "asttokens" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/1d/f03bcb60c4a3212e15f99a56085d93093a497718adf828d050b9d675da81/asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0", size = 62284 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/86/4736ac618d82a20d87d2f92ae19441ebc7ac9e7a581d7e58bbe79233b24a/asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", size = 27764 }, +] + +[[package]] +name = "astunparse" +version = "1.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, + { name = "wheel" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/af/4182184d3c338792894f34a62672919db7ca008c89abee9b564dd34d8029/astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872", size = 18290 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8", size = 12732 }, +] + +[[package]] +name = "atlas4py" +version = "0.35.1.dev15" +source = { registry = "https://test.pypi.org/simple/" } +sdist = { url = "https://test-files.pythonhosted.org/packages/59/e4/48ede747be846f80b30d6303d732f96ca44ee9858504140db5222d2345bb/atlas4py-0.35.1.dev15.tar.gz", hash = "sha256:3c4274261d99a03ffd14a23dfb9ee9265ce79d8db7887751f4fbf1a315091664", size = 15079 } +wheels = [ + { url = "https://test-files.pythonhosted.org/packages/7a/47/0d1f8f7ba596a60bef920638724dfcc76f4edbfdb6bb79932b7e12ec45fc/atlas4py-0.35.1.dev15-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:244ae7f016d28ad04f8e9071de34192c1f8a58fd075477e327c4528cad8daacf", size = 6040572 }, + { url = "https://test-files.pythonhosted.org/packages/5d/f5/2b5645ec670b4088816ca7089fae06c6d72f0a4c301ef186ec8ac8e715fd/atlas4py-0.35.1.dev15-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:12b8f63df17e22d0ddc8310ced42e4db903e73b167c4f261f180cc2c011888ca", size = 5752419 }, + { url = "https://test-files.pythonhosted.org/packages/41/c3/03f3f061d28865f307c7916a0b82b8d37efeddb6cd4085aa687718341aee/atlas4py-0.35.1.dev15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cadd6e5de2e0771d129b6242cbe0bd9268bed16d37ee3cc65b97a7de19a67933", size = 5251334 }, + { url = "https://test-files.pythonhosted.org/packages/22/fe/32d912deb54d7e9eaecc652b813b86925616be358222e069ded6e3bea8c6/atlas4py-0.35.1.dev15-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:0cacea024adb384aacb5da5a5a233e23cf8563e4f357e9687eeac0d9c4c9a4d8", size = 6041915 }, + { url = "https://test-files.pythonhosted.org/packages/ef/94/e85cc3588d836e58974f7be1b362ce321f5989ae8c355a75faee5b09f131/atlas4py-0.35.1.dev15-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:d5f3147e8ad52b890ffc4d92b51d6fd2b34bb39b89e09d6d4d5d7fec9f48aa0f", size = 5753565 }, + { url = "https://test-files.pythonhosted.org/packages/36/5e/71c7c054ae756f7cd5a984a44edad85ca20f4a0364ccc10052363314a9f2/atlas4py-0.35.1.dev15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c13f4a4a88dbe0eb056920d57eafa3e0f1e9fc117bd3c8773cfebca945ed8d76", size = 5253094 }, +] + +[[package]] +name = "attrs" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/7c/fdf464bcc51d23881d110abd74b512a42b3d5d376a55a831b44c603ae17f/attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e", size = 810562 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 }, +] + +[[package]] +name = "autodocsumm" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/03/96/92afe8a7912b327c01f0a8b6408c9556ee13b1aba5b98d587ac7327ff32d/autodocsumm-0.2.14.tar.gz", hash = "sha256:2839a9d4facc3c4eccd306c08695540911042b46eeafcdc3203e6d0bab40bc77", size = 46357 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/bc/3f66af9beb683728e06ca08797e4e9d3e44f432f339718cae3ba856a9cad/autodocsumm-0.2.14-py3-none-any.whl", hash = "sha256:3bad8717fc5190802c60392a7ab04b9f3c97aa9efa8b3780b3d81d615bfe5dc0", size = 14640 }, +] + +[[package]] +name = "babel" +version = "2.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/ca/824b1195773ce6166d388573fc106ce56d4a805bd7427b624e063596ec58/beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", size = 581181 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed", size = 147925 }, +] + +[[package]] +name = "black" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/3b/4ba3f93ac8d90410423fdd31d7541ada9bcee1df32fb90d26de41ed40e1d/black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", size = 1629419 }, + { url = "https://files.pythonhosted.org/packages/b4/02/0bde0485146a8a5e694daed47561785e8b77a0466ccc1f3e485d5ef2925e/black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", size = 1461080 }, + { url = "https://files.pythonhosted.org/packages/52/0e/abdf75183c830eaca7589144ff96d49bce73d7ec6ad12ef62185cc0f79a2/black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", size = 1766886 }, + { url = "https://files.pythonhosted.org/packages/dc/a6/97d8bb65b1d8a41f8a6736222ba0a334db7b7b77b8023ab4568288f23973/black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", size = 1419404 }, + { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372 }, + { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865 }, + { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699 }, + { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028 }, + { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 }, +] + +[[package]] +name = "boltons" +version = "24.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/76/dfc34232b3e88634025563f52a430be0838182647c063f99569086922554/boltons-24.1.0.tar.gz", hash = "sha256:4a49b7d57ee055b83a458c8682a2a6f199d263a8aa517098bda9bab813554b87", size = 240916 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/96/e44606e60a0c005ac5f2a641960a93ca8f449ebdce7479f9bc4f10bead6d/boltons-24.1.0-py3-none-any.whl", hash = "sha256:a1776d47fdc387fb730fba1fe245f405ee184ee0be2fb447dd289773a84aed3b", size = 192196 }, +] + +[[package]] +name = "bracex" +version = "2.5.post1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/6c/57418c4404cd22fe6275b8301ca2b46a8cdaa8157938017a9ae0b3edf363/bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6", size = 26641 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558 }, +] + +[[package]] +name = "bump-my-version" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "questionary" }, + { name = "rich" }, + { name = "rich-click" }, + { name = "tomlkit" }, + { name = "wcmatch" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/4f/57eda33958c5820b462c4c262bc18dc374dca6312bbb63f95606172200cb/bump_my_version-0.30.0.tar.gz", hash = "sha256:d53e784c73abc4bb5759e296f510bc71878e1df078eb525542ec9291b5ceb195", size = 1062228 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/9b/965ad61f85cbde14694516b02dcd38ec0c5cf7132fe33a30fddb4d8b0803/bump_my_version-0.30.0-py3-none-any.whl", hash = "sha256:b0d683a1cb97fbc2f46adf8eb39ff1f0bdd72866c3583fe01f9837d6f031e5e3", size = 55257 }, +] + +[[package]] +name = "cachecontrol" +version = "0.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b7/a4/3390ac4dfa1773f661c8780368018230e8207ec4fd3800d2c0c3adee4456/cachecontrol-0.14.2.tar.gz", hash = "sha256:7d47d19f866409b98ff6025b6a0fca8e4c791fb31abbd95f622093894ce903a2", size = 28832 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/63/baffb44ca6876e7b5fc8fe17b24a7c07bf479d604a592182db9af26ea366/cachecontrol-0.14.2-py3-none-any.whl", hash = "sha256:ebad2091bf12d0d200dfc2464330db638c5deb41d546f6d7aca079e87290f3b0", size = 21780 }, +] + +[package.optional-dependencies] +filecache = [ + { name = "filelock" }, +] + +[[package]] +name = "cached-property" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/4b/3d870836119dbe9a5e3c9a61af8cc1a8b69d75aea564572e385882d5aefb/cached_property-2.0.1.tar.gz", hash = "sha256:484d617105e3ee0e4f1f58725e72a8ef9e93deee462222dbd51cd91230897641", size = 10574 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/0e/7d8225aab3bc1a0f5811f8e1b557aa034ac04bdf641925b30d3caf586b28/cached_property-2.0.1-py3-none-any.whl", hash = "sha256:f617d70ab1100b7bcf6e42228f9ddcb78c676ffa167278d9f730d1c2fba69ccb", size = 7428 }, +] + +[[package]] +name = "cattrs" +version = "24.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/65/af6d57da2cb32c076319b7489ae0958f746949d407109e3ccf4d115f147c/cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85", size = 426462 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/d5/867e75361fc45f6de75fe277dd085627a9db5ebb511a87f27dc1396b5351/cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0", size = 66446 }, +] + +[[package]] +name = "certifi" +version = "2024.12.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/bd/1d41ee578ce09523c81a15426705dd20969f5abf006d1afe8aeff0dd776a/certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db", size = 166010 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/32/8f6669fc4798494966bf446c8c4a162e0b5d893dff088afddf76414f70e1/certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", size = 164927 }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191 }, + { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592 }, + { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024 }, + { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188 }, + { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571 }, + { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687 }, + { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211 }, + { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325 }, + { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784 }, + { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564 }, + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 }, + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/58/5580c1716040bc89206c77d8f74418caf82ce519aae06450393ca73475d1/charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", size = 198013 }, + { url = "https://files.pythonhosted.org/packages/d0/11/00341177ae71c6f5159a08168bcb98c6e6d196d372c94511f9f6c9afe0c6/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", size = 141285 }, + { url = "https://files.pythonhosted.org/packages/01/09/11d684ea5819e5a8f5100fb0b38cf8d02b514746607934134d31233e02c8/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", size = 151449 }, + { url = "https://files.pythonhosted.org/packages/08/06/9f5a12939db324d905dc1f70591ae7d7898d030d7662f0d426e2286f68c9/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", size = 143892 }, + { url = "https://files.pythonhosted.org/packages/93/62/5e89cdfe04584cb7f4d36003ffa2936681b03ecc0754f8e969c2becb7e24/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", size = 146123 }, + { url = "https://files.pythonhosted.org/packages/a9/ac/ab729a15c516da2ab70a05f8722ecfccc3f04ed7a18e45c75bbbaa347d61/charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", size = 147943 }, + { url = "https://files.pythonhosted.org/packages/03/d2/3f392f23f042615689456e9a274640c1d2e5dd1d52de36ab8f7955f8f050/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", size = 142063 }, + { url = "https://files.pythonhosted.org/packages/f2/e3/e20aae5e1039a2cd9b08d9205f52142329f887f8cf70da3650326670bddf/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", size = 150578 }, + { url = "https://files.pythonhosted.org/packages/8d/af/779ad72a4da0aed925e1139d458adc486e61076d7ecdcc09e610ea8678db/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", size = 153629 }, + { url = "https://files.pythonhosted.org/packages/c2/b6/7aa450b278e7aa92cf7732140bfd8be21f5f29d5bf334ae987c945276639/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", size = 150778 }, + { url = "https://files.pythonhosted.org/packages/39/f4/d9f4f712d0951dcbfd42920d3db81b00dd23b6ab520419626f4023334056/charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", size = 146453 }, + { url = "https://files.pythonhosted.org/packages/49/2b/999d0314e4ee0cff3cb83e6bc9aeddd397eeed693edb4facb901eb8fbb69/charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", size = 95479 }, + { url = "https://files.pythonhosted.org/packages/2d/ce/3cbed41cff67e455a386fb5e5dd8906cdda2ed92fbc6297921f2e4419309/charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", size = 102790 }, + { url = "https://files.pythonhosted.org/packages/72/80/41ef5d5a7935d2d3a773e3eaebf0a9350542f2cab4eac59a7a4741fbbbbe/charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", size = 194995 }, + { url = "https://files.pythonhosted.org/packages/7a/28/0b9fefa7b8b080ec492110af6d88aa3dea91c464b17d53474b6e9ba5d2c5/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", size = 139471 }, + { url = "https://files.pythonhosted.org/packages/71/64/d24ab1a997efb06402e3fc07317e94da358e2585165930d9d59ad45fcae2/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", size = 149831 }, + { url = "https://files.pythonhosted.org/packages/37/ed/be39e5258e198655240db5e19e0b11379163ad7070962d6b0c87ed2c4d39/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", size = 142335 }, + { url = "https://files.pythonhosted.org/packages/88/83/489e9504711fa05d8dde1574996408026bdbdbd938f23be67deebb5eca92/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", size = 143862 }, + { url = "https://files.pythonhosted.org/packages/c6/c7/32da20821cf387b759ad24627a9aca289d2822de929b8a41b6241767b461/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", size = 145673 }, + { url = "https://files.pythonhosted.org/packages/68/85/f4288e96039abdd5aeb5c546fa20a37b50da71b5cf01e75e87f16cd43304/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", size = 140211 }, + { url = "https://files.pythonhosted.org/packages/28/a3/a42e70d03cbdabc18997baf4f0227c73591a08041c149e710045c281f97b/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", size = 148039 }, + { url = "https://files.pythonhosted.org/packages/85/e4/65699e8ab3014ecbe6f5c71d1a55d810fb716bbfd74f6283d5c2aa87febf/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", size = 151939 }, + { url = "https://files.pythonhosted.org/packages/b1/82/8e9fe624cc5374193de6860aba3ea8070f584c8565ee77c168ec13274bd2/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", size = 149075 }, + { url = "https://files.pythonhosted.org/packages/3d/7b/82865ba54c765560c8433f65e8acb9217cb839a9e32b42af4aa8e945870f/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", size = 144340 }, + { url = "https://files.pythonhosted.org/packages/b5/b6/9674a4b7d4d99a0d2df9b215da766ee682718f88055751e1e5e753c82db0/charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", size = 95205 }, + { url = "https://files.pythonhosted.org/packages/1e/ab/45b180e175de4402dcf7547e4fb617283bae54ce35c27930a6f35b6bef15/charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", size = 102441 }, + { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, +] + +[[package]] +name = "clang-format" +version = "19.1.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/ee/71d017fe603c06b83d6720df6b3f6f07f03abf330f39beee3fee2a067c56/clang_format-19.1.7.tar.gz", hash = "sha256:bd6fc5272a41034a7844149203461d1f311bece9ed100d22eb3eebd952a25f49", size = 11122 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/c3/2f1c53bc298c1740d0c9f8dc2d9b7030be4826b6f2aa8a04f07ef25a3d9b/clang_format-19.1.7-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:a09f34d2c89d176581858ff718c327eebc14eb6415c176dab4af5bfd8582a999", size = 1428184 }, + { url = "https://files.pythonhosted.org/packages/8e/9d/7c246a3d08105de305553d14971ed6c16cde06d20ab12d6ce7f243cf66f0/clang_format-19.1.7-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:776f89c7b056c498c0e256485bc031cbf514aaebe71e929ed54e50c478524b65", size = 1398224 }, + { url = "https://files.pythonhosted.org/packages/b1/7d/002aa5571351ee7f00f87aae5104cdd30cad1a46f25936226f7d2aed06bf/clang_format-19.1.7-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dac394c83a9233ab6707f66e1cdbd950f8b014b58604142a5b6f7998bf0bcc8c", size = 1730962 }, + { url = "https://files.pythonhosted.org/packages/1c/fe/24b7c13af432e609d65dc32c47c61f0a6c3b80d78eb7b3df37daf0395c56/clang_format-19.1.7-py2.py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbd4f94d929edf6d8d81e990dfaafc22bb10deaefcb2762150a136f281b01c00", size = 1908820 }, + { url = "https://files.pythonhosted.org/packages/7d/a8/86595ffd6ea0bf3a3013aad94e3d55be32ef987567781eddf4621e316d09/clang_format-19.1.7-py2.py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bdcda63fffdbe2aac23b54d46408a6283ad16676a5230a95b3ed49eacd99129b", size = 2622838 }, + { url = "https://files.pythonhosted.org/packages/48/d1/731ebf78c5d5cc043c20b0755c89239350b8e75ac5d667b99689e8110bc7/clang_format-19.1.7-py2.py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c13a5802da986b1400afbee97162c29f841890ab9e20a0be7ede18189219f5f1", size = 1723352 }, + { url = "https://files.pythonhosted.org/packages/3c/e7/0e526915a3a4a23100cc721c24226a192fa0385d394019d06920dc83fe6c/clang_format-19.1.7-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4906fb463dd2033032978f56962caab268c9428a384126b9400543eb667f11c", size = 1740347 }, + { url = "https://files.pythonhosted.org/packages/52/04/ed8e2af6b3e29655a858b3aad145f3f0539df0dd1c77815b95f578260bd3/clang_format-19.1.7-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ffca915c09aed9137f8c649ad7521bd5ce690c939121db1ba54af2ba63ac8374", size = 2675802 }, + { url = "https://files.pythonhosted.org/packages/9a/ab/7874a6f45c167f4cc4d02f517b85d14b6b5fa8412f6e9c7482588d00fccb/clang_format-19.1.7-py2.py3-none-musllinux_1_2_i686.whl", hash = "sha256:fc011dc7bbe3ac8a32e0caa37ab8ba6c1639ceef6ecd04feea8d37360fc175e4", size = 2977872 }, + { url = "https://files.pythonhosted.org/packages/46/b5/c87b6c46eb7e9d0f07e2bd56cd0a62bf7e679f146b4e1447110cfae4bd01/clang_format-19.1.7-py2.py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:afdfb11584f5a6f15127a7061673a7ea12a0393fe9ee8d2ed84e74bb191ffc3b", size = 3125795 }, + { url = "https://files.pythonhosted.org/packages/22/3e/7ea08aba446c1e838367d3c0e13eb3d2e482b23e099a25149d4f7f6b8c75/clang_format-19.1.7-py2.py3-none-musllinux_1_2_s390x.whl", hash = "sha256:6ce81d5b08e0169dc52037d3ff1802eafcaf86c281ceb8b38b8359ba7b6b7bdc", size = 3069663 }, + { url = "https://files.pythonhosted.org/packages/f5/f9/6ce7fe8ff52ded01d02a568358f2ddf993347e44202b6506b039a583b7ed/clang_format-19.1.7-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d27ac1a5a8783c9271d41cd5851766ca547ea003efa4e3764f880f319b2d3ed3", size = 2763172 }, + { url = "https://files.pythonhosted.org/packages/82/fa/77fe5636bb6b6252918bf129226a248506af218a2256deece3a9d95af850/clang_format-19.1.7-py2.py3-none-win32.whl", hash = "sha256:5dfde0be33f038114af89efb917144c2f766f8b7f3a3d3e4cb9c25f76d71ef81", size = 1243262 }, + { url = "https://files.pythonhosted.org/packages/e4/32/0b44f3582b9df0b8f90266ef43975e37ec8ad52bae4f85b71552f264d5a2/clang_format-19.1.7-py2.py3-none-win_amd64.whl", hash = "sha256:3e3c75fbdf8827bbb7277226b3057fc3785dabe7284d3a9d15fceb250f68f529", size = 1441132 }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, +] + +[[package]] +name = "cmake" +version = "3.31.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/50/cb/3a327fa784a5dbaf838b135cb1729f43535c52d83bbf02191fb8a0cb118e/cmake-3.31.4.tar.gz", hash = "sha256:a6ac2242e0b16ad7d94c9f8572d6f232e6169747be50e5cdf497f206c4819ce1", size = 34278 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/db/50efa1d3e29cb2a6e8e143e522e52698b3fc08f4b56100fb35f97a70af79/cmake-3.31.4-py3-none-macosx_10_10_universal2.whl", hash = "sha256:fc048b4b70facd16699a43c737f6782b4eff56e8e6093090db5979532d9db0f6", size = 47198138 }, + { url = "https://files.pythonhosted.org/packages/c7/76/ccb8764761c739ef16bd8957a16ecbda01b03c2d7d241c376bfca6bf2822/cmake-3.31.4-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a37be93534df04513f0845492d71bc80899c3f87b77e3b01c95aff1a7fc9bde", size = 27556485 }, + { url = "https://files.pythonhosted.org/packages/ad/8e/888e2944655d7fa1ea5af46b60883a0e7847bbf9fb7ecc321c8e5f0a1394/cmake-3.31.4-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c9f5f8289c5e7bd2ed654cbac164021fa7723064fee0443a2f0068bc08413d81", size = 26808834 }, + { url = "https://files.pythonhosted.org/packages/59/f4/0b2b1430a441c3c09ee102bf8c5d9ec1dc11d002ff4affef15c656f37ce9/cmake-3.31.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:926d91cae2ba7d2f3df857d0fc066bdac4f3904bf5c95e99b60435e85aabedb4", size = 27140820 }, + { url = "https://files.pythonhosted.org/packages/d1/f9/a274b4e36e457d8e99db1038cc31a6c391bf3bc26230c2dc9caf37499753/cmake-3.31.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:929a8d8d289d69e43784661748ddd08933ce1ec5db8f9bcfce6ee817a48f8787", size = 28868269 }, + { url = "https://files.pythonhosted.org/packages/9b/35/8da1ffa00a3f3853881aa5025cdf11c744303013df70c8716155b83825d3/cmake-3.31.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b463efdf5b92f3b290235aa9f8da092b3dac19b7636c563fd156022dab580649", size = 30732267 }, + { url = "https://files.pythonhosted.org/packages/79/48/bb8485687f5a64d52ac68cfcb02e9b8e46a9e107f380c54d484b6632c87e/cmake-3.31.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:225d9a643b0b60ffce0399ff0cabd7a4820e0dbcb794e97d3aacfcf7c0589ae6", size = 26908885 }, + { url = "https://files.pythonhosted.org/packages/e5/9e/2594d7fa8b263296497bf044469b4ab4797c51675ea629f9672011cdfe09/cmake-3.31.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89143a5e2a5916061f2cfc5012e9fe6281aaf7c0dae7930bdc68d105d22ddc39", size = 27784555 }, + { url = "https://files.pythonhosted.org/packages/95/16/5b1989f1d2287b05cd68792c0a48b721c060f728506d719fcf0e3b80ceb2/cmake-3.31.4-py3-none-manylinux_2_31_armv7l.whl", hash = "sha256:f96127bf663168accd29d5a50ee68ea80f26bcd37f96c7a14ef2378781f19936", size = 24965366 }, + { url = "https://files.pythonhosted.org/packages/5a/4c/289fb0986c6ff63583383eca0c9479147f362330938856a9b5201c84cee8/cmake-3.31.4-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:25c5094394f0cee21130b5678e5b4552f72470e266df6d6fb1d5c505100f0eaa", size = 27824887 }, + { url = "https://files.pythonhosted.org/packages/3c/f3/d45ba2b5bb54f4ef615a6a24cf6258600eec790a9d5017c9584107b445b9/cmake-3.31.4-py3-none-musllinux_1_1_i686.whl", hash = "sha256:466c9295af440bb4a47cc5e1af10576cf2227620528afd0fd0b3effa1d513b49", size = 31368421 }, + { url = "https://files.pythonhosted.org/packages/34/3d/f6b712241ede5fb8e32c13e119c06e142f3f12ead1656721b1f67756106b/cmake-3.31.4-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:f6af3b83a1b1fc1d990d18b6a566ee9c95c0393f986c6df15f2505dda8ad1bcc", size = 32074545 }, + { url = "https://files.pythonhosted.org/packages/f0/23/48cd0404d7238d703a4cd4d7434eeaf12e8fbe68160d52f1489f55f582df/cmake-3.31.4-py3-none-musllinux_1_1_s390x.whl", hash = "sha256:23781e17563693a68b0cef85749746894b8a61488e56e96fc6649b73652e8236", size = 27946950 }, + { url = "https://files.pythonhosted.org/packages/21/03/014d9710bccf5a7e04c6f6ee27bfaba1220e79ee145d7b95f84e7843729b/cmake-3.31.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:838a388b559137f3654d8cf30f62bbdec10f8d1c3624f0d289614d33cdf4fba1", size = 29473412 }, + { url = "https://files.pythonhosted.org/packages/23/de/5a8142732f0a52dedac2887e0c105c9bbb449e517ade500e56bf2af520d1/cmake-3.31.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6a3b0b9557f41c955a6b25c94205f2ca9c3a46edca809ad87507c5ef6bc4274", size = 32971081 }, + { url = "https://files.pythonhosted.org/packages/a5/a1/50c11f0b110986c753592f025970094030b25748df126abe8e38265be722/cmake-3.31.4-py3-none-win32.whl", hash = "sha256:d378c9e58eac906bddafd673c7571262dcd5a9946bb1e8f9e3902572a8fa95ca", size = 33351393 }, + { url = "https://files.pythonhosted.org/packages/0c/7f/331d181b6b1b8942ec5fad23e98fff85218485f29f62f6bc60663d424df8/cmake-3.31.4-py3-none-win_amd64.whl", hash = "sha256:20be7cdb41903edf85e8a498c4beff8d6854acbb087abfb07c362c738bdf0018", size = 36496715 }, + { url = "https://files.pythonhosted.org/packages/65/26/11a78723364716004928b7bea7d96cf2c72dc3abfaa7c163159110fcb649/cmake-3.31.4-py3-none-win_arm64.whl", hash = "sha256:9479a9255197c49e135df039d8484c69aa63158a06ae9c2d0eb939da2f0f7dff", size = 35559239 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "colorlog" +version = "6.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/7a/359f4d5df2353f26172b3cc39ea32daa39af8de522205f512f458923e677/colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2", size = 16624 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/51/9b208e85196941db2f0654ad0357ca6388ab3ed67efdbfc799f35d1f83aa/colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff", size = 11424 }, +] + +[[package]] +name = "comm" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/a8/fb783cb0abe2b5fded9f55e5703015cdf1c9c85b3669087c538dd15a6a86/comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e", size = 6210 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/75/49e5bfe642f71f272236b5b2d2691cf915a7283cc0ceda56357b61daa538/comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3", size = 7180 }, +] + +[[package]] +name = "contourpy" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/25/c2/fc7193cc5383637ff390a712e88e4ded0452c9fbcf84abe3de5ea3df1866/contourpy-1.3.1.tar.gz", hash = "sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699", size = 13465753 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/80937fe3efe0edacf67c9a20b955139a1a622730042c1ea991956f2704ad/contourpy-1.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a045f341a77b77e1c5de31e74e966537bba9f3c4099b35bf4c2e3939dd54cdab", size = 268466 }, + { url = "https://files.pythonhosted.org/packages/82/1d/e3eaebb4aa2d7311528c048350ca8e99cdacfafd99da87bc0a5f8d81f2c2/contourpy-1.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:500360b77259914f7805af7462e41f9cb7ca92ad38e9f94d6c8641b089338124", size = 253314 }, + { url = "https://files.pythonhosted.org/packages/de/f3/d796b22d1a2b587acc8100ba8c07fb7b5e17fde265a7bb05ab967f4c935a/contourpy-1.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2f926efda994cdf3c8d3fdb40b9962f86edbc4457e739277b961eced3d0b4c1", size = 312003 }, + { url = "https://files.pythonhosted.org/packages/bf/f5/0e67902bc4394daee8daa39c81d4f00b50e063ee1a46cb3938cc65585d36/contourpy-1.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adce39d67c0edf383647a3a007de0a45fd1b08dedaa5318404f1a73059c2512b", size = 351896 }, + { url = "https://files.pythonhosted.org/packages/1f/d6/e766395723f6256d45d6e67c13bb638dd1fa9dc10ef912dc7dd3dcfc19de/contourpy-1.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abbb49fb7dac584e5abc6636b7b2a7227111c4f771005853e7d25176daaf8453", size = 320814 }, + { url = "https://files.pythonhosted.org/packages/a9/57/86c500d63b3e26e5b73a28b8291a67c5608d4aa87ebd17bd15bb33c178bc/contourpy-1.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0cffcbede75c059f535725c1680dfb17b6ba8753f0c74b14e6a9c68c29d7ea3", size = 324969 }, + { url = "https://files.pythonhosted.org/packages/b8/62/bb146d1289d6b3450bccc4642e7f4413b92ebffd9bf2e91b0404323704a7/contourpy-1.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab29962927945d89d9b293eabd0d59aea28d887d4f3be6c22deaefbb938a7277", size = 1265162 }, + { url = "https://files.pythonhosted.org/packages/18/04/9f7d132ce49a212c8e767042cc80ae390f728060d2eea47058f55b9eff1c/contourpy-1.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:974d8145f8ca354498005b5b981165b74a195abfae9a8129df3e56771961d595", size = 1324328 }, + { url = "https://files.pythonhosted.org/packages/46/23/196813901be3f97c83ababdab1382e13e0edc0bb4e7b49a7bff15fcf754e/contourpy-1.3.1-cp310-cp310-win32.whl", hash = "sha256:ac4578ac281983f63b400f7fe6c101bedc10651650eef012be1ccffcbacf3697", size = 173861 }, + { url = "https://files.pythonhosted.org/packages/e0/82/c372be3fc000a3b2005061ca623a0d1ecd2eaafb10d9e883a2fc8566e951/contourpy-1.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:174e758c66bbc1c8576992cec9599ce8b6672b741b5d336b5c74e35ac382b18e", size = 218566 }, + { url = "https://files.pythonhosted.org/packages/12/bb/11250d2906ee2e8b466b5f93e6b19d525f3e0254ac8b445b56e618527718/contourpy-1.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e8b974d8db2c5610fb4e76307e265de0edb655ae8169e8b21f41807ccbeec4b", size = 269555 }, + { url = "https://files.pythonhosted.org/packages/67/71/1e6e95aee21a500415f5d2dbf037bf4567529b6a4e986594d7026ec5ae90/contourpy-1.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:20914c8c973f41456337652a6eeca26d2148aa96dd7ac323b74516988bea89fc", size = 254549 }, + { url = "https://files.pythonhosted.org/packages/31/2c/b88986e8d79ac45efe9d8801ae341525f38e087449b6c2f2e6050468a42c/contourpy-1.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19d40d37c1c3a4961b4619dd9d77b12124a453cc3d02bb31a07d58ef684d3d86", size = 313000 }, + { url = "https://files.pythonhosted.org/packages/c4/18/65280989b151fcf33a8352f992eff71e61b968bef7432fbfde3a364f0730/contourpy-1.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:113231fe3825ebf6f15eaa8bc1f5b0ddc19d42b733345eae0934cb291beb88b6", size = 352925 }, + { url = "https://files.pythonhosted.org/packages/f5/c7/5fd0146c93220dbfe1a2e0f98969293b86ca9bc041d6c90c0e065f4619ad/contourpy-1.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dbbc03a40f916a8420e420d63e96a1258d3d1b58cbdfd8d1f07b49fcbd38e85", size = 323693 }, + { url = "https://files.pythonhosted.org/packages/85/fc/7fa5d17daf77306840a4e84668a48ddff09e6bc09ba4e37e85ffc8e4faa3/contourpy-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a04ecd68acbd77fa2d39723ceca4c3197cb2969633836ced1bea14e219d077c", size = 326184 }, + { url = "https://files.pythonhosted.org/packages/ef/e7/104065c8270c7397c9571620d3ab880558957216f2b5ebb7e040f85eeb22/contourpy-1.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c414fc1ed8ee1dbd5da626cf3710c6013d3d27456651d156711fa24f24bd1291", size = 1268031 }, + { url = "https://files.pythonhosted.org/packages/e2/4a/c788d0bdbf32c8113c2354493ed291f924d4793c4a2e85b69e737a21a658/contourpy-1.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:31c1b55c1f34f80557d3830d3dd93ba722ce7e33a0b472cba0ec3b6535684d8f", size = 1325995 }, + { url = "https://files.pythonhosted.org/packages/a6/e6/a2f351a90d955f8b0564caf1ebe4b1451a3f01f83e5e3a414055a5b8bccb/contourpy-1.3.1-cp311-cp311-win32.whl", hash = "sha256:f611e628ef06670df83fce17805c344710ca5cde01edfdc72751311da8585375", size = 174396 }, + { url = "https://files.pythonhosted.org/packages/a8/7e/cd93cab453720a5d6cb75588cc17dcdc08fc3484b9de98b885924ff61900/contourpy-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:b2bdca22a27e35f16794cf585832e542123296b4687f9fd96822db6bae17bfc9", size = 219787 }, + { url = "https://files.pythonhosted.org/packages/3e/4f/e56862e64b52b55b5ddcff4090085521fc228ceb09a88390a2b103dccd1b/contourpy-1.3.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b457d6430833cee8e4b8e9b6f07aa1c161e5e0d52e118dc102c8f9bd7dd060d6", size = 265605 }, + { url = "https://files.pythonhosted.org/packages/b0/2e/52bfeeaa4541889f23d8eadc6386b442ee2470bd3cff9baa67deb2dd5c57/contourpy-1.3.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb76c1a154b83991a3cbbf0dfeb26ec2833ad56f95540b442c73950af2013750", size = 315040 }, + { url = "https://files.pythonhosted.org/packages/52/94/86bfae441707205634d80392e873295652fc313dfd93c233c52c4dc07874/contourpy-1.3.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:44a29502ca9c7b5ba389e620d44f2fbe792b1fb5734e8b931ad307071ec58c53", size = 218221 }, +] + +[[package]] +name = "coverage" +version = "7.6.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/12/2a2a923edf4ddabdffed7ad6da50d96a5c126dae7b80a33df7310e329a1e/coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78", size = 207982 }, + { url = "https://files.pythonhosted.org/packages/ca/49/6985dbca9c7be3f3cb62a2e6e492a0c88b65bf40579e16c71ae9c33c6b23/coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c", size = 208414 }, + { url = "https://files.pythonhosted.org/packages/35/93/287e8f1d1ed2646f4e0b2605d14616c9a8a2697d0d1b453815eb5c6cebdb/coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a", size = 236860 }, + { url = "https://files.pythonhosted.org/packages/de/e1/cfdb5627a03567a10031acc629b75d45a4ca1616e54f7133ca1fa366050a/coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165", size = 234758 }, + { url = "https://files.pythonhosted.org/packages/6d/85/fc0de2bcda3f97c2ee9fe8568f7d48f7279e91068958e5b2cc19e0e5f600/coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988", size = 235920 }, + { url = "https://files.pythonhosted.org/packages/79/73/ef4ea0105531506a6f4cf4ba571a214b14a884630b567ed65b3d9c1975e1/coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5", size = 234986 }, + { url = "https://files.pythonhosted.org/packages/c6/4d/75afcfe4432e2ad0405c6f27adeb109ff8976c5e636af8604f94f29fa3fc/coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3", size = 233446 }, + { url = "https://files.pythonhosted.org/packages/86/5b/efee56a89c16171288cafff022e8af44f8f94075c2d8da563c3935212871/coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5", size = 234566 }, + { url = "https://files.pythonhosted.org/packages/f2/db/67770cceb4a64d3198bf2aa49946f411b85ec6b0a9b489e61c8467a4253b/coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244", size = 210675 }, + { url = "https://files.pythonhosted.org/packages/8d/27/e8bfc43f5345ec2c27bc8a1fa77cdc5ce9dcf954445e11f14bb70b889d14/coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e", size = 211518 }, + { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, + { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, + { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, + { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, + { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, + { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, + { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, + { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, + { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, + { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, + { url = "https://files.pythonhosted.org/packages/a1/70/de81bfec9ed38a64fc44a77c7665e20ca507fc3265597c28b0d989e4082e/coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f", size = 200223 }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] + +[[package]] +name = "cssutils" +version = "2.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/9f/329d26121fe165be44b1dfff21aa0dc348f04633931f1d20ed6cf448a236/cssutils-2.11.1.tar.gz", hash = "sha256:0563a76513b6af6eebbe788c3bf3d01c920e46b3f90c8416738c5cfc773ff8e2", size = 711657 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/ec/bb273b7208c606890dc36540fe667d06ce840a6f62f9fae7e658fcdc90fb/cssutils-2.11.1-py3-none-any.whl", hash = "sha256:a67bfdfdff4f3867fab43698ec4897c1a828eca5973f4073321b3bccaf1199b1", size = 385747 }, +] + +[[package]] +name = "cupy-cuda11x" +version = "13.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastrlock" }, + { name = "numpy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/1b/3afbaea2b78114c82b33ecc9affc79b7d9f4899945940b9b50790c93fd33/cupy_cuda11x-13.3.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:ef854f0c63525d8163ab7af19f503d964de9dde0dd1cf9ea806a6ecb302cdce3", size = 109578634 }, + { url = "https://files.pythonhosted.org/packages/82/94/1da4205249baa861ac848dcbc36208a0b08f2ba2c414634525e53dabf818/cupy_cuda11x-13.3.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:54bf12a6663d0471e3e37e62972add348c5263ce803688f48bbfab1b20ebdb02", size = 96619611 }, + { url = "https://files.pythonhosted.org/packages/3f/ef/6924de40b67d4a0176e9c27f1ea9b0c8700935424473afd104cf72b36eb0/cupy_cuda11x-13.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:972d133efa2af80bb8ef321858ffe7cabc3abf8f58bcc4f13541dd497c05077d", size = 76006133 }, + { url = "https://files.pythonhosted.org/packages/4d/2d/9f01f25a81535572050f77ca618a54d8ad08afc13963c9fc57c162931e42/cupy_cuda11x-13.3.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:766ef1558a3ed967d5f092829bfb99edbcfaf75224925e1fb1a9f531e1e79f36", size = 110899612 }, + { url = "https://files.pythonhosted.org/packages/96/8f/b92bbf066ed86ec9dbeb969a5d6e6b6597bf0bab730f9e8b4c589f7cf198/cupy_cuda11x-13.3.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:77a81fa48d1a392b731885555a53cf2febde39cc33db55f2d78ba64b5ef4689b", size = 97172154 }, + { url = "https://files.pythonhosted.org/packages/08/94/113cc947b06b45b950979441a4f12f257b203d9a33796b1dbe6b82a2c36c/cupy_cuda11x-13.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:a8e8b7f7f73677afe2f70c38562f01f82688e43147550b3e192a5a2206e17fe1", size = 75976673 }, +] + +[[package]] +name = "cupy-cuda12x" +version = "13.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastrlock" }, + { name = "numpy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/60/dc268d1d9c5fdde4673a463feff5e9c70c59f477e647b54b501f65deef60/cupy_cuda12x-13.3.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:674488e990998042cc54d2486d3c37cae80a12ba3787636be5a10b9446dd6914", size = 103601326 }, + { url = "https://files.pythonhosted.org/packages/7a/a9/1e19ecf008011df2935d038f26f721f22f2804c00077fc024f088e0996e6/cupy_cuda12x-13.3.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:cf4a2a0864364715881b50012927e88bd7ec1e6f1de3987970870861ae5ed25e", size = 90619949 }, + { url = "https://files.pythonhosted.org/packages/ce/6b/e77e3fc20648d323021f55d4e0fafc5572eff50c37750d6aeae868e110d8/cupy_cuda12x-13.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7c0dc8c49d271d1c03e49a5d6c8e42e8fee3114b10f269a5ecc387731d693eaa", size = 69594183 }, + { url = "https://files.pythonhosted.org/packages/95/c9/0b88c015e98aad808c18f938267585d79e6211fe08650e0de7132e235e40/cupy_cuda12x-13.3.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:c0cc095b9a3835fd5db66c45ed3c58ecdc5a3bb14e53e1defbfd4a0ce5c8ecdb", size = 104925909 }, + { url = "https://files.pythonhosted.org/packages/8c/1f/596803c35833c01a41da21c6a7bb552f1ed56d807090ddc6727c8f396d7d/cupy_cuda12x-13.3.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:a0e3bead04e502ebde515f0343444ca3f4f7aed09cbc3a316a946cba97f2ea66", size = 91172049 }, + { url = "https://files.pythonhosted.org/packages/d0/a8/5b5929830d2da94608d8126bafe2c52d69929a197fd8698ac09142c068ba/cupy_cuda12x-13.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:5f11df1149c7219858b27e4c8be92cb4eaf7364c94af6b78c40dffb98050a61f", size = 69564719 }, +] + +[[package]] +name = "cupy-rocm-4-3" +version = "13.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastrlock" }, + { name = "numpy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/16/7fd4bc8a8f1a4697f76e52c13f348f284fcc5c37195efd7e4c5d0eb2b15c/cupy_rocm_4_3-13.3.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:fc6b93be093bcea8b820baed856b61efc5c8cb09b02ebdc890431655714366ad", size = 41259087 }, + { url = "https://files.pythonhosted.org/packages/2e/ee/e893b0fdc6b347d8d65024442e5baf5ae13ee92c1364152e8f343906793d/cupy_rocm_4_3-13.3.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:f5e6886f1750810ddc3d261adf84d98b4d42f1d3cb2be5b7f5da181c8bf1593d", size = 41775360 }, +] + +[[package]] +name = "cupy-rocm-5-0" +version = "13.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastrlock" }, + { name = "numpy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/2e/6e4ecd65f5158808a54ef75d90fc7a884afb55bd405c4a7dbc34bb4a8f96/cupy_rocm_5_0-13.3.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:d4c370441f7778b00f3ab80d6f0d669ea0215b6e96bbed9663ecce7ffce83fa9", size = 60056031 }, + { url = "https://files.pythonhosted.org/packages/08/52/8b5b6b32c84616989a2a84f02d9f4ca39d812de9f630276a664f321840bf/cupy_rocm_5_0-13.3.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:00907762735d182737bee317f532dc381337fb8e978bd846acb268df463b2d7b", size = 60576552 }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 }, +] + +[[package]] +name = "cython" +version = "3.0.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/4d/b720d6000f4ca77f030bd70f12550820f0766b568e43f11af7f7ad9061aa/cython-3.0.11.tar.gz", hash = "sha256:7146dd2af8682b4ca61331851e6aebce9fe5158e75300343f80c07ca80b1faff", size = 2755544 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/7f/ab5796a0951328d7818b771c36fe7e1a2077cffa28c917d9fa4a642728c3/Cython-3.0.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:44292aae17524abb4b70a25111fe7dec1a0ad718711d47e3786a211d5408fdaa", size = 3100879 }, + { url = "https://files.pythonhosted.org/packages/d8/3b/67480e609537e9fc899864847910ded481b82d033fea1b7fcf85893a2fc4/Cython-3.0.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75d45fbc20651c1b72e4111149fed3b33d270b0a4fb78328c54d965f28d55e1", size = 3461957 }, + { url = "https://files.pythonhosted.org/packages/f0/89/b1ae45689abecca777f95462781a76e67ff46b55495a481ec5a73a739994/Cython-3.0.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d89a82937ce4037f092e9848a7bbcc65bc8e9fc9aef2bb74f5c15e7d21a73080", size = 3627062 }, + { url = "https://files.pythonhosted.org/packages/44/77/a651da74d5d41c6045bbe0b6990b1515bf4850cd7a8d8580333c90dfce2e/Cython-3.0.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ea2e7e2d3bc0d8630dafe6c4a5a89485598ff8a61885b74f8ed882597efd5", size = 3680431 }, + { url = "https://files.pythonhosted.org/packages/59/45/60e7e8db93c3eb8b2af8c64020c1fa502e355f4b762886a24d46e433f395/Cython-3.0.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cee29846471ce60226b18e931d8c1c66a158db94853e3e79bc2da9bd22345008", size = 3497314 }, + { url = "https://files.pythonhosted.org/packages/f8/0b/6919025958926625319f83523ee7f45e7e7ae516b8054dcff6eb710daf32/Cython-3.0.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eeb6860b0f4bfa402de8929833fe5370fa34069c7ebacb2d543cb017f21fb891", size = 3709091 }, + { url = "https://files.pythonhosted.org/packages/52/3c/c21b9b9271dfaa46fa2938de730f62fc94b9c2ec25ec400585e372f35dcd/Cython-3.0.11-cp310-cp310-win32.whl", hash = "sha256:3699391125ab344d8d25438074d1097d9ba0fb674d0320599316cfe7cf5f002a", size = 2576110 }, + { url = "https://files.pythonhosted.org/packages/f9/de/19fdd1c7a52e0534bf5f544e0346c15d71d20338dbd013117f763b94613f/Cython-3.0.11-cp310-cp310-win_amd64.whl", hash = "sha256:d02f4ebe15aac7cdacce1a628e556c1983f26d140fd2e0ac5e0a090e605a2d38", size = 2776386 }, + { url = "https://files.pythonhosted.org/packages/f8/73/e55be864199cd674cb3426a052726c205589b1ac66fb0090e7fe793b60b3/Cython-3.0.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75ba1c70b6deeaffbac123856b8d35f253da13552207aa969078611c197377e4", size = 3113599 }, + { url = "https://files.pythonhosted.org/packages/09/c9/537108d0980beffff55336baaf8b34162ad0f3f33ededcb5db07069bc8ef/Cython-3.0.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af91497dc098718e634d6ec8f91b182aea6bb3690f333fc9a7777bc70abe8810", size = 3441131 }, + { url = "https://files.pythonhosted.org/packages/93/03/e330b241ad8aa12bb9d98b58fb76d4eb7dcbe747479aab5c29fce937b9e7/Cython-3.0.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3999fb52d3328a6a5e8c63122b0a8bd110dfcdb98dda585a3def1426b991cba7", size = 3595065 }, + { url = "https://files.pythonhosted.org/packages/4a/84/a3c40f2c0439d425daa5aa4e3a6fdbbb41341a14a6fd97f94906f528d9a4/Cython-3.0.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d566a4e09b8979be8ab9f843bac0dd216c81f5e5f45661a9b25cd162ed80508c", size = 3641667 }, + { url = "https://files.pythonhosted.org/packages/6d/93/bdb61e0254ed8f1d21a14088a473584ecb1963d68dba5682158aa45c70ef/Cython-3.0.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:46aec30f217bdf096175a1a639203d44ac73a36fe7fa3dd06bd012e8f39eca0f", size = 3503650 }, + { url = "https://files.pythonhosted.org/packages/f8/62/0da548144c71176155ff5355c4cc40fb28b9effe22e830b55cec8072bdf2/Cython-3.0.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ddd1fe25af330f4e003421636746a546474e4ccd8f239f55d2898d80983d20ed", size = 3709662 }, + { url = "https://files.pythonhosted.org/packages/56/d3/d9c9eaf3611a9fe5256266d07b6a5f9069aa84d20d9f6aa5824289513315/Cython-3.0.11-cp311-cp311-win32.whl", hash = "sha256:221de0b48bf387f209003508e602ce839a80463522fc6f583ad3c8d5c890d2c1", size = 2577870 }, + { url = "https://files.pythonhosted.org/packages/fd/10/236fcc0306f85a2db1b8bc147aea714b66a2f27bac4d9e09e5b2c5d5dcca/Cython-3.0.11-cp311-cp311-win_amd64.whl", hash = "sha256:3ff8ac1f0ecd4f505db4ab051e58e4531f5d098b6ac03b91c3b902e8d10c67b3", size = 2785053 }, + { url = "https://files.pythonhosted.org/packages/43/39/bdbec9142bc46605b54d674bf158a78b191c2b75be527c6dcf3e6dfe90b8/Cython-3.0.11-py2.py3-none-any.whl", hash = "sha256:0e25f6425ad4a700d7f77cd468da9161e63658837d1bc34861a9861a4ef6346d", size = 1171267 }, +] + +[[package]] +name = "cytoolz" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "toolz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/f9/3243eed3a6545c2a33a21f74f655e3fcb5d2192613cd3db81a93369eb339/cytoolz-1.0.1.tar.gz", hash = "sha256:89cc3161b89e1bb3ed7636f74ed2e55984fd35516904fc878cae216e42b2c7d6", size = 626652 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d9/f13d66c16cff1fa1cb6c234698029877c456f35f577ef274aba3b86e7c51/cytoolz-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cec9af61f71fc3853eb5dca3d42eb07d1f48a4599fa502cbe92adde85f74b042", size = 403515 }, + { url = "https://files.pythonhosted.org/packages/4b/2d/4cdf848a69300c7d44984f2ebbebb3b8576e5449c8dea157298f3bdc4da3/cytoolz-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:140bbd649dbda01e91add7642149a5987a7c3ccc251f2263de894b89f50b6608", size = 383936 }, + { url = "https://files.pythonhosted.org/packages/72/a4/ccfdd3f0ed9cc818f734b424261f6018fc61e3ec833bf85225a9aca0d994/cytoolz-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e90124bdc42ff58b88cdea1d24a6bc5f776414a314cc4d94f25c88badb3a16d1", size = 1934569 }, + { url = "https://files.pythonhosted.org/packages/50/fc/38d5344fa595683ad10dc819cfc1d8b9d2b3391ccf3e8cb7bab4899a01f5/cytoolz-1.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e74801b751e28f7c5cc3ad264c123954a051f546f2fdfe089f5aa7a12ccfa6da", size = 2015129 }, + { url = "https://files.pythonhosted.org/packages/28/29/75261748dc54a20a927f33641f4e9aac674cfc6d3fbd4f332e10d0b37639/cytoolz-1.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:582dad4545ddfb5127494ef23f3fa4855f1673a35d50c66f7638e9fb49805089", size = 2000506 }, + { url = "https://files.pythonhosted.org/packages/00/ae/e4ead004cc2698281d153c4a5388638d67cdb5544d6d6cc1e5b3db2bd2a3/cytoolz-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7bd0618e16efe03bd12f19c2a26a27e6e6b75d7105adb7be1cd2a53fa755d8", size = 1957537 }, + { url = "https://files.pythonhosted.org/packages/4a/ff/4f3aa07f4f47701f7f63df60ce0a5669fa09c256c3d4a33503a9414ea5cc/cytoolz-1.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d74cca6acf1c4af58b2e4a89cc565ed61c5e201de2e434748c93e5a0f5c541a5", size = 1863331 }, + { url = "https://files.pythonhosted.org/packages/a2/29/654f57f2a9b8e9765a4ab876765f64f94530b61fc6471a07feea42ece6d4/cytoolz-1.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:823a3763828d8d457f542b2a45d75d6b4ced5e470b5c7cf2ed66a02f508ed442", size = 1849938 }, + { url = "https://files.pythonhosted.org/packages/bc/7b/11f457db6b291060a98315ab2c7198077d8bddeeebe5f7126d9dad98cc54/cytoolz-1.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:51633a14e6844c61db1d68c1ffd077cf949f5c99c60ed5f1e265b9e2966f1b52", size = 1852345 }, + { url = "https://files.pythonhosted.org/packages/6b/92/0dccc96ce0323be236d404f5084479b79b747fa0e74e43a270e95868b5f9/cytoolz-1.0.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f3ec9b01c45348f1d0d712507d54c2bfd69c62fbd7c9ef555c9d8298693c2432", size = 1989877 }, + { url = "https://files.pythonhosted.org/packages/a3/c8/1c5203a81200bae51aa8f7b5fad613f695bf1afa03f16251ca23ecb2ef9f/cytoolz-1.0.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1855022b712a9c7a5bce354517ab4727a38095f81e2d23d3eabaf1daeb6a3b3c", size = 1994492 }, + { url = "https://files.pythonhosted.org/packages/e2/8a/04bc193c4d7ced8ef6bb62cdcd0bf40b5e5eb26586ed2cfb4433ec7dfd0a/cytoolz-1.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9930f7288c4866a1dc1cc87174f0c6ff4cad1671eb1f6306808aa6c445857d78", size = 1896077 }, + { url = "https://files.pythonhosted.org/packages/21/a5/bee63a58f51d2c74856db66e6119a014464ff8cb1c9387fa4bd2d94e49b0/cytoolz-1.0.1-cp310-cp310-win32.whl", hash = "sha256:a9baad795d72fadc3445ccd0f122abfdbdf94269157e6d6d4835636dad318804", size = 322135 }, + { url = "https://files.pythonhosted.org/packages/e8/16/7abfb1685e8b7f2838264551ee33651748994813f566ac4c3d737dfe90e5/cytoolz-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:ad95b386a84e18e1f6136f6d343d2509d4c3aae9f5a536f3dc96808fcc56a8cf", size = 363599 }, + { url = "https://files.pythonhosted.org/packages/dc/ea/8131ae39119820b8867cddc23716fa9f681f2b3bbce6f693e68dfb36b55b/cytoolz-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d958d4f04d9d7018e5c1850790d9d8e68b31c9a2deebca74b903706fdddd2b6", size = 406162 }, + { url = "https://files.pythonhosted.org/packages/26/18/3d9bd4c146f6ea6e51300c242b20cb416966b21d481dac230e1304f1e54b/cytoolz-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f445b8b731fc0ecb1865b8e68a070084eb95d735d04f5b6c851db2daf3048ab", size = 384961 }, + { url = "https://files.pythonhosted.org/packages/e4/73/9034827907c7f85c7c484c9494e905d022fb8174526004e9ef332570349e/cytoolz-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f546a96460a7e28eb2ec439f4664fa646c9b3e51c6ebad9a59d3922bbe65e30", size = 2091698 }, + { url = "https://files.pythonhosted.org/packages/74/af/d5c2733b0fde1a08254ff1a8a8d567874040c9eb1606363cfebc0713c73f/cytoolz-1.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0317681dd065532d21836f860b0563b199ee716f55d0c1f10de3ce7100c78a3b", size = 2188452 }, + { url = "https://files.pythonhosted.org/packages/6a/bb/77c71fa9c217260b4056a732d754748903423c2cdd82a673d6064741e375/cytoolz-1.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c0ef52febd5a7821a3fd8d10f21d460d1a3d2992f724ba9c91fbd7a96745d41", size = 2174203 }, + { url = "https://files.pythonhosted.org/packages/fc/a9/a5b4a3ff5d22faa1b60293bfe97362e2caf4a830c26d37ab5557f60d04b2/cytoolz-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5ebaf419acf2de73b643cf96108702b8aef8e825cf4f63209ceb078d5fbbbfd", size = 2099831 }, + { url = "https://files.pythonhosted.org/packages/35/08/7f6869ea1ff31ce5289a7d58d0e7090acfe7058baa2764473048ff61ea3c/cytoolz-1.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f7f04eeb4088947585c92d6185a618b25ad4a0f8f66ea30c8db83cf94a425e3", size = 1996744 }, + { url = "https://files.pythonhosted.org/packages/46/b4/9ac424c994b51763fd1bbed62d95f8fba8fa0e45c8c3c583904fdaf8f51d/cytoolz-1.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f61928803bb501c17914b82d457c6f50fe838b173fb40d39c38d5961185bd6c7", size = 2013733 }, + { url = "https://files.pythonhosted.org/packages/3e/99/03009765c4b87d742d5b5a8670abb56a8c7ede033c2cdaa4be8662d3b001/cytoolz-1.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d2960cb4fa01ccb985ad1280db41f90dc97a80b397af970a15d5a5de403c8c61", size = 1994850 }, + { url = "https://files.pythonhosted.org/packages/40/9a/8458af9a5557e177ea42f8cf7e477bede518b0bbef564e28c4151feaa52c/cytoolz-1.0.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2b407cc3e9defa8df5eb46644f6f136586f70ba49eba96f43de67b9a0984fd3", size = 2155352 }, + { url = "https://files.pythonhosted.org/packages/5e/5c/2a701423e001fcbec288b4f3fc2bf67557d114c2388237fc1ae67e1e2686/cytoolz-1.0.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8245f929144d4d3bd7b972c9593300195c6cea246b81b4c46053c48b3f044580", size = 2163515 }, + { url = "https://files.pythonhosted.org/packages/36/16/ee2e06e65d9d533bc05cd52a0b355ba9072fc8f60d77289e529c6d2e3750/cytoolz-1.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e37385db03af65763933befe89fa70faf25301effc3b0485fec1c15d4ce4f052", size = 2054431 }, + { url = "https://files.pythonhosted.org/packages/d8/d5/2fac8315f210fa1bc7106e27c19e1211580aa25bb7fa17dfd79505e5baf2/cytoolz-1.0.1-cp311-cp311-win32.whl", hash = "sha256:50f9c530f83e3e574fc95c264c3350adde8145f4f8fc8099f65f00cc595e5ead", size = 322004 }, + { url = "https://files.pythonhosted.org/packages/a9/9e/0b70b641850a95f9ff90adde9d094a4b1d81ec54dadfd97fec0a2aaf440e/cytoolz-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:b7f6b617454b4326af7bd3c7c49b0fc80767f134eb9fd6449917a058d17a0e3c", size = 365358 }, + { url = "https://files.pythonhosted.org/packages/d9/f7/ef2a10daaec5c0f7d781d50758c6187eee484256e356ae8ef178d6c48497/cytoolz-1.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:83d19d55738ad9c60763b94f3f6d3c6e4de979aeb8d76841c1401081e0e58d96", size = 345702 }, + { url = "https://files.pythonhosted.org/packages/c8/14/53c84adddedb67ff1546abb86fea04d26e24298c3ceab8436d20122ed0b9/cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f112a71fad6ea824578e6393765ce5c054603afe1471a5c753ff6c67fd872d10", size = 385695 }, + { url = "https://files.pythonhosted.org/packages/bd/80/3ae356c5e7b8d7dc7d1adb52f6932fee85cd748ed4e1217c269d2dfd610f/cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a515df8f8aa6e1eaaf397761a6e4aff2eef73b5f920aedf271416d5471ae5ee", size = 406261 }, + { url = "https://files.pythonhosted.org/packages/0c/31/8e43761ffc82d90bf9cab7e0959712eedcd1e33c211397e143dd42d7af57/cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92c398e7b7023460bea2edffe5fcd0a76029580f06c3f6938ac3d198b47156f3", size = 397207 }, + { url = "https://files.pythonhosted.org/packages/d1/b9/fe9da37090b6444c65f848a83e390f87d8cb43d6a4df46de1556ad7e5ceb/cytoolz-1.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3237e56211e03b13df47435b2369f5df281e02b04ad80a948ebd199b7bc10a47", size = 343358 }, +] + +[[package]] +name = "dace" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aenum" }, + { name = "astunparse" }, + { name = "dill" }, + { name = "fparser" }, + { name = "networkx" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "ply" }, + { name = "pyreadline", marker = "platform_system == 'Windows' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "pyyaml" }, + { name = "sympy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b4/67/fb1be2673868ee1f08e9c7bacc0b9b77d2bd5ff17ab47896f20006a2a1a5/dace-1.0.1.tar.gz", hash = "sha256:6f7a5defb082ed4f1a81f857d4268ed2bb606f6d9ea9c28d2831d1151e3a80f7", size = 5801727 } + +[[package]] +name = "debugpy" +version = "1.8.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/25/c74e337134edf55c4dfc9af579eccb45af2393c40960e2795a94351e8140/debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce", size = 1641122 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/19/dd58334c0a1ec07babf80bf29fb8daf1a7ca4c1a3bbe61548e40616ac087/debugpy-1.8.12-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:a2ba7ffe58efeae5b8fad1165357edfe01464f9aef25e814e891ec690e7dd82a", size = 2076091 }, + { url = "https://files.pythonhosted.org/packages/4c/37/bde1737da15f9617d11ab7b8d5267165f1b7dae116b2585a6643e89e1fa2/debugpy-1.8.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbd4149c4fc5e7d508ece083e78c17442ee13b0e69bfa6bd63003e486770f45", size = 3560717 }, + { url = "https://files.pythonhosted.org/packages/d9/ca/bc67f5a36a7de072908bc9e1156c0f0b272a9a2224cf21540ab1ffd71a1f/debugpy-1.8.12-cp310-cp310-win32.whl", hash = "sha256:b202f591204023b3ce62ff9a47baa555dc00bb092219abf5caf0e3718ac20e7c", size = 5180672 }, + { url = "https://files.pythonhosted.org/packages/c1/b9/e899c0a80dfa674dbc992f36f2b1453cd1ee879143cdb455bc04fce999da/debugpy-1.8.12-cp310-cp310-win_amd64.whl", hash = "sha256:9649eced17a98ce816756ce50433b2dd85dfa7bc92ceb60579d68c053f98dff9", size = 5212702 }, + { url = "https://files.pythonhosted.org/packages/af/9f/5b8af282253615296264d4ef62d14a8686f0dcdebb31a669374e22fff0a4/debugpy-1.8.12-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:36f4829839ef0afdfdd208bb54f4c3d0eea86106d719811681a8627ae2e53dd5", size = 2174643 }, + { url = "https://files.pythonhosted.org/packages/ef/31/f9274dcd3b0f9f7d1e60373c3fa4696a585c55acb30729d313bb9d3bcbd1/debugpy-1.8.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a28ed481d530e3138553be60991d2d61103ce6da254e51547b79549675f539b7", size = 3133457 }, + { url = "https://files.pythonhosted.org/packages/ab/ca/6ee59e9892e424477e0c76e3798046f1fd1288040b927319c7a7b0baa484/debugpy-1.8.12-cp311-cp311-win32.whl", hash = "sha256:4ad9a94d8f5c9b954e0e3b137cc64ef3f579d0df3c3698fe9c3734ee397e4abb", size = 5106220 }, + { url = "https://files.pythonhosted.org/packages/d5/1a/8ab508ab05ede8a4eae3b139bbc06ea3ca6234f9e8c02713a044f253be5e/debugpy-1.8.12-cp311-cp311-win_amd64.whl", hash = "sha256:4703575b78dd697b294f8c65588dc86874ed787b7348c65da70cfc885efdf1e1", size = 5130481 }, + { url = "https://files.pythonhosted.org/packages/38/c4/5120ad36405c3008f451f94b8f92ef1805b1e516f6ff870f331ccb3c4cc0/debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6", size = 5229490 }, +] + +[[package]] +name = "decorator" +version = "5.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/0c/8d907af351aa16b42caae42f9d6aa37b900c67308052d10fdce809f8d952/decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", size = 35016 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 }, +] + +[[package]] +name = "deepdiff" +version = "8.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "orderly-set" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/4b/ce2d3a36f77186d7dbca0f10b33e6a1c0eee390d9434960d2a14e2736b52/deepdiff-8.1.1.tar.gz", hash = "sha256:dd7bc7d5c8b51b5b90f01b0e2fe23c801fd8b4c6a7ee7e31c5a3c3663fcc7ceb", size = 433560 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/f7/2df72b55635926872b947203aacbe7e1109a51929aec8ebfef8c4a348eb5/deepdiff-8.1.1-py3-none-any.whl", hash = "sha256:b0231fa3afb0f7184e82535f2b4a36636442ed21e94a0cf3aaa7982157e7ebca", size = 84655 }, +] + +[[package]] +name = "devtools" +version = "0.12.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/84/75/b78198620640d394bc435c17bb49db18419afdd6cfa3ed8bcfe14034ec80/devtools-0.12.2.tar.gz", hash = "sha256:efceab184cb35e3a11fa8e602cc4fadacaa2e859e920fc6f87bf130b69885507", size = 75005 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/ae/afb1487556e2dc827a17097aac8158a25b433a345386f0e249f6d2694ccb/devtools-0.12.2-py3-none-any.whl", hash = "sha256:c366e3de1df4cdd635f1ad8cbcd3af01a384d7abda71900e68d43b04eb6aaca7", size = 19411 }, +] + +[[package]] +name = "dict2css" +version = "0.3.0.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cssutils" }, + { name = "domdf-python-tools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/24/eb/776eef1f1aa0188c0fc165c3a60b71027539f71f2eedc43ad21b060e9c39/dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719", size = 7845 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/47/290daabcf91628f4fc0e17c75a1690b354ba067066cd14407712600e609f/dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d", size = 25647 }, +] + +[[package]] +name = "dill" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/43/86fe3f9e130c4137b0f1b50784dd70a5087b911fe07fa81e53e0c4c47fea/dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c", size = 187000 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a", size = 119418 }, +] + +[[package]] +name = "diskcache" +version = "5.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc", size = 67916 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19", size = 45550 }, +] + +[[package]] +name = "distlib" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, +] + +[[package]] +name = "docutils" +version = "0.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, +] + +[[package]] +name = "domdf-python-tools" +version = "3.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "natsort" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6b/78/974e10c583ba9d2302e748c9585313a7f2c7ba00e4f600324f432e38fe68/domdf_python_tools-3.9.0.tar.gz", hash = "sha256:1f8a96971178333a55e083e35610d7688cd7620ad2b99790164e1fc1a3614c18", size = 103792 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/e9/7447a88b217650a74927d3444a89507986479a69b83741900eddd34167fe/domdf_python_tools-3.9.0-py3-none-any.whl", hash = "sha256:4e1ef365cbc24627d6d1e90cf7d46d8ab8df967e1237f4a26885f6986c78872e", size = 127106 }, +] + +[[package]] +name = "esbonio" +version = "0.16.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "pygls" }, + { name = "pyspellchecker" }, + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/c5/0c89af3da1f3133b53f3ba8ae677ed4d4ddff33eec50dbf32c95e01ed2d2/esbonio-0.16.5.tar.gz", hash = "sha256:acab2e16c6cf8f7232fb04e0d48514ce50566516b1f6fcf669ccf2f247e8b10f", size = 145347 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/ca/a0296fca375d4324f471bb34d2ce8a585b48fb9eae21cf9abe00913eb899/esbonio-0.16.5-py3-none-any.whl", hash = "sha256:04ba926e3603f7b1fde1abc690b47afd60749b64b1029b6bce8e1de0bb284921", size = 170830 }, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + +[[package]] +name = "execnet" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612 }, +] + +[[package]] +name = "executing" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 }, +] + +[[package]] +name = "factory-boy" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "faker" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/3d/8070dde623341401b1c80156583d4c793058fe250450178218bb6e45526c/factory_boy-3.3.1.tar.gz", hash = "sha256:8317aa5289cdfc45f9cae570feb07a6177316c82e34d14df3c2e1f22f26abef0", size = 163924 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/cf/44ec67152f3129d0114c1499dd34f0a0a0faf43d9c2af05bc535746ca482/factory_boy-3.3.1-py2.py3-none-any.whl", hash = "sha256:7b1113c49736e1e9995bc2a18f4dbf2c52cf0f841103517010b1d825712ce3ca", size = 36878 }, +] + +[[package]] +name = "faker" +version = "35.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/18/86fe668976308d09e0178041c3756e646a1f5ddc676aa7fb0cf3cd52f5b9/faker-35.0.0.tar.gz", hash = "sha256:42f2da8cf561e38c72b25e9891168b1e25fec42b6b0b5b0b6cd6041da54af885", size = 1855098 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/fe/40452fb1730b10afa34dfe016097b28baa070ad74a1c1a3512ebed438c08/Faker-35.0.0-py3-none-any.whl", hash = "sha256:926d2301787220e0554c2e39afc4dc535ce4b0a8d0a089657137999f66334ef4", size = 1894841 }, +] + +[[package]] +name = "fastjsonschema" +version = "2.21.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/50/4b769ce1ac4071a1ef6d86b1a3fb56cdc3a37615e8c5519e1af96cdac366/fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4", size = 373939 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/2b/0817a2b257fe88725c25589d89aec060581aabf668707a8d03b2e9e0cb2a/fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667", size = 23924 }, +] + +[[package]] +name = "fastrlock" +version = "0.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/b1/1c3d635d955f2b4bf34d45abf8f35492e04dbd7804e94ce65d9f928ef3ec/fastrlock-0.8.3.tar.gz", hash = "sha256:4af6734d92eaa3ab4373e6c9a1dd0d5ad1304e172b1521733c6c3b3d73c8fa5d", size = 79327 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/02/3f771177380d8690812d5b2b7736dc6b6c8cd1c317e4572e65f823eede08/fastrlock-0.8.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:cc5fa9166e05409f64a804d5b6d01af670979cdb12cd2594f555cb33cdc155bd", size = 55094 }, + { url = "https://files.pythonhosted.org/packages/be/b4/aae7ed94b8122c325d89eb91336084596cebc505dc629b795fcc9629606d/fastrlock-0.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7a77ebb0a24535ef4f167da2c5ee35d9be1e96ae192137e9dc3ff75b8dfc08a5", size = 48220 }, + { url = "https://files.pythonhosted.org/packages/96/87/9807af47617fdd65c68b0fcd1e714542c1d4d3a1f1381f591f1aa7383a53/fastrlock-0.8.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:d51f7fb0db8dab341b7f03a39a3031678cf4a98b18533b176c533c122bfce47d", size = 49551 }, + { url = "https://files.pythonhosted.org/packages/9d/12/e201634810ac9aee59f93e3953cb39f98157d17c3fc9d44900f1209054e9/fastrlock-0.8.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:767ec79b7f6ed9b9a00eb9ff62f2a51f56fdb221c5092ab2dadec34a9ccbfc6e", size = 49398 }, + { url = "https://files.pythonhosted.org/packages/15/a1/439962ed439ff6f00b7dce14927e7830e02618f26f4653424220a646cd1c/fastrlock-0.8.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d6a77b3f396f7d41094ef09606f65ae57feeb713f4285e8e417f4021617ca62", size = 53334 }, + { url = "https://files.pythonhosted.org/packages/b5/9e/1ae90829dd40559ab104e97ebe74217d9da794c4bb43016da8367ca7a596/fastrlock-0.8.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:92577ff82ef4a94c5667d6d2841f017820932bc59f31ffd83e4a2c56c1738f90", size = 52495 }, + { url = "https://files.pythonhosted.org/packages/e5/8c/5e746ee6f3d7afbfbb0d794c16c71bfd5259a4e3fb1dda48baf31e46956c/fastrlock-0.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3df8514086e16bb7c66169156a8066dc152f3be892c7817e85bf09a27fa2ada2", size = 51972 }, + { url = "https://files.pythonhosted.org/packages/76/a7/8b91068f00400931da950f143fa0f9018bd447f8ed4e34bed3fe65ed55d2/fastrlock-0.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:001fd86bcac78c79658bac496e8a17472d64d558cd2227fdc768aa77f877fe40", size = 30946 }, + { url = "https://files.pythonhosted.org/packages/90/9e/647951c579ef74b6541493d5ca786d21a0b2d330c9514ba2c39f0b0b0046/fastrlock-0.8.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:f68c551cf8a34b6460a3a0eba44bd7897ebfc820854e19970c52a76bf064a59f", size = 55233 }, + { url = "https://files.pythonhosted.org/packages/be/91/5f3afba7d14b8b7d60ac651375f50fff9220d6ccc3bef233d2bd74b73ec7/fastrlock-0.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:55d42f6286b9d867370af4c27bc70d04ce2d342fe450c4a4fcce14440514e695", size = 48911 }, + { url = "https://files.pythonhosted.org/packages/d5/7a/e37bd72d7d70a8a551b3b4610d028bd73ff5d6253201d5d3cf6296468bee/fastrlock-0.8.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:bbc3bf96dcbd68392366c477f78c9d5c47e5d9290cb115feea19f20a43ef6d05", size = 50357 }, + { url = "https://files.pythonhosted.org/packages/0d/ef/a13b8bab8266840bf38831d7bf5970518c02603d00a548a678763322d5bf/fastrlock-0.8.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:77ab8a98417a1f467dafcd2226718f7ca0cf18d4b64732f838b8c2b3e4b55cb5", size = 50222 }, + { url = "https://files.pythonhosted.org/packages/01/e2/5e5515562b2e9a56d84659377176aef7345da2c3c22909a1897fe27e14dd/fastrlock-0.8.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04bb5eef8f460d13b8c0084ea5a9d3aab2c0573991c880c0a34a56bb14951d30", size = 54553 }, + { url = "https://files.pythonhosted.org/packages/c0/8f/65907405a8cdb2fc8beaf7d09a9a07bb58deff478ff391ca95be4f130b70/fastrlock-0.8.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c9d459ce344c21ff03268212a1845aa37feab634d242131bc16c2a2355d5f65", size = 53362 }, + { url = "https://files.pythonhosted.org/packages/ec/b9/ae6511e52738ba4e3a6adb7c6a20158573fbc98aab448992ece25abb0b07/fastrlock-0.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33e6fa4af4f3af3e9c747ec72d1eadc0b7ba2035456c2afb51c24d9e8a56f8fd", size = 52836 }, + { url = "https://files.pythonhosted.org/packages/88/3e/c26f8192c93e8e43b426787cec04bb46ac36e72b1033b7fe5a9267155fdf/fastrlock-0.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:5e5f1665d8e70f4c5b4a67f2db202f354abc80a321ce5a26ac1493f055e3ae2c", size = 31046 }, +] + +[[package]] +name = "filelock" +version = "3.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 }, +] + +[[package]] +name = "fonttools" +version = "4.55.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/55/55/3b1566c6186a5e58a17a19ad63195f87c6ca4039ef10ff5318a1b9fc5639/fonttools-4.55.7.tar.gz", hash = "sha256:6899e3d97225a8218f525e9754da0376e1c62953a0d57a76c5abaada51e0d140", size = 3458372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/5c/ce2fce845af9696d043ac912f15b9fac4b9002fcd9ff66b80aa513a6c43f/fonttools-4.55.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c2680a3e6e2e2d104a7ea81fb89323e1a9122c23b03d6569d0768887d0d76e69", size = 2752048 }, + { url = "https://files.pythonhosted.org/packages/07/9b/f7f9409adcf22763263c6327d2d31d538babd9ad2d63d1732c9e85d60a78/fonttools-4.55.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7831d16c95b60866772a15fdcc03772625c4bb6d858e0ad8ef3d6e48709b2ef", size = 2280495 }, + { url = "https://files.pythonhosted.org/packages/91/df/348cf4ff1becd63ed952e35e436de3f9fd3245edb74c070457b465c40a58/fonttools-4.55.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:833927d089e6585019f2c85e3f8f7d87733e3fe81cd704ebaca7afa27e2e7113", size = 4561947 }, + { url = "https://files.pythonhosted.org/packages/14/fe/48b808bdf14bb9467e4a5aaa8aa89f8aba9979d52be3f7f1962f065e933e/fonttools-4.55.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7858dc6823296a053d85b831fa8428781c6c6f06fca44582bf7b6b2ff32a9089", size = 4604618 }, + { url = "https://files.pythonhosted.org/packages/52/25/305d88761aa15a8b2761869a15db34c070e72756d166a163756c53d07b35/fonttools-4.55.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:05568a66b090ed9d79aefdce2ceb180bb64fc856961deaedc29f5ad51355ce2c", size = 4558896 }, + { url = "https://files.pythonhosted.org/packages/0c/0b/c6f7877611940ab75dbe50f035d16ca5ce6d9ff2e5e65b9c76da830286ff/fonttools-4.55.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2dbc08e227fbeb716776905a7bd3c4fc62c8e37c8ef7d481acd10cb5fde12222", size = 4728347 }, + { url = "https://files.pythonhosted.org/packages/43/2c/490223b8cfaeccdef3d8819945a455aa8cc57f12f49233a3d40556b739cc/fonttools-4.55.7-cp310-cp310-win32.whl", hash = "sha256:6eb93cbba484a463b5ee83f7dd3211905f27a3871d20d90fb72de84c6c5056e3", size = 2155437 }, + { url = "https://files.pythonhosted.org/packages/37/f8/ee47526b3f03596cbed9dc7f38519cb650e7769bf9365e04bd81ff4a5302/fonttools-4.55.7-cp310-cp310-win_amd64.whl", hash = "sha256:7ff8e606f905048dc91a55a06d994b68065bf35752ae199df54a9bf30013dcaa", size = 2199898 }, + { url = "https://files.pythonhosted.org/packages/07/cb/f1dd2e31553bd03dcb4eb3af1ac6acc7fe41f26067d1bba104005ec1bb04/fonttools-4.55.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:916e1d926823b4b3b3815c59fc79f4ed670696fdd5fd9a5e690a0503eef38f79", size = 2753201 }, + { url = "https://files.pythonhosted.org/packages/21/84/f9f82093789947547b4bc86242669cde816ef4d949b23f472e47e85f125d/fonttools-4.55.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b89da448e0073408d7b2c44935f9fdae4fdc93644899f99f6102ef883ecf083c", size = 2281418 }, + { url = "https://files.pythonhosted.org/packages/46/e1/e0398d2aa7bf5400c84650fc7d85708502289bb92a40f8090e6e71cfe315/fonttools-4.55.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:087ace2d06894ccdb03e6975d05da6bb9cec0c689b2a9983c059880e33a1464a", size = 4869132 }, + { url = "https://files.pythonhosted.org/packages/d4/2d/9d86cd653c758334285a5c95d1bc0a7f13b6a72fc674c6b33fef3b8e3f77/fonttools-4.55.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:775ed0700ee6f781436641f18a0c61b1846a8c1aecae6da6b395c4417e2cb567", size = 4898375 }, + { url = "https://files.pythonhosted.org/packages/48/ce/f49fccb7d9f7c9c6d239434fc48546a0b37a91ba8310c7bcd5127cfeb5f6/fonttools-4.55.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9ec71d0cc0242899f87e4c230ed0b22c7b8681f288fb80e3d81c2c54c5bd2c79", size = 4877574 }, + { url = "https://files.pythonhosted.org/packages/cc/85/afe73e96a1572ba0acc86e82d52554bf69f384b431acd7a15b8c3890833b/fonttools-4.55.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d4b1c5939c0521525f45522823508e6fad21175bca978583688ea3b3736e6625", size = 5045681 }, + { url = "https://files.pythonhosted.org/packages/b8/37/dc59bc5a2f049d39b62996c806c147ae2eee5316f047a37bcf4cb9dbc4ef/fonttools-4.55.7-cp311-cp311-win32.whl", hash = "sha256:23df0f1003abaf8a435543f59583fc247e7ae1b047ee2263510e0654a5f207e0", size = 2154302 }, + { url = "https://files.pythonhosted.org/packages/86/33/281989403a57945c7871df144af3512ad3d1cd223e025b08b7f377847e6d/fonttools-4.55.7-cp311-cp311-win_amd64.whl", hash = "sha256:82163d58b43eff6e2025a25c32905fdb9042a163cc1ff82dab393e7ffc77a7d5", size = 2200818 }, + { url = "https://files.pythonhosted.org/packages/7b/6d/304a16caf63a8c193ec387b1fae1cb10072a59d34549f2eefe7e3fa9f364/fonttools-4.55.7-py3-none-any.whl", hash = "sha256:3304dfcf9ca204dd0ef691a287bd851ddd8e8250108658c0677c3fdfec853a20", size = 1089677 }, +] + +[[package]] +name = "fparser" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools-scm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/af/570c36d7bc374646ab82f579e2bf9d24a619cc53d83f95b38b0992de3492/fparser-0.2.0.tar.gz", hash = "sha256:3901d31c104062c4e532248286929e7405e43b79a6a85815146a176673e69c82", size = 433559 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/91/03999b30650f5621dd5ec9e8245024dea1b71c4e28e52e0c7300aa0c769d/fparser-0.2.0-py3-none-any.whl", hash = "sha256:49fab105e3a977b9b9d5d4489649287c5060e94c688f9936f3d5af3a45d6f4eb", size = 639408 }, +] + +[[package]] +name = "frozendict" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/59/19eb300ba28e7547538bdf603f1c6c34793240a90e1a7b61b65d8517e35e/frozendict-2.4.6.tar.gz", hash = "sha256:df7cd16470fbd26fc4969a208efadc46319334eb97def1ddf48919b351192b8e", size = 316416 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/7f/e80cdbe0db930b2ba9d46ca35a41b0150156da16dfb79edcc05642690c3b/frozendict-2.4.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3a05c0a50cab96b4bb0ea25aa752efbfceed5ccb24c007612bc63e51299336f", size = 37927 }, + { url = "https://files.pythonhosted.org/packages/29/98/27e145ff7e8e63caa95fb8ee4fc56c68acb208bef01a89c3678a66f9a34d/frozendict-2.4.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5b94d5b07c00986f9e37a38dd83c13f5fe3bf3f1ccc8e88edea8fe15d6cd88c", size = 37945 }, + { url = "https://files.pythonhosted.org/packages/ac/f1/a10be024a9d53441c997b3661ea80ecba6e3130adc53812a4b95b607cdd1/frozendict-2.4.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4c789fd70879ccb6289a603cdebdc4953e7e5dea047d30c1b180529b28257b5", size = 117656 }, + { url = "https://files.pythonhosted.org/packages/46/a6/34c760975e6f1cb4db59a990d58dcf22287e10241c851804670c74c6a27a/frozendict-2.4.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da6a10164c8a50b34b9ab508a9420df38f4edf286b9ca7b7df8a91767baecb34", size = 117444 }, + { url = "https://files.pythonhosted.org/packages/62/dd/64bddd1ffa9617f50e7e63656b2a7ad7f0a46c86b5f4a3d2c714d0006277/frozendict-2.4.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9a8a43036754a941601635ea9c788ebd7a7efbed2becba01b54a887b41b175b9", size = 116801 }, + { url = "https://files.pythonhosted.org/packages/45/ae/af06a8bde1947277aad895c2f26c3b8b8b6ee9c0c2ad988fb58a9d1dde3f/frozendict-2.4.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9905dcf7aa659e6a11b8051114c9fa76dfde3a6e50e6dc129d5aece75b449a2", size = 117329 }, + { url = "https://files.pythonhosted.org/packages/d2/df/be3fa0457ff661301228f4c59c630699568c8ed9b5480f113b3eea7d0cb3/frozendict-2.4.6-cp310-cp310-win_amd64.whl", hash = "sha256:323f1b674a2cc18f86ab81698e22aba8145d7a755e0ac2cccf142ee2db58620d", size = 37522 }, + { url = "https://files.pythonhosted.org/packages/4a/6f/c22e0266b4c85f58b4613fec024e040e93753880527bf92b0c1bc228c27c/frozendict-2.4.6-cp310-cp310-win_arm64.whl", hash = "sha256:eabd21d8e5db0c58b60d26b4bb9839cac13132e88277e1376970172a85ee04b3", size = 34056 }, + { url = "https://files.pythonhosted.org/packages/04/13/d9839089b900fa7b479cce495d62110cddc4bd5630a04d8469916c0e79c5/frozendict-2.4.6-py311-none-any.whl", hash = "sha256:d065db6a44db2e2375c23eac816f1a022feb2fa98cbb50df44a9e83700accbea", size = 16148 }, +] + +[[package]] +name = "gitdb" +version = "4.0.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "smmap" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794 }, +] + +[[package]] +name = "gitpython" +version = "3.1.44" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gitdb" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/89/37df0b71473153574a5cdef8f242de422a0f5d26d7a9e231e6f169b4ad14/gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269", size = 214196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110", size = 207599 }, +] + +[[package]] +name = "gridtools-cpp" +version = "2.3.8" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/b8/352120417da7a3e16cc822e95668e1843d0cd9ee7f0269b9a098893471cc/gridtools_cpp-2.3.8-py3-none-any.whl", hash = "sha256:d9cb8aadc5dca7e864677072de15596feb883844eee2158ab108d04f2f17f355", size = 420716 }, +] + +[[package]] +name = "gt4py" +version = "1.0.4" +source = { editable = "." } +dependencies = [ + { name = "attrs" }, + { name = "black" }, + { name = "boltons" }, + { name = "cached-property" }, + { name = "click" }, + { name = "cmake" }, + { name = "cytoolz" }, + { name = "deepdiff" }, + { name = "devtools" }, + { name = "diskcache" }, + { name = "factory-boy" }, + { name = "filelock" }, + { name = "frozendict" }, + { name = "gridtools-cpp" }, + { name = "jinja2" }, + { name = "lark" }, + { name = "mako" }, + { name = "nanobind" }, + { name = "ninja" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pybind11" }, + { name = "setuptools" }, + { name = "tabulate" }, + { name = "toolz" }, + { name = "typing-extensions" }, + { name = "xxhash" }, +] + +[package.optional-dependencies] +all = [ + { name = "clang-format" }, + { name = "dace" }, + { name = "hypothesis" }, + { name = "jax" }, + { name = "pytest" }, + { name = "scipy" }, +] +cuda11 = [ + { name = "cupy-cuda11x" }, +] +cuda12 = [ + { name = "cupy-cuda12x" }, +] +dace = [ + { name = "dace" }, +] +formatting = [ + { name = "clang-format" }, +] +jax = [ + { name = "jax" }, +] +jax-cuda12 = [ + { name = "cupy-cuda12x" }, + { name = "jax", extra = ["cuda12-local"] }, +] +performance = [ + { name = "scipy" }, +] +rocm4-3 = [ + { name = "cupy-rocm-4-3" }, +] +rocm5-0 = [ + { name = "cupy-rocm-5-0" }, +] +testing = [ + { name = "hypothesis" }, + { name = "pytest" }, +] + +[package.dev-dependencies] +build = [ + { name = "bump-my-version" }, + { name = "cython" }, + { name = "pip" }, + { name = "setuptools" }, + { name = "wheel" }, +] +dev = [ + { name = "atlas4py" }, + { name = "bump-my-version" }, + { name = "coverage", extra = ["toml"] }, + { name = "cython" }, + { name = "esbonio" }, + { name = "hypothesis" }, + { name = "jupytext" }, + { name = "matplotlib" }, + { name = "mypy", extra = ["faster-cache"] }, + { name = "myst-parser" }, + { name = "nbmake" }, + { name = "nox" }, + { name = "pip" }, + { name = "pre-commit" }, + { name = "pygments" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "pytest-cache" }, + { name = "pytest-cov" }, + { name = "pytest-factoryboy" }, + { name = "pytest-instafail" }, + { name = "pytest-xdist", extra = ["psutil"] }, + { name = "ruff" }, + { name = "setuptools" }, + { name = "sphinx" }, + { name = "sphinx-rtd-theme" }, + { name = "sphinx-toolbox" }, + { name = "tach" }, + { name = "types-decorator" }, + { name = "types-docutils" }, + { name = "types-pytz" }, + { name = "types-pyyaml" }, + { name = "types-tabulate" }, + { name = "wheel" }, +] +docs = [ + { name = "esbonio" }, + { name = "jupytext" }, + { name = "matplotlib" }, + { name = "myst-parser" }, + { name = "pygments" }, + { name = "sphinx" }, + { name = "sphinx-rtd-theme" }, + { name = "sphinx-toolbox" }, +] +frameworks = [ + { name = "atlas4py" }, +] +lint = [ + { name = "pre-commit" }, + { name = "ruff" }, + { name = "tach" }, +] +test = [ + { name = "coverage", extra = ["toml"] }, + { name = "hypothesis" }, + { name = "nbmake" }, + { name = "nox" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "pytest-cache" }, + { name = "pytest-cov" }, + { name = "pytest-factoryboy" }, + { name = "pytest-instafail" }, + { name = "pytest-xdist", extra = ["psutil"] }, +] +typing = [ + { name = "mypy", extra = ["faster-cache"] }, + { name = "types-decorator" }, + { name = "types-docutils" }, + { name = "types-pytz" }, + { name = "types-pyyaml" }, + { name = "types-tabulate" }, +] + +[package.metadata] +requires-dist = [ + { name = "attrs", specifier = ">=21.3" }, + { name = "black", specifier = ">=22.3" }, + { name = "boltons", specifier = ">=20.1" }, + { name = "cached-property", specifier = ">=1.5.1" }, + { name = "clang-format", marker = "extra == 'formatting'", specifier = ">=9.0" }, + { name = "click", specifier = ">=8.0.0" }, + { name = "cmake", specifier = ">=3.22" }, + { name = "cupy-cuda11x", marker = "extra == 'cuda11'", specifier = ">=12.0" }, + { name = "cupy-cuda12x", marker = "extra == 'cuda12'", specifier = ">=12.0" }, + { name = "cupy-rocm-4-3", marker = "extra == 'rocm4-3'", specifier = ">=13.3.0" }, + { name = "cupy-rocm-5-0", marker = "extra == 'rocm5-0'", specifier = ">=13.3.0" }, + { name = "cytoolz", specifier = ">=0.12.1" }, + { name = "dace", marker = "extra == 'dace'", specifier = ">=1.0.0,<1.1.0" }, + { name = "deepdiff", specifier = ">=5.6.0" }, + { name = "devtools", specifier = ">=0.6" }, + { name = "diskcache", specifier = ">=5.6.3" }, + { name = "factory-boy", specifier = ">=3.3.0" }, + { name = "filelock", specifier = ">=3.16.1" }, + { name = "frozendict", specifier = ">=2.3" }, + { name = "gridtools-cpp", specifier = "==2.*,>=2.3.8" }, + { name = "gt4py", extras = ["cuda12"], marker = "extra == 'jax-cuda12'" }, + { name = "gt4py", extras = ["dace", "formatting", "jax", "performance", "testing"], marker = "extra == 'all'" }, + { name = "hypothesis", marker = "extra == 'testing'", specifier = ">=6.0.0" }, + { name = "jax", marker = "extra == 'jax'", specifier = ">=0.4.26" }, + { name = "jax", extras = ["cuda12-local"], marker = "extra == 'jax-cuda12'", specifier = ">=0.4.26" }, + { name = "jinja2", specifier = ">=3.0.0" }, + { name = "lark", specifier = ">=1.1.2" }, + { name = "mako", specifier = ">=1.1" }, + { name = "nanobind", specifier = ">=1.4.0" }, + { name = "ninja", specifier = ">=1.10" }, + { name = "numpy", specifier = ">=1.23.3" }, + { name = "packaging", specifier = ">=20.0" }, + { name = "pybind11", specifier = ">=2.10.1" }, + { name = "pytest", marker = "extra == 'testing'", specifier = ">=7.0" }, + { name = "scipy", marker = "extra == 'performance'", specifier = ">=1.9.2" }, + { name = "setuptools", specifier = ">=70.0.0" }, + { name = "tabulate", specifier = ">=0.8.10" }, + { name = "toolz", specifier = ">=0.12.1" }, + { name = "typing-extensions", specifier = ">=4.11.0" }, + { name = "xxhash", specifier = ">=1.4.4,<3.1.0" }, +] + +[package.metadata.requires-dev] +build = [ + { name = "bump-my-version", specifier = ">=0.16.0" }, + { name = "cython", specifier = ">=3.0.0" }, + { name = "pip", specifier = ">=22.1.1" }, + { name = "setuptools", specifier = ">=70.0.0" }, + { name = "wheel", specifier = ">=0.33.6" }, +] +dev = [ + { name = "atlas4py", specifier = ">=0.35", index = "https://test.pypi.org/simple/" }, + { name = "bump-my-version", specifier = ">=0.16.0" }, + { name = "coverage", extras = ["toml"], specifier = ">=7.5.0" }, + { name = "cython", specifier = ">=3.0.0" }, + { name = "esbonio", specifier = ">=0.16.0" }, + { name = "hypothesis", specifier = ">=6.0.0" }, + { name = "jupytext", specifier = ">=1.14" }, + { name = "matplotlib", specifier = ">=3.3" }, + { name = "mypy", extras = ["faster-cache"], specifier = ">=1.13.0" }, + { name = "myst-parser", specifier = ">=4.0.0" }, + { name = "nbmake", specifier = ">=1.4.6" }, + { name = "nox", specifier = ">=2024.10.9" }, + { name = "pip", specifier = ">=22.1.1" }, + { name = "pre-commit", specifier = ">=4.0.1" }, + { name = "pygments", specifier = ">=2.7.3" }, + { name = "pytest", specifier = ">=8.0.1" }, + { name = "pytest-benchmark", specifier = ">=5.0.0" }, + { name = "pytest-cache", specifier = ">=1.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, + { name = "pytest-factoryboy", specifier = ">=2.6.1" }, + { name = "pytest-instafail", specifier = ">=0.5.0" }, + { name = "pytest-xdist", extras = ["psutil"], specifier = ">=3.5.0" }, + { name = "ruff", specifier = ">=0.8.0" }, + { name = "setuptools", specifier = ">=70.0.0" }, + { name = "sphinx", specifier = ">=7.3.7" }, + { name = "sphinx-rtd-theme", specifier = ">=3.0.1" }, + { name = "sphinx-toolbox", specifier = ">=3.8.1" }, + { name = "tach", specifier = ">=0.16.0" }, + { name = "types-decorator", specifier = ">=5.1.8" }, + { name = "types-docutils", specifier = ">=0.21.0" }, + { name = "types-pytz", specifier = ">=2024.2.0" }, + { name = "types-pyyaml", specifier = ">=6.0.10" }, + { name = "types-tabulate", specifier = ">=0.8.10" }, + { name = "wheel", specifier = ">=0.33.6" }, +] +docs = [ + { name = "esbonio", specifier = ">=0.16.0" }, + { name = "jupytext", specifier = ">=1.14" }, + { name = "matplotlib", specifier = ">=3.3" }, + { name = "myst-parser", specifier = ">=4.0.0" }, + { name = "pygments", specifier = ">=2.7.3" }, + { name = "sphinx", specifier = ">=7.3.7" }, + { name = "sphinx-rtd-theme", specifier = ">=3.0.1" }, + { name = "sphinx-toolbox", specifier = ">=3.8.1" }, +] +frameworks = [{ name = "atlas4py", specifier = ">=0.35", index = "https://test.pypi.org/simple/" }] +lint = [ + { name = "pre-commit", specifier = ">=4.0.1" }, + { name = "ruff", specifier = ">=0.8.0" }, + { name = "tach", specifier = ">=0.16.0" }, +] +test = [ + { name = "coverage", extras = ["toml"], specifier = ">=7.5.0" }, + { name = "hypothesis", specifier = ">=6.0.0" }, + { name = "nbmake", specifier = ">=1.4.6" }, + { name = "nox", specifier = ">=2024.10.9" }, + { name = "pytest", specifier = ">=8.0.1" }, + { name = "pytest-benchmark", specifier = ">=5.0.0" }, + { name = "pytest-cache", specifier = ">=1.0" }, + { name = "pytest-cov", specifier = ">=5.0.0" }, + { name = "pytest-factoryboy", specifier = ">=2.6.1" }, + { name = "pytest-instafail", specifier = ">=0.5.0" }, + { name = "pytest-xdist", extras = ["psutil"], specifier = ">=3.5.0" }, +] +typing = [ + { name = "mypy", extras = ["faster-cache"], specifier = ">=1.13.0" }, + { name = "types-decorator", specifier = ">=5.1.8" }, + { name = "types-docutils", specifier = ">=0.21.0" }, + { name = "types-pytz", specifier = ">=2024.2.0" }, + { name = "types-pyyaml", specifier = ">=6.0.10" }, + { name = "types-tabulate", specifier = ">=0.8.10" }, +] + +[[package]] +name = "html5lib" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173 }, +] + +[[package]] +name = "hypothesis" +version = "6.124.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/ef/6e3736663ee67369f7f5b697674bfbd3efc91e7096ddd4452bbbc80065ff/hypothesis-6.124.7.tar.gz", hash = "sha256:8ed6c6ae47e7d26d869c1dc3dee04e8fc50c95240715bb9915ded88d6d920f0e", size = 416938 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/48/2412d4aacf1c50882126910ce036c92a838784915e3de66fb603a75c05ec/hypothesis-6.124.7-py3-none-any.whl", hash = "sha256:a6e1f66de84de3152d57f595a187a123ce3ecdea9dc8ef51ff8dcaa069137085", size = 479518 }, +] + +[[package]] +name = "identify" +version = "2.6.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/bf/c68c46601bacd4c6fb4dd751a42b6e7087240eaabc6487f2ef7a48e0e8fc/identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251", size = 99217 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/a1/68a395c17eeefb04917034bd0a1bfa765e7654fa150cca473d669aa3afb5/identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881", size = 99083 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769 }, +] + +[[package]] +name = "inflection" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/7e/691d061b7329bc8d54edbf0ec22fbfb2afe61facb681f9aaa9bff7a27d04/inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", size = 15091 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/91/aa6bde563e0085a02a435aa99b49ef75b0a4b062635e606dab23ce18d720/inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2", size = 9454 }, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, +] + +[[package]] +name = "ipykernel" +version = "6.29.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "platform_system == 'Darwin' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/67594cb0c7055dc50814b21731c22a601101ea3b1b50a9a1b090e11f5d0f/ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215", size = 163367 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/5c/368ae6c01c7628438358e6d337c19b05425727fbb221d2a3c4303c372f42/ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", size = 117173 }, +] + +[[package]] +name = "ipython" +version = "8.31.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "decorator" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "(sys_platform != 'emscripten' and sys_platform != 'win32') or (sys_platform == 'emscripten' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (sys_platform == 'emscripten' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (sys_platform == 'emscripten' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform == 'emscripten' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (sys_platform == 'emscripten' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform == 'emscripten' and extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform == 'win32' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (sys_platform == 'win32' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (sys_platform == 'win32' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform == 'win32' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (sys_platform == 'win32' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform == 'win32' and extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/35/6f90fdddff7a08b7b715fccbd2427b5212c9525cd043d26fdc45bee0708d/ipython-8.31.0.tar.gz", hash = "sha256:b6a2274606bec6166405ff05e54932ed6e5cfecaca1fc05f2cacde7bb074d70b", size = 5501011 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/60/d0feb6b6d9fe4ab89fe8fe5b47cbf6cd936bfd9f1e7ffa9d0015425aeed6/ipython-8.31.0-py3-none-any.whl", hash = "sha256:46ec58f8d3d076a61d128fe517a51eb730e3aaf0c184ea8c17d16e366660c6a6", size = 821583 }, +] + +[[package]] +name = "jax" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jaxlib" }, + { name = "ml-dtypes" }, + { name = "numpy" }, + { name = "opt-einsum" }, + { name = "scipy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4a/cb/22d62b26284f08e62d6eb64603d3b010004cfdb7a97ce6cca5c6cf86edab/jax-0.5.0.tar.gz", hash = "sha256:49df70bf293a345a7fb519f71193506d37a024c4f850b358042eb32d502c81c8", size = 1959707 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/58/cc0721a1030fcbab0984beea0bf3c4610ec103f738423cdfa9c4ceb40598/jax-0.5.0-py3-none-any.whl", hash = "sha256:b3907aa87ae2c340b39cdbf80c07a74550369cafcaf7398fb60ba58d167345ab", size = 2270365 }, +] + +[package.optional-dependencies] +cuda12-local = [ + { name = "jax-cuda12-plugin" }, + { name = "jaxlib" }, +] + +[[package]] +name = "jax-cuda12-pjrt" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/a6/4b161016aaafe04d92e8d9a50b47e6767ea5cf874a8a9d2d1bcd049409d3/jax_cuda12_pjrt-0.5.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:6025cd4b32d8ec04a11705a749764cd96a6cbc8b6273beac947cc481f2584b8c", size = 89441461 }, + { url = "https://files.pythonhosted.org/packages/8e/ac/824ff70eb5b5dd2a4b597a2017ae62f24b9aaa5fd846f04c94dc447aa1ec/jax_cuda12_pjrt-0.5.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d23833c1b885d96c2764000e95052f2b5827c77d492ea68f67e903a132656dbb", size = 103122594 }, +] + +[[package]] +name = "jax-cuda12-plugin" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jax-cuda12-pjrt" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/58/3dab6bb4cdbc43663093c2af4671e87312236a23c84a3fc152d3c3979019/jax_cuda12_plugin-0.5.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:d497dcc9205a11d283c308d8f400fb71507cf808753168d47effd1d4c47f9c3d", size = 16777702 }, + { url = "https://files.pythonhosted.org/packages/c2/46/a54402df9e2d057bb16d7e2ab045bd536fc8b83662cfc8d503fc56f5fc41/jax_cuda12_plugin-0.5.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:0f443a6b37298edfb0796fcdbd1f86ce85a4b084b6bd3f1f50a4fbfd67ded86b", size = 16733143 }, + { url = "https://files.pythonhosted.org/packages/d9/d5/64ad0b832122d938cbad07652625679a35c03e16e2ce4b8eda4ead8feed5/jax_cuda12_plugin-0.5.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:25407ccb030e4eed7d7e2ccccac8ab65f932aa05936ca5cf0e8ded4adfdcad1a", size = 16777553 }, + { url = "https://files.pythonhosted.org/packages/a2/7b/cc9fa545db9397de9054357de8440c8b10d28a6ab5d1cef1eba184c3d426/jax_cuda12_plugin-0.5.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:a98135a0223064b8f5c6853e22ddc1a4e3862152d37fb685f0dbdeffe0c80122", size = 16734352 }, +] + +[[package]] +name = "jaxlib" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ml-dtypes" }, + { name = "numpy" }, + { name = "scipy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/41/3e4ac64df72c4da126df3fd66a2214025a46b6263f7be266728e7b8e473e/jaxlib-0.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1b8a6c4345f137f387650de2dbc488c20251b7412b55dd648e1a4f13bcf507fb", size = 79248968 }, + { url = "https://files.pythonhosted.org/packages/1e/5f/2a16e61f1d54ae5f55fbf3cb3e22ef5bb01bf9d7d6474e0d34fedba19c4d/jaxlib-0.5.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:5b2efe3dfebf18a84c451d3803ac884ee242021c1113b279c13f4bbc378c3dc0", size = 93181077 }, + { url = "https://files.pythonhosted.org/packages/08/c3/573e2f01b99f1247e8fbe1aa46b95a0faa68ef208f9a8e8ef775d607b3e6/jaxlib-0.5.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:74440b632107336400d4f97a16481d767f13ea914c53ba14e544c6fda54819b3", size = 101969119 }, + { url = "https://files.pythonhosted.org/packages/6e/38/512f61ea13da41ca47f2411d7c05af0cf74a37f225e16725ed0e6fb58893/jaxlib-0.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:53478a28eee6c2ef01759b05a9491702daef9268c3ed013d6f8e2e5f5cae0887", size = 63883394 }, + { url = "https://files.pythonhosted.org/packages/92/4b/8875870ff52ad3fbea876c905228f691f05c8dc8556b226cbfaf0fba7f62/jaxlib-0.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6cd762ed1623132499fa701c4203446102e0a9c82ca23194b87288f746d12a29", size = 79242870 }, + { url = "https://files.pythonhosted.org/packages/a0/0f/00cdfa411d7218e4696c10c5867f7d3c396219adbcaeb02e95108ca802de/jaxlib-0.5.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:63088dbfaa85bb56cd521a925a3472fd7328b18ec93c2d8ffa85af331095c995", size = 93181807 }, + { url = "https://files.pythonhosted.org/packages/58/8e/a5c29db03d5a93b0326e297b556d0e0a9805e9c9c1ae5f82f69557273faa/jaxlib-0.5.0-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:09113ef1582ba34d7cbc440fedb318f4855b59b776711a8aba2473c9727d3025", size = 101969212 }, + { url = "https://files.pythonhosted.org/packages/70/86/ceae20e4f37fa07f1cc95551cc0f49170d0db46d2e82fdf511d26bffd801/jaxlib-0.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:78289fc3ddc1e4e9510de2536a6375df9fe1c50de0ac60826c286b7a5c5090fe", size = 63881994 }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 }, +] + +[[package]] +name = "jinja2" +version = "3.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 }, +] + +[[package]] +name = "jsonschema" +version = "4.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, +] + +[[package]] +name = "jupyter-client" +version = "8.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/22/bf9f12fdaeae18019a468b68952a60fe6dbab5d67cd2a103cac7659b41ca/jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419", size = 342019 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/85/b0394e0b6fcccd2c1eeefc230978a6f8cb0c5df1e4cd3e7625735a0d7d1e/jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f", size = 106105 }, +] + +[[package]] +name = "jupyter-core" +version = "5.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "pywin32", marker = "(platform_python_implementation != 'PyPy' and sys_platform == 'win32') or (platform_python_implementation == 'PyPy' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (platform_python_implementation == 'PyPy' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (platform_python_implementation == 'PyPy' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (platform_python_implementation == 'PyPy' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (platform_python_implementation == 'PyPy' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (platform_python_implementation == 'PyPy' and extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform != 'win32' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (sys_platform != 'win32' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (sys_platform != 'win32' and extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform != 'win32' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (sys_platform != 'win32' and extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (sys_platform != 'win32' and extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/11/b56381fa6c3f4cc5d2cf54a7dbf98ad9aa0b339ef7a601d6053538b079a7/jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9", size = 87629 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/fb/108ecd1fe961941959ad0ee4e12ee7b8b1477247f30b1fdfd83ceaf017f0/jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409", size = 28965 }, +] + +[[package]] +name = "jupytext" +version = "1.16.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "mdit-py-plugins" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/e7/58d6fd374e1065d2bccefd07953d2f1f911d8de03fd7dc33dd5a25ac659c/jupytext-1.16.6.tar.gz", hash = "sha256:dbd03f9263c34b737003f388fc069e9030834fb7136879c4c32c32473557baa0", size = 3726029 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/02/27191f18564d4f2c0e543643aa94b54567de58f359cd6a3bed33adb723ac/jupytext-1.16.6-py3-none-any.whl", hash = "sha256:900132031f73fee15a1c9ebd862e05eb5f51e1ad6ab3a2c6fdd97ce2f9c913b4", size = 154200 }, +] + +[[package]] +name = "kiwisolver" +version = "1.4.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/5f/4d8e9e852d98ecd26cdf8eaf7ed8bc33174033bba5e07001b289f07308fd/kiwisolver-1.4.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88c6f252f6816a73b1f8c904f7bbe02fd67c09a69f7cb8a0eecdbf5ce78e63db", size = 124623 }, + { url = "https://files.pythonhosted.org/packages/1d/70/7f5af2a18a76fe92ea14675f8bd88ce53ee79e37900fa5f1a1d8e0b42998/kiwisolver-1.4.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72941acb7b67138f35b879bbe85be0f6c6a70cab78fe3ef6db9c024d9223e5b", size = 66720 }, + { url = "https://files.pythonhosted.org/packages/c6/13/e15f804a142353aefd089fadc8f1d985561a15358c97aca27b0979cb0785/kiwisolver-1.4.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce2cf1e5688edcb727fdf7cd1bbd0b6416758996826a8be1d958f91880d0809d", size = 65413 }, + { url = "https://files.pythonhosted.org/packages/ce/6d/67d36c4d2054e83fb875c6b59d0809d5c530de8148846b1370475eeeece9/kiwisolver-1.4.8-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c8bf637892dc6e6aad2bc6d4d69d08764166e5e3f69d469e55427b6ac001b19d", size = 1650826 }, + { url = "https://files.pythonhosted.org/packages/de/c6/7b9bb8044e150d4d1558423a1568e4f227193662a02231064e3824f37e0a/kiwisolver-1.4.8-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:034d2c891f76bd3edbdb3ea11140d8510dca675443da7304205a2eaa45d8334c", size = 1628231 }, + { url = "https://files.pythonhosted.org/packages/b6/38/ad10d437563063eaaedbe2c3540a71101fc7fb07a7e71f855e93ea4de605/kiwisolver-1.4.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47b28d1dfe0793d5e96bce90835e17edf9a499b53969b03c6c47ea5985844c3", size = 1408938 }, + { url = "https://files.pythonhosted.org/packages/52/ce/c0106b3bd7f9e665c5f5bc1e07cc95b5dabd4e08e3dad42dbe2faad467e7/kiwisolver-1.4.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb158fe28ca0c29f2260cca8c43005329ad58452c36f0edf298204de32a9a3ed", size = 1422799 }, + { url = "https://files.pythonhosted.org/packages/d0/87/efb704b1d75dc9758087ba374c0f23d3254505edaedd09cf9d247f7878b9/kiwisolver-1.4.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5536185fce131780ebd809f8e623bf4030ce1b161353166c49a3c74c287897f", size = 1354362 }, + { url = "https://files.pythonhosted.org/packages/eb/b3/fd760dc214ec9a8f208b99e42e8f0130ff4b384eca8b29dd0efc62052176/kiwisolver-1.4.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:369b75d40abedc1da2c1f4de13f3482cb99e3237b38726710f4a793432b1c5ff", size = 2222695 }, + { url = "https://files.pythonhosted.org/packages/a2/09/a27fb36cca3fc01700687cc45dae7a6a5f8eeb5f657b9f710f788748e10d/kiwisolver-1.4.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:641f2ddf9358c80faa22e22eb4c9f54bd3f0e442e038728f500e3b978d00aa7d", size = 2370802 }, + { url = "https://files.pythonhosted.org/packages/3d/c3/ba0a0346db35fe4dc1f2f2cf8b99362fbb922d7562e5f911f7ce7a7b60fa/kiwisolver-1.4.8-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d561d2d8883e0819445cfe58d7ddd673e4015c3c57261d7bdcd3710d0d14005c", size = 2334646 }, + { url = "https://files.pythonhosted.org/packages/41/52/942cf69e562f5ed253ac67d5c92a693745f0bed3c81f49fc0cbebe4d6b00/kiwisolver-1.4.8-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1732e065704b47c9afca7ffa272f845300a4eb959276bf6970dc07265e73b605", size = 2467260 }, + { url = "https://files.pythonhosted.org/packages/32/26/2d9668f30d8a494b0411d4d7d4ea1345ba12deb6a75274d58dd6ea01e951/kiwisolver-1.4.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bcb1ebc3547619c3b58a39e2448af089ea2ef44b37988caf432447374941574e", size = 2288633 }, + { url = "https://files.pythonhosted.org/packages/98/99/0dd05071654aa44fe5d5e350729961e7bb535372935a45ac89a8924316e6/kiwisolver-1.4.8-cp310-cp310-win_amd64.whl", hash = "sha256:89c107041f7b27844179ea9c85d6da275aa55ecf28413e87624d033cf1f6b751", size = 71885 }, + { url = "https://files.pythonhosted.org/packages/6c/fc/822e532262a97442989335394d441cd1d0448c2e46d26d3e04efca84df22/kiwisolver-1.4.8-cp310-cp310-win_arm64.whl", hash = "sha256:b5773efa2be9eb9fcf5415ea3ab70fc785d598729fd6057bea38d539ead28271", size = 65175 }, + { url = "https://files.pythonhosted.org/packages/da/ed/c913ee28936c371418cb167b128066ffb20bbf37771eecc2c97edf8a6e4c/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84", size = 124635 }, + { url = "https://files.pythonhosted.org/packages/4c/45/4a7f896f7467aaf5f56ef093d1f329346f3b594e77c6a3c327b2d415f521/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561", size = 66717 }, + { url = "https://files.pythonhosted.org/packages/5f/b4/c12b3ac0852a3a68f94598d4c8d569f55361beef6159dce4e7b624160da2/kiwisolver-1.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7", size = 65413 }, + { url = "https://files.pythonhosted.org/packages/a9/98/1df4089b1ed23d83d410adfdc5947245c753bddfbe06541c4aae330e9e70/kiwisolver-1.4.8-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03", size = 1343994 }, + { url = "https://files.pythonhosted.org/packages/8d/bf/b4b169b050c8421a7c53ea1ea74e4ef9c335ee9013216c558a047f162d20/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954", size = 1434804 }, + { url = "https://files.pythonhosted.org/packages/66/5a/e13bd341fbcf73325ea60fdc8af752addf75c5079867af2e04cc41f34434/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79", size = 1450690 }, + { url = "https://files.pythonhosted.org/packages/9b/4f/5955dcb376ba4a830384cc6fab7d7547bd6759fe75a09564910e9e3bb8ea/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6", size = 1376839 }, + { url = "https://files.pythonhosted.org/packages/3a/97/5edbed69a9d0caa2e4aa616ae7df8127e10f6586940aa683a496c2c280b9/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0", size = 1435109 }, + { url = "https://files.pythonhosted.org/packages/13/fc/e756382cb64e556af6c1809a1bbb22c141bbc2445049f2da06b420fe52bf/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab", size = 2245269 }, + { url = "https://files.pythonhosted.org/packages/76/15/e59e45829d7f41c776d138245cabae6515cb4eb44b418f6d4109c478b481/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc", size = 2393468 }, + { url = "https://files.pythonhosted.org/packages/e9/39/483558c2a913ab8384d6e4b66a932406f87c95a6080112433da5ed668559/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25", size = 2355394 }, + { url = "https://files.pythonhosted.org/packages/01/aa/efad1fbca6570a161d29224f14b082960c7e08268a133fe5dc0f6906820e/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc", size = 2490901 }, + { url = "https://files.pythonhosted.org/packages/c9/4f/15988966ba46bcd5ab9d0c8296914436720dd67fca689ae1a75b4ec1c72f/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67", size = 2312306 }, + { url = "https://files.pythonhosted.org/packages/2d/27/bdf1c769c83f74d98cbc34483a972f221440703054894a37d174fba8aa68/kiwisolver-1.4.8-cp311-cp311-win_amd64.whl", hash = "sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34", size = 71966 }, + { url = "https://files.pythonhosted.org/packages/4a/c9/9642ea855604aeb2968a8e145fc662edf61db7632ad2e4fb92424be6b6c0/kiwisolver-1.4.8-cp311-cp311-win_arm64.whl", hash = "sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2", size = 65311 }, + { url = "https://files.pythonhosted.org/packages/1f/f9/ae81c47a43e33b93b0a9819cac6723257f5da2a5a60daf46aa5c7226ea85/kiwisolver-1.4.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e7a019419b7b510f0f7c9dceff8c5eae2392037eae483a7f9162625233802b0a", size = 60403 }, + { url = "https://files.pythonhosted.org/packages/58/ca/f92b5cb6f4ce0c1ebfcfe3e2e42b96917e16f7090e45b21102941924f18f/kiwisolver-1.4.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:286b18e86682fd2217a48fc6be6b0f20c1d0ed10958d8dc53453ad58d7be0bf8", size = 58657 }, + { url = "https://files.pythonhosted.org/packages/80/28/ae0240f732f0484d3a4dc885d055653c47144bdf59b670aae0ec3c65a7c8/kiwisolver-1.4.8-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4191ee8dfd0be1c3666ccbac178c5a05d5f8d689bbe3fc92f3c4abec817f8fe0", size = 84948 }, + { url = "https://files.pythonhosted.org/packages/5d/eb/78d50346c51db22c7203c1611f9b513075f35c4e0e4877c5dde378d66043/kiwisolver-1.4.8-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd2785b9391f2873ad46088ed7599a6a71e762e1ea33e87514b1a441ed1da1c", size = 81186 }, + { url = "https://files.pythonhosted.org/packages/43/f8/7259f18c77adca88d5f64f9a522792e178b2691f3748817a8750c2d216ef/kiwisolver-1.4.8-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c07b29089b7ba090b6f1a669f1411f27221c3662b3a1b7010e67b59bb5a6f10b", size = 80279 }, + { url = "https://files.pythonhosted.org/packages/3a/1d/50ad811d1c5dae091e4cf046beba925bcae0a610e79ae4c538f996f63ed5/kiwisolver-1.4.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:65ea09a5a3faadd59c2ce96dc7bf0f364986a315949dc6374f04396b0d60e09b", size = 71762 }, +] + +[[package]] +name = "lark" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/60/bc7622aefb2aee1c0b4ba23c1446d3e30225c8770b38d7aedbfb65ca9d5a/lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80", size = 252132 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/00/d90b10b962b4277f5e64a78b6609968859ff86889f5b898c1a778c06ec00/lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c", size = 111036 }, +] + +[[package]] +name = "lsprotocol" +version = "2023.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cattrs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/f6/6e80484ec078d0b50699ceb1833597b792a6c695f90c645fbaf54b947e6f/lsprotocol-2023.0.1.tar.gz", hash = "sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d", size = 69434 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/37/2351e48cb3309673492d3a8c59d407b75fb6630e560eb27ecd4da03adc9a/lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2", size = 70826 }, +] + +[[package]] +name = "mako" +version = "1.3.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5f/d9/8518279534ed7dace1795d5a47e49d5299dd0994eed1053996402a8902f9/mako-1.3.8.tar.gz", hash = "sha256:577b97e414580d3e088d47c2dbbe9594aa7a5146ed2875d4dfa9075af2dd3cc8", size = 392069 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/bf/7a6a36ce2e4cafdfb202752be68850e22607fccd692847c45c1ae3c17ba6/Mako-1.3.8-py3-none-any.whl", hash = "sha256:42f48953c7eb91332040ff567eb7eea69b22e7a4affbc5ba8e845e8f730f6627", size = 78569 }, +] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357 }, + { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393 }, + { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732 }, + { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866 }, + { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964 }, + { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977 }, + { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366 }, + { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091 }, + { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065 }, + { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514 }, + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 }, +] + +[[package]] +name = "matplotlib" +version = "3.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/dd/fa2e1a45fce2d09f4aea3cee169760e672c8262325aa5796c49d543dc7e6/matplotlib-3.10.0.tar.gz", hash = "sha256:b886d02a581b96704c9d1ffe55709e49b4d2d52709ccebc4be42db856e511278", size = 36686418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/ec/3cdff7b5239adaaacefcc4f77c316dfbbdf853c4ed2beec467e0fec31b9f/matplotlib-3.10.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2c5829a5a1dd5a71f0e31e6e8bb449bc0ee9dbfb05ad28fc0c6b55101b3a4be6", size = 8160551 }, + { url = "https://files.pythonhosted.org/packages/41/f2/b518f2c7f29895c9b167bf79f8529c63383ae94eaf49a247a4528e9a148d/matplotlib-3.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2a43cbefe22d653ab34bb55d42384ed30f611bcbdea1f8d7f431011a2e1c62e", size = 8034853 }, + { url = "https://files.pythonhosted.org/packages/ed/8d/45754b4affdb8f0d1a44e4e2bcd932cdf35b256b60d5eda9f455bb293ed0/matplotlib-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:607b16c8a73943df110f99ee2e940b8a1cbf9714b65307c040d422558397dac5", size = 8446724 }, + { url = "https://files.pythonhosted.org/packages/09/5a/a113495110ae3e3395c72d82d7bc4802902e46dc797f6b041e572f195c56/matplotlib-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01d2b19f13aeec2e759414d3bfe19ddfb16b13a1250add08d46d5ff6f9be83c6", size = 8583905 }, + { url = "https://files.pythonhosted.org/packages/12/b1/8b1655b4c9ed4600c817c419f7eaaf70082630efd7556a5b2e77a8a3cdaf/matplotlib-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e6c6461e1fc63df30bf6f80f0b93f5b6784299f721bc28530477acd51bfc3d1", size = 9395223 }, + { url = "https://files.pythonhosted.org/packages/5a/85/b9a54d64585a6b8737a78a61897450403c30f39e0bd3214270bb0b96f002/matplotlib-3.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:994c07b9d9fe8d25951e3202a68c17900679274dadfc1248738dcfa1bd40d7f3", size = 8025355 }, + { url = "https://files.pythonhosted.org/packages/0c/f1/e37f6c84d252867d7ddc418fff70fc661cfd363179263b08e52e8b748e30/matplotlib-3.10.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:fd44fc75522f58612ec4a33958a7e5552562b7705b42ef1b4f8c0818e304a363", size = 8171677 }, + { url = "https://files.pythonhosted.org/packages/c7/8b/92e9da1f28310a1f6572b5c55097b0c0ceb5e27486d85fb73b54f5a9b939/matplotlib-3.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c58a9622d5dbeb668f407f35f4e6bfac34bb9ecdcc81680c04d0258169747997", size = 8044945 }, + { url = "https://files.pythonhosted.org/packages/c5/cb/49e83f0fd066937a5bd3bc5c5d63093703f3637b2824df8d856e0558beef/matplotlib-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:845d96568ec873be63f25fa80e9e7fae4be854a66a7e2f0c8ccc99e94a8bd4ef", size = 8458269 }, + { url = "https://files.pythonhosted.org/packages/b2/7d/2d873209536b9ee17340754118a2a17988bc18981b5b56e6715ee07373ac/matplotlib-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5439f4c5a3e2e8eab18e2f8c3ef929772fd5641876db71f08127eed95ab64683", size = 8599369 }, + { url = "https://files.pythonhosted.org/packages/b8/03/57d6cbbe85c61fe4cbb7c94b54dce443d68c21961830833a1f34d056e5ea/matplotlib-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4673ff67a36152c48ddeaf1135e74ce0d4bce1bbf836ae40ed39c29edf7e2765", size = 9405992 }, + { url = "https://files.pythonhosted.org/packages/14/cf/e382598f98be11bf51dd0bc60eca44a517f6793e3dc8b9d53634a144620c/matplotlib-3.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:7e8632baebb058555ac0cde75db885c61f1212e47723d63921879806b40bec6a", size = 8034580 }, + { url = "https://files.pythonhosted.org/packages/32/5f/29def7ce4e815ab939b56280976ee35afffb3bbdb43f332caee74cb8c951/matplotlib-3.10.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:81713dd0d103b379de4516b861d964b1d789a144103277769238c732229d7f03", size = 8155500 }, + { url = "https://files.pythonhosted.org/packages/de/6d/d570383c9f7ca799d0a54161446f9ce7b17d6c50f2994b653514bcaa108f/matplotlib-3.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:359f87baedb1f836ce307f0e850d12bb5f1936f70d035561f90d41d305fdacea", size = 8032398 }, + { url = "https://files.pythonhosted.org/packages/c9/b4/680aa700d99b48e8c4393fa08e9ab8c49c0555ee6f4c9c0a5e8ea8dfde5d/matplotlib-3.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae80dc3a4add4665cf2faa90138384a7ffe2a4e37c58d83e115b54287c4f06ef", size = 8587361 }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.1.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/5b/a36a337438a14116b16480db471ad061c36c3694df7c2084a0da7ba538b7/matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", size = 8159 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899 }, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316 }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, +] + +[[package]] +name = "ml-dtypes" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/32/49/6e67c334872d2c114df3020e579f3718c333198f8312290e09ec0216703a/ml_dtypes-0.5.1.tar.gz", hash = "sha256:ac5b58559bb84a95848ed6984eb8013249f90b6bab62aa5acbad876e256002c9", size = 698772 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/88/11ebdbc75445eeb5b6869b708a0d787d1ed812ff86c2170bbfb95febdce1/ml_dtypes-0.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bd73f51957949069573ff783563486339a9285d72e2f36c18e0c1aa9ca7eb190", size = 671450 }, + { url = "https://files.pythonhosted.org/packages/a4/a4/9321cae435d6140f9b0e7af8334456a854b60e3a9c6101280a16e3594965/ml_dtypes-0.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:810512e2eccdfc3b41eefa3a27402371a3411453a1efc7e9c000318196140fed", size = 4621075 }, + { url = "https://files.pythonhosted.org/packages/16/d8/4502e12c6a10d42e13a552e8d97f20198e3cf82a0d1411ad50be56a5077c/ml_dtypes-0.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141b2ea2f20bb10802ddca55d91fe21231ef49715cfc971998e8f2a9838f3dbe", size = 4738414 }, + { url = "https://files.pythonhosted.org/packages/6b/7e/bc54ae885e4d702e60a4bf50aa9066ff35e9c66b5213d11091f6bffb3036/ml_dtypes-0.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:26ebcc69d7b779c8f129393e99732961b5cc33fcff84090451f448c89b0e01b4", size = 209718 }, + { url = "https://files.pythonhosted.org/packages/c9/fd/691335926126bb9beeb030b61a28f462773dcf16b8e8a2253b599013a303/ml_dtypes-0.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:023ce2f502efd4d6c1e0472cc58ce3640d051d40e71e27386bed33901e201327", size = 671448 }, + { url = "https://files.pythonhosted.org/packages/ff/a6/63832d91f2feb250d865d069ba1a5d0c686b1f308d1c74ce9764472c5e22/ml_dtypes-0.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7000b6e4d8ef07542c05044ec5d8bbae1df083b3f56822c3da63993a113e716f", size = 4625792 }, + { url = "https://files.pythonhosted.org/packages/cc/2a/5421fd3dbe6eef9b844cc9d05f568b9fb568503a2e51cb1eb4443d9fc56b/ml_dtypes-0.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c09526488c3a9e8b7a23a388d4974b670a9a3dd40c5c8a61db5593ce9b725bab", size = 4743893 }, + { url = "https://files.pythonhosted.org/packages/60/30/d3f0fc9499a22801219679a7f3f8d59f1429943c6261f445fb4bfce20718/ml_dtypes-0.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:15ad0f3b0323ce96c24637a88a6f44f6713c64032f27277b069f285c3cf66478", size = 209712 }, +] + +[[package]] +name = "more-itertools" +version = "10.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 }, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 }, +] + +[[package]] +name = "msgpack" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/f9/a892a6038c861fa849b11a2bb0502c07bc698ab6ea53359e5771397d883b/msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", size = 150428 }, + { url = "https://files.pythonhosted.org/packages/df/7a/d174cc6a3b6bb85556e6a046d3193294a92f9a8e583cdbd46dc8a1d7e7f4/msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", size = 84131 }, + { url = "https://files.pythonhosted.org/packages/08/52/bf4fbf72f897a23a56b822997a72c16de07d8d56d7bf273242f884055682/msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", size = 81215 }, + { url = "https://files.pythonhosted.org/packages/02/95/dc0044b439b518236aaf012da4677c1b8183ce388411ad1b1e63c32d8979/msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", size = 371229 }, + { url = "https://files.pythonhosted.org/packages/ff/75/09081792db60470bef19d9c2be89f024d366b1e1973c197bb59e6aabc647/msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", size = 378034 }, + { url = "https://files.pythonhosted.org/packages/32/d3/c152e0c55fead87dd948d4b29879b0f14feeeec92ef1fd2ec21b107c3f49/msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", size = 363070 }, + { url = "https://files.pythonhosted.org/packages/d9/2c/82e73506dd55f9e43ac8aa007c9dd088c6f0de2aa19e8f7330e6a65879fc/msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", size = 359863 }, + { url = "https://files.pythonhosted.org/packages/cb/a0/3d093b248837094220e1edc9ec4337de3443b1cfeeb6e0896af8ccc4cc7a/msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", size = 368166 }, + { url = "https://files.pythonhosted.org/packages/e4/13/7646f14f06838b406cf5a6ddbb7e8dc78b4996d891ab3b93c33d1ccc8678/msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", size = 370105 }, + { url = "https://files.pythonhosted.org/packages/67/fa/dbbd2443e4578e165192dabbc6a22c0812cda2649261b1264ff515f19f15/msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", size = 68513 }, + { url = "https://files.pythonhosted.org/packages/24/ce/c2c8fbf0ded750cb63cbcbb61bc1f2dfd69e16dca30a8af8ba80ec182dcd/msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", size = 74687 }, + { url = "https://files.pythonhosted.org/packages/b7/5e/a4c7154ba65d93be91f2f1e55f90e76c5f91ccadc7efc4341e6f04c8647f/msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", size = 150803 }, + { url = "https://files.pythonhosted.org/packages/60/c2/687684164698f1d51c41778c838d854965dd284a4b9d3a44beba9265c931/msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", size = 84343 }, + { url = "https://files.pythonhosted.org/packages/42/ae/d3adea9bb4a1342763556078b5765e666f8fdf242e00f3f6657380920972/msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", size = 81408 }, + { url = "https://files.pythonhosted.org/packages/dc/17/6313325a6ff40ce9c3207293aee3ba50104aed6c2c1559d20d09e5c1ff54/msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", size = 396096 }, + { url = "https://files.pythonhosted.org/packages/a8/a1/ad7b84b91ab5a324e707f4c9761633e357820b011a01e34ce658c1dda7cc/msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", size = 403671 }, + { url = "https://files.pythonhosted.org/packages/bb/0b/fd5b7c0b308bbf1831df0ca04ec76fe2f5bf6319833646b0a4bd5e9dc76d/msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", size = 387414 }, + { url = "https://files.pythonhosted.org/packages/f0/03/ff8233b7c6e9929a1f5da3c7860eccd847e2523ca2de0d8ef4878d354cfa/msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", size = 383759 }, + { url = "https://files.pythonhosted.org/packages/1f/1b/eb82e1fed5a16dddd9bc75f0854b6e2fe86c0259c4353666d7fab37d39f4/msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", size = 394405 }, + { url = "https://files.pythonhosted.org/packages/90/2e/962c6004e373d54ecf33d695fb1402f99b51832631e37c49273cc564ffc5/msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", size = 396041 }, + { url = "https://files.pythonhosted.org/packages/f8/20/6e03342f629474414860c48aeffcc2f7f50ddaf351d95f20c3f1c67399a8/msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", size = 68538 }, + { url = "https://files.pythonhosted.org/packages/aa/c4/5a582fc9a87991a3e6f6800e9bb2f3c82972912235eb9539954f3e9997c7/msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788", size = 74871 }, +] + +[[package]] +name = "mypy" +version = "1.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/7a/87ae2adb31d68402da6da1e5f30c07ea6063e9f09b5e7cfc9dfa44075e74/mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", size = 11211002 }, + { url = "https://files.pythonhosted.org/packages/e1/23/eada4c38608b444618a132be0d199b280049ded278b24cbb9d3fc59658e4/mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", size = 10358400 }, + { url = "https://files.pythonhosted.org/packages/43/c9/d6785c6f66241c62fd2992b05057f404237deaad1566545e9f144ced07f5/mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", size = 12095172 }, + { url = "https://files.pythonhosted.org/packages/c3/62/daa7e787770c83c52ce2aaf1a111eae5893de9e004743f51bfcad9e487ec/mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", size = 12828732 }, + { url = "https://files.pythonhosted.org/packages/1b/a2/5fb18318a3637f29f16f4e41340b795da14f4751ef4f51c99ff39ab62e52/mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", size = 13012197 }, + { url = "https://files.pythonhosted.org/packages/28/99/e153ce39105d164b5f02c06c35c7ba958aaff50a2babba7d080988b03fe7/mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", size = 9780836 }, + { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432 }, + { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515 }, + { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791 }, + { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203 }, + { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900 }, + { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869 }, + { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, +] + +[package.optional-dependencies] +faster-cache = [ + { name = "orjson" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, +] + +[[package]] +name = "myst-parser" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "jinja2" }, + { name = "markdown-it-py" }, + { name = "mdit-py-plugins" }, + { name = "pyyaml" }, + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/55/6d1741a1780e5e65038b74bce6689da15f620261c490c3511eb4c12bac4b/myst_parser-4.0.0.tar.gz", hash = "sha256:851c9dfb44e36e56d15d05e72f02b80da21a9e0d07cba96baf5e2d476bb91531", size = 93858 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/b4/b036f8fdb667587bb37df29dc6644681dd78b7a2a6321a34684b79412b28/myst_parser-4.0.0-py3-none-any.whl", hash = "sha256:b9317997552424448c6096c2558872fdb6f81d3ecb3a40ce84a7518798f3f28d", size = 84563 }, +] + +[[package]] +name = "nanobind" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/01/a28722f6626e5c8a606dee71cb40c0b2ab9f7715b96bd34a9553c79dbf42/nanobind-2.4.0.tar.gz", hash = "sha256:a0392dee5f58881085b2ac8bfe8e53f74285aa4868b1472bfaf76cfb414e1c96", size = 953467 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/07/abff41fcade3613349eac71dacb166352babef515efd960a751e3175c262/nanobind-2.4.0-py3-none-any.whl", hash = "sha256:8cf27b04fbadeb9deb4a73f02bd838bf9f7e3e5a8ce44c50c93142b5728da58a", size = 232882 }, +] + +[[package]] +name = "natsort" +version = "8.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268 }, +] + +[[package]] +name = "nbclient" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/87/66/7ffd18d58eae90d5721f9f39212327695b749e23ad44b3881744eaf4d9e8/nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193", size = 62424 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/6d/e7fa07f03a4a7b221d94b4d586edb754a9b0dc3c9e2c93353e9fa4e0d117/nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d", size = 25434 }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454 }, +] + +[[package]] +name = "nbmake" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "pygments" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/9a/aae201cee5639e1d562b3843af8fd9f8d018bb323e776a2b973bdd5fc64b/nbmake-1.5.5.tar.gz", hash = "sha256:239dc868ea13a7c049746e2aba2c229bd0f6cdbc6bfa1d22f4c88638aa4c5f5c", size = 85929 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl", hash = "sha256:c6fbe6e48b60cacac14af40b38bf338a3b88f47f085c54ac5b8639ff0babaf4b", size = 12818 }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195 }, +] + +[[package]] +name = "networkx" +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/1d/06475e1cd5264c0b870ea2cc6fdb3e37177c1e565c43f56ff17a10e3937f/networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1", size = 2151368 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/54/dd730b32ea14ea797530a4479b2ed46a6fb250f682a9cfb997e968bf0261/networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f", size = 1723263 }, +] + +[[package]] +name = "ninja" +version = "1.11.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/8f/21a2701f95b7d0d5137736561b3427ece0c4a1e085d4a223b92d16ab7d8b/ninja-1.11.1.3.tar.gz", hash = "sha256:edfa0d2e9d7ead1635b03e40a32ad56cc8f56798b6e2e9848d8300b174897076", size = 129532 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/ba/0069cd4a83d68f7b0308be70e219b15d675e50c8ea28763a3f0373c45bfc/ninja-1.11.1.3-py3-none-macosx_10_9_universal2.whl", hash = "sha256:2b4879ea3f1169f3d855182c57dcc84d1b5048628c8b7be0d702b81882a37237", size = 279132 }, + { url = "https://files.pythonhosted.org/packages/72/6b/3805be87df8417a0c7b21078c8045f2a1e59b34f371bfe4cb4fb0d6df7f2/ninja-1.11.1.3-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bc3ebc8b2e47716149f3541742b5cd8e0b08f51013b825c05baca3e34854370d", size = 472101 }, + { url = "https://files.pythonhosted.org/packages/6b/35/a8e38d54768e67324e365e2a41162be298f51ec93e6bd4b18d237d7250d8/ninja-1.11.1.3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a27e78ca71316c8654965ee94b286a98c83877bfebe2607db96897bbfe458af0", size = 422884 }, + { url = "https://files.pythonhosted.org/packages/2f/99/7996457319e139c02697fb2aa28e42fe32bb0752cef492edc69d56a3552e/ninja-1.11.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2883ea46b3c5079074f56820f9989c6261fcc6fd873d914ee49010ecf283c3b2", size = 157046 }, + { url = "https://files.pythonhosted.org/packages/6d/8b/93f38e5cddf76ccfdab70946515b554f25d2b4c95ef9b2f9cfbc43fa7cc1/ninja-1.11.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c4bdb9fd2d0c06501ae15abfd23407660e95659e384acd36e013b6dd7d8a8e4", size = 180014 }, + { url = "https://files.pythonhosted.org/packages/7d/1d/713884d0fa3c972164f69d552e0701d30e2bf25eba9ef160bfb3dc69926a/ninja-1.11.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:114ed5c61c8474df6a69ab89097a20749b769e2c219a452cb2fadc49b0d581b0", size = 157098 }, + { url = "https://files.pythonhosted.org/packages/c7/22/ecb0f70e77c9e22ee250aa717a608a142756833a34d43943d7d658ee0e56/ninja-1.11.1.3-py3-none-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7fa2247fce98f683bc712562d82b22b8a0a5c000738a13147ca2d1b68c122298", size = 130089 }, + { url = "https://files.pythonhosted.org/packages/ec/a6/3ee846c20ab6ad95b90c5c8703c76cb1f39cc8ce2d1ae468956e3b1b2581/ninja-1.11.1.3-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:a38c6c6c8032bed68b70c3b065d944c35e9f903342875d3a3218c1607987077c", size = 372508 }, + { url = "https://files.pythonhosted.org/packages/95/0d/aa44abe4141f29148ce671ac8c92045878906b18691c6f87a29711c2ff1c/ninja-1.11.1.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:56ada5d33b8741d298836644042faddebc83ee669782d661e21563034beb5aba", size = 419369 }, + { url = "https://files.pythonhosted.org/packages/f7/ec/48bf5105568ac9bd2016b701777bdd5000cc09a14ac837fef9f15e8d634e/ninja-1.11.1.3-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:53409151da081f3c198bb0bfc220a7f4e821e022c5b7d29719adda892ddb31bb", size = 420304 }, + { url = "https://files.pythonhosted.org/packages/18/e5/69df63976cf971a03379899f8520a036c9dbab26330b37197512aed5b3df/ninja-1.11.1.3-py3-none-musllinux_1_1_s390x.whl", hash = "sha256:1ad2112c2b0159ed7c4ae3731595191b1546ba62316fc40808edecd0306fefa3", size = 416056 }, + { url = "https://files.pythonhosted.org/packages/6f/4f/bdb401af7ed0e24a3fef058e13a149f2de1ce4b176699076993615d55610/ninja-1.11.1.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:28aea3c1c280cba95b8608d50797169f3a34280e3e9a6379b6e340f0c9eaeeb0", size = 379725 }, + { url = "https://files.pythonhosted.org/packages/bd/68/05e7863bf13128c61652eeb3ec7096c3d3a602f32f31752dbfb034e3fa07/ninja-1.11.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b6966f83064a88a51693073eea3decd47e08c3965241e09578ef7aa3a7738329", size = 434881 }, + { url = "https://files.pythonhosted.org/packages/bd/ad/edc0d1efe77f29f45bbca2e1dab07ef597f61a88de6e4bccffc0aec2256c/ninja-1.11.1.3-py3-none-win32.whl", hash = "sha256:a4a3b71490557e18c010cbb26bd1ea9a0c32ee67e8f105e9731515b6e0af792e", size = 255988 }, + { url = "https://files.pythonhosted.org/packages/03/93/09a9f7672b4f97438aca6217ac54212a63273f1cd3b46b731d0bb22c53e7/ninja-1.11.1.3-py3-none-win_amd64.whl", hash = "sha256:04d48d14ea7ba11951c156599ab526bdda575450797ff57c6fdf99b2554d09c7", size = 296502 }, + { url = "https://files.pythonhosted.org/packages/d9/9d/0cc1e82849070ff3cbee69f326cb48a839407bcd15d8844443c30a5e7509/ninja-1.11.1.3-py3-none-win_arm64.whl", hash = "sha256:17978ad611d8ead578d83637f5ae80c2261b033db0b493a7ce94f88623f29e1b", size = 270571 }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, +] + +[[package]] +name = "nox" +version = "2024.10.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argcomplete" }, + { name = "colorlog" }, + { name = "packaging" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/93/4df547afcd56e0b2bbaa99bc2637deb218a01802ed62d80f763189be802c/nox-2024.10.9.tar.gz", hash = "sha256:7aa9dc8d1c27e9f45ab046ffd1c3b2c4f7c91755304769df231308849ebded95", size = 4003197 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/00/981f0dcaddf111b6caf6e03d7f7f01b07fd4af117316a7eb1c22039d9e37/nox-2024.10.9-py3-none-any.whl", hash = "sha256:1d36f309a0a2a853e9bccb76bbef6bb118ba92fa92674d15604ca99adeb29eab", size = 61210 }, +] + +[[package]] +name = "numpy" +version = "1.26.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", size = 15786129 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/94/ace0fdea5241a27d13543ee117cbc65868e82213fb31a8eb7fe9ff23f313/numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0", size = 20631468 }, + { url = "https://files.pythonhosted.org/packages/20/f7/b24208eba89f9d1b58c1668bc6c8c4fd472b20c45573cb767f59d49fb0f6/numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a", size = 13966411 }, + { url = "https://files.pythonhosted.org/packages/fc/a5/4beee6488160798683eed5bdb7eead455892c3b4e1f78d79d8d3f3b084ac/numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4", size = 14219016 }, + { url = "https://files.pythonhosted.org/packages/4b/d7/ecf66c1cd12dc28b4040b15ab4d17b773b87fa9d29ca16125de01adb36cd/numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f", size = 18240889 }, + { url = "https://files.pythonhosted.org/packages/24/03/6f229fe3187546435c4f6f89f6d26c129d4f5bed40552899fcf1f0bf9e50/numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a", size = 13876746 }, + { url = "https://files.pythonhosted.org/packages/39/fe/39ada9b094f01f5a35486577c848fe274e374bbf8d8f472e1423a0bbd26d/numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2", size = 18078620 }, + { url = "https://files.pythonhosted.org/packages/d5/ef/6ad11d51197aad206a9ad2286dc1aac6a378059e06e8cf22cd08ed4f20dc/numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07", size = 5972659 }, + { url = "https://files.pythonhosted.org/packages/19/77/538f202862b9183f54108557bfda67e17603fc560c384559e769321c9d92/numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", size = 15808905 }, + { url = "https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71", size = 20630554 }, + { url = "https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef", size = 13997127 }, + { url = "https://files.pythonhosted.org/packages/79/ae/7e5b85136806f9dadf4878bf73cf223fe5c2636818ba3ab1c585d0403164/numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e", size = 14222994 }, + { url = "https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5", size = 18252005 }, + { url = "https://files.pythonhosted.org/packages/09/bf/2b1aaf8f525f2923ff6cfcf134ae5e750e279ac65ebf386c75a0cf6da06a/numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a", size = 13885297 }, + { url = "https://files.pythonhosted.org/packages/df/a0/4e0f14d847cfc2a633a1c8621d00724f3206cfeddeb66d35698c4e2cf3d2/numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a", size = 18093567 }, + { url = "https://files.pythonhosted.org/packages/d2/b7/a734c733286e10a7f1a8ad1ae8c90f2d33bf604a96548e0a4a3a6739b468/numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20", size = 5968812 }, + { url = "https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2", size = 15811913 }, +] + +[[package]] +name = "opt-einsum" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/b9/2ac072041e899a52f20cf9510850ff58295003aa75525e58343591b0cbfb/opt_einsum-3.4.0.tar.gz", hash = "sha256:96ca72f1b886d148241348783498194c577fa30a8faac108586b14f1ba4473ac", size = 63004 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/cd/066e86230ae37ed0be70aae89aabf03ca8d9f39c8aea0dec8029455b5540/opt_einsum-3.4.0-py3-none-any.whl", hash = "sha256:69bb92469f86a1565195ece4ac0323943e83477171b91d24c35afe028a90d7cd", size = 71932 }, +] + +[[package]] +name = "orderly-set" +version = "5.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5d/9e/8fdcb9ab1b6983cc7c185a4ddafc27518118bd80e9ff2f30aba83636af37/orderly_set-5.2.3.tar.gz", hash = "sha256:571ed97c5a5fca7ddeb6b2d26c19aca896b0ed91f334d9c109edd2f265fb3017", size = 19698 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/bb/a3a4eab8430f14c7d1476f9db261d32654cb3d1794c0266a46f6574e1190/orderly_set-5.2.3-py3-none-any.whl", hash = "sha256:d357cedcf67f4ebff0d4cbd5b0997e98eeb65dd24fdf5c990a501ae9e82c7d34", size = 12024 }, +] + +[[package]] +name = "orjson" +version = "3.10.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/5dea21763eeff8c1590076918a446ea3d6140743e0e36f58f369928ed0f4/orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e", size = 5282482 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/09/e5ff18ad009e6f97eb7edc5f67ef98b3ce0c189da9c3eaca1f9587cd4c61/orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04", size = 249532 }, + { url = "https://files.pythonhosted.org/packages/bd/b8/a75883301fe332bd433d9b0ded7d2bb706ccac679602c3516984f8814fb5/orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8", size = 125229 }, + { url = "https://files.pythonhosted.org/packages/83/4b/22f053e7a364cc9c685be203b1e40fc5f2b3f164a9b2284547504eec682e/orjson-3.10.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c2c79fa308e6edb0ffab0a31fd75a7841bf2a79a20ef08a3c6e3b26814c8ca8", size = 150148 }, + { url = "https://files.pythonhosted.org/packages/63/64/1b54fc75ca328b57dd810541a4035fe48c12a161d466e3cf5b11a8c25649/orjson-3.10.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cb85490aa6bf98abd20607ab5c8324c0acb48d6da7863a51be48505646c814", size = 139748 }, + { url = "https://files.pythonhosted.org/packages/5e/ff/ff0c5da781807bb0a5acd789d9a7fbcb57f7b0c6e1916595da1f5ce69f3c/orjson-3.10.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763dadac05e4e9d2bc14938a45a2d0560549561287d41c465d3c58aec818b164", size = 154559 }, + { url = "https://files.pythonhosted.org/packages/4e/9a/11e2974383384ace8495810d4a2ebef5f55aacfc97b333b65e789c9d362d/orjson-3.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a330b9b4734f09a623f74a7490db713695e13b67c959713b78369f26b3dee6bf", size = 130349 }, + { url = "https://files.pythonhosted.org/packages/2d/c4/dd9583aea6aefee1b64d3aed13f51d2aadb014028bc929fe52936ec5091f/orjson-3.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a61a4622b7ff861f019974f73d8165be1bd9a0855e1cad18ee167acacabeb061", size = 138514 }, + { url = "https://files.pythonhosted.org/packages/53/3e/dcf1729230654f5c5594fc752de1f43dcf67e055ac0d300c8cdb1309269a/orjson-3.10.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd271247691574416b3228db667b84775c497b245fa275c6ab90dc1ffbbd2b3", size = 130940 }, + { url = "https://files.pythonhosted.org/packages/e8/2b/b9759fe704789937705c8a56a03f6c03e50dff7df87d65cba9a20fec5282/orjson-3.10.15-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4759b109c37f635aa5c5cc93a1b26927bfde24b254bcc0e1149a9fada253d2d", size = 414713 }, + { url = "https://files.pythonhosted.org/packages/a7/6b/b9dfdbd4b6e20a59238319eb203ae07c3f6abf07eef909169b7a37ae3bba/orjson-3.10.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e992fd5cfb8b9f00bfad2fd7a05a4299db2bbe92e6440d9dd2fab27655b3182", size = 141028 }, + { url = "https://files.pythonhosted.org/packages/7c/b5/40f5bbea619c7caf75eb4d652a9821875a8ed04acc45fe3d3ef054ca69fb/orjson-3.10.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f95fb363d79366af56c3f26b71df40b9a583b07bbaaf5b317407c4d58497852e", size = 129715 }, + { url = "https://files.pythonhosted.org/packages/38/60/2272514061cbdf4d672edbca6e59c7e01cd1c706e881427d88f3c3e79761/orjson-3.10.15-cp310-cp310-win32.whl", hash = "sha256:f9875f5fea7492da8ec2444839dcc439b0ef298978f311103d0b7dfd775898ab", size = 142473 }, + { url = "https://files.pythonhosted.org/packages/11/5d/be1490ff7eafe7fef890eb4527cf5bcd8cfd6117f3efe42a3249ec847b60/orjson-3.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:17085a6aa91e1cd70ca8533989a18b5433e15d29c574582f76f821737c8d5806", size = 133564 }, + { url = "https://files.pythonhosted.org/packages/7a/a2/21b25ce4a2c71dbb90948ee81bd7a42b4fbfc63162e57faf83157d5540ae/orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6", size = 249533 }, + { url = "https://files.pythonhosted.org/packages/b2/85/2076fc12d8225698a51278009726750c9c65c846eda741e77e1761cfef33/orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef", size = 125230 }, + { url = "https://files.pythonhosted.org/packages/06/df/a85a7955f11274191eccf559e8481b2be74a7c6d43075d0a9506aa80284d/orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334", size = 150148 }, + { url = "https://files.pythonhosted.org/packages/37/b3/94c55625a29b8767c0eed194cb000b3787e3c23b4cdd13be17bae6ccbb4b/orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d", size = 139749 }, + { url = "https://files.pythonhosted.org/packages/53/ba/c608b1e719971e8ddac2379f290404c2e914cf8e976369bae3cad88768b1/orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0", size = 154558 }, + { url = "https://files.pythonhosted.org/packages/b2/c4/c1fb835bb23ad788a39aa9ebb8821d51b1c03588d9a9e4ca7de5b354fdd5/orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13", size = 130349 }, + { url = "https://files.pythonhosted.org/packages/78/14/bb2b48b26ab3c570b284eb2157d98c1ef331a8397f6c8bd983b270467f5c/orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5", size = 138513 }, + { url = "https://files.pythonhosted.org/packages/4a/97/d5b353a5fe532e92c46467aa37e637f81af8468aa894cd77d2ec8a12f99e/orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b", size = 130942 }, + { url = "https://files.pythonhosted.org/packages/b5/5d/a067bec55293cca48fea8b9928cfa84c623be0cce8141d47690e64a6ca12/orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399", size = 414717 }, + { url = "https://files.pythonhosted.org/packages/6f/9a/1485b8b05c6b4c4db172c438cf5db5dcfd10e72a9bc23c151a1137e763e0/orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388", size = 141033 }, + { url = "https://files.pythonhosted.org/packages/f8/d2/fc67523656e43a0c7eaeae9007c8b02e86076b15d591e9be11554d3d3138/orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c", size = 129720 }, + { url = "https://files.pythonhosted.org/packages/79/42/f58c7bd4e5b54da2ce2ef0331a39ccbbaa7699b7f70206fbf06737c9ed7d/orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e", size = 142473 }, + { url = "https://files.pythonhosted.org/packages/00/f8/bb60a4644287a544ec81df1699d5b965776bc9848d9029d9f9b3402ac8bb/orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e", size = 133570 }, +] + +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, +] + +[[package]] +name = "parso" +version = "0.8.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772 }, +] + +[[package]] +name = "pillow" +version = "11.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/1c/2dcea34ac3d7bc96a1fd1bd0a6e06a57c67167fec2cff8d95d88229a8817/pillow-11.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8", size = 3229983 }, + { url = "https://files.pythonhosted.org/packages/14/ca/6bec3df25e4c88432681de94a3531cc738bd85dea6c7aa6ab6f81ad8bd11/pillow-11.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192", size = 3101831 }, + { url = "https://files.pythonhosted.org/packages/d4/2c/668e18e5521e46eb9667b09e501d8e07049eb5bfe39d56be0724a43117e6/pillow-11.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2", size = 4314074 }, + { url = "https://files.pythonhosted.org/packages/02/80/79f99b714f0fc25f6a8499ecfd1f810df12aec170ea1e32a4f75746051ce/pillow-11.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26", size = 4394933 }, + { url = "https://files.pythonhosted.org/packages/81/aa/8d4ad25dc11fd10a2001d5b8a80fdc0e564ac33b293bdfe04ed387e0fd95/pillow-11.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07", size = 4353349 }, + { url = "https://files.pythonhosted.org/packages/84/7a/cd0c3eaf4a28cb2a74bdd19129f7726277a7f30c4f8424cd27a62987d864/pillow-11.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482", size = 4476532 }, + { url = "https://files.pythonhosted.org/packages/8f/8b/a907fdd3ae8f01c7670dfb1499c53c28e217c338b47a813af8d815e7ce97/pillow-11.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e", size = 4279789 }, + { url = "https://files.pythonhosted.org/packages/6f/9a/9f139d9e8cccd661c3efbf6898967a9a337eb2e9be2b454ba0a09533100d/pillow-11.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269", size = 4413131 }, + { url = "https://files.pythonhosted.org/packages/a8/68/0d8d461f42a3f37432203c8e6df94da10ac8081b6d35af1c203bf3111088/pillow-11.1.0-cp310-cp310-win32.whl", hash = "sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49", size = 2291213 }, + { url = "https://files.pythonhosted.org/packages/14/81/d0dff759a74ba87715509af9f6cb21fa21d93b02b3316ed43bda83664db9/pillow-11.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a", size = 2625725 }, + { url = "https://files.pythonhosted.org/packages/ce/1f/8d50c096a1d58ef0584ddc37e6f602828515219e9d2428e14ce50f5ecad1/pillow-11.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65", size = 2375213 }, + { url = "https://files.pythonhosted.org/packages/dd/d6/2000bfd8d5414fb70cbbe52c8332f2283ff30ed66a9cde42716c8ecbe22c/pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", size = 3229968 }, + { url = "https://files.pythonhosted.org/packages/d9/45/3fe487010dd9ce0a06adf9b8ff4f273cc0a44536e234b0fad3532a42c15b/pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", size = 3101806 }, + { url = "https://files.pythonhosted.org/packages/e3/72/776b3629c47d9d5f1c160113158a7a7ad177688d3a1159cd3b62ded5a33a/pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", size = 4322283 }, + { url = "https://files.pythonhosted.org/packages/e4/c2/e25199e7e4e71d64eeb869f5b72c7ddec70e0a87926398785ab944d92375/pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070", size = 4402945 }, + { url = "https://files.pythonhosted.org/packages/c1/ed/51d6136c9d5911f78632b1b86c45241c712c5a80ed7fa7f9120a5dff1eba/pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6", size = 4361228 }, + { url = "https://files.pythonhosted.org/packages/48/a4/fbfe9d5581d7b111b28f1d8c2762dee92e9821bb209af9fa83c940e507a0/pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1", size = 4484021 }, + { url = "https://files.pythonhosted.org/packages/39/db/0b3c1a5018117f3c1d4df671fb8e47d08937f27519e8614bbe86153b65a5/pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2", size = 4287449 }, + { url = "https://files.pythonhosted.org/packages/d9/58/bc128da7fea8c89fc85e09f773c4901e95b5936000e6f303222490c052f3/pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96", size = 4419972 }, + { url = "https://files.pythonhosted.org/packages/5f/bb/58f34379bde9fe197f51841c5bbe8830c28bbb6d3801f16a83b8f2ad37df/pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f", size = 2291201 }, + { url = "https://files.pythonhosted.org/packages/3a/c6/fce9255272bcf0c39e15abd2f8fd8429a954cf344469eaceb9d0d1366913/pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761", size = 2625686 }, + { url = "https://files.pythonhosted.org/packages/c8/52/8ba066d569d932365509054859f74f2a9abee273edcef5cd75e4bc3e831e/pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71", size = 2375194 }, + { url = "https://files.pythonhosted.org/packages/fa/c5/389961578fb677b8b3244fcd934f720ed25a148b9a5cc81c91bdf59d8588/pillow-11.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90", size = 3198345 }, + { url = "https://files.pythonhosted.org/packages/c4/fa/803c0e50ffee74d4b965229e816af55276eac1d5806712de86f9371858fd/pillow-11.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb", size = 3072938 }, + { url = "https://files.pythonhosted.org/packages/dc/67/2a3a5f8012b5d8c63fe53958ba906c1b1d0482ebed5618057ef4d22f8076/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442", size = 3400049 }, + { url = "https://files.pythonhosted.org/packages/e5/a0/514f0d317446c98c478d1872497eb92e7cde67003fed74f696441e647446/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83", size = 3422431 }, + { url = "https://files.pythonhosted.org/packages/cd/00/20f40a935514037b7d3f87adfc87d2c538430ea625b63b3af8c3f5578e72/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f", size = 3446208 }, + { url = "https://files.pythonhosted.org/packages/28/3c/7de681727963043e093c72e6c3348411b0185eab3263100d4490234ba2f6/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73", size = 3509746 }, + { url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353 }, +] + +[[package]] +name = "pip" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/3e/68beeeeb306ea20ffd30b3ed993f531d16cd884ec4f60c9b1e238f69f2af/pip-25.0.tar.gz", hash = "sha256:8e0a97f7b4c47ae4a494560da84775e9e2f671d415d8d828e052efefb206b30b", size = 1950328 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/8a/1ddf40be20103bcc605db840e9ade09c8e8c9f920a03e9cfe88eae97a058/pip-25.0-py3-none-any.whl", hash = "sha256:b6eb97a803356a52b2dd4bb73ba9e65b2ba16caa6bcb25a7497350a4e5859b65", size = 1841506 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + +[[package]] +name = "ply" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e5/69/882ee5c9d017149285cab114ebeab373308ef0f874fcdac9beb90e0ac4da/ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3", size = 159130 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce", size = 49567 }, +] + +[[package]] +name = "pre-commit" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/13/b62d075317d8686071eb843f0bb1f195eb332f48869d3c31a4c6f1e063ac/pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4", size = 193330 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/b3/df14c580d82b9627d173ceea305ba898dca135feb360b6d84019d0803d3b/pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b", size = 220560 }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.50" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/e1/bd15cb8ffdcfeeb2bdc215de3c3cffca11408d829e4b8416dcfe71ba8854/prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab", size = 429087 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/ea/d836f008d33151c7a1f62caf3d8dd782e4d15f6a43897f64480c2b8de2ad/prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198", size = 387816 }, +] + +[[package]] +name = "psutil" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1f/5a/07871137bb752428aa4b659f910b399ba6f291156bdea939be3e96cae7cb/psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5", size = 508502 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/99/ca79d302be46f7bdd8321089762dd4476ee725fce16fc2b2e1dbba8cac17/psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8", size = 247511 }, + { url = "https://files.pythonhosted.org/packages/0b/6b/73dbde0dd38f3782905d4587049b9be64d76671042fdcaf60e2430c6796d/psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377", size = 248985 }, + { url = "https://files.pythonhosted.org/packages/17/38/c319d31a1d3f88c5b79c68b3116c129e5133f1822157dd6da34043e32ed6/psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003", size = 284488 }, + { url = "https://files.pythonhosted.org/packages/9c/39/0f88a830a1c8a3aba27fededc642da37613c57cbff143412e3536f89784f/psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160", size = 287477 }, + { url = "https://files.pythonhosted.org/packages/47/da/99f4345d4ddf2845cb5b5bd0d93d554e84542d116934fde07a0c50bd4e9f/psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3", size = 289017 }, + { url = "https://files.pythonhosted.org/packages/38/53/bd755c2896f4461fd4f36fa6a6dcb66a88a9e4b9fd4e5b66a77cf9d4a584/psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53", size = 250602 }, + { url = "https://files.pythonhosted.org/packages/7b/d7/7831438e6c3ebbfa6e01a927127a6cb42ad3ab844247f3c5b96bea25d73d/psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649", size = 254444 }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993 }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842 }, +] + +[[package]] +name = "py-cpuinfo" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335 }, +] + +[[package]] +name = "pybind11" +version = "2.13.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d2/c1/72b9622fcb32ff98b054f724e213c7f70d6898baa714f4516288456ceaba/pybind11-2.13.6.tar.gz", hash = "sha256:ba6af10348c12b24e92fa086b39cfba0eff619b61ac77c406167d813b096d39a", size = 218403 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/2f/0f24b288e2ce56f51c920137620b4434a38fd80583dbbe24fc2a1656c388/pybind11-2.13.6-py3-none-any.whl", hash = "sha256:237c41e29157b962835d356b370ededd57594a26d5894a795960f0047cb5caf5", size = 243282 }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, +] + +[[package]] +name = "pydantic" +version = "2.10.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 }, +] + +[[package]] +name = "pydantic-core" +version = "2.27.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/bc/fed5f74b5d802cf9a03e83f60f18864e90e3aed7223adaca5ffb7a8d8d64/pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", size = 1895938 }, + { url = "https://files.pythonhosted.org/packages/71/2a/185aff24ce844e39abb8dd680f4e959f0006944f4a8a0ea372d9f9ae2e53/pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", size = 1815684 }, + { url = "https://files.pythonhosted.org/packages/c3/43/fafabd3d94d159d4f1ed62e383e264f146a17dd4d48453319fd782e7979e/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", size = 1829169 }, + { url = "https://files.pythonhosted.org/packages/a2/d1/f2dfe1a2a637ce6800b799aa086d079998959f6f1215eb4497966efd2274/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", size = 1867227 }, + { url = "https://files.pythonhosted.org/packages/7d/39/e06fcbcc1c785daa3160ccf6c1c38fea31f5754b756e34b65f74e99780b5/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", size = 2037695 }, + { url = "https://files.pythonhosted.org/packages/7a/67/61291ee98e07f0650eb756d44998214231f50751ba7e13f4f325d95249ab/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", size = 2741662 }, + { url = "https://files.pythonhosted.org/packages/32/90/3b15e31b88ca39e9e626630b4c4a1f5a0dfd09076366f4219429e6786076/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", size = 1993370 }, + { url = "https://files.pythonhosted.org/packages/ff/83/c06d333ee3a67e2e13e07794995c1535565132940715931c1c43bfc85b11/pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", size = 1996813 }, + { url = "https://files.pythonhosted.org/packages/7c/f7/89be1c8deb6e22618a74f0ca0d933fdcb8baa254753b26b25ad3acff8f74/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", size = 2005287 }, + { url = "https://files.pythonhosted.org/packages/b7/7d/8eb3e23206c00ef7feee17b83a4ffa0a623eb1a9d382e56e4aa46fd15ff2/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", size = 2128414 }, + { url = "https://files.pythonhosted.org/packages/4e/99/fe80f3ff8dd71a3ea15763878d464476e6cb0a2db95ff1c5c554133b6b83/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", size = 2155301 }, + { url = "https://files.pythonhosted.org/packages/2b/a3/e50460b9a5789ca1451b70d4f52546fa9e2b420ba3bfa6100105c0559238/pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", size = 1816685 }, + { url = "https://files.pythonhosted.org/packages/57/4c/a8838731cb0f2c2a39d3535376466de6049034d7b239c0202a64aaa05533/pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", size = 1982876 }, + { url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421 }, + { url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998 }, + { url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167 }, + { url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071 }, + { url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244 }, + { url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470 }, + { url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291 }, + { url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613 }, + { url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355 }, + { url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661 }, + { url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261 }, + { url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 }, + { url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 }, + { url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 }, + { url = "https://files.pythonhosted.org/packages/46/72/af70981a341500419e67d5cb45abe552a7c74b66326ac8877588488da1ac/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", size = 1891159 }, + { url = "https://files.pythonhosted.org/packages/ad/3d/c5913cccdef93e0a6a95c2d057d2c2cba347815c845cda79ddd3c0f5e17d/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", size = 1768331 }, + { url = "https://files.pythonhosted.org/packages/f6/f0/a3ae8fbee269e4934f14e2e0e00928f9346c5943174f2811193113e58252/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", size = 1822467 }, + { url = "https://files.pythonhosted.org/packages/d7/7a/7bbf241a04e9f9ea24cd5874354a83526d639b02674648af3f350554276c/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", size = 1979797 }, + { url = "https://files.pythonhosted.org/packages/4f/5f/4784c6107731f89e0005a92ecb8a2efeafdb55eb992b8e9d0a2be5199335/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", size = 1987839 }, + { url = "https://files.pythonhosted.org/packages/6d/a7/61246562b651dff00de86a5f01b6e4befb518df314c54dec187a78d81c84/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", size = 1998861 }, + { url = "https://files.pythonhosted.org/packages/86/aa/837821ecf0c022bbb74ca132e117c358321e72e7f9702d1b6a03758545e2/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", size = 2116582 }, + { url = "https://files.pythonhosted.org/packages/81/b0/5e74656e95623cbaa0a6278d16cf15e10a51f6002e3ec126541e95c29ea3/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", size = 2151985 }, + { url = "https://files.pythonhosted.org/packages/63/37/3e32eeb2a451fddaa3898e2163746b0cffbbdbb4740d38372db0490d67f3/pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", size = 2004715 }, +] + +[[package]] +name = "pydantic-settings" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718 }, +] + +[[package]] +name = "pydot" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/dd/e0e6a4fb84c22050f6a9701ad9fd6a67ef82faa7ba97b97eb6fdc6b49b34/pydot-3.0.4.tar.gz", hash = "sha256:3ce88b2558f3808b0376f22bfa6c263909e1c3981e2a7b629b65b451eee4a25d", size = 168167 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/5f/1ebfd430df05c4f9e438dd3313c4456eab937d976f6ab8ce81a98f9fb381/pydot-3.0.4-py3-none-any.whl", hash = "sha256:bfa9c3fc0c44ba1d132adce131802d7df00429d1a79cc0346b0a5cd374dbe9c6", size = 35776 }, +] + +[[package]] +name = "pygls" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cattrs" }, + { name = "lsprotocol" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/b9/41d173dad9eaa9db9c785a85671fc3d68961f08d67706dc2e79011e10b5c/pygls-1.3.1.tar.gz", hash = "sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018", size = 45527 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/19/b74a10dd24548e96e8c80226cbacb28b021bc3a168a7d2709fb0d0185348/pygls-1.3.1-py3-none-any.whl", hash = "sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e", size = 56031 }, +] + +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, +] + +[[package]] +name = "pyparsing" +version = "3.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716 }, +] + +[[package]] +name = "pyreadline" +version = "2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/7c/d724ef1ec3ab2125f38a1d53285745445ec4a8f19b9bb0761b4064316679/pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1", size = 109189 } + +[[package]] +name = "pyspellchecker" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/42/5d/86d94aceb9c0813f27004ec71c036d8ec6a6324d989854ff0fe13fe036dc/pyspellchecker-0.8.2.tar.gz", hash = "sha256:2b026be14a162ba810bdda8e5454c56e364f42d3b9e14aeff31706e5ebcdc78f", size = 7149207 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/8e/7c79443d302a80cfd59bc365938d51e36e7e9aa7ce8ab1d8a0ca0c8e6065/pyspellchecker-0.8.2-py3-none-any.whl", hash = "sha256:4fee22e1859c5153c3bc3953ac3041bf07d4541520b7e01901e955062022290a", size = 7147898 }, +] + +[[package]] +name = "pytest" +version = "8.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, +] + +[[package]] +name = "pytest-benchmark" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "py-cpuinfo" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/d0/a8bd08d641b393db3be3819b03e2d9bb8760ca8479080a26a5f6e540e99c/pytest-benchmark-5.1.0.tar.gz", hash = "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105", size = 337810 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/d6/b41653199ea09d5969d4e385df9bbfd9a100f28ca7e824ce7c0a016e3053/pytest_benchmark-5.1.0-py3-none-any.whl", hash = "sha256:922de2dfa3033c227c96da942d1878191afa135a29485fb942e85dff1c592c89", size = 44259 }, +] + +[[package]] +name = "pytest-cache" +version = "1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/15/082fd0428aab33d2bafa014f3beb241830427ba803a8912a5aaeaf3a5663/pytest-cache-1.0.tar.gz", hash = "sha256:be7468edd4d3d83f1e844959fd6e3fd28e77a481440a7118d430130ea31b07a9", size = 16242 } + +[[package]] +name = "pytest-cov" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, +] + +[[package]] +name = "pytest-factoryboy" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "factory-boy" }, + { name = "inflection" }, + { name = "packaging" }, + { name = "pytest" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/bc/179653e8cce651575ac95377e4fdf9afd3c4821ab4bba101aae913ebcc27/pytest_factoryboy-2.7.0.tar.gz", hash = "sha256:67fc54ec8669a3feb8ac60094dd57cd71eb0b20b2c319d2957873674c776a77b", size = 17398 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/56/d3ef25286dc8df9d1da0b325ee4b1b1ffd9736e44f9b30cfbe464e9f4f14/pytest_factoryboy-2.7.0-py3-none-any.whl", hash = "sha256:bf3222db22d954fbf46f4bff902a0a8d82f3fc3594a47c04bbdc0546ff4c59a6", size = 16268 }, +] + +[[package]] +name = "pytest-instafail" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/bd/e0ba6c3cd20b9aa445f0af229f3a9582cce589f083537978a23e6f14e310/pytest-instafail-0.5.0.tar.gz", hash = "sha256:33a606f7e0c8e646dc3bfee0d5e3a4b7b78ef7c36168cfa1f3d93af7ca706c9e", size = 5849 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/c0/c32dc39fc172e684fdb3d30169843efb65c067be1e12689af4345731126e/pytest_instafail-0.5.0-py3-none-any.whl", hash = "sha256:6855414487e9e4bb76a118ce952c3c27d3866af15487506c4ded92eb72387819", size = 4176 }, +] + +[[package]] +name = "pytest-xdist" +version = "3.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/c4/3c310a19bc1f1e9ef50075582652673ef2bfc8cd62afef9585683821902f/pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d", size = 84060 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/82/1d96bf03ee4c0fdc3c0cbe61470070e659ca78dc0086fb88b66c185e2449/pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", size = 46108 }, +] + +[package.optional-dependencies] +psutil = [ + { name = "psutil" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, +] + +[[package]] +name = "python-dotenv" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, +] + +[[package]] +name = "pywin32" +version = "308" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/a6/3e9f2c474895c1bb61b11fa9640be00067b5c5b363c501ee9c3fa53aec01/pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e", size = 5927028 }, + { url = "https://files.pythonhosted.org/packages/d9/b4/84e2463422f869b4b718f79eb7530a4c1693e96b8a4e5e968de38be4d2ba/pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e", size = 6558484 }, + { url = "https://files.pythonhosted.org/packages/9f/8f/fb84ab789713f7c6feacaa08dad3ec8105b88ade8d1c4f0f0dfcaaa017d6/pywin32-308-cp310-cp310-win_arm64.whl", hash = "sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c", size = 7971454 }, + { url = "https://files.pythonhosted.org/packages/eb/e2/02652007469263fe1466e98439831d65d4ca80ea1a2df29abecedf7e47b7/pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a", size = 5928156 }, + { url = "https://files.pythonhosted.org/packages/48/ef/f4fb45e2196bc7ffe09cad0542d9aff66b0e33f6c0954b43e49c33cad7bd/pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b", size = 6559559 }, + { url = "https://files.pythonhosted.org/packages/79/ef/68bb6aa865c5c9b11a35771329e95917b5559845bd75b65549407f9fc6b4/pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6", size = 7972495 }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199 }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758 }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463 }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280 }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239 }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802 }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527 }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052 }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774 }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, +] + +[[package]] +name = "pyzmq" +version = "26.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/05/bed626b9f7bb2322cdbbf7b4bd8f54b1b617b0d2ab2d3547d6e39428a48e/pyzmq-26.2.0.tar.gz", hash = "sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f", size = 271975 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/a8/9837c39aba390eb7d01924ace49d761c8dbe7bc2d6082346d00c8332e431/pyzmq-26.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629", size = 1340058 }, + { url = "https://files.pythonhosted.org/packages/a2/1f/a006f2e8e4f7d41d464272012695da17fb95f33b54342612a6890da96ff6/pyzmq-26.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b", size = 1008818 }, + { url = "https://files.pythonhosted.org/packages/b6/09/b51b6683fde5ca04593a57bbe81788b6b43114d8f8ee4e80afc991e14760/pyzmq-26.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89289a5ee32ef6c439086184529ae060c741334b8970a6855ec0b6ad3ff28764", size = 673199 }, + { url = "https://files.pythonhosted.org/packages/c9/78/486f3e2e824f3a645238332bf5a4c4b4477c3063033a27c1e4052358dee2/pyzmq-26.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5506f06d7dc6ecf1efacb4a013b1f05071bb24b76350832c96449f4a2d95091c", size = 911762 }, + { url = "https://files.pythonhosted.org/packages/5e/3b/2eb1667c9b866f53e76ee8b0c301b0469745a23bd5a87b7ee3d5dd9eb6e5/pyzmq-26.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ea039387c10202ce304af74def5021e9adc6297067f3441d348d2b633e8166a", size = 868773 }, + { url = "https://files.pythonhosted.org/packages/16/29/ca99b4598a9dc7e468b5417eda91f372b595be1e3eec9b7cbe8e5d3584e8/pyzmq-26.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2224fa4a4c2ee872886ed00a571f5e967c85e078e8e8c2530a2fb01b3309b88", size = 868834 }, + { url = "https://files.pythonhosted.org/packages/ad/e5/9efaeb1d2f4f8c50da04144f639b042bc52869d3a206d6bf672ab3522163/pyzmq-26.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:28ad5233e9c3b52d76196c696e362508959741e1a005fb8fa03b51aea156088f", size = 1202861 }, + { url = "https://files.pythonhosted.org/packages/c3/62/c721b5608a8ac0a69bb83cbb7d07a56f3ff00b3991a138e44198a16f94c7/pyzmq-26.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1c17211bc037c7d88e85ed8b7d8f7e52db6dc8eca5590d162717c654550f7282", size = 1515304 }, + { url = "https://files.pythonhosted.org/packages/87/84/e8bd321aa99b72f48d4606fc5a0a920154125bd0a4608c67eab742dab087/pyzmq-26.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b8f86dd868d41bea9a5f873ee13bf5551c94cf6bc51baebc6f85075971fe6eea", size = 1414712 }, + { url = "https://files.pythonhosted.org/packages/cd/cd/420e3fd1ac6977b008b72e7ad2dae6350cc84d4c5027fc390b024e61738f/pyzmq-26.2.0-cp310-cp310-win32.whl", hash = "sha256:46a446c212e58456b23af260f3d9fb785054f3e3653dbf7279d8f2b5546b21c2", size = 578113 }, + { url = "https://files.pythonhosted.org/packages/5c/57/73930d56ed45ae0cb4946f383f985c855c9b3d4063f26416998f07523c0e/pyzmq-26.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:49d34ab71db5a9c292a7644ce74190b1dd5a3475612eefb1f8be1d6961441971", size = 641631 }, + { url = "https://files.pythonhosted.org/packages/61/d2/ae6ac5c397f1ccad59031c64beaafce7a0d6182e0452cc48f1c9c87d2dd0/pyzmq-26.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:bfa832bfa540e5b5c27dcf5de5d82ebc431b82c453a43d141afb1e5d2de025fa", size = 543528 }, + { url = "https://files.pythonhosted.org/packages/12/20/de7442172f77f7c96299a0ac70e7d4fb78cd51eca67aa2cf552b66c14196/pyzmq-26.2.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218", size = 1340639 }, + { url = "https://files.pythonhosted.org/packages/98/4d/5000468bd64c7910190ed0a6c76a1ca59a68189ec1f007c451dc181a22f4/pyzmq-26.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3a495b30fc91db2db25120df5847d9833af237546fd59170701acd816ccc01c4", size = 1008710 }, + { url = "https://files.pythonhosted.org/packages/e1/bf/c67fd638c2f9fbbab8090a3ee779370b97c82b84cc12d0c498b285d7b2c0/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef", size = 673129 }, + { url = "https://files.pythonhosted.org/packages/86/94/99085a3f492aa538161cbf27246e8886ff850e113e0c294a5b8245f13b52/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ace4f71f1900a548f48407fc9be59c6ba9d9aaf658c2eea6cf2779e72f9f317", size = 910107 }, + { url = "https://files.pythonhosted.org/packages/31/1d/346809e8a9b999646d03f21096428453465b1bca5cd5c64ecd048d9ecb01/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92a78853d7280bffb93df0a4a6a2498cba10ee793cc8076ef797ef2f74d107cf", size = 867960 }, + { url = "https://files.pythonhosted.org/packages/ab/68/6fb6ae5551846ad5beca295b7bca32bf0a7ce19f135cb30e55fa2314e6b6/pyzmq-26.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e", size = 869204 }, + { url = "https://files.pythonhosted.org/packages/0f/f9/18417771dee223ccf0f48e29adf8b4e25ba6d0e8285e33bcbce078070bc3/pyzmq-26.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aca98bc423eb7d153214b2df397c6421ba6373d3397b26c057af3c904452e37", size = 1203351 }, + { url = "https://files.pythonhosted.org/packages/e0/46/f13e67fe0d4f8a2315782cbad50493de6203ea0d744610faf4d5f5b16e90/pyzmq-26.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f3496d76b89d9429a656293744ceca4d2ac2a10ae59b84c1da9b5165f429ad3", size = 1514204 }, + { url = "https://files.pythonhosted.org/packages/50/11/ddcf7343b7b7a226e0fc7b68cbf5a5bb56291fac07f5c3023bb4c319ebb4/pyzmq-26.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5c2b3bfd4b9689919db068ac6c9911f3fcb231c39f7dd30e3138be94896d18e6", size = 1414339 }, + { url = "https://files.pythonhosted.org/packages/01/14/1c18d7d5b7be2708f513f37c61bfadfa62161c10624f8733f1c8451b3509/pyzmq-26.2.0-cp311-cp311-win32.whl", hash = "sha256:eac5174677da084abf378739dbf4ad245661635f1600edd1221f150b165343f4", size = 576928 }, + { url = "https://files.pythonhosted.org/packages/3b/1b/0a540edd75a41df14ec416a9a500b9fec66e554aac920d4c58fbd5756776/pyzmq-26.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5", size = 642317 }, + { url = "https://files.pythonhosted.org/packages/98/77/1cbfec0358078a4c5add529d8a70892db1be900980cdb5dd0898b3d6ab9d/pyzmq-26.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0e6091b157d48cbe37bd67233318dbb53e1e6327d6fc3bb284afd585d141003", size = 543834 }, + { url = "https://files.pythonhosted.org/packages/53/fb/36b2b2548286e9444e52fcd198760af99fd89102b5be50f0660fcfe902df/pyzmq-26.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:706e794564bec25819d21a41c31d4df2d48e1cc4b061e8d345d7fb4dd3e94072", size = 906955 }, + { url = "https://files.pythonhosted.org/packages/77/8f/6ce54f8979a01656e894946db6299e2273fcee21c8e5fa57c6295ef11f57/pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b435f2753621cd36e7c1762156815e21c985c72b19135dac43a7f4f31d28dd1", size = 565701 }, + { url = "https://files.pythonhosted.org/packages/ee/1c/bf8cd66730a866b16db8483286078892b7f6536f8c389fb46e4beba0a970/pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:160c7e0a5eb178011e72892f99f918c04a131f36056d10d9c1afb223fc952c2d", size = 794312 }, + { url = "https://files.pythonhosted.org/packages/71/43/91fa4ff25bbfdc914ab6bafa0f03241d69370ef31a761d16bb859f346582/pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4a71d5d6e7b28a47a394c0471b7e77a0661e2d651e7ae91e0cab0a587859ca", size = 752775 }, + { url = "https://files.pythonhosted.org/packages/ec/d2/3b2ab40f455a256cb6672186bea95cd97b459ce4594050132d71e76f0d6f/pyzmq-26.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:90412f2db8c02a3864cbfc67db0e3dcdbda336acf1c469526d3e869394fe001c", size = 550762 }, +] + +[[package]] +name = "questionary" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/b8/d16eb579277f3de9e56e5ad25280fab52fc5774117fb70362e8c2e016559/questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587", size = 26775 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/3f/11dd4cd4f39e05128bfd20138faea57bec56f9ffba6185d276e3107ba5b2/questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec", size = 36747 }, +] + +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775 }, +] + +[[package]] +name = "requests" +version = "2.32.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, +] + +[[package]] +name = "rich" +version = "13.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, +] + +[[package]] +name = "rich-click" +version = "1.8.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/31/103501e85e885e3e202c087fa612cfe450693210372766552ce1ab5b57b9/rich_click-1.8.5.tar.gz", hash = "sha256:a3eebe81da1c9da3c32f3810017c79bd687ff1b3fa35bfc9d8a3338797f1d1a1", size = 38229 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/0b/e2de98c538c0ee9336211d260f88b7e69affab44969750aaca0b48a697c8/rich_click-1.8.5-py3-none-any.whl", hash = "sha256:0fab7bb5b66c15da17c210b4104277cd45f3653a7322e0098820a169880baee0", size = 35081 }, +] + +[[package]] +name = "rpds-py" +version = "0.22.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/80/cce854d0921ff2f0a9fa831ba3ad3c65cee3a46711addf39a2af52df2cfd/rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d", size = 26771 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/2a/ead1d09e57449b99dcc190d8d2323e3a167421d8f8fdf0f217c6f6befe47/rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967", size = 359514 }, + { url = "https://files.pythonhosted.org/packages/8f/7e/1254f406b7793b586c68e217a6a24ec79040f85e030fff7e9049069284f4/rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37", size = 349031 }, + { url = "https://files.pythonhosted.org/packages/aa/da/17c6a2c73730d426df53675ff9cc6653ac7a60b6438d03c18e1c822a576a/rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24", size = 381485 }, + { url = "https://files.pythonhosted.org/packages/aa/13/2dbacd820466aa2a3c4b747afb18d71209523d353cf865bf8f4796c969ea/rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff", size = 386794 }, + { url = "https://files.pythonhosted.org/packages/6d/62/96905d0a35ad4e4bc3c098b2f34b2e7266e211d08635baa690643d2227be/rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c", size = 423523 }, + { url = "https://files.pythonhosted.org/packages/eb/1b/d12770f2b6a9fc2c3ec0d810d7d440f6d465ccd8b7f16ae5385952c28b89/rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e", size = 446695 }, + { url = "https://files.pythonhosted.org/packages/4d/cf/96f1fd75512a017f8e07408b6d5dbeb492d9ed46bfe0555544294f3681b3/rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec", size = 381959 }, + { url = "https://files.pythonhosted.org/packages/ab/f0/d1c5b501c8aea85aeb938b555bfdf7612110a2f8cdc21ae0482c93dd0c24/rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c", size = 410420 }, + { url = "https://files.pythonhosted.org/packages/33/3b/45b6c58fb6aad5a569ae40fb890fc494c6b02203505a5008ee6dc68e65f7/rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09", size = 557620 }, + { url = "https://files.pythonhosted.org/packages/83/62/3fdd2d3d47bf0bb9b931c4c73036b4ab3ec77b25e016ae26fab0f02be2af/rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00", size = 584202 }, + { url = "https://files.pythonhosted.org/packages/04/f2/5dced98b64874b84ca824292f9cee2e3f30f3bcf231d15a903126684f74d/rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf", size = 552787 }, + { url = "https://files.pythonhosted.org/packages/67/13/2273dea1204eda0aea0ef55145da96a9aa28b3f88bb5c70e994f69eda7c3/rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652", size = 220088 }, + { url = "https://files.pythonhosted.org/packages/4e/80/8c8176b67ad7f4a894967a7a4014ba039626d96f1d4874d53e409b58d69f/rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8", size = 231737 }, + { url = "https://files.pythonhosted.org/packages/15/ad/8d1ddf78f2805a71253fcd388017e7b4a0615c22c762b6d35301fef20106/rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f", size = 359773 }, + { url = "https://files.pythonhosted.org/packages/c8/75/68c15732293a8485d79fe4ebe9045525502a067865fa4278f178851b2d87/rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a", size = 349214 }, + { url = "https://files.pythonhosted.org/packages/3c/4c/7ce50f3070083c2e1b2bbd0fb7046f3da55f510d19e283222f8f33d7d5f4/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5", size = 380477 }, + { url = "https://files.pythonhosted.org/packages/9a/e9/835196a69cb229d5c31c13b8ae603bd2da9a6695f35fe4270d398e1db44c/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb", size = 386171 }, + { url = "https://files.pythonhosted.org/packages/f9/8e/33fc4eba6683db71e91e6d594a2cf3a8fbceb5316629f0477f7ece5e3f75/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2", size = 422676 }, + { url = "https://files.pythonhosted.org/packages/37/47/2e82d58f8046a98bb9497a8319604c92b827b94d558df30877c4b3c6ccb3/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0", size = 446152 }, + { url = "https://files.pythonhosted.org/packages/e1/78/79c128c3e71abbc8e9739ac27af11dc0f91840a86fce67ff83c65d1ba195/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1", size = 381300 }, + { url = "https://files.pythonhosted.org/packages/c9/5b/2e193be0e8b228c1207f31fa3ea79de64dadb4f6a4833111af8145a6bc33/rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d", size = 409636 }, + { url = "https://files.pythonhosted.org/packages/c2/3f/687c7100b762d62186a1c1100ffdf99825f6fa5ea94556844bbbd2d0f3a9/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648", size = 556708 }, + { url = "https://files.pythonhosted.org/packages/8c/a2/c00cbc4b857e8b3d5e7f7fc4c81e23afd8c138b930f4f3ccf9a41a23e9e4/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74", size = 583554 }, + { url = "https://files.pythonhosted.org/packages/d0/08/696c9872cf56effdad9ed617ac072f6774a898d46b8b8964eab39ec562d2/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a", size = 552105 }, + { url = "https://files.pythonhosted.org/packages/18/1f/4df560be1e994f5adf56cabd6c117e02de7c88ee238bb4ce03ed50da9d56/rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64", size = 220199 }, + { url = "https://files.pythonhosted.org/packages/b8/1b/c29b570bc5db8237553002788dc734d6bd71443a2ceac2a58202ec06ef12/rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c", size = 231775 }, + { url = "https://files.pythonhosted.org/packages/8b/63/e29f8ee14fcf383574f73b6bbdcbec0fbc2e5fc36b4de44d1ac389b1de62/rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d", size = 360786 }, + { url = "https://files.pythonhosted.org/packages/d3/e0/771ee28b02a24e81c8c0e645796a371350a2bb6672753144f36ae2d2afc9/rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd", size = 350589 }, + { url = "https://files.pythonhosted.org/packages/cf/49/abad4c4a1e6f3adf04785a99c247bfabe55ed868133e2d1881200aa5d381/rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493", size = 381848 }, + { url = "https://files.pythonhosted.org/packages/3a/7d/f4bc6d6fbe6af7a0d2b5f2ee77079efef7c8528712745659ec0026888998/rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96", size = 387879 }, + { url = "https://files.pythonhosted.org/packages/13/b0/575c797377fdcd26cedbb00a3324232e4cb2c5d121f6e4b0dbf8468b12ef/rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123", size = 423916 }, + { url = "https://files.pythonhosted.org/packages/54/78/87157fa39d58f32a68d3326f8a81ad8fb99f49fe2aa7ad9a1b7d544f9478/rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad", size = 448410 }, + { url = "https://files.pythonhosted.org/packages/59/69/860f89996065a88be1b6ff2d60e96a02b920a262d8aadab99e7903986597/rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9", size = 382841 }, + { url = "https://files.pythonhosted.org/packages/bd/d7/bc144e10d27e3cb350f98df2492a319edd3caaf52ddfe1293f37a9afbfd7/rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e", size = 409662 }, + { url = "https://files.pythonhosted.org/packages/14/2a/6bed0b05233c291a94c7e89bc76ffa1c619d4e1979fbfe5d96024020c1fb/rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338", size = 558221 }, + { url = "https://files.pythonhosted.org/packages/11/23/cd8f566de444a137bc1ee5795e47069a947e60810ba4152886fe5308e1b7/rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566", size = 583780 }, + { url = "https://files.pythonhosted.org/packages/8d/63/79c3602afd14d501f751e615a74a59040328da5ef29ed5754ae80d236b84/rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe", size = 553619 }, + { url = "https://files.pythonhosted.org/packages/9f/2e/c5c1689e80298d4e94c75b70faada4c25445739d91b94c211244a3ed7ed1/rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d", size = 233338 }, +] + +[[package]] +name = "ruamel-yaml" +version = "0.18.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ruamel-yaml-clib", marker = "platform_python_implementation == 'CPython' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729 }, +] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5", size = 131301 }, + { url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969", size = 633728 }, + { url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df", size = 722230 }, + { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712 }, + { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936 }, + { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580 }, + { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393 }, + { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326 }, + { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079 }, + { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224 }, + { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480 }, + { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068 }, + { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012 }, + { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352 }, + { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344 }, + { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498 }, + { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205 }, + { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185 }, +] + +[[package]] +name = "ruff" +version = "0.9.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/7f/60fda2eec81f23f8aa7cbbfdf6ec2ca11eb11c273827933fb2541c2ce9d8/ruff-0.9.3.tar.gz", hash = "sha256:8293f89985a090ebc3ed1064df31f3b4b56320cdfcec8b60d3295bddb955c22a", size = 3586740 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/77/4fb790596d5d52c87fd55b7160c557c400e90f6116a56d82d76e95d9374a/ruff-0.9.3-py3-none-linux_armv6l.whl", hash = "sha256:7f39b879064c7d9670197d91124a75d118d00b0990586549949aae80cdc16624", size = 11656815 }, + { url = "https://files.pythonhosted.org/packages/a2/a8/3338ecb97573eafe74505f28431df3842c1933c5f8eae615427c1de32858/ruff-0.9.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a187171e7c09efa4b4cc30ee5d0d55a8d6c5311b3e1b74ac5cb96cc89bafc43c", size = 11594821 }, + { url = "https://files.pythonhosted.org/packages/8e/89/320223c3421962762531a6b2dd58579b858ca9916fb2674874df5e97d628/ruff-0.9.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c59ab92f8e92d6725b7ded9d4a31be3ef42688a115c6d3da9457a5bda140e2b4", size = 11040475 }, + { url = "https://files.pythonhosted.org/packages/b2/bd/1d775eac5e51409535804a3a888a9623e87a8f4b53e2491580858a083692/ruff-0.9.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc153c25e715be41bb228bc651c1e9b1a88d5c6e5ed0194fa0dfea02b026439", size = 11856207 }, + { url = "https://files.pythonhosted.org/packages/7f/c6/3e14e09be29587393d188454064a4aa85174910d16644051a80444e4fd88/ruff-0.9.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:646909a1e25e0dc28fbc529eab8eb7bb583079628e8cbe738192853dbbe43af5", size = 11420460 }, + { url = "https://files.pythonhosted.org/packages/ef/42/b7ca38ffd568ae9b128a2fa76353e9a9a3c80ef19746408d4ce99217ecc1/ruff-0.9.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a5a46e09355695fbdbb30ed9889d6cf1c61b77b700a9fafc21b41f097bfbba4", size = 12605472 }, + { url = "https://files.pythonhosted.org/packages/a6/a1/3167023f23e3530fde899497ccfe239e4523854cb874458ac082992d206c/ruff-0.9.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c4bb09d2bbb394e3730d0918c00276e79b2de70ec2a5231cd4ebb51a57df9ba1", size = 13243123 }, + { url = "https://files.pythonhosted.org/packages/d0/b4/3c600758e320f5bf7de16858502e849f4216cb0151f819fa0d1154874802/ruff-0.9.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96a87ec31dc1044d8c2da2ebbed1c456d9b561e7d087734336518181b26b3aa5", size = 12744650 }, + { url = "https://files.pythonhosted.org/packages/be/38/266fbcbb3d0088862c9bafa8b1b99486691d2945a90b9a7316336a0d9a1b/ruff-0.9.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bb7554aca6f842645022fe2d301c264e6925baa708b392867b7a62645304df4", size = 14458585 }, + { url = "https://files.pythonhosted.org/packages/63/a6/47fd0e96990ee9b7a4abda62de26d291bd3f7647218d05b7d6d38af47c30/ruff-0.9.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cabc332b7075a914ecea912cd1f3d4370489c8018f2c945a30bcc934e3bc06a6", size = 12419624 }, + { url = "https://files.pythonhosted.org/packages/84/5d/de0b7652e09f7dda49e1a3825a164a65f4998175b6486603c7601279baad/ruff-0.9.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:33866c3cc2a575cbd546f2cd02bdd466fed65118e4365ee538a3deffd6fcb730", size = 11843238 }, + { url = "https://files.pythonhosted.org/packages/9e/be/3f341ceb1c62b565ec1fb6fd2139cc40b60ae6eff4b6fb8f94b1bb37c7a9/ruff-0.9.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:006e5de2621304c8810bcd2ee101587712fa93b4f955ed0985907a36c427e0c2", size = 11484012 }, + { url = "https://files.pythonhosted.org/packages/a3/c8/ff8acbd33addc7e797e702cf00bfde352ab469723720c5607b964491d5cf/ruff-0.9.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ba6eea4459dbd6b1be4e6bfc766079fb9b8dd2e5a35aff6baee4d9b1514ea519", size = 12038494 }, + { url = "https://files.pythonhosted.org/packages/73/b1/8d9a2c0efbbabe848b55f877bc10c5001a37ab10aca13c711431673414e5/ruff-0.9.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:90230a6b8055ad47d3325e9ee8f8a9ae7e273078a66401ac66df68943ced029b", size = 12473639 }, + { url = "https://files.pythonhosted.org/packages/cb/44/a673647105b1ba6da9824a928634fe23186ab19f9d526d7bdf278cd27bc3/ruff-0.9.3-py3-none-win32.whl", hash = "sha256:eabe5eb2c19a42f4808c03b82bd313fc84d4e395133fb3fc1b1516170a31213c", size = 9834353 }, + { url = "https://files.pythonhosted.org/packages/c3/01/65cadb59bf8d4fbe33d1a750103e6883d9ef302f60c28b73b773092fbde5/ruff-0.9.3-py3-none-win_amd64.whl", hash = "sha256:040ceb7f20791dfa0e78b4230ee9dce23da3b64dd5848e40e3bf3ab76468dcf4", size = 10821444 }, + { url = "https://files.pythonhosted.org/packages/69/cb/b3fe58a136a27d981911cba2f18e4b29f15010623b79f0f2510fd0d31fd3/ruff-0.9.3-py3-none-win_arm64.whl", hash = "sha256:800d773f6d4d33b0a3c60e2c6ae8f4c202ea2de056365acfa519aa48acf28e0b", size = 10038168 }, +] + +[[package]] +name = "scipy" +version = "1.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/c6/8eb0654ba0c7d0bb1bf67bf8fbace101a8e4f250f7722371105e8b6f68fc/scipy-1.15.1.tar.gz", hash = "sha256:033a75ddad1463970c96a88063a1df87ccfddd526437136b6ee81ff0312ebdf6", size = 59407493 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/53/b204ce5a4433f1864001b9d16f103b9c25f5002a602ae83585d0ea5f9c4a/scipy-1.15.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:c64ded12dcab08afff9e805a67ff4480f5e69993310e093434b10e85dc9d43e1", size = 41414518 }, + { url = "https://files.pythonhosted.org/packages/c7/fc/54ffa7a8847f7f303197a6ba65a66104724beba2e38f328135a78f0dc480/scipy-1.15.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5b190b935e7db569960b48840e5bef71dc513314cc4e79a1b7d14664f57fd4ff", size = 32519265 }, + { url = "https://files.pythonhosted.org/packages/f1/77/a98b8ba03d6f371dc31a38719affd53426d4665729dcffbed4afe296784a/scipy-1.15.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:4b17d4220df99bacb63065c76b0d1126d82bbf00167d1730019d2a30d6ae01ea", size = 24792859 }, + { url = "https://files.pythonhosted.org/packages/a7/78/70bb9f0df7444b18b108580934bfef774822e28fd34a68e5c263c7d2828a/scipy-1.15.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:63b9b6cd0333d0eb1a49de6f834e8aeaefe438df8f6372352084535ad095219e", size = 27886506 }, + { url = "https://files.pythonhosted.org/packages/14/a7/f40f6033e06de4176ddd6cc8c3ae9f10a226c3bca5d6b4ab883bc9914a14/scipy-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f151e9fb60fbf8e52426132f473221a49362091ce7a5e72f8aa41f8e0da4f25", size = 38375041 }, + { url = "https://files.pythonhosted.org/packages/17/03/390a1c5c61fd76b0fa4b3c5aa3bdd7e60f6c46f712924f1a9df5705ec046/scipy-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21e10b1dd56ce92fba3e786007322542361984f8463c6d37f6f25935a5a6ef52", size = 40597556 }, + { url = "https://files.pythonhosted.org/packages/4e/70/fa95b3ae026b97eeca58204a90868802e5155ac71b9d7bdee92b68115dd3/scipy-1.15.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5dff14e75cdbcf07cdaa1c7707db6017d130f0af9ac41f6ce443a93318d6c6e0", size = 42938505 }, + { url = "https://files.pythonhosted.org/packages/d6/07/427859116bdd71847c898180f01802691f203c3e2455a1eb496130ff07c5/scipy-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:f82fcf4e5b377f819542fbc8541f7b5fbcf1c0017d0df0bc22c781bf60abc4d8", size = 43909663 }, + { url = "https://files.pythonhosted.org/packages/8e/2e/7b71312da9c2dabff53e7c9a9d08231bc34d9d8fdabe88a6f1155b44591c/scipy-1.15.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:5bd8d27d44e2c13d0c1124e6a556454f52cd3f704742985f6b09e75e163d20d2", size = 41424362 }, + { url = "https://files.pythonhosted.org/packages/81/8c/ab85f1aa1cc200c796532a385b6ebf6a81089747adc1da7482a062acc46c/scipy-1.15.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:be3deeb32844c27599347faa077b359584ba96664c5c79d71a354b80a0ad0ce0", size = 32535910 }, + { url = "https://files.pythonhosted.org/packages/3b/9c/6f4b787058daa8d8da21ddff881b4320e28de4704a65ec147adb50cb2230/scipy-1.15.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:5eb0ca35d4b08e95da99a9f9c400dc9f6c21c424298a0ba876fdc69c7afacedf", size = 24809398 }, + { url = "https://files.pythonhosted.org/packages/16/2b/949460a796df75fc7a1ee1becea202cf072edbe325ebe29f6d2029947aa7/scipy-1.15.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:74bb864ff7640dea310a1377d8567dc2cb7599c26a79ca852fc184cc851954ac", size = 27918045 }, + { url = "https://files.pythonhosted.org/packages/5f/36/67fe249dd7ccfcd2a38b25a640e3af7e59d9169c802478b6035ba91dfd6d/scipy-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:667f950bf8b7c3a23b4199db24cb9bf7512e27e86d0e3813f015b74ec2c6e3df", size = 38332074 }, + { url = "https://files.pythonhosted.org/packages/fc/da/452e1119e6f720df3feb588cce3c42c5e3d628d4bfd4aec097bd30b7de0c/scipy-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395be70220d1189756068b3173853029a013d8c8dd5fd3d1361d505b2aa58fa7", size = 40588469 }, + { url = "https://files.pythonhosted.org/packages/7f/71/5f94aceeac99a4941478af94fe9f459c6752d497035b6b0761a700f5f9ff/scipy-1.15.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce3a000cd28b4430426db2ca44d96636f701ed12e2b3ca1f2b1dd7abdd84b39a", size = 42965214 }, + { url = "https://files.pythonhosted.org/packages/af/25/caa430865749d504271757cafd24066d596217e83326155993980bc22f97/scipy-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:3fe1d95944f9cf6ba77aa28b82dd6bb2a5b52f2026beb39ecf05304b8392864b", size = 43896034 }, +] + +[[package]] +name = "setuptools" +version = "75.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ec/089608b791d210aec4e7f97488e67ab0d33add3efccb83a056cbafe3a2a6/setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", size = 1343222 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8a/b9dc7678803429e4a3bc9ba462fa3dd9066824d3c607490235c6a796be5a/setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3", size = 1228782 }, +] + +[[package]] +name = "setuptools-scm" +version = "8.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "setuptools" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/a4/00a9ac1b555294710d4a68d2ce8dfdf39d72aa4d769a7395d05218d88a42/setuptools_scm-8.1.0.tar.gz", hash = "sha256:42dea1b65771cba93b7a515d65a65d8246e560768a66b9106a592c8e7f26c8a7", size = 76465 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/b9/1906bfeb30f2fc13bb39bf7ddb8749784c05faadbd18a21cf141ba37bff2/setuptools_scm-8.1.0-py3-none-any.whl", hash = "sha256:897a3226a6fd4a6eb2f068745e49733261a21f70b1bb28fce0339feb978d9af3", size = 43666 }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, +] + +[[package]] +name = "smmap" +version = "5.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303 }, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/44/7b/af302bebf22c749c56c9c3e8ae13190b5b5db37a33d9068652e8f73b7089/snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", size = 86699 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a", size = 93002 }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, +] + +[[package]] +name = "soupsieve" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, +] + +[[package]] +name = "sphinx" +version = "8.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-jax-cuda12') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-cuda11' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm4-3') or (extra == 'extra-5-gt4py-jax-cuda12' and extra == 'extra-5-gt4py-rocm5-0') or (extra == 'extra-5-gt4py-rocm4-3' and extra == 'extra-5-gt4py-rocm5-0')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125 }, +] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/f0/43c6a5ff3e7b08a8c3b32f81b859f1b518ccc31e45f22e2b41ced38be7b9/sphinx_autodoc_typehints-3.0.1.tar.gz", hash = "sha256:b9b40dd15dee54f6f810c924f863f9cf1c54f9f3265c495140ea01be7f44fa55", size = 36282 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/dc/dc46c5c7c566b7ec5e8f860f9c89533bf03c0e6aadc96fb9b337867e4460/sphinx_autodoc_typehints-3.0.1-py3-none-any.whl", hash = "sha256:4b64b676a14b5b79cefb6628a6dc8070e320d4963e8ff640a2f3e9390ae9045a", size = 20245 }, +] + +[[package]] +name = "sphinx-jinja2-compat" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/df/27282da6f8c549f765beca9de1a5fc56f9651ed87711a5cac1e914137753/sphinx_jinja2_compat-0.3.0.tar.gz", hash = "sha256:f3c1590b275f42e7a654e081db5e3e5fb97f515608422bde94015ddf795dfe7c", size = 4998 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/42/2fd09d672eaaa937d6893d8b747d07943f97a6e5e30653aee6ebd339b704/sphinx_jinja2_compat-0.3.0-py3-none-any.whl", hash = "sha256:b1e4006d8e1ea31013fa9946d1b075b0c8d2a42c6e3425e63542c1e9f8be9084", size = 7883 }, +] + +[[package]] +name = "sphinx-prompt" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "docutils" }, + { name = "idna" }, + { name = "pygments" }, + { name = "sphinx" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/fe/ac4e24f35b5148b31ac717ae7dcc7a2f7ec56eb729e22c7252ed8ad2d9a5/sphinx_prompt-1.9.0.tar.gz", hash = "sha256:471b3c6d466dce780a9b167d9541865fd4e9a80ed46e31b06a52a0529ae995a1", size = 5340 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/98/e90ca466e0ede452d3e5a8d92b8fb68db6de269856e019ed9cab69440522/sphinx_prompt-1.9.0-py3-none-any.whl", hash = "sha256:fd731446c03f043d1ff6df9f22414495b23067c67011cc21658ea8d36b3575fc", size = 7311 }, +] + +[[package]] +name = "sphinx-rtd-theme" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "sphinx" }, + { name = "sphinxcontrib-jquery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/91/44/c97faec644d29a5ceddd3020ae2edffa69e7d00054a8c7a6021e82f20335/sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85", size = 7620463 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/77/46e3bac77b82b4df5bb5b61f2de98637724f246b4966cfc34bc5895d852a/sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13", size = 7655561 }, +] + +[[package]] +name = "sphinx-tabs" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "pygments" }, + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/32/ab475e252dc2b704e82a91141fa404cdd8901a5cf34958fd22afacebfccd/sphinx-tabs-3.4.5.tar.gz", hash = "sha256:ba9d0c1e3e37aaadd4b5678449eb08176770e0fc227e769b6ce747df3ceea531", size = 16070 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/9f/4ac7dbb9f23a2ff5a10903a4f9e9f43e0ff051f63a313e989c962526e305/sphinx_tabs-3.4.5-py3-none-any.whl", hash = "sha256:92cc9473e2ecf1828ca3f6617d0efc0aa8acb06b08c56ba29d1413f2f0f6cf09", size = 9904 }, +] + +[[package]] +name = "sphinx-toolbox" +version = "3.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "apeye" }, + { name = "autodocsumm" }, + { name = "beautifulsoup4" }, + { name = "cachecontrol", extra = ["filecache"] }, + { name = "dict2css" }, + { name = "docutils" }, + { name = "domdf-python-tools" }, + { name = "filelock" }, + { name = "html5lib" }, + { name = "ruamel-yaml" }, + { name = "sphinx" }, + { name = "sphinx-autodoc-typehints" }, + { name = "sphinx-jinja2-compat" }, + { name = "sphinx-prompt" }, + { name = "sphinx-tabs" }, + { name = "tabulate" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/80/f837e85c8c216cdeef9b60393e4b00c9092a1e3d734106e0021abbf5930c/sphinx_toolbox-3.8.1.tar.gz", hash = "sha256:a4b39a6ea24fc8f10e24f052199bda17837a0bf4c54163a56f521552395f5e1a", size = 111977 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/d6/2a28ee4cbc158ae65afb2cfcb6895ef54d972ce1e167f8a63c135b14b080/sphinx_toolbox-3.8.1-py3-none-any.whl", hash = "sha256:53d8e77dd79e807d9ef18590c4b2960a5aa3c147415054b04c31a91afed8b88b", size = 194621 }, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300 }, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530 }, +] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705 }, +] + +[[package]] +name = "sphinxcontrib-jquery" +version = "4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/85/749bd22d1a68db7291c89e2ebca53f4306c3f205853cf31e9de279034c3c/sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae", size = 121104 }, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071 }, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743 }, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072 }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521 }, +] + +[[package]] +name = "sympy" +version = "1.13.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/11/8a/5a7fd6284fa8caac23a26c9ddf9c30485a48169344b4bd3b0f02fef1890f/sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9", size = 7533196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73", size = 6189483 }, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252 }, +] + +[[package]] +name = "tach" +version = "0.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "gitpython" }, + { name = "networkx" }, + { name = "prompt-toolkit" }, + { name = "pydot" }, + { name = "pyyaml" }, + { name = "rich" }, + { name = "tomli" }, + { name = "tomli-w" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/4b/de2e7ad0a22e63fbed979064381da1290391dd623a3fd80d0728ea72d545/tach-0.23.0.tar.gz", hash = "sha256:ae123491231ab0712417d579b9a3259014d713d72626805ff64552955e43e912", size = 482218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/87/9aa4142dc31314500af0003f406851a212b589a7e680e78c39751fc26681/tach-0.23.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:aa30db4158e48694154d346def14d3a096672381fa09e3cf09eae190ff9066f0", size = 3240516 }, + { url = "https://files.pythonhosted.org/packages/b3/db/3d856d856a688b024470494785dc8d177e1728904e180aa9394e80d8787e/tach-0.23.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:2e54365a3101c08a35d51357007e37723cd86c8bf464b73a3b43401edd2053d8", size = 3095903 }, + { url = "https://files.pythonhosted.org/packages/19/c9/1302175f5b350891727356c03bfdbffb884323db3c30cc34b2c7e93c932b/tach-0.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0af6be9328ec907deac141165b43b7db58f055bc20ea46b65b82b10fed72cd3", size = 3373159 }, + { url = "https://files.pythonhosted.org/packages/af/3d/ad4a2f4e2142b789085886a3acbb2f8e1a99068014303c7aa1166350aa38/tach-0.23.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b8205440863f61389b29a9baf2e2cd171d87c6931f3d6baf69eda69092440df", size = 3325828 }, + { url = "https://files.pythonhosted.org/packages/ab/87/4114a20e97f9a8652865bdf541d7b3121a731d6539d7f6b7d6bb70a86f46/tach-0.23.0-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b783d0f121c579f761dad7bf6ceeddec8f901e3778ed29a2db57c1c17804577", size = 3627127 }, + { url = "https://files.pythonhosted.org/packages/b5/cd/88b4f103eea5d2a3b0696265131f43f07e5bf9b1b81ccc0471512121ceae/tach-0.23.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:625403b59430eee9b5c2c05dff9575c8623ea88bcf58728e55b843fdbf04031d", size = 3623389 }, + { url = "https://files.pythonhosted.org/packages/12/77/3be44b77ad3ab8a6f05c245e399ff1e9f48df6be5e706c34b0863eaa4bdc/tach-0.23.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c9671d4be806f9aa6a714a38ac26b455704ac01019555f2441445335e749fb5", size = 3884923 }, + { url = "https://files.pythonhosted.org/packages/d7/8b/d7f9c9a1cb6a0f6745a1c4cdb824bc1abbac2a4f9fa30e57de37b7a223b9/tach-0.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caede4e23800d412c83b96288c7f03845971f6ea10dcfff40a026d294db1996f", size = 3483408 }, + { url = "https://files.pythonhosted.org/packages/48/8e/930460944b5cddeff297de774981ce8ffd1e80c59ea5f0616ade89a6871b/tach-0.23.0-cp37-abi3-win32.whl", hash = "sha256:828a59f7e2effdac3802025177b1a83e53b27ee54b00ef6305a0e36cec448e55", size = 2725999 }, + { url = "https://files.pythonhosted.org/packages/ea/01/4e4c9b551fa9ffd0db74e14966c393928aefa59019b6d5bd8a9a645ee714/tach-0.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:5dc03ef01d1a2e9d39fa238c271e9a4f8d9db2459212425ceb05b8ed0547000f", size = 2930346 }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +] + +[[package]] +name = "tomli-w" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675 }, +] + +[[package]] +name = "tomlkit" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 }, +] + +[[package]] +name = "toolz" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/0b/d80dfa675bf592f636d1ea0b835eab4ec8df6e9415d8cfd766df54456123/toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02", size = 66790 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236", size = 56383 }, +] + +[[package]] +name = "tornado" +version = "6.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/45/a0daf161f7d6f36c3ea5fc0c2de619746cc3dd4c76402e9db545bd920f63/tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b", size = 501135 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/7e/71f604d8cea1b58f82ba3590290b66da1e72d840aeb37e0d5f7291bd30db/tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1", size = 436299 }, + { url = "https://files.pythonhosted.org/packages/96/44/87543a3b99016d0bf54fdaab30d24bf0af2e848f1d13d34a3a5380aabe16/tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803", size = 434253 }, + { url = "https://files.pythonhosted.org/packages/cb/fb/fdf679b4ce51bcb7210801ef4f11fdac96e9885daa402861751353beea6e/tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec", size = 437602 }, + { url = "https://files.pythonhosted.org/packages/4f/3b/e31aeffffc22b475a64dbeb273026a21b5b566f74dee48742817626c47dc/tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946", size = 436972 }, + { url = "https://files.pythonhosted.org/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf", size = 437173 }, + { url = "https://files.pythonhosted.org/packages/79/5e/be4fb0d1684eb822c9a62fb18a3e44a06188f78aa466b2ad991d2ee31104/tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634", size = 437892 }, + { url = "https://files.pythonhosted.org/packages/f5/33/4f91fdd94ea36e1d796147003b490fe60a0215ac5737b6f9c65e160d4fe0/tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73", size = 437334 }, + { url = "https://files.pythonhosted.org/packages/2b/ae/c1b22d4524b0e10da2f29a176fb2890386f7bd1f63aacf186444873a88a0/tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c", size = 437261 }, + { url = "https://files.pythonhosted.org/packages/b5/25/36dbd49ab6d179bcfc4c6c093a51795a4f3bed380543a8242ac3517a1751/tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482", size = 438463 }, + { url = "https://files.pythonhosted.org/packages/61/cc/58b1adeb1bb46228442081e746fcdbc4540905c87e8add7c277540934edb/tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38", size = 438907 }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359 }, +] + +[[package]] +name = "types-decorator" +version = "5.1.8.20250121" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/e6/88de14bb1d1073495b9d9459f90fbb78fe93d89beefcf0af94b871993a56/types_decorator-5.1.8.20250121.tar.gz", hash = "sha256:1b89bb1c481a1d3399e28f1aa3459366b76dde951490992ae8475ba91287cd04", size = 8496 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/0e/59b9637fa66fbe419886b17d59b90e5e4256325c01f94f81dcc44fbeda53/types_decorator-5.1.8.20250121-py3-none-any.whl", hash = "sha256:6bfd5f4464f444a1ee0aea92705ed8466d74c0ddd7ade4bbd003c235db51d21a", size = 8078 }, +] + +[[package]] +name = "types-docutils" +version = "0.21.0.20241128" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/df/64e7ab01a4fc5ce46895dc94e31cffc8b8087c8d91ee54c45ac2d8d82445/types_docutils-0.21.0.20241128.tar.gz", hash = "sha256:4dd059805b83ac6ec5a223699195c4e9eeb0446a4f7f2aeff1759a4a7cc17473", size = 26739 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/b6/10ba95739f2cbb9c5bd2f6568148d62b468afe01a94c633e8892a2936d8a/types_docutils-0.21.0.20241128-py3-none-any.whl", hash = "sha256:e0409204009639e9b0bf4521eeabe58b5e574ce9c0db08421c2ac26c32be0039", size = 34677 }, +] + +[[package]] +name = "types-pytz" +version = "2024.2.0.20241221" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/26/516311b02b5a215e721155fb65db8a965d061372e388d6125ebce8d674b0/types_pytz-2024.2.0.20241221.tar.gz", hash = "sha256:06d7cde9613e9f7504766a0554a270c369434b50e00975b3a4a0f6eed0f2c1a9", size = 10213 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/db/c92ca6920cccd9c2998b013601542e2ac5e59bc805bcff94c94ad254b7df/types_pytz-2024.2.0.20241221-py3-none-any.whl", hash = "sha256:8fc03195329c43637ed4f593663df721fef919b60a969066e22606edf0b53ad5", size = 10008 }, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.20241230" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/f9/4d566925bcf9396136c0a2e5dc7e230ff08d86fa011a69888dd184469d80/types_pyyaml-6.0.12.20241230.tar.gz", hash = "sha256:7f07622dbd34bb9c8b264fe860a17e0efcad00d50b5f27e93984909d9363498c", size = 17078 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/c1/48474fbead512b70ccdb4f81ba5eb4a58f69d100ba19f17c92c0c4f50ae6/types_PyYAML-6.0.12.20241230-py3-none-any.whl", hash = "sha256:fa4d32565219b68e6dee5f67534c722e53c00d1cfc09c435ef04d7353e1e96e6", size = 20029 }, +] + +[[package]] +name = "types-tabulate" +version = "0.9.0.20241207" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/43/16030404a327e4ff8c692f2273854019ed36718667b2993609dc37d14dd4/types_tabulate-0.9.0.20241207.tar.gz", hash = "sha256:ac1ac174750c0a385dfd248edc6279fa328aaf4ea317915ab879a2ec47833230", size = 8195 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/86/a9ebfd509cbe74471106dffed320e208c72537f9aeb0a55eaa6b1b5e4d17/types_tabulate-0.9.0.20241207-py3-none-any.whl", hash = "sha256:b8dad1343c2a8ba5861c5441370c3e35908edd234ff036d4298708a1d4cf8a85", size = 8307 }, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] + +[[package]] +name = "urllib3" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, +] + +[[package]] +name = "virtualenv" +version = "20.29.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/9b/599bcfc7064fbe5740919e78c5df18e5dceb0887e676256a1061bb5ae232/virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779", size = 4282379 }, +] + +[[package]] +name = "wcmatch" +version = "10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bracex" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/ab/b3a52228538ccb983653c446c1656eddf1d5303b9cb8b9aef6a91299f862/wcmatch-10.0.tar.gz", hash = "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a", size = 115578 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/df/4ee467ab39cc1de4b852c212c1ed3becfec2e486a51ac1ce0091f85f38d7/wcmatch-10.0-py3-none-any.whl", hash = "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a", size = 39347 }, +] + +[[package]] +name = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774 }, +] + +[[package]] +name = "wheel" +version = "0.45.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494 }, +] + +[[package]] +name = "xxhash" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/3e/ca49932bade8b3308e74df951c36cbc84c8230c9b8715bae1e0014831aa7/xxhash-3.0.0.tar.gz", hash = "sha256:30b2d97aaf11fb122023f6b44ebb97c6955e9e00d7461a96415ca030b5ceb9c7", size = 74279 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/fe/41444c518df82da46bc7125c9daa4159e6cfc2b682ccc73493b0485b8a70/xxhash-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:219cba13991fd73cf21a5efdafa5056f0ae0b8f79e5e0112967e3058daf73eea", size = 34110 }, + { url = "https://files.pythonhosted.org/packages/6f/83/0afffed636656f65f78e35da174c9bdd86367f9d4da23a87fc9d1b933bbe/xxhash-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fcbb846af15eff100c412ae54f4974ff277c92eacd41f1ec7803a64fd07fa0c", size = 30664 }, + { url = "https://files.pythonhosted.org/packages/8c/b1/cde24bf3c9d4d6bbe02e9e82604dbd40ab21c9799b0fdb66a4fe2046e96d/xxhash-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f475fa817ff7955fc118fc1ca29a6e691d329b7ff43f486af36c22dbdcff1db", size = 241825 }, + { url = "https://files.pythonhosted.org/packages/70/fd/7ebfe1549551c87875b64cf9c925e3cf8be53e475d29aed933643f6dd8aa/xxhash-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9200a90f02ff6fd5fb63dea107842da71d8626d99b768fd31be44f3002c60bbe", size = 206492 }, + { url = "https://files.pythonhosted.org/packages/d2/6f/eafbb4ec3baf499423f2de3a5f3b6c5898f3bf4a8714e100d5dfb911fbad/xxhash-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a1403e4f551c9ef7bcef09af55f1adb169f13e4de253db0887928e5129f87af1", size = 286394 }, + { url = "https://files.pythonhosted.org/packages/64/05/504e1a7accc8f115ebfba96104c2f4a4aea3fb415bd664a6a1cc8915671e/xxhash-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa7f6ca53170189a2268c83af0980e6c10aae69e6a5efa7ca989f89fff9f8c02", size = 211550 }, + { url = "https://files.pythonhosted.org/packages/f8/b9/b6558ba62479dbdd18f894842f6ec01bbbf94aa8a26340f889c1af550fa8/xxhash-3.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b63fbeb6d9c93d50ae0dc2b8a8b7f52f2de19e40fe9edc86637bfa5743b8ba2", size = 219718 }, + { url = "https://files.pythonhosted.org/packages/19/7a/270f9c47d9748b7d43ec2ce0ee1d50c189ccf21e7ba6adc39e4045fcd450/xxhash-3.0.0-cp310-cp310-win32.whl", hash = "sha256:31f25efd10b6f1f6d5c34cd231986d8aae9a42e042daa90b783917f170807869", size = 30157 }, + { url = "https://files.pythonhosted.org/packages/67/54/f98d6eccb96da4fc51f4397123828c593c6f2731ede141f2318d1aab8a6b/xxhash-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:807e88ed56e0fb347cb57d5bf44851f9878360fed700f2f63e622ef4eede87a5", size = 29918 }, +] From 5752f2b807e254fe55ee60273b49e07e7f8b5061 Mon Sep 17 00:00:00 2001 From: edopao Date: Thu, 30 Jan 2025 06:42:44 +0100 Subject: [PATCH 05/13] feat[next][dace]: keep transients on the output of a mapped nested SDFG (#1828) Small change to the lowering from GTIR, that keeps a transient buffer on the output of a nested SDFG, before the write memlet through the `MapExit` node. Removal of the transient, which was the baseline behavior, prevents map fusion in the optimization workflow. --- .../next/program_processors/runners/dace/gtir_dataflow.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py b/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py index a34828afcb..59d1a0087a 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py @@ -233,8 +233,12 @@ def connect( ) -> None: # retrieve the node which writes the result last_node = self.state.in_edges(self.result.dc_node)[0].src - if isinstance(last_node, (dace.nodes.Tasklet, dace.nodes.NestedSDFG)): + if isinstance(last_node, dace.nodes.Tasklet): # the last transient node can be deleted + # Note that it could also be applied when `last_node` is a NestedSDFG, + # but an exception would be when the inner write to global data is a + # WCR memlet, because that prevents fusion of the outer map. This case + # happens for the reduce with skip values, which uses a map with WCR. last_node_connector = self.state.in_edges(self.result.dc_node)[0].src_conn self.state.remove_node(self.result.dc_node) else: From 1ccc7c90a9ed5b726bb4d10c9106bb2d19346d2b Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Thu, 30 Jan 2025 17:20:48 +0100 Subject: [PATCH 06/13] docs: update detailed nox examples (#1838) ## Description Fixed the detailed examples for working with nox (listing all sessions, running a specific session) in the contribution guidelines. ## Requirements - [x] All fixes and/or new features come with corresponding tests. Tested locally by copy/pasting the commands. - [ ] Important design decisions have been documented in the appropriate ADR inside the [docs/development/ADRs/](docs/development/ADRs/Index.md) folder. N/A Co-authored-by: Roman Cattaneo <1116746+romanc@users.noreply.github.com> --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e0ef75d31e..28134a61b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -146,11 +146,11 @@ Check `pytest` documentation (`pytest --help`) for all the options to select and We recommended you to use `nox` for running the test suite in different environments. `nox` runs the package installation script in properly isolated environments to run tests in a reproducible way. A simple way to start with `nox` would be: ```bash -# List all the available task environments -nox list +# List all available sessions +nox --list -# Run a specific task environment -nox -e cartesian-py38-internal-cpu +# Run a specific session +nox -s "test_cartesian-3.10(internal, cpu)" ``` Check `nox` documentation (`nox --help`) for the complete reference. From 050d3b36ac176196f6758459f65efdac9ba084eb Mon Sep 17 00:00:00 2001 From: Roman Cattaneo Date: Thu, 30 Jan 2025 17:27:45 +0100 Subject: [PATCH 07/13] refactor[cartesian]: Minor cleanup in backends (#1833) ## Description I was reading a lot of code around DaCe/gt-codegen when debugging the new DaCe/gt4py bridge. This PR combines three cleanup commits: - Always get stencil_ir from builder in GTBaseBackends. I've found no usage of `stencil_ir` being anything else than `self.build.gtir` if it was explicitly passed as an argument at all. There's thus no need to pass around `self.build.gtir` as long as we stay in the same class hierarchy. - Avoid unnecessary indenting in generated code. Generated code is optionally formatted, but even if not, we can make sure the code doesn't look too ugly. - Avoid double formatting of source code (if gt4py/dace is configured to do so). No need for formatting intermediate code parts because it's formatted anyway at the end. ## Requirements - [x] All fixes and/or new features come with corresponding tests. Updated test accordingly. - [ ] Important design decisions have been documented in the appropriate ADR inside the [docs/development/ADRs/](docs/development/ADRs/Index.md) folder. N/A --------- Co-authored-by: Roman Cattaneo <1116746+romanc@users.noreply.github.com> --- src/gt4py/cartesian/backend/cuda_backend.py | 2 +- src/gt4py/cartesian/backend/dace_backend.py | 64 +++++++++---------- src/gt4py/cartesian/backend/gtc_common.py | 39 +++++------ src/gt4py/cartesian/backend/gtcpp_backend.py | 2 +- .../backend_tests/test_backend_api.py | 6 +- 5 files changed, 50 insertions(+), 63 deletions(-) diff --git a/src/gt4py/cartesian/backend/cuda_backend.py b/src/gt4py/cartesian/backend/cuda_backend.py index afa749e3f1..9646383c0f 100644 --- a/src/gt4py/cartesian/backend/cuda_backend.py +++ b/src/gt4py/cartesian/backend/cuda_backend.py @@ -141,7 +141,7 @@ class CudaBackend(BaseGTBackend, CLIBackendMixin): GT_BACKEND_T = "gpu" def generate_extension(self, **kwargs: Any) -> Tuple[str, str]: - return self.make_extension(stencil_ir=self.builder.gtir, uses_cuda=True) + return self.make_extension(uses_cuda=True) def generate(self) -> Type[StencilObject]: self.check_options(self.builder.options) diff --git a/src/gt4py/cartesian/backend/dace_backend.py b/src/gt4py/cartesian/backend/dace_backend.py index 35265f0530..5b822a1ab5 100644 --- a/src/gt4py/cartesian/backend/dace_backend.py +++ b/src/gt4py/cartesian/backend/dace_backend.py @@ -12,7 +12,6 @@ import os import pathlib import re -import textwrap from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type import dace @@ -432,20 +431,20 @@ def __call__(self, stencil_ir: gtir.Stencil) -> Dict[str, Dict[str, str]]: class DaCeComputationCodegen: template = as_mako( - """ - auto ${name}(const std::array& domain) { - return [domain](${",".join(functor_args)}) { - const int __I = domain[0]; - const int __J = domain[1]; - const int __K = domain[2]; - ${name}${state_suffix} dace_handle; - ${backend_specifics} - auto allocator = gt::sid::cached_allocator(&${allocator}); - ${"\\n".join(tmp_allocs)} - __program_${name}(${",".join(["&dace_handle", *dace_args])}); - }; - } - """ + """\ +auto ${name}(const std::array& domain) { + return [domain](${",".join(functor_args)}) { + const int __I = domain[0]; + const int __J = domain[1]; + const int __K = domain[2]; + ${name}${state_suffix} dace_handle; + ${backend_specifics} + auto allocator = gt::sid::cached_allocator(&${allocator}); + ${"\\n".join(tmp_allocs)} + __program_${name}(${",".join(["&dace_handle", *dace_args])}); + }; +} +""" ) def generate_tmp_allocs(self, sdfg): @@ -511,7 +510,7 @@ def _postprocess_dace_code(code_objects, is_gpu, builder): lines = lines[0:i] + cuda_code.split("\n") + lines[i + 1 :] break - def keep_line(line): + def keep_line(line: str) -> bool: line = line.strip() if line == '#include "../../include/hash.h"': return False @@ -521,11 +520,7 @@ def keep_line(line): return False return True - lines = filter(keep_line, lines) - generated_code = "\n".join(lines) - if builder.options.format_source: - generated_code = codegen.format_source("cpp", generated_code, style="LLVM") - return generated_code + return "\n".join(filter(keep_line, lines)) @classmethod def apply(cls, stencil_ir: gtir.Stencil, builder: StencilBuilder, sdfg: dace.SDFG): @@ -563,17 +558,18 @@ def apply(cls, stencil_ir: gtir.Stencil, builder: StencilBuilder, sdfg: dace.SDF allocator="gt::cuda_util::cuda_malloc" if is_gpu else "std::make_unique", state_suffix=dace.Config.get("compiler.codegen_state_struct_suffix"), ) - generated_code = textwrap.dedent( - f"""#include - #include - #include - {"#include " if is_gpu else omp_header} - namespace gt = gridtools; - {computations} - - {interface} - """ - ) + generated_code = f"""\ +#include +#include +#include +{"#include " if is_gpu else omp_header} +namespace gt = gridtools; + +{computations} + +{interface} +""" + if builder.options.format_source: generated_code = codegen.format_source("cpp", generated_code, style="LLVM") @@ -794,7 +790,7 @@ class DaceCPUBackend(BaseDaceBackend): options = BaseGTBackend.GT_BACKEND_OPTS def generate_extension(self, **kwargs: Any) -> Tuple[str, str]: - return self.make_extension(stencil_ir=self.builder.gtir, uses_cuda=False) + return self.make_extension(uses_cuda=False) @register @@ -815,4 +811,4 @@ class DaceGPUBackend(BaseDaceBackend): options = {**BaseGTBackend.GT_BACKEND_OPTS, "device_sync": {"versioning": True, "type": bool}} def generate_extension(self, **kwargs: Any) -> Tuple[str, str]: - return self.make_extension(stencil_ir=self.builder.gtir, uses_cuda=True) + return self.make_extension(uses_cuda=True) diff --git a/src/gt4py/cartesian/backend/gtc_common.py b/src/gt4py/cartesian/backend/gtc_common.py index abc4baede1..348e85de92 100644 --- a/src/gt4py/cartesian/backend/gtc_common.py +++ b/src/gt4py/cartesian/backend/gtc_common.py @@ -236,19 +236,15 @@ def generate(self) -> Type[StencilObject]: def generate_computation(self) -> Dict[str, Union[str, Dict]]: dir_name = f"{self.builder.options.name}_src" - src_files = self.make_extension_sources(stencil_ir=self.builder.gtir) + src_files = self._make_extension_sources() return {dir_name: src_files["computation"]} - def generate_bindings( - self, language_name: str, *, stencil_ir: Optional[gtir.Stencil] = None - ) -> Dict[str, Union[str, Dict]]: - if not stencil_ir: - stencil_ir = self.builder.gtir - assert stencil_ir is not None + def generate_bindings(self, language_name: str) -> Dict[str, Union[str, Dict]]: if language_name != "python": return super().generate_bindings(language_name) + dir_name = f"{self.builder.options.name}_src" - src_files = self.make_extension_sources(stencil_ir=stencil_ir) + src_files = self._make_extension_sources() return {dir_name: src_files["bindings"]} @abc.abstractmethod @@ -260,32 +256,26 @@ def generate_extension(self, **kwargs: Any) -> Tuple[str, str]: """ pass - def make_extension( - self, *, stencil_ir: Optional[gtir.Stencil] = None, uses_cuda: bool = False - ) -> Tuple[str, str]: + def make_extension(self, *, uses_cuda: bool = False) -> Tuple[str, str]: build_info = self.builder.options.build_info if build_info is not None: start_time = time.perf_counter() - if not stencil_ir: - stencil_ir = self.builder.gtir - assert stencil_ir is not None - # Generate source gt_pyext_files: Dict[str, Any] gt_pyext_sources: Dict[str, Any] - if not self.builder.options._impl_opts.get("disable-code-generation", False): - gt_pyext_files = self.make_extension_sources(stencil_ir=stencil_ir) - gt_pyext_sources = { - **gt_pyext_files["computation"], - **gt_pyext_files["bindings"], - } - else: + if self.builder.options._impl_opts.get("disable-code-generation", False): # Pass NOTHING to the self.builder means try to reuse the source code files gt_pyext_files = {} gt_pyext_sources = { key: gt_utils.NOTHING for key in self.PYEXT_GENERATOR_CLASS.TEMPLATE_FILES.keys() } + else: + gt_pyext_files = self._make_extension_sources() + gt_pyext_sources = { + **gt_pyext_files["computation"], + **gt_pyext_files["bindings"], + } if build_info is not None: next_time = time.perf_counter() @@ -317,10 +307,11 @@ def make_extension( return result - def make_extension_sources(self, *, stencil_ir: gtir.Stencil) -> Dict[str, Dict[str, str]]: + def _make_extension_sources(self) -> Dict[str, Dict[str, str]]: """Generate the source for the stencil independently from use case.""" if "computation_src" in self.builder.backend_data: return self.builder.backend_data["computation_src"] + class_name = self.pyext_class_name if self.builder.stencil_id else self.builder.options.name module_name = ( self.pyext_module_name @@ -328,7 +319,7 @@ def make_extension_sources(self, *, stencil_ir: gtir.Stencil) -> Dict[str, Dict[ else f"{self.builder.options.name}_pyext" ) gt_pyext_generator = self.PYEXT_GENERATOR_CLASS(class_name, module_name, self) - gt_pyext_sources = gt_pyext_generator(stencil_ir) + gt_pyext_sources = gt_pyext_generator(self.builder.gtir) final_ext = ".cu" if self.languages and self.languages["computation"] == "cuda" else ".cpp" comp_src = gt_pyext_sources["computation"] for key in [k for k in comp_src.keys() if k.endswith(".src")]: diff --git a/src/gt4py/cartesian/backend/gtcpp_backend.py b/src/gt4py/cartesian/backend/gtcpp_backend.py index 8053409195..96f5672ae4 100644 --- a/src/gt4py/cartesian/backend/gtcpp_backend.py +++ b/src/gt4py/cartesian/backend/gtcpp_backend.py @@ -129,7 +129,7 @@ class GTBaseBackend(BaseGTBackend, CLIBackendMixin): PYEXT_GENERATOR_CLASS = GTExtGenerator def _generate_extension(self, uses_cuda: bool) -> Tuple[str, str]: - return self.make_extension(stencil_ir=self.builder.gtir, uses_cuda=uses_cuda) + return self.make_extension(uses_cuda=uses_cuda) def generate(self) -> Type[StencilObject]: self.check_options(self.builder.options) diff --git a/tests/cartesian_tests/unit_tests/backend_tests/test_backend_api.py b/tests/cartesian_tests/unit_tests/backend_tests/test_backend_api.py index c47ad10e94..3fbf586b35 100644 --- a/tests/cartesian_tests/unit_tests/backend_tests/test_backend_api.py +++ b/tests/cartesian_tests/unit_tests/backend_tests/test_backend_api.py @@ -79,7 +79,7 @@ def test_generate_bindings(backend, tmp_path): ) else: # assumption: only gt backends support python bindings for other languages than python - result = builder.backend.generate_bindings("python", stencil_ir=builder.gtir) + result = builder.backend.generate_bindings("python") assert "init_1_src" in result - srcs = result["init_1_src"] - assert "bindings.cpp" in srcs or "bindings.cu" in srcs + sources = result["init_1_src"] + assert "bindings.cpp" in sources or "bindings.cu" in sources From f0c67e62134a466aed1986f0d853ef5530244906 Mon Sep 17 00:00:00 2001 From: edopao Date: Thu, 30 Jan 2025 22:33:51 +0100 Subject: [PATCH 08/13] feat[next][dace]: support for field origin in lowering to SDFG (#1818) This PR adds support for GT4Py field arguments with non-zero start index, for example: `inp = constructors.empty(common.domain({IDim: (1, 9)}), ...)` which was supported in baseline only for temporary fields, by means of a data structure called `field_offsets`. This data structure is removed for two reasons: 1. the name "offset" is a left-over from previous design based on dace array offset 3. offset has a different meaning in GT4Py We introduce the GT4Py concept of field origin and use it for both temporary fields and program arguments. The field origin corresponds to the start of the field domain range. This PR also changes the symbolic definition of array shape. Before, the array shape was defined as `[data_size_0, data_size_1, ...]`, now the size corresponds to the range extent `stop - start` as `[(data_0_range_1 - data_0_range_0), (data_1_range_1 - data_1_range_0), ...]`. The translation stage of the dace workflow is extended with an option `disable_field_origin_on_program_arguments` to set the field range start symbols to constant value zero. This is needed for the dace orchestration, because the signature of a dace-orchestrated program does not provide the domain origin. --- .../runners/dace/gtir_builtin_translators.py | 177 +++++++++--- .../runners/dace/gtir_dataflow.py | 9 +- .../runners/dace/gtir_python_codegen.py | 11 +- .../runners/dace/gtir_scan_translator.py | 102 +++---- .../runners/dace/gtir_sdfg.py | 268 ++++++++++-------- .../runners/dace/program.py | 6 +- .../runners/dace/sdfg_callable.py | 54 ++-- .../program_processors/runners/dace/utils.py | 38 ++- .../runners/dace/workflow/translation.py | 10 +- tests/next_tests/definitions.py | 1 - .../feature_tests/dace/test_orchestration.py | 36 ++- .../feature_tests/dace/test_program.py | 4 - .../iterator_tests/test_hdiff.py | 1 + .../dace_tests/test_dace_utils.py | 21 ++ .../dace_tests/test_gtir_to_sdfg.py | 159 ++++++----- 15 files changed, 540 insertions(+), 357 deletions(-) create mode 100644 tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace_utils.py diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_builtin_translators.py b/src/gt4py/next/program_processors/runners/dace/gtir_builtin_translators.py index 0fe776c3ee..6b2a32c063 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_builtin_translators.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_builtin_translators.py @@ -39,31 +39,28 @@ def get_domain_indices( - dims: Sequence[gtx_common.Dimension], offsets: Optional[Sequence[dace.symbolic.SymExpr]] = None + dims: Sequence[gtx_common.Dimension], origin: Optional[Sequence[dace.symbolic.SymExpr]] ) -> dace_subsets.Indices: """ Helper function to construct the list of indices for a field domain, applying - an optional offset in each dimension as start index. + an optional origin in each dimension as start index. Args: dims: The field dimensions. - offsets: The range start index in each dimension. + origin: The domain start index in each dimension. If set to `None`, assume all zeros. Returns: A list of indices for field access in dace arrays. As this list is returned as `dace.subsets.Indices`, it should be converted to `dace.subsets.Range` before being used in memlet subset because ranges are better supported throughout DaCe. """ - index_variables = [dace.symbolic.SymExpr(gtir_sdfg_utils.get_map_variable(dim)) for dim in dims] - if offsets is None: - return dace_subsets.Indices(index_variables) - else: - return dace_subsets.Indices( - [ - index - offset if offset != 0 else index - for index, offset in zip(index_variables, offsets, strict=True) - ] - ) + index_variables = [ + dace.symbolic.pystr_to_symbolic(gtir_sdfg_utils.get_map_variable(dim)) for dim in dims + ] + origin = [0] * len(index_variables) if origin is None else origin + return dace_subsets.Indices( + [index - start_index for index, start_index in zip(index_variables, origin, strict=True)] + ) @dataclasses.dataclass(frozen=True) @@ -78,18 +75,58 @@ class FieldopData: Args: dc_node: DaCe access node to the data storage. gt_type: GT4Py type definition, which includes the field domain information. - offset: List of index offsets, in each dimension, when the dimension range - does not start from zero; assume zero offset, if not set. + origin: Tuple of start indices, in each dimension, for `FieldType` data. + Pass an empty tuple for `ScalarType` data or zero-dimensional fields. """ dc_node: dace.nodes.AccessNode gt_type: ts.FieldType | ts.ScalarType - offset: Optional[list[dace.symbolic.SymExpr]] + origin: tuple[dace.symbolic.SymbolicType, ...] + + def __post_init__(self) -> None: + """Implements a sanity check on the constructed data type.""" + assert ( + len(self.origin) == 0 + if isinstance(self.gt_type, ts.ScalarType) + else len(self.origin) == len(self.gt_type.dims) + ) + + def map_to_parent_sdfg( + self, + sdfg_builder: gtir_sdfg.SDFGBuilder, + inner_sdfg: dace.SDFG, + outer_sdfg: dace.SDFG, + outer_sdfg_state: dace.SDFGState, + symbol_mapping: dict[str, dace.symbolic.SymbolicType], + ) -> FieldopData: + """ + Make the data descriptor which 'self' refers to, and which is located inside + a NestedSDFG, available in its parent SDFG. - def make_copy(self, data_node: dace.nodes.AccessNode) -> FieldopData: - """Create a copy of this data descriptor with a different access node.""" - assert data_node != self.dc_node - return FieldopData(data_node, self.gt_type, self.offset) + Thus, it turns 'self' into a non-transient array and creates a new data + descriptor inside the parent SDFG, with same shape and strides. + """ + inner_desc = self.dc_node.desc(inner_sdfg) + assert inner_desc.transient + inner_desc.transient = False + + if isinstance(self.gt_type, ts.ScalarType): + outer, outer_desc = sdfg_builder.add_temp_scalar(outer_sdfg, inner_desc.dtype) + outer_origin = [] + else: + outer, outer_desc = sdfg_builder.add_temp_array_like(outer_sdfg, inner_desc) + # We cannot use a copy of the inner data descriptor directly, we have to apply the symbol mapping. + dace.symbolic.safe_replace( + symbol_mapping, + lambda m: dace.sdfg.replace_properties_dict(outer_desc, m), + ) + # Same applies to the symbols used as field origin (the domain range start) + outer_origin = [ + gtx_dace_utils.safe_replace_symbolic(val, symbol_mapping) for val in self.origin + ] + + outer_node = outer_sdfg_state.add_access(outer) + return FieldopData(outer_node, self.gt_type, tuple(outer_origin)) def get_local_view( self, domain: FieldopDomain @@ -97,18 +134,20 @@ def get_local_view( """Helper method to access a field in local view, given the compute domain of a field operator.""" if isinstance(self.gt_type, ts.ScalarType): return gtir_dataflow.MemletExpr( - dc_node=self.dc_node, gt_dtype=self.gt_type, subset=dace_subsets.Indices([0]) + dc_node=self.dc_node, + gt_dtype=self.gt_type, + subset=dace_subsets.Range.from_string("0"), ) if isinstance(self.gt_type, ts.FieldType): domain_dims = [dim for dim, _, _ in domain] - domain_indices = get_domain_indices(domain_dims) + domain_indices = get_domain_indices(domain_dims, origin=None) it_indices: dict[gtx_common.Dimension, gtir_dataflow.DataExpr] = { dim: gtir_dataflow.SymbolExpr(index, INDEX_DTYPE) for dim, index in zip(domain_dims, domain_indices) } - field_domain = [ - (dim, dace.symbolic.SymExpr(0) if self.offset is None else self.offset[i]) + field_origin = [ + (dim, dace.symbolic.SymExpr(0) if self.origin is None else self.origin[i]) for i, dim in enumerate(self.gt_type.dims) ] # The property below is ensured by calling `make_field()` to construct `FieldopData`. @@ -116,11 +155,48 @@ def get_local_view( # to `ListType` element type, while the field domain consists of all global dimensions. assert all(dim != gtx_common.DimensionKind.LOCAL for dim in self.gt_type.dims) return gtir_dataflow.IteratorExpr( - self.dc_node, self.gt_type.dtype, field_domain, it_indices + self.dc_node, self.gt_type.dtype, field_origin, it_indices ) raise NotImplementedError(f"Node type {type(self.gt_type)} not supported.") + def get_symbol_mapping( + self, dataname: str, sdfg: dace.SDFG + ) -> dict[str, dace.symbolic.SymExpr]: + """ + Helper method to create the symbol mapping for array storage in a nested SDFG. + + Args: + dataname: Name of the data container insiode the nested SDFG. + sdfg: The parent SDFG where the `FieldopData` object lives. + + Returns: + Mapping from symbols in nested SDFG to the corresponding symbolic values + in the parent SDFG. This includes the range start and stop symbols (used + to calculate the array shape as range 'stop - start') and the strides. + """ + if isinstance(self.gt_type, ts.ScalarType): + return {} + ndims = len(self.gt_type.dims) + outer_desc = self.dc_node.desc(sdfg) + assert isinstance(outer_desc, dace.data.Array) + # origin and size of the local dimension, in case of a field with `ListType` data, + # are assumed to be compiled-time values (not symbolic), therefore the start and + # stop range symbols of the inner field only extend over the global dimensions + return ( + {gtx_dace_utils.range_start_symbol(dataname, i): (self.origin[i]) for i in range(ndims)} + | { + gtx_dace_utils.range_stop_symbol(dataname, i): ( + self.origin[i] + outer_desc.shape[i] + ) + for i in range(ndims) + } + | { + gtx_dace_utils.field_stride_symbol_name(dataname, i): stride + for i, stride in enumerate(outer_desc.strides) + } + ) + FieldopDomain: TypeAlias = list[ tuple[gtx_common.Dimension, dace.symbolic.SymbolicType, dace.symbolic.SymbolicType] @@ -141,6 +217,33 @@ def get_local_view( """Data type used for field indexing.""" +def get_arg_symbol_mapping( + dataname: str, arg: FieldopResult, sdfg: dace.SDFG +) -> dict[str, dace.symbolic.SymExpr]: + """ + Helper method to build the mapping from inner to outer SDFG of all symbols + used for storage of a field or a tuple of fields. + + Args: + dataname: The storage name inside the nested SDFG. + arg: The argument field in the parent SDFG. + sdfg: The parent SDFG where the argument field lives. + + Returns: + A mapping from inner symbol names to values or symbolic definitions + in the parent SDFG. + """ + if isinstance(arg, FieldopData): + return arg.get_symbol_mapping(dataname, sdfg) + + symbol_mapping: dict[str, dace.symbolic.SymExpr] = {} + for i, elem in enumerate(arg): + dataname_elem = f"{dataname}_{i}" + symbol_mapping |= get_arg_symbol_mapping(dataname_elem, elem, sdfg) + + return symbol_mapping + + def get_tuple_type(data: tuple[FieldopResult, ...]) -> ts.TupleType: """ Compute the `ts.TupleType` corresponding to the tuple structure of `FieldopResult`. @@ -239,7 +342,7 @@ def get_field_layout( Returns: A tuple of three lists containing: - the domain dimensions - - the domain offset in each dimension + - the domain origin, that is the start indices in all dimensions - the domain size in each dimension """ domain_dims, domain_lbs, domain_ubs = zip(*domain) @@ -278,9 +381,9 @@ def _create_field_operator_impl( dataflow_output_desc = output_edge.result.dc_node.desc(sdfg) # the memory layout of the output field follows the field operator compute domain - domain_dims, domain_offset, domain_shape = get_field_layout(domain) - domain_indices = get_domain_indices(domain_dims, domain_offset) - domain_subset = dace_subsets.Range.from_indices(domain_indices) + field_dims, field_origin, field_shape = get_field_layout(domain) + field_indices = get_domain_indices(field_dims, field_origin) + field_subset = dace_subsets.Range.from_indices(field_indices) if isinstance(output_edge.result.gt_dtype, ts.ScalarType): if output_edge.result.gt_dtype != output_type.dtype: @@ -288,8 +391,6 @@ def _create_field_operator_impl( f"Type mismatch, expected {output_type.dtype} got {output_edge.result.gt_dtype}." ) assert isinstance(dataflow_output_desc, dace.data.Scalar) - field_shape = domain_shape - field_subset = domain_subset else: assert isinstance(output_type.dtype, ts.ListType) assert isinstance(output_edge.result.gt_dtype.element_type, ts.ScalarType) @@ -301,8 +402,8 @@ def _create_field_operator_impl( assert len(dataflow_output_desc.shape) == 1 # extend the array with the local dimensions added by the field operator (e.g. `neighbors`) assert output_edge.result.gt_dtype.offset_type is not None - field_shape = [*domain_shape, dataflow_output_desc.shape[0]] - field_subset = domain_subset + dace_subsets.Range.from_array(dataflow_output_desc) + field_shape = [*field_shape, dataflow_output_desc.shape[0]] + field_subset = field_subset + dace_subsets.Range.from_array(dataflow_output_desc) # allocate local temporary storage field_name, _ = sdfg_builder.add_temp_array(sdfg, field_shape, dataflow_output_desc.dtype) @@ -312,9 +413,7 @@ def _create_field_operator_impl( output_edge.connect(map_exit, field_node, field_subset) return FieldopData( - field_node, - ts.FieldType(domain_dims, output_edge.result.gt_dtype), - offset=(domain_offset if set(domain_offset) != {0} else None), + field_node, ts.FieldType(field_dims, output_edge.result.gt_dtype), tuple(field_origin) ) @@ -535,7 +634,7 @@ def construct_output(inner_data: FieldopData) -> FieldopData: outer, _ = sdfg_builder.add_temp_array_like(sdfg, inner_desc) outer_node = state.add_access(outer) - return inner_data.make_copy(outer_node) + return FieldopData(outer_node, inner_data.gt_type, inner_data.origin) result_temps = gtx_utils.tree_map(construct_output)(true_br_args) @@ -696,7 +795,7 @@ def translate_literal( data_type = node.type data_node = _get_symbolic_value(sdfg, state, sdfg_builder, node.value, data_type) - return FieldopData(data_node, data_type, offset=None) + return FieldopData(data_node, data_type, origin=()) def translate_make_tuple( @@ -818,7 +917,7 @@ def translate_scalar_expr( dace.Memlet(data=temp_name, subset="0"), ) - return FieldopData(temp_node, node.type, offset=None) + return FieldopData(temp_node, node.type, origin=()) def translate_symbol_ref( diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py b/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py index 59d1a0087a..584ce849e1 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_dataflow.py @@ -807,6 +807,7 @@ def write_output_of_nested_sdfg_to_temporary(inner_value: ValueExpr) -> ValueExp nsdfg.add_edge(entry_state, fstate, dace.InterstateEdge(condition="not (__cond)")) input_memlets: dict[str, MemletExpr | ValueExpr] = {} + nsdfg_symbols_mapping: Optional[dict[str, dace.symbol]] = None # define scalar or symbol for the condition value inside the nested SDFG if isinstance(condition_value, SymbolExpr): @@ -845,12 +846,16 @@ def write_output_of_nested_sdfg_to_temporary(inner_value: ValueExpr) -> ValueExp outputs = {outval.dc_node.data for outval in gtx_utils.flatten_nested_tuple((result,))} + # all free symbols are mapped to the symbols available in parent SDFG + nsdfg_symbols_mapping = {str(sym): sym for sym in nsdfg.free_symbols} + if isinstance(condition_value, SymbolExpr): + nsdfg_symbols_mapping["__cond"] = condition_value.value nsdfg_node = self.state.add_nested_sdfg( nsdfg, self.sdfg, inputs=set(input_memlets.keys()), outputs=outputs, - symbol_mapping=None, # implicitly map all free symbols to the symbols available in parent SDFG + symbol_mapping=nsdfg_symbols_mapping, ) for inner, input_expr in input_memlets.items(): @@ -1504,7 +1509,7 @@ def _make_unstructured_shift( shifted_indices[neighbor_dim] = MemletExpr( dc_node=offset_table_node, gt_dtype=it.gt_dtype, - subset=dace_subsets.Indices([origin_index.value, offset_expr.value]), + subset=dace_subsets.Range.from_string(f"{origin_index.value}, {offset_expr.value}"), ) else: # dynamic offset: we cannot use a memlet to retrieve the offset value, use a tasklet node diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_python_codegen.py b/src/gt4py/next/program_processors/runners/dace/gtir_python_codegen.py index 56a67510e7..763c292836 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_python_codegen.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_python_codegen.py @@ -74,19 +74,16 @@ } -def builtin_cast(*args: Any) -> str: - val, target_type = args +def builtin_cast(val: str, target_type: str) -> str: assert target_type in builtins.TYPE_BUILTINS return MATH_BUILTINS_MAPPING[target_type].format(val) -def builtin_if(*args: Any) -> str: - cond, true_val, false_val = args +def builtin_if(cond: str, true_val: str, false_val: str) -> str: return f"{true_val} if {cond} else {false_val}" -def builtin_tuple_get(*args: Any) -> str: - index, tuple_name = args +def builtin_tuple_get(index: str, tuple_name: str) -> str: return f"{tuple_name}_{index}" @@ -99,7 +96,7 @@ def make_const_list(arg: str) -> str: return arg -GENERAL_BUILTIN_MAPPING: dict[str, Callable[[Any], str]] = { +GENERAL_BUILTIN_MAPPING: dict[str, Callable[..., str]] = { "cast_": builtin_cast, "if_": builtin_if, "make_const_list": make_const_list, diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py b/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py index ec88cd8f84..791440c37a 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_scan_translator.py @@ -22,7 +22,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Iterable, Optional +import itertools +from typing import TYPE_CHECKING, Any, Iterable import dace from dace import subsets as dace_subsets @@ -108,19 +109,19 @@ def _create_scan_field_operator_impl( assert isinstance(dataflow_output_desc, dace.data.Array) # the memory layout of the output field follows the field operator compute domain - domain_dims, domain_offset, domain_shape = gtir_translators.get_field_layout(domain) - domain_indices = gtir_translators.get_domain_indices(domain_dims, domain_offset) - domain_subset = dace_subsets.Range.from_indices(domain_indices) + field_dims, field_origin, field_shape = gtir_translators.get_field_layout(domain) + field_indices = gtir_translators.get_domain_indices(field_dims, field_origin) + field_subset = dace_subsets.Range.from_indices(field_indices) # the vertical dimension used as scan column is computed by the `LoopRegion` # inside the map scope, therefore it is excluded from the map range - scan_dim_index = [sdfg_builder.is_column_axis(dim) for dim in domain_dims].index(True) + scan_dim_index = [sdfg_builder.is_column_axis(dim) for dim in field_dims].index(True) # the map scope writes the full-shape dimension corresponding to the scan column field_subset = ( - dace_subsets.Range(domain_subset[:scan_dim_index]) + dace_subsets.Range(field_subset[:scan_dim_index]) + dace_subsets.Range.from_string(f"0:{dataflow_output_desc.shape[0]}") - + dace_subsets.Range(domain_subset[scan_dim_index + 1 :]) + + dace_subsets.Range(field_subset[scan_dim_index + 1 :]) ) if isinstance(output_edge.result.gt_dtype, ts.ScalarType): @@ -130,7 +131,6 @@ def _create_scan_field_operator_impl( f"Type mismatch, expected {output_type.dtype} got {output_edge.result.gt_dtype}." ) field_dtype = output_edge.result.gt_dtype - field_shape = domain_shape # the scan field operator computes a column of scalar values assert len(dataflow_output_desc.shape) == 1 else: @@ -146,7 +146,7 @@ def _create_scan_field_operator_impl( assert len(dataflow_output_desc.shape) == 2 # the lines below extend the array with the local dimension added by the field operator assert output_edge.result.gt_dtype.offset_type is not None - field_shape = [*domain_shape, dataflow_output_desc.shape[1]] + field_shape = [*field_shape, dataflow_output_desc.shape[1]] field_subset = field_subset + dace_subsets.Range.from_string( f"0:{dataflow_output_desc.shape[1]}" ) @@ -158,7 +158,7 @@ def _create_scan_field_operator_impl( # the inner and outer strides have to match scan_output_stride = field_desc.strides[scan_dim_index] # also consider the stride of the local dimension, in case the scan field operator computes a list - local_strides = field_desc.strides[len(domain_dims) :] + local_strides = field_desc.strides[len(field_dims) :] assert len(local_strides) == (1 if isinstance(output_edge.result.gt_dtype, ts.ListType) else 0) new_inner_strides = [scan_output_stride, *local_strides] dataflow_output_desc.set_shape(dataflow_output_desc.shape, new_inner_strides) @@ -168,9 +168,7 @@ def _create_scan_field_operator_impl( output_edge.connect(map_exit, field_node, field_subset) return gtir_translators.FieldopData( - field_node, - ts.FieldType(domain_dims, output_edge.result.gt_dtype), - offset=(domain_offset if set(domain_offset) != {0} else None), + field_node, ts.FieldType(field_dims, output_edge.result.gt_dtype), tuple(field_origin) ) @@ -271,7 +269,6 @@ def _lower_lambda_to_nested_sdfg( domain: gtir_translators.FieldopDomain, init_data: gtir_translators.FieldopResult, lambda_symbols: dict[str, ts.DataType], - lambda_field_offsets: dict[str, Optional[list[dace.symbolic.SymExpr]]], scan_forward: bool, scan_carry_symbol: gtir.Sym, ) -> tuple[dace.SDFG, gtir_translators.FieldopResult]: @@ -297,8 +294,6 @@ def _lower_lambda_to_nested_sdfg( init_data: The data produced in the field operator context that is used to initialize the scan carry value. lambda_symbols: List of symbols used as parameters of the stencil expressions. - lambda_field_offsets: Mapping from symbol name to field origin, - `None` if field origin is 0 in all dimensions. scan_forward: When True, the loop should range starting from the origin; when False, traverse towards origin. scan_carry_symbol: The symbol used in the stencil expression to carry the @@ -317,9 +312,7 @@ def _lower_lambda_to_nested_sdfg( # the lambda expression, i.e. body of the scan, will be created inside a nested SDFG. nsdfg = dace.SDFG(sdfg_builder.unique_nsdfg_name(sdfg, "scan")) nsdfg.debuginfo = gtir_sdfg_utils.debug_info(lambda_node, default=sdfg.debuginfo) - lambda_translator = sdfg_builder.setup_nested_context( - lambda_node, nsdfg, lambda_symbols, lambda_field_offsets - ) + lambda_translator = sdfg_builder.setup_nested_context(lambda_node, nsdfg, lambda_symbols) # use the vertical dimension in the domain as scan dimension scan_domain = [ @@ -474,7 +467,7 @@ def connect_scan_output( ) output_type = ts.FieldType(dims=[scan_dim], dtype=scan_result.gt_dtype) - return gtir_translators.FieldopData(output_node, output_type, offset=scan_lower_bound) + return gtir_translators.FieldopData(output_node, output_type, origin=(scan_lower_bound,)) # write the stencil result (value on one vertical level) into a 1D field # with full vertical shape representing one column @@ -603,24 +596,36 @@ def translate_scan( for p, arg_type in zip(stencil_expr.params, lambda_arg_types, strict=True) } + # lower the scan stencil expression in a separate SDFG context + nsdfg, lambda_output = _lower_lambda_to_nested_sdfg( + stencil_expr, + sdfg, + sdfg_builder, + domain, + init_data, + lambda_symbols, + scan_forward, + im.sym(scan_carry, scan_carry_type), + ) + # visit the arguments to be passed to the lambda expression # this must be executed before visiting the lambda expression, in order to populate # the data descriptor with the correct field domain offsets for field arguments lambda_args = [sdfg_builder.visit(arg, sdfg=sdfg, head_state=state) for arg in node.args] - lambda_args_mapping = { - _scan_input_name(scan_carry): init_data, - } | { - str(param.id): arg for param, arg in zip(stencil_expr.params[1:], lambda_args, strict=True) - } + lambda_args_mapping = [ + (im.sym(_scan_input_name(scan_carry), scan_carry_type), init_data), + ] + [ + (im.sym(param.id, arg.gt_type), arg) + for param, arg in zip(stencil_expr.params[1:], lambda_args, strict=True) + ] + + lambda_arg_nodes = dict( + itertools.chain( + *[gtir_translators.flatten_tuples(psym.id, arg) for psym, arg in lambda_args_mapping] + ) + ) - # parse the dataflow input and output symbols - lambda_flat_args: dict[str, gtir_translators.FieldopData] = {} - # the field offset is set to `None` when it is zero in all dimensions - lambda_field_offsets: dict[str, Optional[list[dace.symbolic.SymExpr]]] = {} - for param, outer_arg in lambda_args_mapping.items(): - tuple_fields = gtir_translators.flatten_tuples(param, outer_arg) - lambda_field_offsets |= {tsym: tfield.offset for tsym, tfield in tuple_fields} - lambda_flat_args |= dict(tuple_fields) + # parse the dataflow output symbols if isinstance(scan_carry_type, ts.TupleType): lambda_flat_outs = { str(sym.id): sym.type @@ -631,46 +636,23 @@ def translate_scan( else: lambda_flat_outs = {_scan_output_name(scan_carry): scan_carry_type} - # lower the scan stencil expression in a separate SDFG context - nsdfg, lambda_output = _lower_lambda_to_nested_sdfg( - stencil_expr, - sdfg, - sdfg_builder, - domain, - init_data, - lambda_symbols, - lambda_field_offsets, - scan_forward, - im.sym(scan_carry, scan_carry_type), - ) - # build the mapping of symbols from nested SDFG to field operator context nsdfg_symbols_mapping = {str(sym): sym for sym in nsdfg.free_symbols} - for inner_dataname, outer_arg in lambda_flat_args.items(): - inner_desc = nsdfg.data(inner_dataname) - outer_desc = outer_arg.dc_node.desc(sdfg) - nsdfg_symbols_mapping |= { - str(nested_symbol): parent_symbol - for nested_symbol, parent_symbol in zip( - [*inner_desc.shape, *inner_desc.strides], - [*outer_desc.shape, *outer_desc.strides], - strict=True, - ) - if dace.symbolic.issymbolic(nested_symbol) - } + for psym, arg in lambda_args_mapping: + nsdfg_symbols_mapping |= gtir_translators.get_arg_symbol_mapping(psym.id, arg, sdfg) # the scan nested SDFG is ready: it is instantiated in the field operator context # where the map scope over the horizontal domain lives nsdfg_node = state.add_nested_sdfg( nsdfg, sdfg, - inputs=set(lambda_flat_args.keys()), + inputs=set(lambda_arg_nodes.keys()), outputs=set(lambda_flat_outs.keys()), symbol_mapping=nsdfg_symbols_mapping, ) lambda_input_edges = [] - for input_connector, outer_arg in lambda_flat_args.items(): + for input_connector, outer_arg in lambda_arg_nodes.items(): arg_desc = outer_arg.dc_node.desc(sdfg) input_subset = dace_subsets.Range.from_array(arg_desc) input_edge = gtir_dataflow.MemletInputEdge( diff --git a/src/gt4py/next/program_processors/runners/dace/gtir_sdfg.py b/src/gt4py/next/program_processors/runners/dace/gtir_sdfg.py index b306a59305..a58e8bcf8a 100644 --- a/src/gt4py/next/program_processors/runners/dace/gtir_sdfg.py +++ b/src/gt4py/next/program_processors/runners/dace/gtir_sdfg.py @@ -16,7 +16,6 @@ import abc import dataclasses -import functools import itertools import operator from typing import Any, Dict, Iterable, List, Optional, Protocol, Sequence, Set, Tuple, Union @@ -34,6 +33,7 @@ from gt4py.next.program_processors.runners.dace import ( gtir_builtin_translators, gtir_sdfg_utils, + transformations as gtx_transformations, utils as gtx_dace_utils, ) from gt4py.next.type_system import type_specifications as ts, type_translation as tt @@ -121,7 +121,9 @@ class SDFGBuilder(DataflowBuilder, Protocol): @abc.abstractmethod def make_field( - self, data_node: dace.nodes.AccessNode, data_type: ts.FieldType | ts.ScalarType + self, + data_node: dace.nodes.AccessNode, + data_type: ts.FieldType | ts.ScalarType, ) -> gtir_builtin_translators.FieldopData: """Retrieve the field data descriptor including the domain offset information.""" ... @@ -142,7 +144,6 @@ def setup_nested_context( expr: gtir.Expr, sdfg: dace.SDFG, global_symbols: dict[str, ts.DataType], - field_offsets: dict[str, Optional[list[dace.symbolic.SymExpr]]], ) -> SDFGBuilder: """ Create an SDFG context to translate a nested expression, indipendent @@ -156,7 +157,6 @@ def setup_nested_context( expr: The nested expresson to be lowered. sdfg: The SDFG where to lower the nested expression. global_symbols: Mapping from symbol name to GTIR data type. - field_offsets: Mapping from symbol name to field origin, `None` if field origin is 0 in all dimensions. Returns: A visitor object implementing the `SDFGBuilder` protocol. @@ -201,6 +201,24 @@ def _collect_symbols_in_domain_expressions( ) +def _make_access_index_for_field( + domain: gtir_builtin_translators.FieldopDomain, data: gtir_builtin_translators.FieldopData +) -> dace.subsets.Range: + """Helper method to build a memlet subset of a field over the given domain.""" + # convert domain expression to dictionary to ease access to the dimensions, + # since the access indices have to follow the order of dimensions in field domain + if isinstance(data.gt_type, ts.FieldType) and len(data.gt_type.dims) != 0: + assert data.origin is not None + domain_ranges = {dim: (lb, ub) for dim, lb, ub in domain} + return dace.subsets.Range( + (domain_ranges[dim][0] - origin, domain_ranges[dim][1] - origin - 1, 1) + for dim, origin in zip(data.gt_type.dims, data.origin, strict=True) + ) + else: + assert len(domain) == 0 + return dace.subsets.Range.from_string("0") + + @dataclasses.dataclass(frozen=True) class GTIRToSDFG(eve.NodeVisitor, SDFGBuilder): """Provides translation capability from a GTIR program to a DaCe SDFG. @@ -217,10 +235,7 @@ class GTIRToSDFG(eve.NodeVisitor, SDFGBuilder): offset_provider_type: gtx_common.OffsetProviderType column_axis: Optional[gtx_common.Dimension] - global_symbols: dict[str, ts.DataType] = dataclasses.field(default_factory=dict) - field_offsets: dict[str, Optional[list[dace.symbolic.SymExpr]]] = dataclasses.field( - default_factory=dict - ) + global_symbols: dict[str, ts.DataType] map_uids: eve.utils.UIDGenerator = dataclasses.field( init=False, repr=False, default_factory=lambda: eve.utils.UIDGenerator(prefix="map") ) @@ -232,18 +247,23 @@ def get_offset_provider_type(self, offset: str) -> gtx_common.OffsetProviderType return self.offset_provider_type[offset] def make_field( - self, data_node: dace.nodes.AccessNode, data_type: ts.FieldType | ts.ScalarType + self, + data_node: dace.nodes.AccessNode, + data_type: ts.FieldType | ts.ScalarType, ) -> gtir_builtin_translators.FieldopData: """ - Helper method to build the field data type associated with an access node in the SDFG. + Helper method to build the field data type associated with a data access node. - In case of `ScalarType` data, the descriptor is constructed with `offset=None`. + In case of `ScalarType` data, the `FieldopData` is constructed with `origin=None`. In case of `FieldType` data, the field origin is added to the data descriptor. Besides, if the `FieldType` contains a local dimension, the descriptor is converted to a canonical form where the field domain consists of all global dimensions (the grid axes) and the field data type is `ListType`, with `offset_type` equal to the field local dimension. + TODO(edoapo): consider refactoring this method and moving it to a type module + close to the `FieldopData` type declaration. + Args: data_node: The access node to the SDFG data storage. data_type: The GT4Py data descriptor, which can either come from a field parameter @@ -253,8 +273,7 @@ def make_field( The descriptor associated with the SDFG data storage, filled with field origin. """ if isinstance(data_type, ts.ScalarType): - return gtir_builtin_translators.FieldopData(data_node, data_type, offset=None) - domain_offset = self.field_offsets.get(data_node.data, None) + return gtir_builtin_translators.FieldopData(data_node, data_type, origin=()) local_dims = [dim for dim in data_type.dims if dim.kind == gtx_common.DimensionKind.LOCAL] if len(local_dims) == 0: # do nothing: the field domain consists of all global dimensions @@ -279,7 +298,11 @@ def make_field( raise NotImplementedError( "Fields with more than one local dimension are not supported." ) - return gtir_builtin_translators.FieldopData(data_node, field_type, domain_offset) + field_origin = tuple( + dace.symbolic.pystr_to_symbolic(gtx_dace_utils.range_start_symbol(data_node.data, axis)) + for axis in range(len(field_type.dims)) + ) + return gtir_builtin_translators.FieldopData(data_node, field_type, field_origin) def get_symbol_type(self, symbol_name: str) -> ts.DataType: return self.global_symbols[symbol_name] @@ -293,11 +316,8 @@ def setup_nested_context( expr: gtir.Expr, sdfg: dace.SDFG, global_symbols: dict[str, ts.DataType], - field_offsets: dict[str, Optional[list[dace.symbolic.SymExpr]]], ) -> SDFGBuilder: - nsdfg_builder = GTIRToSDFG( - self.offset_provider_type, self.column_axis, global_symbols, field_offsets - ) + nsdfg_builder = GTIRToSDFG(self.offset_provider_type, self.column_axis, global_symbols) nsdfg_params = [ gtir.Sym(id=p_name, type=p_type) for p_name, p_type in global_symbols.items() ] @@ -321,28 +341,45 @@ def unique_tasklet_name(self, name: str) -> str: def _make_array_shape_and_strides( self, name: str, dims: Sequence[gtx_common.Dimension] - ) -> tuple[list[dace.symbol], list[dace.symbol]]: + ) -> tuple[list[dace.symbolic.SymbolicType], list[dace.symbolic.SymbolicType]]: """ Parse field dimensions and allocate symbols for array shape and strides. For local dimensions, the size is known at compile-time and therefore the corresponding array shape dimension is set to an integer literal value. + This method is only called for non-transient arrays, which require symbolic + memory layout. The memory layout of transient arrays, used for temporary + fields, is left to the DaCe default (row major, not necessarily the optimal + one) and might be changed during optimization. + Returns: Two lists of symbols, one for the shape and the other for the strides of the array. """ - dc_dtype = gtir_builtin_translators.INDEX_DTYPE neighbor_table_types = gtx_dace_utils.filter_connectivity_types(self.offset_provider_type) - shape = [ - ( - neighbor_table_types[dim.value].max_neighbors - if dim.kind == gtx_common.DimensionKind.LOCAL - else dace.symbol(gtx_dace_utils.field_size_symbol_name(name, i), dc_dtype) - ) - for i, dim in enumerate(dims) - ] + shape = [] + for i, dim in enumerate(dims): + if dim.kind == gtx_common.DimensionKind.LOCAL: + # for local dimension, the size is taken from the associated connectivity type + shape.append(neighbor_table_types[dim.value].max_neighbors) + elif gtx_dace_utils.is_connectivity_identifier(name, self.offset_provider_type): + # we use symbolic size for the global dimension of a connectivity + shape.append( + dace.symbolic.pystr_to_symbolic(gtx_dace_utils.field_size_symbol_name(name, i)) + ) + else: + # the size of global dimensions for a regular field is the symbolic + # expression of domain range 'stop - start' + shape.append( + dace.symbolic.pystr_to_symbolic( + "{} - {}".format( + gtx_dace_utils.range_stop_symbol(name, i), + gtx_dace_utils.range_start_symbol(name, i), + ) + ) + ) strides = [ - dace.symbol(gtx_dace_utils.field_stride_symbol_name(name, i), dc_dtype) + dace.symbolic.pystr_to_symbolic(gtx_dace_utils.field_stride_symbol_name(name, i)) for i in range(len(dims)) ] return shape, strides @@ -470,7 +507,7 @@ def make_temps( head_state.add_nedge( field.dc_node, temp_node, sdfg.make_array_memlet(field.dc_node.data) ) - return field.make_copy(temp_node) + return gtir_builtin_translators.FieldopData(temp_node, field.gt_type, field.origin) temp_result = gtx_utils.tree_map(make_temps)(result) return list(gtx_utils.flatten_nested_tuple((temp_result,))) @@ -498,7 +535,6 @@ def _add_sdfg_params( sdfg_args += self._add_storage( sdfg, symbolic_arguments, pname, param.type, transient=False ) - self.global_symbols[pname] = param.type # add SDFG storage for connectivity tables for offset, connectivity_type in gtx_dace_utils.filter_connectivity_types( @@ -532,13 +568,6 @@ def visit_Program(self, node: gtir.Program) -> dace.SDFG: The temporary data is global, therefore available everywhere in the SDFG but not outside. Then, all statements are translated, one after the other. """ - if node.function_definitions: - raise NotImplementedError("Functions expected to be inlined as lambda calls.") - - # Since program field arguments are passed to the SDFG as full-shape arrays, - # there is no offset that needs to be compensated. - assert len(self.field_offsets) == 0 - sdfg = dace.SDFG(node.id) sdfg.debuginfo = gtir_sdfg_utils.debug_info(node) @@ -605,10 +634,8 @@ def visit_SetAt( # in case the statement returns more than one field target_fields = self._visit_expression(stmt.target, sdfg, state, use_temp=False) - # convert domain expression to dictionary to ease access to dimension boundaries - domain = { - dim: (lb, ub) for dim, lb, ub in gtir_builtin_translators.extract_domain(stmt.domain) - } + # visit the domain expression + domain = gtir_builtin_translators.extract_domain(stmt.domain) expr_input_args = { sym_id @@ -626,22 +653,9 @@ def visit_SetAt( target_desc = sdfg.arrays[target.dc_node.data] assert not target_desc.transient - if isinstance(target.gt_type, ts.FieldType): - target_subset = ",".join( - f"{domain[dim][0]}:{domain[dim][1]}" for dim in target.gt_type.dims - ) - source_subset = ( - target_subset - if source.offset is None - else ",".join( - f"{domain[dim][0] - offset}:{domain[dim][1] - offset}" - for dim, offset in zip(target.gt_type.dims, source.offset, strict=True) - ) - ) - else: - assert len(domain) == 0 - target_subset = "0" - source_subset = "0" + assert source.gt_type == target.gt_type + source_subset = _make_access_index_for_field(domain, source) + target_subset = _make_access_index_for_field(domain, target) if target.dc_node.data in state_input_data: # if inout argument, write the result in separate next state @@ -725,15 +739,11 @@ def visit_Lambda( i.e. a lambda parameter with the same name as a symbol in scope, the parameter will shadow the previous symbol during traversal of the lambda expression. """ - lambda_args_mapping = [ - (str(param.id), arg) for param, arg in zip(node.params, args, strict=True) - ] - lambda_arg_nodes = dict( itertools.chain( *[ - gtir_builtin_translators.flatten_tuples(pname, arg) - for pname, arg in lambda_args_mapping + gtir_builtin_translators.flatten_tuples(psym.id, arg) + for psym, arg in zip(node.params, args, strict=True) ] ) ) @@ -743,44 +753,16 @@ def visit_Lambda( sym: self.global_symbols[sym] for sym in symbol_ref_utils.collect_symbol_refs(node.expr, self.global_symbols.keys()) } | { - pname: gtir_builtin_translators.get_tuple_type(arg) + psym.id: gtir_builtin_translators.get_tuple_type(arg) if isinstance(arg, tuple) else arg.gt_type - for pname, arg in lambda_args_mapping + for psym, arg in zip(node.params, args, strict=True) } - def get_field_domain_offset( - p_name: str, p_type: ts.DataType - ) -> dict[str, Optional[list[dace.symbolic.SymExpr]]]: - if isinstance(p_type, ts.FieldType): - if p_name in lambda_arg_nodes: - arg = lambda_arg_nodes[p_name] - assert isinstance(arg, gtir_builtin_translators.FieldopData) - return {p_name: arg.offset} - elif field_domain_offset := self.field_offsets.get(p_name, None): - return {p_name: field_domain_offset} - elif isinstance(p_type, ts.TupleType): - tsyms = gtir_sdfg_utils.flatten_tuple_fields(p_name, p_type) - return functools.reduce( - lambda field_offsets, sym: ( - field_offsets | get_field_domain_offset(sym.id, sym.type) # type: ignore[arg-type] - ), - tsyms, - {}, - ) - return {} - - # populate mapping from field name to domain offset - lambda_field_offsets: dict[str, Optional[list[dace.symbolic.SymExpr]]] = {} - for p_name, p_type in lambda_symbols.items(): - lambda_field_offsets |= get_field_domain_offset(p_name, p_type) - # lower let-statement lambda node as a nested SDFG nsdfg = dace.SDFG(name=self.unique_nsdfg_name(sdfg, "lambda")) nsdfg.debuginfo = gtir_sdfg_utils.debug_info(node, default=sdfg.debuginfo) - lambda_translator = self.setup_nested_context( - node.expr, nsdfg, lambda_symbols, lambda_field_offsets - ) + lambda_translator = self.setup_nested_context(node.expr, nsdfg, lambda_symbols) nstate = nsdfg.add_state("lambda") lambda_result = lambda_translator.visit( @@ -800,7 +782,6 @@ def get_field_domain_offset( } input_memlets = {} - nsdfg_symbols_mapping = {str(sym): sym for sym in nsdfg.free_symbols} for nsdfg_dataname, nsdfg_datadesc in nsdfg.arrays.items(): if nsdfg_datadesc.transient: continue @@ -809,15 +790,6 @@ def get_field_domain_offset( src_node = lambda_arg_nodes[nsdfg_dataname].dc_node dataname = src_node.data datadesc = src_node.desc(sdfg) - nsdfg_symbols_mapping |= { - str(nested_symbol): parent_symbol - for nested_symbol, parent_symbol in zip( - [*nsdfg_datadesc.shape, *nsdfg_datadesc.strides], - [*datadesc.shape, *datadesc.strides], - strict=True, - ) - if dace.symbolic.issymbolic(nested_symbol) - } else: dataname = nsdfg_dataname datadesc = sdfg.arrays[nsdfg_dataname] @@ -855,6 +827,13 @@ def get_field_domain_offset( if output_data.dc_node.desc(nsdfg).transient } + # map free symbols to parent SDFG + nsdfg_symbols_mapping = {str(sym): sym for sym in nsdfg.free_symbols} + for sym, arg in zip(node.params, args, strict=True): + nsdfg_symbols_mapping |= gtir_builtin_translators.get_arg_symbol_mapping( + sym.id, arg, sdfg + ) + nsdfg_node = head_state.add_nested_sdfg( nsdfg, parent=sdfg, @@ -888,33 +867,34 @@ def construct_output_for_nested_sdfg( arguments, that are simply returned by the lambda: it can be directly accessed in the parent SDFG. """ inner_desc = inner_data.dc_node.desc(nsdfg) + inner_dataname = inner_data.dc_node.data if inner_desc.transient: # Transient data nodes only exist within the nested SDFG. In order to return some result data, # the corresponding data container inside the nested SDFG has to be changed to non-transient, # that is externally allocated, as required by the SDFG IR. An output edge will write the result # from the nested-SDFG to a new intermediate data container allocated in the parent SDFG. - inner_desc.transient = False - outer, outer_desc = self.add_temp_array_like(sdfg, inner_desc) - # We cannot use a copy of the inner data descriptor directly, we have to apply the symbol mapping. - dace.symbolic.safe_replace( - nsdfg_symbols_mapping, - lambda m: dace.sdfg.replace_properties_dict(outer_desc, m), + outer_data = inner_data.map_to_parent_sdfg( + self, nsdfg, sdfg, head_state, nsdfg_symbols_mapping ) - connector = inner_data.dc_node.data - outer_node = head_state.add_access(outer) head_state.add_edge( - nsdfg_node, connector, outer_node, None, sdfg.make_array_memlet(outer) + nsdfg_node, + inner_dataname, + outer_data.dc_node, + None, + sdfg.make_array_memlet(outer_data.dc_node.data), ) - outer_data = inner_data.make_copy(outer_node) - elif inner_data.dc_node.data in lambda_arg_nodes: + elif inner_dataname in lambda_arg_nodes: # This if branch and the next one handle the non-transient result nodes. # Non-transient nodes are just input nodes that are immediately returned # by the lambda expression. Therefore, these nodes are already available # in the parent context and can be directly accessed there. - outer_data = lambda_arg_nodes[inner_data.dc_node.data] + outer_data = lambda_arg_nodes[inner_dataname] else: - outer_node = head_state.add_access(inner_data.dc_node.data) - outer_data = inner_data.make_copy(outer_node) + # This must be a symbol captured from the lambda parent scope. + outer_node = head_state.add_access(inner_dataname) + outer_data = gtir_builtin_translators.FieldopData( + outer_node, inner_data.gt_type, inner_data.origin + ) # Isolated access node will make validation fail. # Isolated access nodes can be found in the join-state of an if-expression # or in lambda expressions that just construct tuples from input arguments. @@ -941,10 +921,50 @@ def visit_SymRef( return gtir_builtin_translators.translate_symbol_ref(node, sdfg, head_state, self) +def _remove_field_origin_symbols(ir: gtir.Program, sdfg: dace.SDFG) -> None: + """ + Helper function to remove the origin symbols used in program field arguments, + that is only for non-transient data descriptors in the top-level SDFG. + The start symbol of field domain range is set to constant value 0, thus removing + the corresponding free symbol. These values are propagated to all nested SDFGs. + + This function is only used by `build_sdfg_from_gtir()` when the option flag + `disable_field_origin_on_program_arguments` is set to True. + """ + + # collect symbols used as range start for all program arguments + range_start_symbols: dict[str, dace.symbolic.SymExpr] = {} + for p in ir.params: + if isinstance(p.type, ts.TupleType): + psymbols = [ + sym + for sym in gtir_sdfg_utils.flatten_tuple_fields(p.id, p.type) + if isinstance(sym.type, ts.FieldType) + ] + elif isinstance(p.type, ts.FieldType): + psymbols = [p] + else: + psymbols = [] + for psymbol in psymbols: + assert isinstance(psymbol.type, ts.FieldType) + if len(psymbol.type.dims) == 0: + # zero-dimensional field + continue + dataname = str(psymbol.id) + # set all range start symbols to constant value 0 + range_start_symbols |= { + gtx_dace_utils.range_start_symbol(dataname, i): 0 + for i in range(len(psymbol.type.dims)) + } + # we set all range start symbols to 0 in the top-level SDFG and proagate them to nested SDFGs + gtx_transformations.gt_substitute_compiletime_symbols(sdfg, range_start_symbols, validate=True) + + def build_sdfg_from_gtir( ir: gtir.Program, offset_provider_type: gtx_common.OffsetProviderType, column_axis: Optional[gtx_common.Dimension] = None, + disable_field_origin_on_program_arguments: bool = False, ) -> dace.SDFG: """ Receives a GTIR program and lowers it to a DaCe SDFG. @@ -956,11 +976,15 @@ def build_sdfg_from_gtir( ir: The GTIR program node to be lowered to SDFG offset_provider_type: The definitions of offset providers used by the program node column_axis: Vertical dimension used for column scan expressions. + disable_field_origin_on_program_arguments: When True, the field range in all dimensions is assumed to start from 0 Returns: An SDFG in the DaCe canonical form (simplified) """ + if ir.function_definitions: + raise NotImplementedError("Functions expected to be inlined as lambda calls.") + ir = gtir_type_inference.infer(ir, offset_provider_type=offset_provider_type) ir = ir_prune_casts.PruneCasts().visit(ir) @@ -970,11 +994,15 @@ def build_sdfg_from_gtir( # Here we find new names for invalid symbols present in the IR. ir = gtir_sdfg_utils.replace_invalid_symbols(ir) - sdfg_genenerator = GTIRToSDFG(offset_provider_type, column_axis) + global_symbols = {str(p.id): p.type for p in ir.params if isinstance(p.type, ts.DataType)} + sdfg_genenerator = GTIRToSDFG(offset_provider_type, column_axis, global_symbols) sdfg = sdfg_genenerator.visit(ir) assert isinstance(sdfg, dace.SDFG) # TODO(edopao): remove inlining when DaCe transformations support LoopRegion construct dace_sdfg_utils.inline_loop_blocks(sdfg) + if disable_field_origin_on_program_arguments: + _remove_field_origin_symbols(ir, sdfg) + return sdfg diff --git a/src/gt4py/next/program_processors/runners/dace/program.py b/src/gt4py/next/program_processors/runners/dace/program.py index 78016db0a9..a381346a1e 100644 --- a/src/gt4py/next/program_processors/runners/dace/program.py +++ b/src/gt4py/next/program_processors/runners/dace/program.py @@ -85,11 +85,13 @@ def __sdfg__(self, *args: Any, **kwargs: Any) -> dace.sdfg.sdfg.SDFG: if not hasattr(self.backend.executor, "step") else self.backend.executor.step, ) # We know which backend we are using, but we don't know if the compile workflow is cached. - # TODO(ricoh): switch 'itir_transforms_off=True' because we ran them separately previously + # TODO(ricoh): switch 'disable_itir_transforms=True' because we ran them separately previously # and so we can ensure the SDFG does not know any runtime info it shouldn't know. Remove with # the other parts of the workaround when possible. sdfg = dace.SDFG.from_json( - compile_workflow.translation.replace(itir_transforms_off=True)(gtir_stage).source_code + compile_workflow.translation.replace( + disable_itir_transforms=True, disable_field_origin_on_program_arguments=True + )(gtir_stage).source_code ) self.sdfg_closure_cache["arrays"] = sdfg.arrays diff --git a/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py b/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py index 7f221a5a41..09720ddf3c 100644 --- a/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py +++ b/src/gt4py/next/program_processors/runners/dace/sdfg_callable.py @@ -7,7 +7,7 @@ # SPDX-License-Identifier: BSD-3-Clause import warnings from collections.abc import Mapping, Sequence -from typing import Any +from typing import Any, Optional import dace import numpy as np @@ -24,32 +24,40 @@ cp = None -def _convert_arg(arg: Any, sdfg_param: str) -> Any: +def _convert_arg(arg: Any) -> tuple[Any, Optional[gtx_common.Domain]]: if not isinstance(arg, gtx_common.Field): - return arg + return arg, None if len(arg.domain.dims) == 0: # Pass zero-dimensional fields as scalars. - return arg.as_scalar() - # field domain offsets are not supported - non_zero_offsets = [ - (dim, dim_range) - for dim, dim_range in zip(arg.domain.dims, arg.domain.ranges, strict=True) - if dim_range.start != 0 - ] - if non_zero_offsets: - dim, dim_range = non_zero_offsets[0] - raise RuntimeError( - f"Field '{sdfg_param}' passed as array slice with offset {dim_range.start} on dimension {dim.value}." - ) - return arg.ndarray + return arg.as_scalar(), None + return arg.ndarray, arg.domain def _get_args(sdfg: dace.SDFG, args: Sequence[Any]) -> dict[str, Any]: sdfg_params: Sequence[str] = sdfg.arg_names - return { - sdfg_param: _convert_arg(arg, sdfg_param) - for sdfg_param, arg in zip(sdfg_params, args, strict=True) - } + sdfg_arguments = {} + range_symbols: dict[str, int] = {} + for sdfg_param, arg in zip(sdfg_params, args, strict=True): + sdfg_arg, domain = _convert_arg(arg) + sdfg_arguments[sdfg_param] = sdfg_arg + if domain: + assert gtx_common.Domain.is_finite(domain) + range_symbols |= { + gtx_dace_utils.range_start_symbol(sdfg_param, i): r.start + for i, r in enumerate(domain.ranges) + } + range_symbols |= { + gtx_dace_utils.range_stop_symbol(sdfg_param, i): r.stop + for i, r in enumerate(domain.ranges) + } + # sanity check in case range symbols are passed as explicit program arguments + for range_symbol, value in range_symbols.items(): + if (sdfg_arg := sdfg_arguments.get(range_symbol, None)) is not None: + if sdfg_arg != value: + raise ValueError( + f"Received program argument {range_symbol} with value {sdfg_arg}, expected {value}." + ) + return sdfg_arguments | range_symbols def _ensure_is_on_device( @@ -150,18 +158,16 @@ def get_sdfg_args( dace_args = _get_args(sdfg, args) dace_field_args = {n: v for n, v in dace_args.items() if not np.isscalar(v)} + dace_field_strides = _get_stride_args(sdfg.arrays, dace_field_args) dace_conn_args = get_sdfg_conn_args(sdfg, offset_provider, on_gpu) - dace_shapes = _get_shape_args(sdfg.arrays, dace_field_args) dace_conn_shapes = _get_shape_args(sdfg.arrays, dace_conn_args) - dace_strides = _get_stride_args(sdfg.arrays, dace_field_args) dace_conn_strides = _get_stride_args(sdfg.arrays, dace_conn_args) all_args = { **dace_args, **dace_conn_args, - **dace_shapes, **dace_conn_shapes, - **dace_strides, **dace_conn_strides, + **dace_field_strides, } if check_args: diff --git a/src/gt4py/next/program_processors/runners/dace/utils.py b/src/gt4py/next/program_processors/runners/dace/utils.py index cca0c001e7..5fdace73a9 100644 --- a/src/gt4py/next/program_processors/runners/dace/utils.py +++ b/src/gt4py/next/program_processors/runners/dace/utils.py @@ -9,7 +9,7 @@ from __future__ import annotations import re -from typing import Final, Literal +from typing import Final, Literal, Mapping, Union import dace @@ -73,6 +73,16 @@ def field_stride_symbol_name(field_name: str, axis: int) -> str: return field_symbol_name(field_name, axis, "stride") +def range_start_symbol(field_name: str, axis: int) -> str: + """Format name of start symbol for domain range, as expected by GTIR.""" + return f"__{field_name}_{axis}_range_0" + + +def range_stop_symbol(field_name: str, axis: int) -> str: + """Format name of stop symbol for domain range, as expected by GTIR.""" + return f"__{field_name}_{axis}_range_1" + + def is_field_symbol(name: str) -> bool: return FIELD_SYMBOL_RE.match(name) is not None @@ -90,3 +100,29 @@ def filter_connectivity_types( for offset, conn in offset_provider_type.items() if isinstance(conn, gtx_common.NeighborConnectivityType) } + + +def safe_replace_symbolic( + val: dace.symbolic.SymbolicType, + symbol_mapping: Mapping[ + Union[dace.symbolic.SymbolicType, str], Union[dace.symbolic.SymbolicType, str] + ], +) -> dace.symbolic.SymbolicType: + """ + Replace free symbols in a dace symbolic expression, using `safe_replace()` + in order to avoid clashes in case the new symbol value is also a free symbol + in the original exoression. + + Args: + val: The symbolic expression where to apply the replacement. + symbol_mapping: The mapping table for symbol replacement. + + Returns: + A new symbolic expression as result of symbol replacement. + """ + # The list `x` is needed because `subs()` returns a new object and can not handle + # replacement dicts of the form `{'x': 'y', 'y': 'x'}`. + # The utility `safe_replace()` will call `subs()` twice in case of such dicts. + x = [val] + dace.symbolic.safe_replace(symbol_mapping, lambda m, xx=x: xx.append(xx[-1].subs(m))) + return x[-1] diff --git a/src/gt4py/next/program_processors/runners/dace/workflow/translation.py b/src/gt4py/next/program_processors/runners/dace/workflow/translation.py index 96be93de5e..6e1b3a6f32 100644 --- a/src/gt4py/next/program_processors/runners/dace/workflow/translation.py +++ b/src/gt4py/next/program_processors/runners/dace/workflow/translation.py @@ -35,7 +35,8 @@ class DaCeTranslator( ): device_type: core_defs.DeviceType auto_optimize: bool - itir_transforms_off: bool = False + disable_itir_transforms: bool = False + disable_field_origin_on_program_arguments: bool = False def _language_settings(self) -> languages.LanguageSettings: return languages.LanguageSettings( @@ -50,10 +51,13 @@ def generate_sdfg( auto_opt: bool, on_gpu: bool, ) -> dace.SDFG: - if not self.itir_transforms_off: + if not self.disable_itir_transforms: ir = itir_transforms.apply_fieldview_transforms(ir, offset_provider=offset_provider) sdfg = gtir_sdfg.build_sdfg_from_gtir( - ir, common.offset_provider_to_type(offset_provider), column_axis + ir, + common.offset_provider_to_type(offset_provider), + column_axis, + disable_field_origin_on_program_arguments=self.disable_field_origin_on_program_arguments, ) if auto_opt: diff --git a/tests/next_tests/definitions.py b/tests/next_tests/definitions.py index 522250cafc..a96d967430 100644 --- a/tests/next_tests/definitions.py +++ b/tests/next_tests/definitions.py @@ -152,7 +152,6 @@ class ProgramFormatterId(_PythonObjectIdMixin, str, enum.Enum): (USES_CAN_DEREF, XFAIL, UNSUPPORTED_MESSAGE), (USES_COMPOSITE_SHIFTS, XFAIL, UNSUPPORTED_MESSAGE), (USES_LIFT, XFAIL, UNSUPPORTED_MESSAGE), - (USES_ORIGIN, XFAIL, UNSUPPORTED_MESSAGE), (USES_REDUCE_WITH_LAMBDA, XFAIL, UNSUPPORTED_MESSAGE), (USES_SCAN_IN_STENCIL, XFAIL, BINDINGS_UNSUPPORTED_MESSAGE), (USES_SPARSE_FIELDS, XFAIL, UNSUPPORTED_MESSAGE), diff --git a/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py b/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py index 8fe0634302..3ba376b08f 100644 --- a/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py +++ b/tests/next_tests/integration_tests/feature_tests/dace/test_orchestration.py @@ -37,9 +37,6 @@ def test_sdfgConvertible_laplap(cartesian_case): # noqa: F811 if not cartesian_case.backend or "dace" not in cartesian_case.backend.name: pytest.skip("DaCe-related test: Test SDFGConvertible interface for GT4Py programs") - # TODO(edopao): add support for range symbols in field domain and re-enable this test - pytest.skip("Requires support for field domain range.") - backend = cartesian_case.backend in_field = cases.allocate(cartesian_case, laplap_program, "in_field")() @@ -62,7 +59,9 @@ def sdfg(): tmp_field, out_field ) - sdfg() + # use unique cache name based on process id to avoid clashes between parallel pytest workers + with dace.config.set_temporary("cache", value="unique"): + sdfg() assert np.allclose( gtx.field_utils.asnumpy(out_field)[2:-2, 2:-2], @@ -85,9 +84,6 @@ def test_sdfgConvertible_connectivities(unstructured_case): # noqa: F811 if not unstructured_case.backend or "dace" not in unstructured_case.backend.name: pytest.skip("DaCe-related test: Test SDFGConvertible interface for GT4Py programs") - # TODO(edopao): add support for range symbols in field domain and re-enable this test - pytest.skip("Requires support for field domain range.") - allocator, backend = unstructured_case.allocator, unstructured_case.backend if gtx_allocators.is_field_allocator_for(allocator, gtx_allocators.CUPY_DEVICE): @@ -139,16 +135,18 @@ def get_stride_from_numpy_to_dace(arg: core_defs.NDArrayObject, axis: int) -> in # DaCe strides: number of elements to jump return arg.strides[axis] // arg.itemsize - cSDFG( - a, - out, - offset_provider, - rows=3, - cols=2, - connectivity_E2V=e2v, - __connectivity_E2V_stride_0=get_stride_from_numpy_to_dace(e2v.ndarray, 0), - __connectivity_E2V_stride_1=get_stride_from_numpy_to_dace(e2v.ndarray, 1), - ) + # use unique cache name based on process id to avoid clashes between parallel pytest workers + with dace.config.set_temporary("cache", value="unique"): + cSDFG( + a, + out, + offset_provider, + rows=3, + cols=2, + connectivity_E2V=e2v, + __connectivity_E2V_stride_0=get_stride_from_numpy_to_dace(e2v.ndarray, 0), + __connectivity_E2V_stride_1=get_stride_from_numpy_to_dace(e2v.ndarray, 1), + ) e2v_np = e2v.asnumpy() assert np.allclose(out.asnumpy(), a.asnumpy()[e2v_np[:, 0]]) @@ -160,8 +158,8 @@ def get_stride_from_numpy_to_dace(arg: core_defs.NDArrayObject, axis: int) -> in allocator=allocator, ) offset_provider = OffsetProvider_t.dtype._typeclass.as_ctypes()(E2V=e2v.data_ptr()) - with dace.config.temporary_config(): - dace.config.Config.set("compiler", "allow_view_arguments", value=True) + # use unique cache name based on process id to avoid clashes between parallel pytest workers + with dace.config.set_temporary("cache", value="unique"): cSDFG( a, out, diff --git a/tests/next_tests/integration_tests/feature_tests/dace/test_program.py b/tests/next_tests/integration_tests/feature_tests/dace/test_program.py index 4edaf9f85f..e5e2f18608 100644 --- a/tests/next_tests/integration_tests/feature_tests/dace/test_program.py +++ b/tests/next_tests/integration_tests/feature_tests/dace/test_program.py @@ -77,13 +77,9 @@ def unstructured(request, gtir_dace_backend, mesh_descriptor): # noqa: F811 ) -@pytest.mark.skipif(dace is None, reason="DaCe not found") def test_halo_exchange_helper_attrs(unstructured): local_int = gtx.int - # TODO(edopao): add support for range symbols in field domain and re-enable this test - pytest.skip("Requires support for field domain range.") - @gtx.field_operator(backend=unstructured.backend) def testee_op( a: gtx.Field[[Vertex, KDim], gtx.int], diff --git a/tests/next_tests/integration_tests/multi_feature_tests/iterator_tests/test_hdiff.py b/tests/next_tests/integration_tests/multi_feature_tests/iterator_tests/test_hdiff.py index e44e92013f..1726956332 100644 --- a/tests/next_tests/integration_tests/multi_feature_tests/iterator_tests/test_hdiff.py +++ b/tests/next_tests/integration_tests/multi_feature_tests/iterator_tests/test_hdiff.py @@ -61,6 +61,7 @@ def hdiff(inp, coeff, out, x, y): set_at(as_fieldop(hdiff_sten, domain)(inp, coeff), domain, out) +@pytest.mark.uses_lift @pytest.mark.uses_origin def test_hdiff(hdiff_reference, program_processor): program_processor, validate = program_processor diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace_utils.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace_utils.py new file mode 100644 index 0000000000..eec68a6486 --- /dev/null +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_dace_utils.py @@ -0,0 +1,21 @@ +# GT4Py - GridTools Framework +# +# Copyright (c) 2014-2024, ETH Zurich +# All rights reserved. +# +# Please, refer to the LICENSE file in the root directory. +# SPDX-License-Identifier: BSD-3-Clause + +"""Test utility functions of the dace backend module.""" + +import pytest + +dace = pytest.importorskip("dace") + +from gt4py.next.program_processors.runners.dace import utils as gtx_dace_utils + + +def test_safe_replace_symbolic(): + assert gtx_dace_utils.safe_replace_symbolic( + dace.symbolic.pystr_to_symbolic("x*x + y"), symbol_mapping={"x": "y", "y": "x"} + ) == dace.symbolic.pystr_to_symbolic("y*y + x") diff --git a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py index 7431ad2b4a..8ebb240339 100644 --- a/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py +++ b/tests/next_tests/unit_tests/program_processor_tests/runners_tests/dace_tests/test_gtir_to_sdfg.py @@ -13,6 +13,7 @@ """ import functools +from typing import Any, Callable import numpy as np import pytest @@ -52,13 +53,13 @@ SKIP_VALUE_MESH: MeshDescriptor = skip_value_mesh() SIZE_TYPE = ts.ScalarType(ts.ScalarKind.INT32) FSYMBOLS = dict( - __w_size_0=N, + __w_0_range_1=N, __w_stride_0=1, - __x_size_0=N, + __x_0_range_1=N, __x_stride_0=1, - __y_size_0=N, + __y_0_range_1=N, __y_stride_0=1, - __z_size_0=N, + __z_0_range_1=N, __z_stride_0=1, size=N, ) @@ -69,31 +70,39 @@ def make_mesh_symbols(mesh: MeshDescriptor): ncells=mesh.num_cells, nedges=mesh.num_edges, nvertices=mesh.num_vertices, - __cells_size_0=mesh.num_cells, + __cells_0_range_1=mesh.num_cells, __cells_stride_0=1, - __edges_size_0=mesh.num_edges, + __edges_0_range_1=mesh.num_edges, __edges_stride_0=1, - __vertices_size_0=mesh.num_vertices, + __vertices_0_range_1=mesh.num_vertices, __vertices_stride_0=1, - __connectivity_C2E_size_0=mesh.num_cells, + __connectivity_C2E_0_range_1=mesh.num_cells, __connectivity_C2E_size_1=mesh.offset_provider_type["C2E"].max_neighbors, __connectivity_C2E_stride_0=mesh.offset_provider_type["C2E"].max_neighbors, __connectivity_C2E_stride_1=1, - __connectivity_C2V_size_0=mesh.num_cells, + __connectivity_C2V_0_range_1=mesh.num_cells, __connectivity_C2V_size_1=mesh.offset_provider_type["C2V"].max_neighbors, __connectivity_C2V_stride_0=mesh.offset_provider_type["C2V"].max_neighbors, __connectivity_C2V_stride_1=1, - __connectivity_E2V_size_0=mesh.num_edges, + __connectivity_E2V_0_range_1=mesh.num_edges, __connectivity_E2V_size_1=mesh.offset_provider_type["E2V"].max_neighbors, __connectivity_E2V_stride_0=mesh.offset_provider_type["E2V"].max_neighbors, __connectivity_E2V_stride_1=1, - __connectivity_V2E_size_0=mesh.num_vertices, + __connectivity_V2E_0_range_1=mesh.num_vertices, __connectivity_V2E_size_1=mesh.offset_provider_type["V2E"].max_neighbors, __connectivity_V2E_stride_0=mesh.offset_provider_type["V2E"].max_neighbors, __connectivity_V2E_stride_1=1, ) +def build_dace_sdfg( + ir: gtir.Program, offset_provider_type: gtx_common.OffsetProviderType +) -> Callable[..., Any]: + return dace_backend.build_sdfg_from_gtir( + ir, offset_provider_type, disable_field_origin_on_program_arguments=True + ) + + def test_gtir_broadcast(): val = np.random.rand() domain = im.domain(gtx_common.GridType.CARTESIAN, ranges={IDim: (0, "size")}) @@ -116,7 +125,7 @@ def test_gtir_broadcast(): a = np.empty(N, dtype=np.float64) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, **FSYMBOLS) np.testing.assert_array_equal(a, val) @@ -152,7 +161,7 @@ def test_gtir_cast(): b = a.astype(np.float32) c = np.empty_like(a, dtype=np.bool_) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, c, **FSYMBOLS) np.testing.assert_array_equal(c, True) @@ -180,7 +189,7 @@ def test_gtir_copy_self(): a = np.random.rand(N) ref = a.copy() - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, **FSYMBOLS) assert np.allclose(a, ref) @@ -211,7 +220,7 @@ def test_gtir_tuple_swap(): b = np.random.rand(N) ref = (a.copy(), b.copy()) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, **FSYMBOLS) assert np.allclose(a, ref[1]) @@ -250,16 +259,16 @@ def test_gtir_tuple_args(): b = np.random.rand(N) c = np.empty_like(a) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) x_fields = (a, a, b) tuple_symbols = { - "__x_0_size_0": N, + "__x_0_0_range_1": N, "__x_0_stride_0": 1, - "__x_1_0_size_0": N, + "__x_1_0_0_range_1": N, "__x_1_0_stride_0": 1, - "__x_1_1_size_0": N, + "__x_1_1_0_range_1": N, "__x_1_1_stride_0": 1, } @@ -302,7 +311,7 @@ def test_gtir_tuple_expr(): b = np.random.rand(N) c = np.empty_like(a) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, c, **FSYMBOLS) assert np.allclose(c, a * 2 + b) @@ -356,7 +365,7 @@ def test_gtir_tuple_broadcast_scalar(): c = np.random.rand() d = np.empty(N, dtype=type(a)) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) x_fields = (a, b, c) @@ -387,7 +396,7 @@ def test_gtir_zero_dim_fields(): a = np.asarray(np.random.rand()) b = np.empty(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a.item(), b, **FSYMBOLS) assert np.allclose(a, b) @@ -421,16 +430,16 @@ def test_gtir_tuple_return(): a = np.random.rand(N) b = np.random.rand(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) z_fields = (np.empty_like(a), np.empty_like(a), np.empty_like(a)) tuple_symbols = { - "__z_0_0_size_0": N, + "__z_0_0_0_range_1": N, "__z_0_0_stride_0": 1, - "__z_0_1_size_0": N, + "__z_0_1_0_range_1": N, "__z_0_1_stride_0": 1, - "__z_1_size_0": N, + "__z_1_0_range_1": N, "__z_1_stride_0": 1, } @@ -464,7 +473,7 @@ def test_gtir_tuple_target(): b = np.empty_like(a) ref = a.copy() - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, **FSYMBOLS) assert np.allclose(a, ref + 1) @@ -496,7 +505,7 @@ def test_gtir_update(): ) ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) a = np.random.rand(N) ref = a - 1.0 @@ -530,7 +539,7 @@ def test_gtir_sum2(): b = np.random.rand(N) c = np.empty_like(a) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, c, **FSYMBOLS) assert np.allclose(c, (a + b)) @@ -559,7 +568,7 @@ def test_gtir_sum2_sym(): a = np.random.rand(N) b = np.empty_like(a) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) sdfg(a, b, **FSYMBOLS) assert np.allclose(b, (a + a)) @@ -601,7 +610,7 @@ def test_gtir_sum3(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) d = np.empty_like(a) @@ -645,7 +654,7 @@ def test_gtir_cond(): b = np.random.rand(N) c = np.random.rand(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) for s1, s2 in [(1, 2), (2, 1)]: d = np.empty_like(a) @@ -687,12 +696,12 @@ def test_gtir_cond_with_tuple_return(): b = np.random.rand(N) c = np.random.rand(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) tuple_symbols = { - "__z_0_size_0": N, + "__z_0_0_range_1": N, "__z_0_stride_0": 1, - "__z_1_size_0": N, + "__z_1_0_range_1": N, "__z_1_stride_0": 1, } @@ -735,7 +744,7 @@ def test_gtir_cond_nested(): a = np.random.rand(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) for s1 in [False, True]: for s2 in [False, True]: @@ -841,9 +850,9 @@ def test_gtir_cartesian_shift_left(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) - sdfg(a, a_offset, b, **FSYMBOLS, __x_offset_size_0=N, __x_offset_stride_0=1) + sdfg(a, a_offset, b, **FSYMBOLS, __x_offset_0_range_1=N, __x_offset_stride_0=1) assert np.allclose(a[OFFSET:] + DELTA, b[:-OFFSET]) @@ -936,9 +945,9 @@ def test_gtir_cartesian_shift_right(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) - sdfg(a, a_offset, b, **FSYMBOLS, __x_offset_size_0=N, __x_offset_stride_0=1) + sdfg(a, a_offset, b, **FSYMBOLS, __x_offset_0_range_1=N, __x_offset_stride_0=1) assert np.allclose(a[:-OFFSET] + DELTA, b[OFFSET:]) @@ -1075,7 +1084,7 @@ def test_gtir_connectivity_shift(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SIMPLE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SIMPLE_MESH.offset_provider_type) ce = np.empty([SIMPLE_MESH.num_cells, SIMPLE_MESH.num_edges]) @@ -1088,17 +1097,17 @@ def test_gtir_connectivity_shift(): connectivity_E2V=connectivity_E2V.ndarray, **FSYMBOLS, **make_mesh_symbols(SIMPLE_MESH), - __ce_field_size_0=SIMPLE_MESH.num_cells, + __ce_field_0_range_1=SIMPLE_MESH.num_cells, __ce_field_size_1=SIMPLE_MESH.num_edges, __ce_field_stride_0=SIMPLE_MESH.num_edges, __ce_field_stride_1=1, - __ev_field_size_0=SIMPLE_MESH.num_edges, + __ev_field_0_range_1=SIMPLE_MESH.num_edges, __ev_field_size_1=SIMPLE_MESH.num_vertices, __ev_field_stride_0=SIMPLE_MESH.num_vertices, __ev_field_stride_1=1, - __c2e_offset_size_0=SIMPLE_MESH.num_cells, + __c2e_offset_0_range_1=SIMPLE_MESH.num_cells, __c2e_offset_stride_0=1, - __e2v_offset_size_0=SIMPLE_MESH.num_edges, + __e2v_offset_0_range_1=SIMPLE_MESH.num_edges, __e2v_offset_stride_0=1, ) assert np.allclose(ce, ref) @@ -1136,7 +1145,7 @@ def test_gtir_connectivity_shift_chain(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SIMPLE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SIMPLE_MESH.offset_provider_type) connectivity_E2V = SIMPLE_MESH.offset_provider["E2V"] assert isinstance(connectivity_E2V, gtx_common.NeighborTable) @@ -1158,7 +1167,7 @@ def test_gtir_connectivity_shift_chain(): connectivity_V2E=connectivity_V2E.ndarray, **FSYMBOLS, **make_mesh_symbols(SIMPLE_MESH), - __edges_out_size_0=SIMPLE_MESH.num_edges, + __edges_out_0_range_1=SIMPLE_MESH.num_edges, __edges_out_stride_0=1, ) assert np.allclose(e_out, ref) @@ -1196,7 +1205,7 @@ def test_gtir_neighbors_as_input(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SIMPLE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SIMPLE_MESH.offset_provider_type) connectivity_V2E = SIMPLE_MESH.offset_provider["V2E"] assert isinstance(connectivity_V2E, gtx_common.NeighborTable) @@ -1217,7 +1226,7 @@ def test_gtir_neighbors_as_input(): connectivity_V2E=connectivity_V2E.ndarray, **FSYMBOLS, **make_mesh_symbols(SIMPLE_MESH), - __v2e_field_size_0=SIMPLE_MESH.num_vertices, + __v2e_field_0_range_1=SIMPLE_MESH.num_vertices, __v2e_field_size_1=connectivity_V2E.shape[1], __v2e_field_stride_0=connectivity_V2E.shape[1], __v2e_field_stride_1=1, @@ -1254,7 +1263,7 @@ def test_gtir_neighbors_as_output(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SIMPLE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SIMPLE_MESH.offset_provider_type) connectivity_V2E = SIMPLE_MESH.offset_provider["V2E"] assert isinstance(connectivity_V2E, gtx_common.NeighborTable) @@ -1268,7 +1277,7 @@ def test_gtir_neighbors_as_output(): connectivity_V2E=connectivity_V2E.ndarray, **FSYMBOLS, **make_mesh_symbols(SIMPLE_MESH), - __v2e_field_size_0=SIMPLE_MESH.num_vertices, + __v2e_field_0_range_1=SIMPLE_MESH.num_vertices, __v2e_field_size_1=connectivity_V2E.max_neighbors, __v2e_field_stride_0=connectivity_V2E.max_neighbors, __v2e_field_stride_1=1, @@ -1317,7 +1326,7 @@ def test_gtir_reduce(): ) ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SIMPLE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SIMPLE_MESH.offset_provider_type) # new empty output field v = np.empty(SIMPLE_MESH.num_vertices, dtype=e.dtype) @@ -1377,7 +1386,7 @@ def test_gtir_reduce_with_skip_values(): ) ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SKIP_VALUE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SKIP_VALUE_MESH.offset_provider_type) # new empty output field v = np.empty(SKIP_VALUE_MESH.num_vertices, dtype=e.dtype) @@ -1446,7 +1455,7 @@ def test_gtir_reduce_dot_product(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SKIP_VALUE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SKIP_VALUE_MESH.offset_provider_type) sdfg( v2e_field, @@ -1454,7 +1463,7 @@ def test_gtir_reduce_dot_product(): v, connectivity_V2E=connectivity_V2E.ndarray, **make_mesh_symbols(SKIP_VALUE_MESH), - __v2e_field_size_0=SKIP_VALUE_MESH.num_vertices, + __v2e_field_0_range_1=SKIP_VALUE_MESH.num_vertices, __v2e_field_size_1=connectivity_V2E.shape[1], __v2e_field_stride_0=connectivity_V2E.shape[1], __v2e_field_stride_1=1, @@ -1503,7 +1512,7 @@ def test_gtir_reduce_with_cond_neighbors(): e = np.random.rand(SKIP_VALUE_MESH.num_edges) for use_sparse in [False, True]: - sdfg = dace_backend.build_sdfg_from_gtir(testee, SKIP_VALUE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SKIP_VALUE_MESH.offset_provider_type) v = np.empty(SKIP_VALUE_MESH.num_vertices, dtype=e.dtype) v_ref = [ @@ -1531,7 +1540,7 @@ def test_gtir_reduce_with_cond_neighbors(): connectivity_V2E=connectivity_V2E.ndarray, **FSYMBOLS, **make_mesh_symbols(SKIP_VALUE_MESH), - __v2e_field_size_0=SKIP_VALUE_MESH.num_vertices, + __v2e_field_0_range_1=SKIP_VALUE_MESH.num_vertices, __v2e_field_size_1=connectivity_V2E.shape[1], __v2e_field_stride_0=connectivity_V2E.shape[1], __v2e_field_stride_1=1, @@ -1618,7 +1627,7 @@ def test_gtir_symbolic_domain(): b = np.random.rand(N) ref = np.concatenate((b[0:MARGIN], a[MARGIN : N - MARGIN] * 8, b[N - MARGIN : N])) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, **FSYMBOLS) assert np.allclose(b, ref) @@ -1666,7 +1675,7 @@ def test_gtir_let_lambda(): b = np.random.rand(N) ref = np.concatenate((b[0:1], a[1 : N - 1] * 8, b[N - 1 : N])) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) sdfg(a, b, **FSYMBOLS) assert np.allclose(b, ref) @@ -1701,7 +1710,7 @@ def test_gtir_let_lambda_scalar_expression(): c = np.random.rand(N) d = np.empty_like(c) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) sdfg(a, b, c, d, **FSYMBOLS) assert np.allclose(d, (a * a * b * b * c)) @@ -1750,7 +1759,7 @@ def test_gtir_let_lambda_with_connectivity(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, SIMPLE_MESH.offset_provider_type) + sdfg = build_dace_sdfg(testee, SIMPLE_MESH.offset_provider_type) e = np.random.rand(SIMPLE_MESH.num_edges) v = np.random.rand(SIMPLE_MESH.num_vertices) @@ -1797,7 +1806,7 @@ def test_gtir_let_lambda_with_cond(): ], ) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) a = np.random.rand(N) for s in [False, True]: @@ -1835,16 +1844,16 @@ def test_gtir_let_lambda_with_tuple1(): a = np.random.rand(N) b = np.random.rand(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) z_fields = (np.empty_like(a), np.empty_like(a)) a_ref = np.concatenate((z_fields[0][:1], a[1 : N - 1], z_fields[0][N - 1 :])) b_ref = np.concatenate((z_fields[1][:1], b[1 : N - 1], z_fields[1][N - 1 :])) tuple_symbols = { - "__z_0_size_0": N, + "__z_0_0_range_1": N, "__z_0_stride_0": 1, - "__z_1_size_0": N, + "__z_1_0_range_1": N, "__z_1_stride_0": 1, } @@ -1884,16 +1893,16 @@ def test_gtir_let_lambda_with_tuple2(): a = np.random.rand(N) b = np.random.rand(N) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) z_fields = (np.empty_like(a), np.empty_like(a), np.empty_like(a)) tuple_symbols = { - "__z_0_size_0": N, + "__z_0_0_range_1": N, "__z_0_stride_0": 1, - "__z_1_size_0": N, + "__z_1_0_range_1": N, "__z_1_stride_0": 1, - "__z_2_size_0": N, + "__z_2_0_range_1": N, "__z_2_stride_0": 1, } @@ -1947,14 +1956,14 @@ def test_gtir_if_scalars(): d1 = np.random.randint(0, 1000) d2 = np.random.randint(0, 1000) - sdfg = dace_backend.build_sdfg_from_gtir(testee, {}) + sdfg = build_dace_sdfg(testee, {}) tuple_symbols = { - "__x_0_size_0": N, + "__x_0_0_range_1": N, "__x_0_stride_0": 1, - "__x_1_0_size_0": N, + "__x_1_0_0_range_1": N, "__x_1_0_stride_0": 1, - "__x_1_1_size_0": N, + "__x_1_1_0_range_1": N, "__x_1_1_stride_0": 1, } @@ -1990,7 +1999,7 @@ def test_gtir_if_values(): b = np.random.rand(N) c = np.empty_like(a) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) sdfg(a, b, c, **FSYMBOLS) assert np.allclose(c, np.where(a < b, a, b)) @@ -2032,7 +2041,7 @@ def test_gtir_index(): # we need to run domain inference in order to add the domain annex information to the index node. testee = infer_domain.infer_program(testee, offset_provider=CARTESIAN_OFFSETS) - sdfg = dace_backend.build_sdfg_from_gtir(testee, CARTESIAN_OFFSETS) + sdfg = build_dace_sdfg(testee, CARTESIAN_OFFSETS) ref = np.concatenate( (v[:MARGIN], np.arange(MARGIN, N - MARGIN, dtype=np.int32), v[N - MARGIN :]) From c06cac31f043f6da5ef612db57adab4fe3649d73 Mon Sep 17 00:00:00 2001 From: Till Ehrengruber Date: Fri, 31 Jan 2025 07:58:32 +0100 Subject: [PATCH 09/13] bug[next]: Use same python in CMake as used for execution (#1567) Co-authored-by: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> --- .../next/otf/compilation/build_systems/cmake_lists.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gt4py/next/otf/compilation/build_systems/cmake_lists.py b/src/gt4py/next/otf/compilation/build_systems/cmake_lists.py index 0533adac81..23c80793c7 100644 --- a/src/gt4py/next/otf/compilation/build_systems/cmake_lists.py +++ b/src/gt4py/next/otf/compilation/build_systems/cmake_lists.py @@ -88,9 +88,15 @@ def visit_FindDependency(self, dep: FindDependency) -> str: # Instead, design this to be extensible (refer to ADR-0016). match dep.name: case "nanobind": + import sys + import nanobind - py = "find_package(Python COMPONENTS Interpreter Development REQUIRED)" + py = f""" + set(Python_EXECUTABLE {sys.executable}) + + find_package(Python COMPONENTS Interpreter Development REQUIRED) + """ nb = f"find_package(nanobind CONFIG REQUIRED PATHS {nanobind.cmake_dir()} NO_DEFAULT_PATHS)" return py + "\n" + nb case "gridtools_cpu" | "gridtools_gpu": From 6f835983edb0dd8c2b19831098acf52ea338c282 Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Fri, 31 Jan 2025 10:20:33 +0100 Subject: [PATCH 10/13] build: use frozen dependencies when running mypy in pre-commit (#1841) ... otherwise it might update `uv.lock` which will create a pre-commit error because of changed files. See also https://github.com/astral-sh/uv/issues/10845 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4222224cc4..afca7bfa05 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -63,7 +63,7 @@ repos: hooks: - id: mypy name: mypy static type checker - entry: uv run mypy --no-install-types src/ + entry: uv run --frozen mypy --no-install-types src/ language: system types_or: [python, pyi] pass_filenames: false From b18bbf98e20d70646a693030762bd766571fba9c Mon Sep 17 00:00:00 2001 From: Till Ehrengruber Date: Sat, 1 Feb 2025 20:41:00 +0100 Subject: [PATCH 11/13] bug[next]: Fix accept args (#1830) `type_info.accept_args` is used in the iterator type inference to check if a node with type `ts.FunctionType` is callable for a given set of arguments [here](https://github.com/GridTools/gt4py/blob/764ef5098078b327d086c4e06db357b45b046669/src/gt4py/next/iterator/type_system/inference.py#L237). This failed when the function type had an iterator argument with `position_dims="unknown"`. This PR promotes the `_is_compatible_type` function from the iterator type inference to a shared function available in all type systems and switches `accept_args` (or more precisely `function_signature_incompatibilities_func`) to use that function instead of `is_concretizable`. Additionally this PR contains a small cleanup of the type deduction / type system tests: - `test_type_deduction.py` was moved from integration to unit tests (as it only contains unit tests). - All type system tests are moved from `test_type_deduction.py` as they are not specific to the frontend type deduction. Co-authored-by: SF-N --- .../next/iterator/type_system/inference.py | 63 +-- src/gt4py/next/type_system/type_info.py | 72 ++- .../ffront_tests/test_type_deduction.py | 414 +++++++++++++++++ .../test_type_system.py} | 419 +----------------- 4 files changed, 505 insertions(+), 463 deletions(-) create mode 100644 tests/next_tests/unit_tests/ffront_tests/test_type_deduction.py rename tests/next_tests/{integration_tests/feature_tests/ffront_tests/test_type_deduction.py => unit_tests/test_type_system.py} (51%) diff --git a/src/gt4py/next/iterator/type_system/inference.py b/src/gt4py/next/iterator/type_system/inference.py index 901cb103da..fe450625db 100644 --- a/src/gt4py/next/iterator/type_system/inference.py +++ b/src/gt4py/next/iterator/type_system/inference.py @@ -32,66 +32,11 @@ def _is_representable_as_int(s: int | str) -> bool: return False -def _is_compatible_type(type_a: ts.TypeSpec, type_b: ts.TypeSpec): - """ - Predicate to determine if two types are compatible. - - This function gracefully handles: - - iterators with unknown positions which are considered compatible to any other positions - of another iterator. - - iterators which are defined everywhere, i.e. empty defined dimensions - Beside that this function simply checks for equality of types. - - >>> bool_type = ts.ScalarType(kind=ts.ScalarKind.BOOL) - >>> IDim = common.Dimension(value="IDim") - >>> type_on_i_of_i_it = it_ts.IteratorType( - ... position_dims=[IDim], defined_dims=[IDim], element_type=bool_type - ... ) - >>> type_on_undefined_of_i_it = it_ts.IteratorType( - ... position_dims="unknown", defined_dims=[IDim], element_type=bool_type - ... ) - >>> _is_compatible_type(type_on_i_of_i_it, type_on_undefined_of_i_it) - True - - >>> JDim = common.Dimension(value="JDim") - >>> type_on_j_of_j_it = it_ts.IteratorType( - ... position_dims=[JDim], defined_dims=[JDim], element_type=bool_type - ... ) - >>> _is_compatible_type(type_on_i_of_i_it, type_on_j_of_j_it) - False - """ - is_compatible = True - - if isinstance(type_a, it_ts.IteratorType) and isinstance(type_b, it_ts.IteratorType): - if not any(el_type.position_dims == "unknown" for el_type in [type_a, type_b]): - is_compatible &= type_a.position_dims == type_b.position_dims - if type_a.defined_dims and type_b.defined_dims: - is_compatible &= type_a.defined_dims == type_b.defined_dims - is_compatible &= type_a.element_type == type_b.element_type - elif isinstance(type_a, ts.TupleType) and isinstance(type_b, ts.TupleType): - for el_type_a, el_type_b in zip(type_a.types, type_b.types, strict=True): - is_compatible &= _is_compatible_type(el_type_a, el_type_b) - elif isinstance(type_a, ts.FunctionType) and isinstance(type_b, ts.FunctionType): - for arg_a, arg_b in zip(type_a.pos_only_args, type_b.pos_only_args, strict=True): - is_compatible &= _is_compatible_type(arg_a, arg_b) - for arg_a, arg_b in zip( - type_a.pos_or_kw_args.values(), type_b.pos_or_kw_args.values(), strict=True - ): - is_compatible &= _is_compatible_type(arg_a, arg_b) - for arg_a, arg_b in zip( - type_a.kw_only_args.values(), type_b.kw_only_args.values(), strict=True - ): - is_compatible &= _is_compatible_type(arg_a, arg_b) - is_compatible &= _is_compatible_type(type_a.returns, type_b.returns) - else: - is_compatible &= type_info.is_concretizable(type_a, type_b) - - return is_compatible - - def _set_node_type(node: itir.Node, type_: ts.TypeSpec) -> None: if node.type: - assert _is_compatible_type(node.type, type_), "Node already has a type which differs." + assert type_info.is_compatible_type( + node.type, type_ + ), "Node already has a type which differs." node.type = type_ @@ -475,7 +420,7 @@ def visit(self, node: concepts.RootNode, **kwargs: Any) -> Any: if isinstance(node, itir.Node): if isinstance(result, ts.TypeSpec): if node.type and not isinstance(node.type, ts.DeferredType): - assert _is_compatible_type(node.type, result) + assert type_info.is_compatible_type(node.type, result) node.type = result elif isinstance(result, ObservableTypeSynthesizer) or result is None: pass diff --git a/src/gt4py/next/type_system/type_info.py b/src/gt4py/next/type_system/type_info.py index 26373c647f..27dd2cf02c 100644 --- a/src/gt4py/next/type_system/type_info.py +++ b/src/gt4py/next/type_system/type_info.py @@ -26,6 +26,7 @@ from gt4py.eve.utils import XIterable, xiter from gt4py.next import common +from gt4py.next.iterator.type_system import type_specifications as it_ts from gt4py.next.type_system import type_specifications as ts @@ -432,6 +433,69 @@ def contains_local_field(type_: ts.TypeSpec) -> bool: ) +# TODO(tehrengruber): This function has specializations on Iterator types, which are not part of +# the general / shared type system. This functionality should be moved to the iterator-only +# type system, but we need some sort of multiple dispatch for that. +# TODO(tehrengruber): Should this have a direction like is_concretizable? +def is_compatible_type(type_a: ts.TypeSpec, type_b: ts.TypeSpec) -> bool: + """ + Predicate to determine if two types are compatible. + + This function gracefully handles: + - iterators with unknown positions which are considered compatible to any other positions + of another iterator. + - iterators which are defined everywhere, i.e. empty defined dimensions + Beside that this function simply checks for equality of types. + + >>> bool_type = ts.ScalarType(kind=ts.ScalarKind.BOOL) + >>> IDim = common.Dimension(value="IDim") + >>> type_on_i_of_i_it = it_ts.IteratorType( + ... position_dims=[IDim], defined_dims=[IDim], element_type=bool_type + ... ) + >>> type_on_undefined_of_i_it = it_ts.IteratorType( + ... position_dims="unknown", defined_dims=[IDim], element_type=bool_type + ... ) + >>> is_compatible_type(type_on_i_of_i_it, type_on_undefined_of_i_it) + True + + >>> JDim = common.Dimension(value="JDim") + >>> type_on_j_of_j_it = it_ts.IteratorType( + ... position_dims=[JDim], defined_dims=[JDim], element_type=bool_type + ... ) + >>> is_compatible_type(type_on_i_of_i_it, type_on_j_of_j_it) + False + """ + is_compatible = True + + if isinstance(type_a, it_ts.IteratorType) and isinstance(type_b, it_ts.IteratorType): + if not any(el_type.position_dims == "unknown" for el_type in [type_a, type_b]): + is_compatible &= type_a.position_dims == type_b.position_dims + if type_a.defined_dims and type_b.defined_dims: + is_compatible &= type_a.defined_dims == type_b.defined_dims + is_compatible &= type_a.element_type == type_b.element_type + elif isinstance(type_a, ts.TupleType) and isinstance(type_b, ts.TupleType): + if len(type_a.types) != len(type_b.types): + return False + for el_type_a, el_type_b in zip(type_a.types, type_b.types, strict=True): + is_compatible &= is_compatible_type(el_type_a, el_type_b) + elif isinstance(type_a, ts.FunctionType) and isinstance(type_b, ts.FunctionType): + for arg_a, arg_b in zip(type_a.pos_only_args, type_b.pos_only_args, strict=True): + is_compatible &= is_compatible_type(arg_a, arg_b) + for arg_a, arg_b in zip( + type_a.pos_or_kw_args.values(), type_b.pos_or_kw_args.values(), strict=True + ): + is_compatible &= is_compatible_type(arg_a, arg_b) + for arg_a, arg_b in zip( + type_a.kw_only_args.values(), type_b.kw_only_args.values(), strict=True + ): + is_compatible &= is_compatible_type(arg_a, arg_b) + is_compatible &= is_compatible_type(type_a.returns, type_b.returns) + else: + is_compatible &= is_concretizable(type_a, type_b) + + return is_compatible + + def is_concretizable(symbol_type: ts.TypeSpec, to_type: ts.TypeSpec) -> bool: """ Check if ``symbol_type`` can be concretized to ``to_type``. @@ -725,11 +789,7 @@ def function_signature_incompatibilities_func( for i, (a_arg, b_arg) in enumerate( zip(list(func_type.pos_only_args) + list(func_type.pos_or_kw_args.values()), args) ): - if ( - b_arg is not UNDEFINED_ARG - and a_arg != b_arg - and not is_concretizable(a_arg, to_type=b_arg) - ): + if b_arg is not UNDEFINED_ARG and a_arg != b_arg and not is_compatible_type(a_arg, b_arg): if i < len(func_type.pos_only_args): arg_repr = f"{_number_to_ordinal_number(i + 1)} argument" else: @@ -739,7 +799,7 @@ def function_signature_incompatibilities_func( for kwarg in set(func_type.kw_only_args.keys()) & set(kwargs.keys()): if (a_kwarg := func_type.kw_only_args[kwarg]) != ( b_kwarg := kwargs[kwarg] - ) and not is_concretizable(a_kwarg, to_type=b_kwarg): + ) and not is_compatible_type(a_kwarg, b_kwarg): yield f"Expected keyword argument '{kwarg}' to be of type '{func_type.kw_only_args[kwarg]}', got '{kwargs[kwarg]}'." diff --git a/tests/next_tests/unit_tests/ffront_tests/test_type_deduction.py b/tests/next_tests/unit_tests/ffront_tests/test_type_deduction.py new file mode 100644 index 0000000000..254772fd8a --- /dev/null +++ b/tests/next_tests/unit_tests/ffront_tests/test_type_deduction.py @@ -0,0 +1,414 @@ +# GT4Py - GridTools Framework +# +# Copyright (c) 2014-2024, ETH Zurich +# All rights reserved. +# +# Please, refer to the LICENSE file in the root directory. +# SPDX-License-Identifier: BSD-3-Clause + +import re +from typing import Optional, Pattern + +import pytest + +import gt4py.next.ffront.type_specifications +from gt4py.next import ( + Dimension, + DimensionKind, + Field, + FieldOffset, + astype, + broadcast, + common, + errors, + float32, + float64, + int32, + int64, + neighbor_sum, + where, +) +from gt4py.next.ffront.ast_passes import single_static_assign as ssa +from gt4py.next.ffront.experimental import as_offset +from gt4py.next.ffront.func_to_foast import FieldOperatorParser +from gt4py.next.type_system import type_info, type_specifications as ts + +TDim = Dimension("TDim") # Meaningless dimension, used for tests. + + +def test_unpack_assign(): + def unpack_explicit_tuple( + a: Field[[TDim], float64], b: Field[[TDim], float64] + ) -> tuple[Field[[TDim], float64], Field[[TDim], float64]]: + tmp_a, tmp_b = (a, b) + return tmp_a, tmp_b + + parsed = FieldOperatorParser.apply_to_function(unpack_explicit_tuple) + + assert parsed.body.annex.symtable[ssa.unique_name("tmp_a", 0)].type == ts.FieldType( + dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64, shape=None) + ) + assert parsed.body.annex.symtable[ssa.unique_name("tmp_b", 0)].type == ts.FieldType( + dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64, shape=None) + ) + + +def test_assign_tuple(): + def temp_tuple(a: Field[[TDim], float64], b: Field[[TDim], int64]): + tmp = a, b + return tmp + + parsed = FieldOperatorParser.apply_to_function(temp_tuple) + + assert parsed.body.annex.symtable[ssa.unique_name("tmp", 0)].type == ts.TupleType( + types=[ + ts.FieldType(dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64, shape=None)), + ts.FieldType(dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64, shape=None)), + ] + ) + + +def test_adding_bool(): + """Expect an error when using arithmetic on bools.""" + + def add_bools(a: Field[[TDim], bool], b: Field[[TDim], bool]): + return a + b + + with pytest.raises( + errors.DSLError, match=(r"Type 'Field\[\[TDim\], bool\]' can not be used in operator '\+'.") + ): + _ = FieldOperatorParser.apply_to_function(add_bools) + + +def test_binop_nonmatching_dims(): + """Binary operations can only work when both fields have the same dimensions.""" + X = Dimension("X") + Y = Dimension("Y") + + def nonmatching(a: Field[[X], float64], b: Field[[Y], float64]): + return a + b + + with pytest.raises( + errors.DSLError, + match=( + r"Could not promote 'Field\[\[X], float64\]' and 'Field\[\[Y\], float64\]' to common type in call to +." + ), + ): + _ = FieldOperatorParser.apply_to_function(nonmatching) + + +def test_bitopping_float(): + def float_bitop(a: Field[[TDim], float], b: Field[[TDim], float]): + return a & b + + with pytest.raises( + errors.DSLError, + match=(r"Type 'Field\[\[TDim\], float64\]' can not be used in operator '\&'."), + ): + _ = FieldOperatorParser.apply_to_function(float_bitop) + + +def test_signing_bool(): + def sign_bool(a: Field[[TDim], bool]): + return -a + + with pytest.raises( + errors.DSLError, + match=r"Incompatible type for unary operator '\-': 'Field\[\[TDim\], bool\]'.", + ): + _ = FieldOperatorParser.apply_to_function(sign_bool) + + +def test_notting_int(): + def not_int(a: Field[[TDim], int64]): + return not a + + with pytest.raises( + errors.DSLError, + match=r"Incompatible type for unary operator 'not': 'Field\[\[TDim\], int64\]'.", + ): + _ = FieldOperatorParser.apply_to_function(not_int) + + +@pytest.fixture +def premap_setup(): + X = Dimension("X") + Y = Dimension("Y") + Y2XDim = Dimension("Y2X", kind=DimensionKind.LOCAL) + Y2X = FieldOffset("Y2X", source=X, target=(Y, Y2XDim)) + return X, Y, Y2XDim, Y2X + + +def test_premap(premap_setup): + X, Y, Y2XDim, Y2X = premap_setup + + def premap_fo(bar: Field[[X], int64]) -> Field[[Y], int64]: + return bar(Y2X[0]) + + parsed = FieldOperatorParser.apply_to_function(premap_fo) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64) + ) + + +def test_premap_nbfield(premap_setup): + X, Y, Y2XDim, Y2X = premap_setup + + def premap_fo(bar: Field[[X], int64]) -> Field[[Y, Y2XDim], int64]: + return bar(Y2X) + + parsed = FieldOperatorParser.apply_to_function(premap_fo) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[Y, Y2XDim], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64) + ) + + +def test_premap_reduce(premap_setup): + X, Y, Y2XDim, Y2X = premap_setup + + def premap_fo(bar: Field[[X], int32]) -> Field[[Y], int32]: + return 2 * neighbor_sum(bar(Y2X), axis=Y2XDim) + + parsed = FieldOperatorParser.apply_to_function(premap_fo) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32) + ) + + +def test_premap_reduce_sparse(premap_setup): + X, Y, Y2XDim, Y2X = premap_setup + + def premap_fo(bar: Field[[Y, Y2XDim], int32]) -> Field[[Y], int32]: + return 5 * neighbor_sum(bar, axis=Y2XDim) + + parsed = FieldOperatorParser.apply_to_function(premap_fo) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32) + ) + + +def test_mismatched_literals(): + def mismatched_lit() -> Field[[TDim], "float32"]: + return float32("1.0") + float64("1.0") + + with pytest.raises( + errors.DSLError, + match=(r"Could not promote 'float32' and 'float64' to common type in call to +."), + ): + _ = FieldOperatorParser.apply_to_function(mismatched_lit) + + +def test_broadcast_multi_dim(): + ADim = Dimension("ADim") + BDim = Dimension("BDim") + CDim = Dimension("CDim") + + def simple_broadcast(a: Field[[ADim], float64]): + return broadcast(a, (ADim, BDim, CDim)) + + parsed = FieldOperatorParser.apply_to_function(simple_broadcast) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[ADim, BDim, CDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) + ) + + +def test_broadcast_disjoint(): + ADim = Dimension("ADim") + BDim = Dimension("BDim") + CDim = Dimension("CDim") + + def disjoint_broadcast(a: Field[[ADim], float64]): + return broadcast(a, (BDim, CDim)) + + with pytest.raises(errors.DSLError, match=r"expected broadcast dimension\(s\) \'.*\' missing"): + _ = FieldOperatorParser.apply_to_function(disjoint_broadcast) + + +def test_broadcast_badtype(): + ADim = Dimension("ADim") + BDim = "BDim" + CDim = Dimension("CDim") + + def badtype_broadcast(a: Field[[ADim], float64]): + return broadcast(a, (BDim, CDim)) + + with pytest.raises( + errors.DSLError, match=r"expected all broadcast dimensions to be of type 'Dimension'." + ): + _ = FieldOperatorParser.apply_to_function(badtype_broadcast) + + +def test_where_dim(): + ADim = Dimension("ADim") + BDim = Dimension("BDim") + + def simple_where(a: Field[[ADim], bool], b: Field[[ADim, BDim], float64]): + return where(a, b, 9.0) + + parsed = FieldOperatorParser.apply_to_function(simple_where) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[ADim, BDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) + ) + + +def test_where_broadcast_dim(): + ADim = Dimension("ADim") + + def simple_where(a: Field[[ADim], bool]): + return where(a, 5.0, 9.0) + + parsed = FieldOperatorParser.apply_to_function(simple_where) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) + ) + + +def test_where_tuple_dim(): + ADim = Dimension("ADim") + + def tuple_where(a: Field[[ADim], bool], b: Field[[ADim], float64]): + return where(a, ((5.0, 9.0), (b, 6.0)), ((8.0, b), (5.0, 9.0))) + + parsed = FieldOperatorParser.apply_to_function(tuple_where) + + assert parsed.body.stmts[0].value.type == ts.TupleType( + types=[ + ts.TupleType( + types=[ + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ] + ), + ts.TupleType( + types=[ + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ] + ), + ] + ) + + +def test_where_bad_dim(): + ADim = Dimension("ADim") + + def bad_dim_where(a: Field[[ADim], bool], b: Field[[ADim], float64]): + return where(a, ((5.0, 9.0), (b, 6.0)), b) + + with pytest.raises(errors.DSLError, match=r"Return arguments need to be of same type"): + _ = FieldOperatorParser.apply_to_function(bad_dim_where) + + +def test_where_mixed_dims(): + ADim = Dimension("ADim") + BDim = Dimension("BDim") + + def tuple_where_mix_dims( + a: Field[[ADim], bool], b: Field[[ADim], float64], c: Field[[ADim, BDim], float64] + ): + return where(a, ((c, 9.0), (b, 6.0)), ((8.0, b), (5.0, 9.0))) + + parsed = FieldOperatorParser.apply_to_function(tuple_where_mix_dims) + + assert parsed.body.stmts[0].value.type == ts.TupleType( + types=[ + ts.TupleType( + types=[ + ts.FieldType( + dims=[ADim, BDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) + ), + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ] + ), + ts.TupleType( + types=[ + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), + ] + ), + ] + ) + + +def test_astype_dtype(): + def simple_astype(a: Field[[TDim], float64]): + return astype(a, bool) + + parsed = FieldOperatorParser.apply_to_function(simple_astype) + + assert parsed.body.stmts[0].value.type == ts.FieldType( + dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.BOOL) + ) + + +def test_astype_wrong_dtype(): + def simple_astype(a: Field[[TDim], float64]): + # we just use broadcast here, but anything with type function is fine + return astype(a, broadcast) + + with pytest.raises( + errors.DSLError, + match=r"Invalid call to 'astype': second argument must be a scalar type, got.", + ): + _ = FieldOperatorParser.apply_to_function(simple_astype) + + +def test_astype_wrong_value_type(): + def simple_astype(a: Field[[TDim], float64]): + # we just use broadcast here but anything that is not a field, scalar or tuple thereof works + return astype(broadcast, bool) + + with pytest.raises(errors.DSLError) as exc_info: + _ = FieldOperatorParser.apply_to_function(simple_astype) + + assert ( + re.search("Expected 1st argument to be of type", exc_info.value.__cause__.args[0]) + is not None + ) + + +def test_mod_floats(): + def modulo_floats(inp: Field[[TDim], float]): + return inp % 3.0 + + with pytest.raises(errors.DSLError, match=r"Type 'float64' can not be used in operator '%'"): + _ = FieldOperatorParser.apply_to_function(modulo_floats) + + +def test_undefined_symbols(): + def return_undefined(): + return undefined_symbol + + with pytest.raises(errors.DSLError, match="Undeclared symbol"): + _ = FieldOperatorParser.apply_to_function(return_undefined) + + +def test_as_offset_dim(): + ADim = Dimension("ADim") + BDim = Dimension("BDim") + Boff = FieldOffset("Boff", source=BDim, target=(BDim,)) + + def as_offset_dim(a: Field[[ADim, BDim], float], b: Field[[ADim], int]): + return a(as_offset(Boff, b)) + + with pytest.raises(errors.DSLError, match=f"not in list of offset field dimensions"): + _ = FieldOperatorParser.apply_to_function(as_offset_dim) + + +def test_as_offset_dtype(): + ADim = Dimension("ADim") + BDim = Dimension("BDim") + Boff = FieldOffset("Boff", source=BDim, target=(BDim,)) + + def as_offset_dtype(a: Field[[ADim, BDim], float], b: Field[[BDim], float]): + return a(as_offset(Boff, b)) + + with pytest.raises(errors.DSLError, match=f"expected integer for offset field dtype"): + _ = FieldOperatorParser.apply_to_function(as_offset_dtype) diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py b/tests/next_tests/unit_tests/test_type_system.py similarity index 51% rename from tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py rename to tests/next_tests/unit_tests/test_type_system.py index 5352724827..99758d6f14 100644 --- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py +++ b/tests/next_tests/unit_tests/test_type_system.py @@ -11,28 +11,13 @@ import pytest -import gt4py.next.ffront.type_specifications from gt4py.next import ( Dimension, DimensionKind, - Field, - FieldOffset, - astype, - broadcast, - common, - errors, - float32, - float64, - int32, - int64, - neighbor_sum, - where, ) -from gt4py.next.ffront.ast_passes import single_static_assign as ssa -from gt4py.next.ffront.experimental import as_offset -from gt4py.next.ffront.func_to_foast import FieldOperatorParser from gt4py.next.type_system import type_info, type_specifications as ts - +from gt4py.next.ffront import type_specifications as ts_ffront +from gt4py.next.iterator.type_system import type_specifications as ts_it TDim = Dimension("TDim") # Meaningless dimension, used for tests. @@ -107,7 +92,7 @@ def callable_type_info_cases(): unary_tuple_arg_func_type = ts.FunctionType( pos_only_args=[tuple_type], pos_or_kw_args={}, kw_only_args={}, returns=ts.VoidType() ) - fieldop_type = gt4py.next.ffront.type_specifications.FieldOperatorType( + fieldop_type = ts_ffront.FieldOperatorType( definition=ts.FunctionType( pos_only_args=[field_type, float_type], pos_or_kw_args={}, @@ -115,7 +100,7 @@ def callable_type_info_cases(): returns=field_type, ) ) - scanop_type = gt4py.next.ffront.type_specifications.ScanOperatorType( + scanop_type = ts_ffront.ScanOperatorType( axis=KDim, definition=ts.FunctionType( pos_only_args=[], @@ -124,7 +109,7 @@ def callable_type_info_cases(): returns=float_type, ), ) - tuple_scanop_type = gt4py.next.ffront.type_specifications.ScanOperatorType( + tuple_scanop_type = ts_ffront.ScanOperatorType( axis=KDim, definition=ts.FunctionType( pos_only_args=[], @@ -367,6 +352,22 @@ def callable_type_info_cases(): ], ts.FieldType(dims=[IDim, JDim, KDim], dtype=float_type), ), + ( + ts.FunctionType( + pos_only_args=[ + ts_it.IteratorType( + position_dims="unknown", defined_dims=[], element_type=float_type + ), + ], + pos_or_kw_args={}, + kw_only_args={}, + returns=ts.VoidType(), + ), + [ts_it.IteratorType(position_dims=[IDim], defined_dims=[], element_type=float_type)], + {}, + [], + ts.VoidType(), + ), ] @@ -408,381 +409,3 @@ def test_return_type( accepts_args = type_info.accepts_args(func_type, with_args=args, with_kwargs=kwargs) if accepts_args: assert type_info.return_type(func_type, with_args=args, with_kwargs=kwargs) == return_type - - -def test_unpack_assign(): - def unpack_explicit_tuple( - a: Field[[TDim], float64], b: Field[[TDim], float64] - ) -> tuple[Field[[TDim], float64], Field[[TDim], float64]]: - tmp_a, tmp_b = (a, b) - return tmp_a, tmp_b - - parsed = FieldOperatorParser.apply_to_function(unpack_explicit_tuple) - - assert parsed.body.annex.symtable[ssa.unique_name("tmp_a", 0)].type == ts.FieldType( - dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64, shape=None) - ) - assert parsed.body.annex.symtable[ssa.unique_name("tmp_b", 0)].type == ts.FieldType( - dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64, shape=None) - ) - - -def test_assign_tuple(): - def temp_tuple(a: Field[[TDim], float64], b: Field[[TDim], int64]): - tmp = a, b - return tmp - - parsed = FieldOperatorParser.apply_to_function(temp_tuple) - - assert parsed.body.annex.symtable[ssa.unique_name("tmp", 0)].type == ts.TupleType( - types=[ - ts.FieldType(dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64, shape=None)), - ts.FieldType(dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64, shape=None)), - ] - ) - - -def test_adding_bool(): - """Expect an error when using arithmetic on bools.""" - - def add_bools(a: Field[[TDim], bool], b: Field[[TDim], bool]): - return a + b - - with pytest.raises( - errors.DSLError, match=(r"Type 'Field\[\[TDim\], bool\]' can not be used in operator '\+'.") - ): - _ = FieldOperatorParser.apply_to_function(add_bools) - - -def test_binop_nonmatching_dims(): - """Binary operations can only work when both fields have the same dimensions.""" - X = Dimension("X") - Y = Dimension("Y") - - def nonmatching(a: Field[[X], float64], b: Field[[Y], float64]): - return a + b - - with pytest.raises( - errors.DSLError, - match=( - r"Could not promote 'Field\[\[X], float64\]' and 'Field\[\[Y\], float64\]' to common type in call to +." - ), - ): - _ = FieldOperatorParser.apply_to_function(nonmatching) - - -def test_bitopping_float(): - def float_bitop(a: Field[[TDim], float], b: Field[[TDim], float]): - return a & b - - with pytest.raises( - errors.DSLError, - match=(r"Type 'Field\[\[TDim\], float64\]' can not be used in operator '\&'."), - ): - _ = FieldOperatorParser.apply_to_function(float_bitop) - - -def test_signing_bool(): - def sign_bool(a: Field[[TDim], bool]): - return -a - - with pytest.raises( - errors.DSLError, - match=r"Incompatible type for unary operator '\-': 'Field\[\[TDim\], bool\]'.", - ): - _ = FieldOperatorParser.apply_to_function(sign_bool) - - -def test_notting_int(): - def not_int(a: Field[[TDim], int64]): - return not a - - with pytest.raises( - errors.DSLError, - match=r"Incompatible type for unary operator 'not': 'Field\[\[TDim\], int64\]'.", - ): - _ = FieldOperatorParser.apply_to_function(not_int) - - -@pytest.fixture -def premap_setup(): - X = Dimension("X") - Y = Dimension("Y") - Y2XDim = Dimension("Y2X", kind=DimensionKind.LOCAL) - Y2X = FieldOffset("Y2X", source=X, target=(Y, Y2XDim)) - return X, Y, Y2XDim, Y2X - - -def test_premap(premap_setup): - X, Y, Y2XDim, Y2X = premap_setup - - def premap_fo(bar: Field[[X], int64]) -> Field[[Y], int64]: - return bar(Y2X[0]) - - parsed = FieldOperatorParser.apply_to_function(premap_fo) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64) - ) - - -def test_premap_nbfield(premap_setup): - X, Y, Y2XDim, Y2X = premap_setup - - def premap_fo(bar: Field[[X], int64]) -> Field[[Y, Y2XDim], int64]: - return bar(Y2X) - - parsed = FieldOperatorParser.apply_to_function(premap_fo) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[Y, Y2XDim], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64) - ) - - -def test_premap_reduce(premap_setup): - X, Y, Y2XDim, Y2X = premap_setup - - def premap_fo(bar: Field[[X], int32]) -> Field[[Y], int32]: - return 2 * neighbor_sum(bar(Y2X), axis=Y2XDim) - - parsed = FieldOperatorParser.apply_to_function(premap_fo) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32) - ) - - -def test_premap_reduce_sparse(premap_setup): - X, Y, Y2XDim, Y2X = premap_setup - - def premap_fo(bar: Field[[Y, Y2XDim], int32]) -> Field[[Y], int32]: - return 5 * neighbor_sum(bar, axis=Y2XDim) - - parsed = FieldOperatorParser.apply_to_function(premap_fo) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32) - ) - - -def test_mismatched_literals(): - def mismatched_lit() -> Field[[TDim], "float32"]: - return float32("1.0") + float64("1.0") - - with pytest.raises( - errors.DSLError, - match=(r"Could not promote 'float32' and 'float64' to common type in call to +."), - ): - _ = FieldOperatorParser.apply_to_function(mismatched_lit) - - -def test_broadcast_multi_dim(): - ADim = Dimension("ADim") - BDim = Dimension("BDim") - CDim = Dimension("CDim") - - def simple_broadcast(a: Field[[ADim], float64]): - return broadcast(a, (ADim, BDim, CDim)) - - parsed = FieldOperatorParser.apply_to_function(simple_broadcast) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[ADim, BDim, CDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) - ) - - -def test_broadcast_disjoint(): - ADim = Dimension("ADim") - BDim = Dimension("BDim") - CDim = Dimension("CDim") - - def disjoint_broadcast(a: Field[[ADim], float64]): - return broadcast(a, (BDim, CDim)) - - with pytest.raises(errors.DSLError, match=r"expected broadcast dimension\(s\) \'.*\' missing"): - _ = FieldOperatorParser.apply_to_function(disjoint_broadcast) - - -def test_broadcast_badtype(): - ADim = Dimension("ADim") - BDim = "BDim" - CDim = Dimension("CDim") - - def badtype_broadcast(a: Field[[ADim], float64]): - return broadcast(a, (BDim, CDim)) - - with pytest.raises( - errors.DSLError, match=r"expected all broadcast dimensions to be of type 'Dimension'." - ): - _ = FieldOperatorParser.apply_to_function(badtype_broadcast) - - -def test_where_dim(): - ADim = Dimension("ADim") - BDim = Dimension("BDim") - - def simple_where(a: Field[[ADim], bool], b: Field[[ADim, BDim], float64]): - return where(a, b, 9.0) - - parsed = FieldOperatorParser.apply_to_function(simple_where) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[ADim, BDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) - ) - - -def test_where_broadcast_dim(): - ADim = Dimension("ADim") - - def simple_where(a: Field[[ADim], bool]): - return where(a, 5.0, 9.0) - - parsed = FieldOperatorParser.apply_to_function(simple_where) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) - ) - - -def test_where_tuple_dim(): - ADim = Dimension("ADim") - - def tuple_where(a: Field[[ADim], bool], b: Field[[ADim], float64]): - return where(a, ((5.0, 9.0), (b, 6.0)), ((8.0, b), (5.0, 9.0))) - - parsed = FieldOperatorParser.apply_to_function(tuple_where) - - assert parsed.body.stmts[0].value.type == ts.TupleType( - types=[ - ts.TupleType( - types=[ - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ] - ), - ts.TupleType( - types=[ - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ] - ), - ] - ) - - -def test_where_bad_dim(): - ADim = Dimension("ADim") - - def bad_dim_where(a: Field[[ADim], bool], b: Field[[ADim], float64]): - return where(a, ((5.0, 9.0), (b, 6.0)), b) - - with pytest.raises(errors.DSLError, match=r"Return arguments need to be of same type"): - _ = FieldOperatorParser.apply_to_function(bad_dim_where) - - -def test_where_mixed_dims(): - ADim = Dimension("ADim") - BDim = Dimension("BDim") - - def tuple_where_mix_dims( - a: Field[[ADim], bool], b: Field[[ADim], float64], c: Field[[ADim, BDim], float64] - ): - return where(a, ((c, 9.0), (b, 6.0)), ((8.0, b), (5.0, 9.0))) - - parsed = FieldOperatorParser.apply_to_function(tuple_where_mix_dims) - - assert parsed.body.stmts[0].value.type == ts.TupleType( - types=[ - ts.TupleType( - types=[ - ts.FieldType( - dims=[ADim, BDim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64) - ), - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ] - ), - ts.TupleType( - types=[ - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ts.FieldType(dims=[ADim], dtype=ts.ScalarType(kind=ts.ScalarKind.FLOAT64)), - ] - ), - ] - ) - - -def test_astype_dtype(): - def simple_astype(a: Field[[TDim], float64]): - return astype(a, bool) - - parsed = FieldOperatorParser.apply_to_function(simple_astype) - - assert parsed.body.stmts[0].value.type == ts.FieldType( - dims=[TDim], dtype=ts.ScalarType(kind=ts.ScalarKind.BOOL) - ) - - -def test_astype_wrong_dtype(): - def simple_astype(a: Field[[TDim], float64]): - # we just use broadcast here, but anything with type function is fine - return astype(a, broadcast) - - with pytest.raises( - errors.DSLError, - match=r"Invalid call to 'astype': second argument must be a scalar type, got.", - ): - _ = FieldOperatorParser.apply_to_function(simple_astype) - - -def test_astype_wrong_value_type(): - def simple_astype(a: Field[[TDim], float64]): - # we just use broadcast here but anything that is not a field, scalar or tuple thereof works - return astype(broadcast, bool) - - with pytest.raises(errors.DSLError) as exc_info: - _ = FieldOperatorParser.apply_to_function(simple_astype) - - assert ( - re.search("Expected 1st argument to be of type", exc_info.value.__cause__.args[0]) - is not None - ) - - -def test_mod_floats(): - def modulo_floats(inp: Field[[TDim], float]): - return inp % 3.0 - - with pytest.raises(errors.DSLError, match=r"Type 'float64' can not be used in operator '%'"): - _ = FieldOperatorParser.apply_to_function(modulo_floats) - - -def test_undefined_symbols(): - def return_undefined(): - return undefined_symbol - - with pytest.raises(errors.DSLError, match="Undeclared symbol"): - _ = FieldOperatorParser.apply_to_function(return_undefined) - - -def test_as_offset_dim(): - ADim = Dimension("ADim") - BDim = Dimension("BDim") - Boff = FieldOffset("Boff", source=BDim, target=(BDim,)) - - def as_offset_dim(a: Field[[ADim, BDim], float], b: Field[[ADim], int]): - return a(as_offset(Boff, b)) - - with pytest.raises(errors.DSLError, match=f"not in list of offset field dimensions"): - _ = FieldOperatorParser.apply_to_function(as_offset_dim) - - -def test_as_offset_dtype(): - ADim = Dimension("ADim") - BDim = Dimension("BDim") - Boff = FieldOffset("Boff", source=BDim, target=(BDim,)) - - def as_offset_dtype(a: Field[[ADim, BDim], float], b: Field[[BDim], float]): - return a(as_offset(Boff, b)) - - with pytest.raises(errors.DSLError, match=f"expected integer for offset field dtype"): - _ = FieldOperatorParser.apply_to_function(as_offset_dtype) From ac253b6b10a8adf87313a48b62328debaf39f07f Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Mon, 3 Feb 2025 10:28:47 +0100 Subject: [PATCH 12/13] fix[next]: reshuffling for fields with non-zero domain start (#1845) --- src/gt4py/next/embedded/nd_array_field.py | 5 ++++- .../unit_tests/embedded_tests/test_nd_array_field.py | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gt4py/next/embedded/nd_array_field.py b/src/gt4py/next/embedded/nd_array_field.py index e15fb4266a..537482508b 100644 --- a/src/gt4py/next/embedded/nd_array_field.py +++ b/src/gt4py/next/embedded/nd_array_field.py @@ -657,7 +657,10 @@ def _reshuffling_premap( conn_map[dim] = _identity_connectivity(new_domain, dim, cls=type(connectivity)) # Take data - take_indices = tuple(conn_map[dim].ndarray for dim in data.domain.dims) + take_indices = tuple( + conn_map[dim].ndarray - data.domain[dim].unit_range.start # shift to 0-based indexing + for dim in data.domain.dims + ) new_buffer = data._ndarray.__getitem__(take_indices) return data.__class__.from_array( diff --git a/tests/next_tests/unit_tests/embedded_tests/test_nd_array_field.py b/tests/next_tests/unit_tests/embedded_tests/test_nd_array_field.py index 9dde5bb40a..9bdc6ab5c1 100644 --- a/tests/next_tests/unit_tests/embedded_tests/test_nd_array_field.py +++ b/tests/next_tests/unit_tests/embedded_tests/test_nd_array_field.py @@ -364,10 +364,11 @@ def test_reshuffling_premap(): ij_field = common._field( np.asarray([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]), - domain=common.Domain(dims=(I, J), ranges=(UnitRange(0, 3), UnitRange(0, 3))), + domain=common.Domain(dims=(I, J), ranges=(UnitRange(1, 4), UnitRange(2, 5))), ) + max_ij_conn = common._connectivity( - np.fromfunction(lambda i, j: np.maximum(i, j), (3, 3), dtype=int), + np.asarray([[1, 2, 3], [2, 2, 3], [3, 3, 3]], dtype=int), domain=common.Domain( dims=ij_field.domain.dims, ranges=ij_field.domain.ranges, @@ -378,7 +379,7 @@ def test_reshuffling_premap(): result = ij_field.premap(max_ij_conn) expected = common._field( np.asarray([[0.0, 4.0, 8.0], [3.0, 4.0, 8.0], [6.0, 7.0, 8.0]]), - domain=common.Domain(dims=(I, J), ranges=(UnitRange(0, 3), UnitRange(0, 3))), + domain=common.Domain(dims=(I, J), ranges=(UnitRange(1, 4), UnitRange(2, 5))), ) assert result.domain == expected.domain From c17b88259190a5eefee67f039150f4e92337fe61 Mon Sep 17 00:00:00 2001 From: Till Ehrengruber Date: Tue, 4 Feb 2025 14:14:46 +0100 Subject: [PATCH 13/13] bug[next]: Fix for GTIR partial type inference (#1840) Co-authored-by: Edoardo Paone Co-authored-by: Hannes Vogt --- src/gt4py/next/iterator/type_system/type_synthesizer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gt4py/next/iterator/type_system/type_synthesizer.py b/src/gt4py/next/iterator/type_system/type_synthesizer.py index f5aeac7943..19ab3ecdda 100644 --- a/src/gt4py/next/iterator/type_system/type_synthesizer.py +++ b/src/gt4py/next/iterator/type_system/type_synthesizer.py @@ -141,7 +141,9 @@ def can_deref(it: it_ts.IteratorType | ts.DeferredType) -> ts.ScalarType: @_register_builtin_type_synthesizer -def if_(pred: ts.ScalarType, true_branch: ts.DataType, false_branch: ts.DataType) -> ts.DataType: +def if_( + pred: ts.ScalarType | ts.DeferredType, true_branch: ts.DataType, false_branch: ts.DataType +) -> ts.DataType: if isinstance(true_branch, ts.TupleType) and isinstance(false_branch, ts.TupleType): return tree_map( collection_type=ts.TupleType, @@ -149,7 +151,9 @@ def if_(pred: ts.ScalarType, true_branch: ts.DataType, false_branch: ts.DataType )(functools.partial(if_, pred))(true_branch, false_branch) assert not isinstance(true_branch, ts.TupleType) and not isinstance(false_branch, ts.TupleType) - assert isinstance(pred, ts.ScalarType) and pred.kind == ts.ScalarKind.BOOL + assert isinstance(pred, ts.DeferredType) or ( + isinstance(pred, ts.ScalarType) and pred.kind == ts.ScalarKind.BOOL + ) # TODO(tehrengruber): Enable this or a similar check. In case the true- and false-branch are # iterators defined on different positions this fails. For the GTFN backend we also don't # want this, but for roundtrip it is totally fine.