diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a84ac06 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: [push] + +jobs: + ci: + name: ${{ matrix.plat.name }} Build + Test + runs-on: ${{ matrix.plat.os }} + strategy: + fail-fast: false + matrix: + plat: + - { os: ubuntu-latest, name: Ubuntu } + - { os: macos-latest, name: macOS } + + steps: + - uses: actions/checkout@v5 + + - name: Download submodules + shell: bash + run: git submodule update --init --recursive + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: pyproject.toml + + - name: Install uv + uses: astral-sh/setup-uv@v6 + + - name: Build Drudge + run: uv sync --locked --extra dev + + - name: Install coverage tools + run: uv pip install coverage coveralls + + - name: Run tests with coverage + env: + DUMMY_SPARK: 1 + run: uv run coverage run --source=drudge -m pytest tests + + - name: Upload coverage to Coveralls (Ubuntu only) + if: ${{ always() && matrix.plat.os == 'ubuntu-latest' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: uv run coveralls --service=github + diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 0000000..89b7816 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,37 @@ +name: Copilot Setup Steps + +on: + workflow_dispatch: + push: + paths: [".github/workflows/copilot-setup-steps.yml"] + pull_request: + paths: [".github/workflows/copilot-setup-steps.yml"] + +jobs: + copilot-setup-steps: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Download submodules + shell: bash + run: | + git submodule update --init --recursive + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: "pyproject.toml" + + - name: Setup uv + uses: astral-sh/setup-uv@v6 + + - name: Install the project + run: | + uv sync --locked --extra dev + uv build + diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml deleted file mode 100644 index 586741b..0000000 --- a/.github/workflows/pythonapp.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Python application - -on: [push, pull_request] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Download submodules - shell: bash - run: | - git submodule update --init --recursive - - name: Set up Python 3.7 - uses: actions/setup-python@v1 - with: - python-version: 3.7 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - # pip install -r requirements.txt - git clone https://github.com/tschijnmo/DummyRDD.git - cd DummyRDD; python3 setup.py install; cd .. - - name: Install - run: | - python3 setup.py install - - name: Test with pytest - env: - DUMMY_SPARK: 1 - run: | - cd tests - pip install pytest - pip install coveralls - coverage run --source=drudge -m pytest -sv - cd .. - coveralls - diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000..7cdb583 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,38 @@ +name: CI + +on: [push] + +jobs: + windows: + name: Windows Build + Test + runs-on: windows-latest + + steps: + - uses: actions/checkout@v5 + + - name: Download submodules + shell: bash + run: git submodule update --init --recursive + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: pyproject.toml + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install uv + uses: astral-sh/setup-uv@v6 + + - name: Build Drudge + run: uv sync --locked --extra dev + + - name: Install coverage tools + run: uv pip install coverage + + - name: Run tests with coverage + env: + DUMMY_SPARK: 1 + run: uv run coverage run --source=drudge -m pytest tests + diff --git a/.gitignore b/.gitignore index 0dff672..aa24398 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ celerybeat-schedule .env # virtualenv +.venv/ venv/ ENV/ @@ -102,3 +103,10 @@ ENV/ # For usage in dockerignore. .git + +# Editors +.idea/ +.ycm_extra_conf.py + +# macOS cruft +.DS_Store diff --git a/.idea/dictionaries/tschijnmo.xml b/.idea/dictionaries/tschijnmo.xml deleted file mode 100644 index 19b8c75..0000000 --- a/.idea/dictionaries/tschijnmo.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - adjoint - alegbras - bogoliubov - cartan - hermitian - indexable - noncommutative - noncommutativity - subalgebra - summand - summands - - - \ No newline at end of file diff --git a/.idea/drudge.iml b/.idea/drudge.iml deleted file mode 100644 index 4e850c1..0000000 --- a/.idea/drudge.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index c23ecac..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 2f9f52e..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index dc7d84f..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3c0a645..0000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: python -python: - - 3.6 - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-7 - - g++-7 - -before_install: - - pip3 install coveralls - - git clone https://github.com/tschijnmo/DummyRDD.git - - cd DummyRDD; python3 setup.py install; cd .. -install: - - export CC=gcc-7 - - export CXX=g++-7 - - python3 setup.py install - -script: - - export DUMMY_SPARK=1 - - cd tests - - coverage run --source=drudge -m pytest -sv - -after_success: - - coveralls - diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py deleted file mode 100644 index efbbc03..0000000 --- a/.ycm_extra_conf.py +++ /dev/null @@ -1,16 +0,0 @@ -import os -import subprocess - -def FlagsForFile(filename, **kwargs): - - flags = ['-std=c++14', '-I/usr/local/include'] - - proj_root = os.path.dirname(os.path.abspath(__file__)) - libcanon_include = ''.join(['-I', proj_root, '/deps/libcanon/include']) - python_include = subprocess.run( - ["pkg-config", '--cflags', 'python3'], stdout=subprocess.PIPE - ).stdout.decode("utf-8") - proj_include = ''.join(['-I', proj_root, '/drudge']) - flags.extend([libcanon_include, proj_include]) - - return {'flags': flags} diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..62183b9 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,38 @@ +cff-version: 1.2.0 +message: "If you use Drudge, please cite the following works." +authors: + - family-names: Zhao + given-names: Jinmo + - family-names: Chen + given-names: Guo P. + - family-names: Harsha + given-names: Gaurav + - family-names: Wholey + given-names: Matthew + - family-names: Henderson + given-names: Thomas M. + - family-names: Scuseria + given-names: Gustavo E. +title: "Drudge: A symbolic algebra system for tensorial and noncommutative algebras" +type: software +repository-code: "https://github.com/DrudgeCAS/drudge" +abstract: "Drudge is a symbolic algebra system built on top of SymPy, focusing primarily on tensorial and noncommutative algebras. It is motivated by tedious symbolic derivations in quantum chemistry and many-body theory but is also useful for any symbolic manipulation and simplification involving indexed quantities, symbolic summations, and noncommutative algebras." +keywords: + - symbolic algebra + - tensor algebra + - quantum chemistry + - many-body theory +license: MIT +version: 0.11.0 +date-released: 2025-09-15 + +references: + - type: thesis + authors: + - family-names: Zhao + given-names: Jinmo + title: "Symbolic Solution for Computational Quantum Many-Body Theory Development" + year: 2018 + publisher: Rice University + url: "https://www.proquest.com/openview/61a9a86c07dbb6e5270bdeb1c84384db/1?pq-origsite=gscholar&cbl=18750&diss=y" + diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..82488ca --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +recursive-include drudge *.h + +recursive-include deps/libcanon/include *.h + +recursive-include drudge/templates * + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4cb5bad --- /dev/null +++ b/README.md @@ -0,0 +1,127 @@ +[![CI](https://github.com/DrudgeCAS/drudge/actions/workflows/ci.yml/badge.svg)](https://github.com/DrudgeCAS/drudge/actions/workflows/ci.yml) +[![Coveralls](https://coveralls.io/repos/github/DrudgeCAS/drudge/badge.svg?branch=master)](https://coveralls.io/github/DrudgeCAS/drudge?branch=master) +[![Cite this repo](https://img.shields.io/badge/Cite-this_repo-blue.svg)](./CITATION.cff) + +

Drudge

+ +Drudge is a symbolic algebra system built on top of +[SymPy](http://www.sympy.org), focusing primarily on tensorial and +noncommutative algebras. It is motivated by tedious symbolic derivations in +quantum chemistry and many-body theory but is also useful for any symbolic +manipulation and simplification involving indexed quantities, symbolic +summations, and noncommutative algebras. + +Leveraging the generic algorithms implemented in +[libcanon](https://github.com/DrudgeCAS/libcanon) for canonicalization of +combinatorial objects, such as strings and graphs, Drudge can find canonical +forms for mathematical expressions involving tensors with symmetries and +symbolic summations. For example, considering a fourth-order tensor $u$ +satisfying + +$$ +u_{abcd} = -u_{bacd} = -u_{abdc} = u_{badc}, +$$ + +an expression like + +$$ +\sum_{cd} u_{acbd} \rho_{dc} - \sum_{cd} u_{cabd} \rho_{dc} + \sum_{cd} u_{cdbc} \rho_{cd} +$$ + +can be automatically simplified to a single term, + +$$ +3 \sum_{cd} u_{acbd} \rho_{dc}, +$$ + +irrespective of the names and ordering of the summation indices. + +In addition to fully considering the permutational symmetries of tensors and +summations, Drudge provides a general framework for handling noncommutative +algebraic systems. Currently, Drudge natively supports the [canonical +commutation relations (CCR) and canonical anticommutation relations (CAR) +algebras](https://en.wikipedia.org/wiki/CCR_and_CAR_algebras) for fermions and +bosons, respectively, in many-body theory, general [Clifford +algebras](https://en.wikipedia.org/wiki/Clifford_algebra), and the [su(2) +algebra](https://en.m.wikipedia.org/wiki/Special_unitary_group#Lie_Algebra) in +its Cartan-Killing basis. Other noncommutative algebraic systems can be added +with ease. + +Using symbolic expressions from Drudge, the companion package +[gristmill](https://github.com/DrudgeCAS/gristmill) can automatically optimize +and generate numerical code. Optimal computational complexity can be achieved +for various methods in quantum chemistry, which heavily rely on tensor +contractions and their sums. + + +## Installation + +Drudge can be installed directly from the GitHub repository using +[uv](https://github.com/astral-sh/uv) (recommended) +```bash +uv pip install git+https://github.com/DrudgeCAS/drudge.git +``` +or [pip](https://pypi.org/project/pip/) +```bash +pip install git+https://github.com/DrudgeCAS/drudge.git +``` + +> **Note:** Native Windows builds are currently not working. Please use WSL +> (Windows Subsystem for Linux) to install and run Drudge on Windows for now. + + +## Documentation + +Please refer to the documentation at +[https://drudgecas.github.io/drudge/](https://drudgecas.github.io/drudge/). +Additional examples can be found in the `./docs/examples` directory. + + +## Citation + +If you use Drudge in your work, please cite this repository and Jinmo Zhao's +Ph.D. thesis: + +**1. The Drudge GitHub repository** +```bibtex +@misc{DrudgeCAS, + author = {Jinmo Zhao and Guo P. Chen and Gaurav Harsha and Matthew Wholey and Thomas M. Henderson and Gustavo E. Scuseria}, + title = {Drudge: A symbolic algebra system for tensorial and noncommutative algebras}, + publisher = {GitHub}, + year = {2016--2025}, + url = {https://github.com/DrudgeCAS/drudge}, + note = {GitHub repository} +} +``` + +**2. Jinmo Zhao’s Ph.D. thesis** +```bibtex +@phdthesis{Zhao2018Drudge, + author = {Jinmo Zhao}, + title = {Symbolic Solution for Computational Quantum Many-Body Theory Development}, + school = {Rice University}, + year = {2018}, + month = {April}, + address = {Houston, Texas, USA}, + type = {PhD thesis}, + url = {https://www.proquest.com/openview/61a9a86c07dbb6e5270bdeb1c84384db/1?pq-origsite=gscholar&cbl=18750&diss=y} +} +``` +Link: [Symbolic Solution for Computational Quantum Many-Body Theory Development — Jinmo Zhao (2018)](https://www.proquest.com/openview/61a9a86c07dbb6e5270bdeb1c84384db/1?pq-origsite=gscholar&cbl=18750&diss=y) + +--- + +You may also use the [`CITATION.cff`](./CITATION.cff) file provided in this +repository, which is compatible with citation managers such as Zotero and +Mendeley. + +## Acknowledgments + +Drudge was originally developed by Jinmo Zhao during his Ph.D. at Rice +University, under the supervision of Prof. Gustavo E. Scuseria. The project was +supported as part of the Center for the Computational Design of Functional +Layered Materials, an Energy Frontier Research Center funded by the U.S. +Department of Energy, Office of Science, Basic Energy Sciences under Award +DE-SC0012575. The package is currently maintained by Guo P. Chen, Gaurav +Harsha, Matthew Wholey, and members of the Scueria group. + diff --git a/README.rst b/README.rst deleted file mode 100644 index 13d0de4..0000000 --- a/README.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. image:: https://circleci.com/gh/tschijnmo/drudge.svg?style=shield - :target: https://circleci.com/gh/tschijnmo/drudge - -.. image:: https://travis-ci.org/tschijnmo/drudge.svg?branch=master - :target: https://travis-ci.org/tschijnmo/drudge - -.. image:: https://coveralls.io/repos/github/tschijnmo/drudge/badge.svg?branch=master - :target: https://coveralls.io/github/tschijnmo/drudge?branch=master - - -Drudge ------- - -Drudge is a symbolic algebra system built on top of the `SymPy`_ library with -its primary focus on tensorial and non-commutative algebras. It is motivated by -complex symbolic problems in quantum chemistry and many-body theory, but it -could be useful for any tedious and error-prone symbolic manipulation and -simplification in any problem with indexed quantities, symbolic summations, and -non-commutative algebra. - -Built on the generic algorithm for the canonicalization of combinatorial -objects, like strings and graphs, in `libcanon`_, drudge is able to find a -canonical form for mathematical expressions with tensors with symmetries and -symbolic summations. For instance, for a 4th-order tensor *u* with symmetry - -.. math:: - - u_{abcd} = -u_{bacd} = -u_{abdc} = u_{badc} - -expression like - -.. math:: - - \sum_{cd} u_{acbd} \rho_{dc} - \sum_{cd} u_{cabd} \rho_{dc} - + \sum_{cd} u_{cdbc} \rho_{cd} - -can be automatically simplified into a single term like, - -.. math:: - - 3 \sum_{cd} u_{acbd} \rho_{dc} - -despite the initial different placement of the indices to the symmetric *u* -tensor and different naming of the dummy indices for summations. - -In addition to the full consideration of the combinatorial properties of -symmetric tensors and summations during the simplification, drudge also offers a -general system for handling non-commutative algebraic systems. Currently, -drudge directly supports the `CCR and CAR algebra`_ for treating fermions and -bosons in many-body theory, general `Clifford algebras`_, and `su(2) algebra`_ -in its Cartan-Killing basis. Other non-commutative algebraic systems should be -able to be added with ease. - - -Based on the symbolic results from drudge, a companion package `gristmill`_ is -able to automatically optimize and generate numerical code. For computations -with heavy dependence on tensor contraction and sums of tensor contractions, -substantial optimization could be given. - - -Drudge is developed by Jinmo Zhao and Prof Gustavo E Scuseria at Rice -University, and was supported as part of the Center for the Computational Design -of Functional Layered Materials, an Energy Frontier Research Center funded by -the U.S. Department of Energy, Office of Science, Basic Energy Sciences under -Award DE-SC0012575. - - -.. _SymPy: http://www.sympy.org -.. _libcanon: https://github.com/tschijnmo/libcanon -.. _CCR and CAR algebra: https://en.wikipedia.org/wiki/CCR_and_CAR_algebras -.. _Clifford algebras: https://en.wikipedia.org/wiki/Clifford_algebra -.. _su(2) algebra: https://en.m.wikipedia.org/wiki/Special_unitary_group#Lie_Algebra -.. _gristmill: https://github.com/tschijnmo/gristmill diff --git a/drudge/canonpy.cpp b/drudge/canonpy.cpp index f6489f3..2561a59 100644 --- a/drudge/canonpy.cpp +++ b/drudge/canonpy.cpp @@ -131,10 +131,10 @@ static Simple_perm make_perm_from_args(PyObject* args, PyObject* kwargs) PyObject* pre_images; char acc = 0; - static char* kwlist[] = { "pre_images", "acc", NULL }; + static const char* kwlist[] = { "pre_images", "acc", nullptr }; auto args_stat = PyArg_ParseTupleAndKeywords( - args, kwargs, "O|b", kwlist, &pre_images, &acc); + args, kwargs, "O|b", const_cast(kwlist), &pre_images, &acc); if (!args_stat) throw err; @@ -222,7 +222,7 @@ static Simple_perm make_perm_from_args(PyObject* args, PyObject* kwargs) // ------------------- // -const static char* perm_getnewargs_doc +static const char* perm_getnewargs_doc = "Get the arguments for new to construct the Perm."; static PyObject* perm_getnewargs(Perm_object* self) @@ -317,7 +317,7 @@ static PyObject* perm_repr(Perm_object* self) // This is used for empty or non-empty permutation. repr += L')'; - return PyUnicode_FromUnicode(repr.data(), repr.size()); + return PyUnicode_FromWideChar(repr.data(), (Py_ssize_t)repr.size()); } /** Creates a new Perm object. @@ -744,10 +744,10 @@ static Transv_ptr build_sims_transv_from_args(PyObject* args, PyObject* kwargs) { PyObject* input; - static char* kwlist[] = { "gens", NULL }; + static const char* kwlist[] = { "gens", NULL }; auto args_stat - = PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &input); + = PyArg_ParseTupleAndKeywords(args, kwargs, "O", const_cast(kwlist), &input); if (!args_stat) { return nullptr; } @@ -813,7 +813,7 @@ static Transv_ptr build_sims_transv_from_args(PyObject* args, PyObject* kwargs) // ------------------- // -const static char* group_getnewargs_doc +static const char* group_getnewargs_doc = "Get the arguments for new to construct the Group."; static PyObject* group_getnewargs(Group_object* self) @@ -1188,9 +1188,9 @@ static PyObject* canon_eldag_func( constexpr int err_code = 1; - static char* kwlist[] = { "edges", "ia", "symms", "colours", NULL }; + static const char* kwlist[] = { "edges", "ia", "symms", "colours", NULL }; - auto arg_stat = PyArg_ParseTupleAndKeywords(args, keywds, "OOOO", kwlist, + auto arg_stat = PyArg_ParseTupleAndKeywords(args, keywds, "OOOO", const_cast(kwlist), &edges_arg, &ia_arg, &symms_arg, &colours_arg); if (!arg_stat) { return NULL; diff --git a/drudge/drs.py b/drudge/drs.py index d9c465b..a41a17e 100644 --- a/drudge/drs.py +++ b/drudge/drs.py @@ -82,7 +82,7 @@ def __getitem__(self, indices): In drudge scripts, all symbols are by itself indexed bases. """ base = IndexedBase(self._orig) - if isinstance(indices, collections.Sequence): + if isinstance(indices, collections.abc.Sequence): return DrsIndexed(self._drudge, base, *indices) else: return DrsIndexed(self._drudge, base, indices) @@ -135,9 +135,19 @@ def __getnewargs__(self): """Get the arguments for __new__.""" return None, self.name + def __getnewargs_ex__(self): + """Get the arguments and keyword arguments for __new__. + + This method takes precedence over __getnewargs__ in Python 3.6+ + and is used by SymPy v1.9+. We need to override it to ensure + proper pickling/unpickling of DrsSymbol objects. + """ + return (None, self.name), {} + def __getstate__(self): """Get the state for pickling.""" - return None + # Return a non-None state to ensure __setstate__ is called + return {} def __setstate__(self, state): """Set the state according to pickled content.""" @@ -205,10 +215,20 @@ def __getnewargs__(self): """Get the arguments for __new__.""" return (None, self.base) + self.indices + def __getnewargs_ex__(self): + """Get the arguments and keyword arguments for __new__. + + This method takes precedence over __getnewargs__ in Python 3.6+ + and is used by SymPy v1.9+. We need to override it to ensure + proper pickling/unpickling of DrsIndexed objects. + """ + return ((None, self.base) + self.indices), {} + def __getstate__(self): """Get the state for pickling.""" - return None - + # Return a non-None state to ensure __setstate__ is called + return {} + def __setstate__(self, state): """Set the state according to pickled content.""" from .drudge import current_drudge @@ -235,9 +255,9 @@ class _NumFixer(ast.NodeTransformer): Integer literals will be changed into creation of symbolic integers. """ - def visit_Num(self, node: ast.Num): + def visit_Constant(self, node: ast.Constant): """Update the number nodes.""" - val = node.n + val = node.value if isinstance(val, int): constr = ast.Name(id='Integer', ctx=ast.Load()) ast.copy_location(constr, node) @@ -245,7 +265,7 @@ def visit_Num(self, node: ast.Num): ast.copy_location(fixed, node) return fixed else: - return val + return node _DEF_METH_NAME = 'def_as' diff --git a/drudge/drudge.py b/drudge/drudge.py index 8f9f6a0..b782b86 100644 --- a/drudge/drudge.py +++ b/drudge/drudge.py @@ -435,7 +435,7 @@ def _reset_dumms(self, terms: RDD, excl) -> RDD: ) return res_terms - def simplify_amps(self): + def simplify_amps(self, **kwargs): """Simplify the amplitudes in the tensor. This method simplifies the amplitude in the terms of the tensor by using @@ -445,15 +445,19 @@ def simplify_amps(self): # Some free variables might be canceled. return self.apply( - self._simplify_amps, free_vars=None, repartitioned=False + functools.partial( + self._simplify_amps, **kwargs + ), + free_vars=None, repartitioned=False ) @staticmethod - def _simplify_amps(terms): + def _simplify_amps(terms, **kwargs): """Get the terms with amplitude simplified by SymPy.""" simplified_terms = terms.map( - lambda term: term.map(lambda x: x.simplify(), skip_vecs=True) + lambda term: term.map(lambda x: x.simplify(**kwargs), + skip_vecs=True) ).filter(_is_nonzero) return simplified_terms @@ -694,7 +698,7 @@ def normal_order(self): # The driver simplification. # - def simplify(self): + def simplify(self, **kwargs): """Simplify the tensor. This is the master driver function for tensor simplification. Inside @@ -705,7 +709,7 @@ def simplify(self): """ result = Tensor( - self._drudge, self._simplify(self._terms), expanded=True + self._drudge, self._simplify(self._terms, **kwargs), expanded=True ) if self._drudge.inside_drs: @@ -714,7 +718,7 @@ def simplify(self): return result - def _simplify(self, terms): + def _simplify(self, terms, **kwargs): """Get the terms in the simplified form.""" num_partitions = self._drudge.num_partitions @@ -733,9 +737,9 @@ def _simplify(self, terms): terms = terms.repartition(num_partitions) # Simplify the amplitude part. - terms = self._simplify_amps(terms) + terms = self._simplify_amps(terms, **kwargs) terms = self._simplify_sums(terms) - terms = self._simplify_amps(terms) + terms = self._simplify_amps(terms, **kwargs) terms = self._simplify_deltas(terms, False) # Canonicalize the terms and see if they can be merged. @@ -750,7 +754,7 @@ def _simplify(self, terms): # Finally simplify the merged amplitude again. if self._drudge.full_simplify: - terms = self._simplify_amps(terms) + terms = self._simplify_amps(terms, **kwargs) # Make the final expansion. terms = self._expand(terms) @@ -1657,7 +1661,7 @@ class TensorDef(Tensor): .. math:: - \sum_j o_{i, j} f_j + \\sum_j o_{i, j} f_j can be construed as a tensor. By storing it as a :py:class:`Tensor` object, we can mathematically manipulate it. With an explicit left-hand @@ -1665,7 +1669,7 @@ class TensorDef(Tensor): .. math:: - t_j = \sum_j o_{i, j} f_j + t_j = \\sum_j o_{i, j} f_j is now a tensor definition, which can be handled by the current class. @@ -1673,7 +1677,7 @@ class TensorDef(Tensor): left-hand side, it can be convenient to be used for :py:meth:`Tensor.subst` or :py:meth:`Tensor.subst_all` method, or it can be directly indexed. For example, with the above definition stored in ``t_def``, for tensor ``v`` - holding :math:`\sum_j u_{i, j} t_j`, + holding :math:`\\sum_j u_{i, j} t_j`, :: @@ -1691,7 +1695,7 @@ class TensorDef(Tensor): .. math:: - \sum_{j, k} u_{i, j} o_{j, k} f_k + \\sum_{j, k} u_{i, j} o_{j, k} f_k Tensor definition can also be directly subscripts, like ``t_def[1]`` gives :math:`sum_i o_{1, i} f_i`. @@ -3490,7 +3494,7 @@ def _union(orig, new): def _inters(orig, new): - """Make the interaction of two sets. + """Make the intersection of two sets. If the original is a None value, a new set will be created with elements from the new set. When both operands are None, the result is None. diff --git a/drudge/nuclear.py b/drudge/nuclear.py index 4eb2049..07d940f 100644 --- a/drudge/nuclear.py +++ b/drudge/nuclear.py @@ -11,6 +11,7 @@ sqrt, factor, Mul, Expr, Matrix, Pow ) from sympy.physics.quantum.cg import CG, Wigner3j, Wigner6j, Wigner9j +from sympy.concrete.summations import eval_sum_symbolic from .drudge import Tensor from .fock import BogoliubovDrudge @@ -184,6 +185,9 @@ def __init__( CG=CG, Wigner3j=Wigner3j, Wigner6j=Wigner6j, Wigner9j=Wigner9j ) + self.sum_simplifiers = BCastVar(self._ctx, { + 1: [_simplify_symbolic_sum_nodoit] + }) self._am_sum_simplifiers = BCastVar(self.ctx, { # TODO: Add more simplifications here. 2: [_sum_2_3j_to_delta], @@ -434,13 +438,13 @@ def deep_simplify(tensor: Tensor): """ # Initial simplification. - res = tensor.simplify() + res = tensor.simplify(doit=False) # This can possibly reduce the number of terms. res = res.merge_j() res = res.simplify_am() # Final trial. - res = res.simplify().merge_j() + res = res.simplify(doit=False).merge_j() return res @@ -1644,3 +1648,14 @@ def _simpl_varsh_911_8(expr: Sum): ) * KroneckerDelta(match[m], match[m_prm]) * Wigner6j( match[j1], match[j2], match[j12], match[j3], match[j], match[j23] ) + + +def _simplify_symbolic_sum_nodoit(expr, **_): + """Try to simplify a symbolic summation of one dummy with `doit=False`. + """ + + assert len(expr.args) == 2 + + return eval_sum_symbolic( + expr.args[0].simplify(doit=False), expr.args[1] + ) diff --git a/drudge/term.py b/drudge/term.py index fceb82a..3c776da 100644 --- a/drudge/term.py +++ b/drudge/term.py @@ -1839,21 +1839,21 @@ def proc_delta(arg1, arg2, sums_dict, resolvers): else: return _NAUGHT, None - eqn = Eq(arg1, arg2).simplify() + eqn = Eq(arg1.simplify(), arg2.simplify()) # We try to solve for each of the dummies. Most likely this will only be # executed for one loop. for dumm in dumms: range_ = sums_dict[dumm] - # Here we assume the same integral domain, since dummies are summed over - # and we can mostly assume that they are integral. + # Here we assume the integer domain, since dummies are summed over + # and we can mostly assume that they are integers. # # TODO: infer actual domain from the range. domain = S.Integers sol = solveset(eqn, dumm, domain) - # Strip off trivial intersecting with the domain. + # Strip off trivial intersecting with the domain (integers). if isinstance(sol, Intersection) and len(sol.args) == 2: if sol.args[0] == domain: sol = sol.args[1] diff --git a/drudge/utils.py b/drudge/utils.py index ac489e3..d97e349 100644 --- a/drudge/utils.py +++ b/drudge/utils.py @@ -89,7 +89,7 @@ def __call__(self, *args, **kwargs): return self._func(*args, **kwargs) -class _EnumSymbsMeta(ManagedProperties): +class _EnumSymbsMeta(type): """The meta class for enumeration symbols. The primary purpose of this metaclass is to set the concrete singleton @@ -140,7 +140,7 @@ class EnumSymbs(AtomicExpr, metaclass=_EnumSymbsMeta): Subclasses can set `_symbs_` inside the class body to be a sequence of string pairs. Then attributes named after the first field of the pairs will - be created, with the LaTeX form controlled by the second pair. + be created, with the LaTeX form controlled by the second field of the pair. The resulted values are valid SymPy expressions. They are ordered according to their order in the given enumeration sequence. @@ -222,6 +222,15 @@ def __rsub__(self, other): """ return self.__sub__(other) + def __getstate__(self): + """Retrieve state of object for pickling/serialization""" + return {slot: getattr(self, slot) for slot in self.__slots__} + + def __setstate__(self, state): + """Create state of object for deserialization""" + for key, value in state.items(): + setattr(self, key, value) + def sort_key(self, order=None): return ( self.class_key(), diff --git a/drudge/wickcore.cpp b/drudge/wickcore.cpp index cea7411..44a10b7 100644 --- a/drudge/wickcore.cpp +++ b/drudge/wickcore.cpp @@ -169,10 +169,10 @@ static PyObject* compose_wick_func( PyObject* vec_order_arg; PyObject* contrs_arg; - static char* kwlist[] = { "vec_order", "contrs", NULL }; + static const char* kwlist[] = { "vec_order", "contrs", NULL }; auto arg_stat = PyArg_ParseTupleAndKeywords( - args, keywds, "OO", kwlist, &vec_order_arg, &contrs_arg); + args, keywds, "OO", const_cast(kwlist), &vec_order_arg, &contrs_arg); if (!arg_stat) { return NULL; } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..cc1c1b6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,51 @@ +[build-system] +requires = ["setuptools>=77", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "drudge" +version = "0.11.0" +description = "A symbolic algebra system for tensorial and noncommutative algebras" +requires-python = ">=3.12" +dependencies = [ + "sympy>=1.14", + "jinja2", + "pyspark>=3.5,<3.6", + "ipython>=9.0", + "dummyrdd @ git+https://github.com/DrudgeCAS/DummyRDD.git@master" +] +classifiers = [ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: Implementation :: CPython', + 'Topic :: Scientific/Engineering :: Mathematics' +] +readme = "README.md" +license = {text = "MIT"} +authors = [ + { name = "Jinmo Zhao" }, + { name = "Gustavo E. Scuseria" } +] +maintainers = [ + { name = "Guo P. Chen" }, + { name = "Gaurav Harsha" }, + { name = "Matthew Wholey" } +] + +[project.optional-dependencies] +docs = ["sphinx"] +dev = ["pytest"] + +[project.urls] +Homepage = "https://github.com/DrudgeCAS/drudge" + +[project.scripts] +drudge = "drudge.drs:main" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.package-data] +drudge = ["templates/*", "*.h"] diff --git a/setup.py b/setup.py index 2dbdd0e..57b7eb2 100644 --- a/setup.py +++ b/setup.py @@ -1,28 +1,23 @@ """Setup script for drudge.""" import os.path +import sys from setuptools import setup, find_packages, Extension -with open('README.rst', 'r') as readme: - DESCRIPTION = readme.read() - -CLASSIFIERS = [ - 'Development Status :: 1 - Planning', - 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: Implementation :: CPython', - 'Topic :: Scientific/Engineering :: Mathematics' -] - PROJ_ROOT = os.path.dirname(os.path.abspath(__file__)) INCLUDE_DIRS = [ - '/'.join([PROJ_ROOT, i]) + os.path.join(PROJ_ROOT, i) for i in ['deps/libcanon/include', 'drudge'] ] -COMPILE_FLAGS = ['-std=c++14'] + +# Platform-specific compiler flags +if sys.platform == "win32": + # MSVC compiler flags + COMPILE_FLAGS = ['/std:c++14', '/EHsc', '/bigobj', '/wd4996', '/wd4267', '/Zc:twoPhase-'] +else: + # GCC/Clang compiler flags + COMPILE_FLAGS = ['-std=c++14'] canonpy = Extension( 'drudge.canonpy', @@ -39,22 +34,7 @@ ) setup( - name='drudge', - version='0.10.0dev0', - description=DESCRIPTION.splitlines()[0], - long_description=DESCRIPTION, - url='https://github.com/tschijnmo/drudge', - author='Jinmo Zhao and Gustavo E Scuseria', - author_email='tschijnmotschau@gmail.com', - license='MIT', - classifiers=CLASSIFIERS, packages=find_packages(), ext_modules=[canonpy, wickcore], package_data={'drudge': ['templates/*']}, - install_requires=['sympy', 'ipython', 'Jinja2', 'pyspark'], - entry_points={ - 'console_scripts': [ - 'drudge = drudge.drs:main' - ] - } ) diff --git a/tests/free_algebra_test.py b/tests/free_algebra_test.py index a45075e..45448b0 100644 --- a/tests/free_algebra_test.py +++ b/tests/free_algebra_test.py @@ -19,7 +19,7 @@ from conftest import skip_in_spark -@pytest.fixture(scope='module') +@pytest.fixture def free_alg(spark_ctx): """Initialize the environment for a free algebra.""" diff --git a/tests/nuclear_test.py b/tests/nuclear_test.py index 45093fc..6c88734 100644 --- a/tests/nuclear_test.py +++ b/tests/nuclear_test.py @@ -113,6 +113,7 @@ def test_varsh_872_5(nuclear: NuclearBogoliubovDrudge): TODO: Investigate its failure in Apache Spark environment. """ + dr = nuclear a, alpha, b, beta, b_prm, beta_prm = symbols( 'a alpha b beta bprm betaprm', integer=True @@ -208,7 +209,7 @@ def test_wigner3j_sum_to_wigner6j(nuclear: NuclearBogoliubovDrudge): ((-1) ** (j3 - m3) / (2 * j3 + 1)) * KroneckerDelta(j3, jprm3) * KroneckerDelta(m3, mprm3) * Wigner6j(j1, j2, j3, j4, j5, j6) - ).expand().simplify() + ).expand().simplify(doit=False) # For performance reason, just test a random arrangement of the summations. random.shuffle(sums) diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..aa03206 --- /dev/null +++ b/uv.lock @@ -0,0 +1,575 @@ +version = 1 +requires-python = ">=3.12" + +[[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 = "asttokens" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537 }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655 }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223 }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366 }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104 }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830 }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854 }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670 }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501 }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173 }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822 }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543 }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326 }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008 }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196 }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819 }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350 }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644 }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468 }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187 }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699 }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580 }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366 }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342 }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995 }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640 }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636 }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939 }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580 }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870 }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797 }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224 }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086 }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400 }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175 }, +] + +[[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 = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190 }, +] + +[[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 = "drudge" +version = "0.11.0" +source = { editable = "." } +dependencies = [ + { name = "dummyrdd" }, + { name = "ipython" }, + { name = "jinja2" }, + { name = "pyspark" }, + { name = "sympy" }, +] + +[package.optional-dependencies] +dev = [ + { name = "pytest" }, +] +docs = [ + { name = "sphinx" }, +] + +[package.metadata] +requires-dist = [ + { name = "dummyrdd", git = "https://github.com/DrudgeCAS/DummyRDD.git?rev=master" }, + { name = "ipython", specifier = ">=9.0" }, + { name = "jinja2" }, + { name = "pyspark", specifier = ">=3.5,<3.6" }, + { name = "pytest", marker = "extra == 'dev'" }, + { name = "sphinx", marker = "extra == 'docs'" }, + { name = "sympy", specifier = ">=1.14" }, +] + +[[package]] +name = "dummyrdd" +version = "0.0.8.dev0" +source = { git = "https://github.com/DrudgeCAS/DummyRDD.git?rev=master#0f53b93b64ef5e9db38aa8d2dc3d5bf025a581d6" } + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317 }, +] + +[[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 = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, +] + +[[package]] +name = "ipython" +version = "9.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/71/a86262bf5a68bf211bcc71fe302af7e05f18a2852fdc610a854d20d085e6/ipython-9.5.0.tar.gz", hash = "sha256:129c44b941fe6d9b82d36fc7a7c18127ddb1d6f02f78f867f402e2e3adde3113", size = 4389137 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/2a/5628a99d04acb2d2f2e749cdf4ea571d2575e898df0528a090948018b726/ipython-9.5.0-py3-none-any.whl", hash = "sha256:88369ffa1d5817d609120daa523a6da06d02518e582347c29f8451732a9c5e72", size = 612426 }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074 }, +] + +[[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.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, +] + +[[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/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, +] + +[[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 = "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 = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, +] + +[[package]] +name = "parso" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668 }, +] + +[[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 = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431 }, +] + +[[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 = "py4j" +version = "0.10.9.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/f2/b34255180c72c36ff7097f7c2cdca02abcbd89f5eebf7c7c41262a9a0637/py4j-0.10.9.7.tar.gz", hash = "sha256:0b6e5315bb3ada5cf62ac651d107bb2ebc02def3dee9d9548e3baac644ea8dbb", size = 1508234 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/30/a58b32568f1623aaad7db22aa9eafc4c6c194b429ff35bdc55ca2726da47/py4j-0.10.9.7-py2.py3-none-any.whl", hash = "sha256:85defdfd2b2376eb3abf5ca6474b51ab7e0de341c75a02f46dc9b5976f5a5c1b", size = 200481 }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217 }, +] + +[[package]] +name = "pyspark" +version = "3.5.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "py4j" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/62/36e50d38e5fe158e97cddec983b44f9417b1e205b02320e3c463b5f802fa/pyspark-3.5.6.tar.gz", hash = "sha256:f8b1c4360e41ab398c64904fae08740503bcb6bd389457d659fa6d9f2952cc48", size = 317359167 } + +[[package]] +name = "pytest" +version = "8.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474 }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738 }, +] + +[[package]] +name = "roman-numerals-py" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742 }, +] + +[[package]] +name = "snowballstemmer" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274 }, +] + +[[package]] +name = "sphinx" +version = "8.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "roman-numerals-py" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741 }, +] + +[[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-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.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353 }, +] + +[[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 = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795 }, +] + +[[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 }, +]