diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 027f902..ca4893b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,4 +52,28 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: psf/black@stable \ No newline at end of file + - uses: psf/black@stable + + typecheck-python: + name: "Typecheck (pyright)" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + name: Checkout repository + + - name: Install poetry + run: pipx install poetry + + - name: Set up Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: "3.11" + cache: 'poetry' + + - name: Install dependencies + run: | + poetry install + + - run: echo "$(poetry env info --path)/bin" >> $GITHUB_PATH + + - uses: jakebailey/pyright-action@v1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6e8f457..29225aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,165 @@ -build/* -dist/* -*.egg-info -__pycache__ -.ruff_cache -.pytest-runtimes +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +.ruff_cache/ + +.vscode/ +monkeytype.sqlite3 diff --git a/CHANGES.md b/CHANGES.md index 9697481..1e61b73 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,286 +1,264 @@ ## v0.27 -* **[Breaking change]** This package now only supports Python 3.9 and higher. -* **[Breaking change]** `get_percentiles` and `get_log_percentiles` now always return a dictionary, even if there's only one element. -* **[Breaking change]** `.type` is now removed from distribution objects. -* Package load time is now ~2x faster. -* Pandas and matplotlib as removed as required dependencies, but their related features are lazily enabled when the modules are available. These packages are still available for install as extras, installable with `pip install squigglepy[plots]` (for plotting-related functionality, matplotlib for now), `pip install squigglepy[ecosystem]` (for pandas, and in the future other related packages), or `pip install squigglepy[all]` (for all extras). -* Multicore distribution now does extra checks to avoid crashing from race conditions. -* Distribution objects now have the version of squigglepy they were created with, which can be accessed via `obj._version`. This should be helpful for debugging and noticing stale objects, especially when squigglepy distributions are stored in caches. -* Using black now for formatting. -* Switched from `flake8` to `ruff`. +- **[Breaking change]** This package now only supports Python 3.9 and higher. +- **[Breaking change]** `get_percentiles` and `get_log_percentiles` now always return a dictionary, even if there's only one element. +- **[Breaking change]** `.type` is now removed from distribution objects. +- **[Breaking change]** The signature of `dist_fn` has changed to make it simpler: + - `dist_fn` no longer takes `None` positional arguments. (i.e. `dist_fn(dist1, None, np.ceil)` is now `dist_fn(dist1, np.ceil)`). + - `dist_fn` no longer supports passing arbitrary arguments as if they were distributions. Use partials instead (i.e. `dist_fn(d1, 2, round)` is now `dist_fn(d1, partial(round, digits=2))`). +- Package load time is now ~2x faster. +- Pandas and matplotlib as removed as required dependencies, but their related features are lazily enabled when the modules are available. These packages are still available for install as extras, installable with `pip install squigglepy[plots]` (for plotting-related functionality, matplotlib for now), `pip install squigglepy[ecosystem]` (for pandas, and in the future other related packages), or `pip install squigglepy[all]` (for all extras). +- Multicore distribution now does extra checks to avoid crashing from race conditions. +- Distribution objects now have the version of squigglepy they were created with, which can be accessed via `obj._version`. This should be helpful for debugging and noticing stale objects, especially when squigglepy distributions are stored in caches. +- Using black now for formatting. +- Switched from `flake8` to `ruff`. ## v0.26 -* **[Breaking change]** `lognorm` can now be defined either referencing the mean and sd of the underlying normal distribution via `norm_mean` / `norm_sd` or via the mean and sd of the lognormal distribution itself via `lognorm_mean` / `lognorm_sd`. To further disambiguate, `mean` and `sd` are no longer variables that can be passed to `lognorm`. - +- **[Breaking change]** `lognorm` can now be defined either referencing the mean and sd of the underlying normal distribution via `norm_mean` / `norm_sd` or via the mean and sd of the lognormal distribution itself via `lognorm_mean` / `lognorm_sd`. To further disambiguate, `mean` and `sd` are no longer variables that can be passed to `lognorm`. ## v0.25 -* Added `plot` as a method to more easily plot distributions. -* Added `dist_log` and `dist_exp` operators on distributions. -* Added `growth_rate_to_doubling_time` and `doubling_time_to_growth_rate` convenience functions. These take numbers, numpy arrays or distributions. -* Mixture distributions now print with weights in addition to distributions. -* Changes `get_log_percentiles` to report in scientific notation. -* `bayes` now supports separate arguments for `memcache_load` and `memcache_save` to better customize how memcache behavior works. `memcache` remains a parameter that sets both `memcache_load` and `memcache_save` to True. - +- Added `plot` as a method to more easily plot distributions. +- Added `dist_log` and `dist_exp` operators on distributions. +- Added `growth_rate_to_doubling_time` and `doubling_time_to_growth_rate` convenience functions. These take numbers, numpy arrays or distributions. +- Mixture distributions now print with weights in addition to distributions. +- Changes `get_log_percentiles` to report in scientific notation. +- `bayes` now supports separate arguments for `memcache_load` and `memcache_save` to better customize how memcache behavior works. `memcache` remains a parameter that sets both `memcache_load` and `memcache_save` to True. ## v0.24 -* Distributions can now be negated with `-` (e.g., `-lognorm(0.1, 1)`). -* Numpy ints and floats can now be used for determining the number of samples. -* Fixed some typos in the documentation. - +- Distributions can now be negated with `-` (e.g., `-lognorm(0.1, 1)`). +- Numpy ints and floats can now be used for determining the number of samples. +- Fixed some typos in the documentation. ## v0.23 -* Added `pareto` distribution. -* Added `get_median_and_ci` to return the median and a given confidence interval for data. -* `discrete` and `mixture` distributions now give more detail when printed. -* Fixed some typos in the documentation. - +- Added `pareto` distribution. +- Added `get_median_and_ci` to return the median and a given confidence interval for data. +- `discrete` and `mixture` distributions now give more detail when printed. +- Fixed some typos in the documentation. ## v0.22 -* Added `extremize` to extremize predictions. -* Added `normalize` to normalize a list of numbers to sum to 1. -* Added `get_mean_and_ci` to return the mean and a given confidence interval for data. -* Added `is_dist` to determine if an object is a Squigglepy distribution. -* Added `is_sampleable` to determine if an object can be sampled using `sample`. -* Support for working within Pandas is now explicitly added. `pandas` has been added as a requirement. -* `discrete` sampling now will compress a large array if possible for more efficient sampling. -* `clip`, `lclip`, and `rclip` can now be used without needing distributions. -* Some functions (e.g, `geomean`) previously only supported lists, dictionaries, and numpy arrays. They have been expanded to support all iterables. -* `dist_max` and `dist_min` now support pipes (`>>`) -* `get_percentiles` now coerces output to integer if `digits` is less than or equal to 0, instead of just exactly 0. - +- Added `extremize` to extremize predictions. +- Added `normalize` to normalize a list of numbers to sum to 1. +- Added `get_mean_and_ci` to return the mean and a given confidence interval for data. +- Added `is_dist` to determine if an object is a Squigglepy distribution. +- Added `is_sampleable` to determine if an object can be sampled using `sample`. +- Support for working within Pandas is now explicitly added. `pandas` has been added as a requirement. +- `discrete` sampling now will compress a large array if possible for more efficient sampling. +- `clip`, `lclip`, and `rclip` can now be used without needing distributions. +- Some functions (e.g, `geomean`) previously only supported lists, dictionaries, and numpy arrays. They have been expanded to support all iterables. +- `dist_max` and `dist_min` now support pipes (`>>`) +- `get_percentiles` now coerces output to integer if `digits` is less than or equal to 0, instead of just exactly 0. ## v0.21 -* Mixture sampling is now 4-23x faster. -* You can now get the version of squigglepy via `sq.__version__`. -* Fixes a bug where the tqdm was displayed with the incorrect count when collecting cores during a multicore `sample`. - +- Mixture sampling is now 4-23x faster. +- You can now get the version of squigglepy via `sq.__version__`. +- Fixes a bug where the tqdm was displayed with the incorrect count when collecting cores during a multicore `sample`. ## v0.20 -* Fixes how package dependencies are handled in `setup.py` an specifies Python >= 3.7 must be used. This should fix install errors. - +- Fixes how package dependencies are handled in `setup.py` an specifies Python >= 3.7 must be used. This should fix install errors. ## v0.19 #### Bugfixes -* Fixes a bug where `lclip` and/or `rclip` on `mixture` distribution were not working correctly. -* Fixes a bug where `dist_fn` did not work with `np.vectorize` functions. -* Fixes a bug where in-memory caching was invoked for `bayesnet` when not desired. +- Fixes a bug where `lclip` and/or `rclip` on `mixture` distribution were not working correctly. +- Fixes a bug where `dist_fn` did not work with `np.vectorize` functions. +- Fixes a bug where in-memory caching was invoked for `bayesnet` when not desired. #### Caching and Multicore -* **[Breaking change]** `bayesnet` caching is now based on binary files instead of pickle files (uses `msgspec` as the underlying library). -* **[Breaking change]** `sample` caching is now based on numpy files instead of pickle files. -* A cache can now be loaded via `sample(load_cache=cachefile)` or `bayesnet(load_cache=cachefile)`, without needing to pass the distribution / function. -* `bayesnet` and `sample` now take an argument `cores` (default 1). If greater than 1, will run the calculations on multiple cores using the pathos package. +- **[Breaking change]** `bayesnet` caching is now based on binary files instead of pickle files (uses `msgspec` as the underlying library). +- **[Breaking change]** `sample` caching is now based on numpy files instead of pickle files. +- A cache can now be loaded via `sample(load_cache=cachefile)` or `bayesnet(load_cache=cachefile)`, without needing to pass the distribution / function. +- `bayesnet` and `sample` now take an argument `cores` (default 1). If greater than 1, will run the calculations on multiple cores using the pathos package. #### Other -* Functions that take `weights` now can instead take a parameter `relative_weights` where waits are automatically normalized to sum to 1 (instead of erroring, which is still the behavior if using `weights`). -* Verbose output for `bayesnet` and `sample` is now clearer (and slightly more verbose). - +- Functions that take `weights` now can instead take a parameter `relative_weights` where waits are automatically normalized to sum to 1 (instead of erroring, which is still the behavior if using `weights`). +- Verbose output for `bayesnet` and `sample` is now clearer (and slightly more verbose). ## v0.18 -* **[Breaking change]** The default `t` for t-distributions has changed from 1 to 20. -* `sample` results can now be cached in-memory using `memcache=True`. They can also be cached to a file -- use `dump_cache_file` to write the file and `load_cache_file` to load from the file. -* _(Non-visible backend change)_ Weights that are set to 0 are now dropped entirely. - +- **[Breaking change]** The default `t` for t-distributions has changed from 1 to 20. +- `sample` results can now be cached in-memory using `memcache=True`. They can also be cached to a file -- use `dump_cache_file` to write the file and `load_cache_file` to load from the file. +- _(Non-visible backend change)_ Weights that are set to 0 are now dropped entirely. ## v0.17 -* When `verbose=True` is used in `sample`, the progress bar now pops up in more relevant places and is much more likely to get triggered when relevant. -* `discrete_sample` and `mixture_sample` now can take `verbose` parameter. - +- When `verbose=True` is used in `sample`, the progress bar now pops up in more relevant places and is much more likely to get triggered when relevant. +- `discrete_sample` and `mixture_sample` now can take `verbose` parameter. ## v0.16 -* `zero_inflated` can create an arbitrary zero-inflated distribution. -* Individual sampling functions (`normal_sample`, `lognormal_sample`, etc.) can now take an argument `samples` to generate multiple samples. -* A large speedup has been achieved to sampling from the same distribution multiple times. -* `requirements.txt` has been updated. - +- `zero_inflated` can create an arbitrary zero-inflated distribution. +- Individual sampling functions (`normal_sample`, `lognormal_sample`, etc.) can now take an argument `samples` to generate multiple samples. +- A large speedup has been achieved to sampling from the same distribution multiple times. +- `requirements.txt` has been updated. ## v0.15 -* **[Breaking change]** `bayesnet` function now refers to parameter `memcache` where previously this parameter was called `cache`. -* **[Breaking change]** If `get_percentiles` or `get_log_percentiles` is called with just one elemement for `percentiles`, it will return that value instead of a dict. -* Fixed a bug where `get_percentiles` would not round correctly. -* `bayesnet` results can now be cached to a file. Use `dump_cache_file` to write the file and `load_cache_file` to load from the file. -* `discrete` now works with numpy arrays in addition to lists. -* Added `one_in` as a shorthand to convert percentages into "1 in X" notation. -* Distributions can now be compared with `==` and `!=`. - +- **[Breaking change]** `bayesnet` function now refers to parameter `memcache` where previously this parameter was called `cache`. +- **[Breaking change]** If `get_percentiles` or `get_log_percentiles` is called with just one elemement for `percentiles`, it will return that value instead of a dict. +- Fixed a bug where `get_percentiles` would not round correctly. +- `bayesnet` results can now be cached to a file. Use `dump_cache_file` to write the file and `load_cache_file` to load from the file. +- `discrete` now works with numpy arrays in addition to lists. +- Added `one_in` as a shorthand to convert percentages into "1 in X" notation. +- Distributions can now be compared with `==` and `!=`. ## v0.14 -* Nested sampling now works as intended. -* You can now use `>>` for pipes for distributions. For example, `sq.norm(1, 2) >> dist_ceil` -* Distributions can now be compared with `>`, `<`, `>=`, and `<=`. -* `dist_max` can be used to get the maximum value between two distributions. This family of functions are not evaluated until the distribution is sampled and they work with pipes. -* `dist_min` can be used to get the minimum value between two distributions. -* `dist_round` can be used to round the final output of a distribution. This makes the distribution discrete. -* `dist_ceil` can be used to ceiling round the final output of a distribution. This makes the distribution discrete. -* `dist_floor` can be used to floor round the final output of a distribution. This makes the distribution discrete. -* `lclip` can be used to clip a distribution to a lower bound. This is the same functionality that is available within the distribution and the `sample` method. -* `rclip` can be used to clip a distribution to an upper bound. This is the same functionality that is available within the distribution and the `sample` method. -* `clip` can be used to clip a distribution to both an upper bound and a lower bound. This is the same functionality that is available within the distribution and the `sample` method. -* `sample` can now be used directly on numbers. This makes `const` functionally obsolete, but `const` is maintained for backwards compatibility and in case it is useful. -* `sample(None)` now returns `None` instead of an error. - +- Nested sampling now works as intended. +- You can now use `>>` for pipes for distributions. For example, `sq.norm(1, 2) >> dist_ceil` +- Distributions can now be compared with `>`, `<`, `>=`, and `<=`. +- `dist_max` can be used to get the maximum value between two distributions. This family of functions are not evaluated until the distribution is sampled and they work with pipes. +- `dist_min` can be used to get the minimum value between two distributions. +- `dist_round` can be used to round the final output of a distribution. This makes the distribution discrete. +- `dist_ceil` can be used to ceiling round the final output of a distribution. This makes the distribution discrete. +- `dist_floor` can be used to floor round the final output of a distribution. This makes the distribution discrete. +- `lclip` can be used to clip a distribution to a lower bound. This is the same functionality that is available within the distribution and the `sample` method. +- `rclip` can be used to clip a distribution to an upper bound. This is the same functionality that is available within the distribution and the `sample` method. +- `clip` can be used to clip a distribution to both an upper bound and a lower bound. This is the same functionality that is available within the distribution and the `sample` method. +- `sample` can now be used directly on numbers. This makes `const` functionally obsolete, but `const` is maintained for backwards compatibility and in case it is useful. +- `sample(None)` now returns `None` instead of an error. ## v0.13 -* Sample shorthand notation can go in either order. That is, `100 @ sq.norm(1, 2)` now works and is the same as `sq.norm(1, 2) @ 100`, which is the same as `sq.sample(sq.norm(1, 2), n=100)`. - +- Sample shorthand notation can go in either order. That is, `100 @ sq.norm(1, 2)` now works and is the same as `sq.norm(1, 2) @ 100`, which is the same as `sq.sample(sq.norm(1, 2), n=100)`. ## v0.12 -* Distributions now implement math directly. That is, you can do things like `sq.norm(2, 3) + sq.norm(4, 5)`, whereas previously this would not work. Thanks to Dawn Drescher for helping me implement this. -* `~sq.norm(1, 2)` is now a shorthand for `sq.sample(sq.norm(1, 2))`. Thanks to Dawn Drescher for helping me implement this shorthand. -* `sq.norm(1, 2) @ 100` is now a shorthand for `sq.sample(sq.norm(1, 2), n=100)` - +- Distributions now implement math directly. That is, you can do things like `sq.norm(2, 3) + sq.norm(4, 5)`, whereas previously this would not work. Thanks to Dawn Drescher for helping me implement this. +- `~sq.norm(1, 2)` is now a shorthand for `sq.sample(sq.norm(1, 2))`. Thanks to Dawn Drescher for helping me implement this shorthand. +- `sq.norm(1, 2) @ 100` is now a shorthand for `sq.sample(sq.norm(1, 2), n=100)` ## v0.11 #### Distributions -* **[Breaking change]** `tdist` and `log_tdist` have been modified to better approximate the desired credible intervals. -* `tdist` now can be defined by just `t`, producing a classic t-distribution. -* `tdist` now has a default value for `t`: 1. -* Added `chisquare` distribution. -* `lognormal` now returns an error if it is defined with a zero or negative value. +- **[Breaking change]** `tdist` and `log_tdist` have been modified to better approximate the desired credible intervals. +- `tdist` now can be defined by just `t`, producing a classic t-distribution. +- `tdist` now has a default value for `t`: 1. +- Added `chisquare` distribution. +- `lognormal` now returns an error if it is defined with a zero or negative value. #### Other -* All functions now have docstrings. -* Added `kelly` to calculate Kelly criterion for bet sizing with probabilities. -* Added `full_kelly`, `half_kelly`, `quarter_kelly` as helpful aliases. - +- All functions now have docstrings. +- Added `kelly` to calculate Kelly criterion for bet sizing with probabilities. +- Added `full_kelly`, `half_kelly`, `quarter_kelly` as helpful aliases. ## v0.10 -* **[Breaking change]** `credibility` is now defined using a number out of 100 (e.g., `credibility=80` to define an 80% CI) rather than a decimal out of 1 (e.g., `credibility=0.8` to define an 80% CI). -* Distribution objects now print their parameters. - +- **[Breaking change]** `credibility` is now defined using a number out of 100 (e.g., `credibility=80` to define an 80% CI) rather than a decimal out of 1 (e.g., `credibility=0.8` to define an 80% CI). +- Distribution objects now print their parameters. ## v0.9 -* `goemean` and `geomean_odds` now can take the nested-list-based and dictionary-based formats for passing weights. - +- `goemean` and `geomean_odds` now can take the nested-list-based and dictionary-based formats for passing weights. ## v0.8 #### Bayesian library updates -* **[Breaking change]** `bayes.update` now updates normal distributions from the distribution rather than from samples. -* **[Breaking change]** `bayes.update` no longer takes a `type` parameter but can now infer the type from the passed distribution. -* **[Breaking change]** Corrected a bug in how `bayes.update` implemented `evidence_weight` when updating normal distributions. +- **[Breaking change]** `bayes.update` now updates normal distributions from the distribution rather than from samples. +- **[Breaking change]** `bayes.update` no longer takes a `type` parameter but can now infer the type from the passed distribution. +- **[Breaking change]** Corrected a bug in how `bayes.update` implemented `evidence_weight` when updating normal distributions. #### Non-visible backend changes -* Distributions are now implemented as classes (rather than lists). - +- Distributions are now implemented as classes (rather than lists). ## v0.7 #### Bugfixes -* Fixes an issue with sampling from the `bernoulli` distribution. -* Fixes a bug with the implementation of `lclip` and `rclip`. +- Fixes an issue with sampling from the `bernoulli` distribution. +- Fixes a bug with the implementation of `lclip` and `rclip`. #### New distributions -* Adds `discrete` to calculate a discrete distribution. Example: `discrete({'A': 0.3, 'B': 0.3, 'C': 0.4})` will return A 30% of the time, B 30% of the time, and C 40% of the time. -* Adds `poisson(lam)` to calculate a poisson distribution. -* Adds `gamma(size, scale)` to calculate a gamma distribution. +- Adds `discrete` to calculate a discrete distribution. Example: `discrete({'A': 0.3, 'B': 0.3, 'C': 0.4})` will return A 30% of the time, B 30% of the time, and C 40% of the time. +- Adds `poisson(lam)` to calculate a poisson distribution. +- Adds `gamma(size, scale)` to calculate a gamma distribution. #### Bayesian library updates -* Adds `bayes.bayesnet` to do bayesian inferece (see README). -* `bayes.update` now can take an `evidence_weight` parameter. Typically this would be equal to the number of samples. -* **[Breaking change]** `bayes.bayes` has been renamed `bayes.simple_bayes`. +- Adds `bayes.bayesnet` to do bayesian inferece (see README). +- `bayes.update` now can take an `evidence_weight` parameter. Typically this would be equal to the number of samples. +- **[Breaking change]** `bayes.bayes` has been renamed `bayes.simple_bayes`. #### Other -* **[Breaking change]** `credibility`, which defines the size of the interval (e.g., `credibility=0.8` for an 80% CI), is now a property of the distribution rather than the sampler. That is, you should now call `sample(norm(1, 3, credibility=0.8))` whereas previously it was `sample(norm(1, 3), credibility=0.8)`. This will allow mixing of distributions with different credible ranges. -* **[Breaking change]** Numbers have been changed from functions to global variables. Use `thousand` or `K` instead of `thousand()` (old/deprecated). -* `sample` now has a nice progress reporter if `verbose=True`. -* The `exponential` distribution now implements `lclip` and `rclip`. -* The `mixture` distribution can infer equal weights if no weights are given. -* The `mixture` distribution can infer the last weight if the last weight is not given. -* `geomean` and `geomean_odds` can infer the last weight if the last weight is not given. -* You can use `flip_coin` and `roll_die(sides)` to flip a coin or roll a die. -* `event_happens` and `event` are aliases for `event_occurs`. -* `get_percentiles` will now cast output to `int` if `digits=0`. -* `get_log_percentiles` now has a default value for `percentiles`. -* You can now set the seed for the RNG using `sq.set_seed`. +- **[Breaking change]** `credibility`, which defines the size of the interval (e.g., `credibility=0.8` for an 80% CI), is now a property of the distribution rather than the sampler. That is, you should now call `sample(norm(1, 3, credibility=0.8))` whereas previously it was `sample(norm(1, 3), credibility=0.8)`. This will allow mixing of distributions with different credible ranges. +- **[Breaking change]** Numbers have been changed from functions to global variables. Use `thousand` or `K` instead of `thousand()` (old/deprecated). +- `sample` now has a nice progress reporter if `verbose=True`. +- The `exponential` distribution now implements `lclip` and `rclip`. +- The `mixture` distribution can infer equal weights if no weights are given. +- The `mixture` distribution can infer the last weight if the last weight is not given. +- `geomean` and `geomean_odds` can infer the last weight if the last weight is not given. +- You can use `flip_coin` and `roll_die(sides)` to flip a coin or roll a die. +- `event_happens` and `event` are aliases for `event_occurs`. +- `get_percentiles` will now cast output to `int` if `digits=0`. +- `get_log_percentiles` now has a default value for `percentiles`. +- You can now set the seed for the RNG using `sq.set_seed`. #### Non-visible backend changes -* Now has tests via pytest. -* The random numbers now come from a numpy generator as opposed to the previous deprecated `np.random` methods. -* The `sample` module (containing the `sample` function) has been renamed `samplers`. - +- Now has tests via pytest. +- The random numbers now come from a numpy generator as opposed to the previous deprecated `np.random` methods. +- The `sample` module (containing the `sample` function) has been renamed `samplers`. ## v0.6 #### New distributions -* Add `triangular(left, mode, right)` to calculate a triangular distribution. -* Add `binomial(n, p)` to calculate a binomial distribution. -* Add `beta(a, b)` to calculate a beta distribution. -* Add `bernoulli(p)` to calculate a bernoulli distribution. -* Add `exponential(scale)` to calculate an exponential distribution. +- Add `triangular(left, mode, right)` to calculate a triangular distribution. +- Add `binomial(n, p)` to calculate a binomial distribution. +- Add `beta(a, b)` to calculate a beta distribution. +- Add `bernoulli(p)` to calculate a bernoulli distribution. +- Add `exponential(scale)` to calculate an exponential distribution. #### New Bayesian library -* Add `bayes.update` to get a posterior distribution from a prior distribution and an evidence distribution. -* Add `bayes.average` to average distributions (via a mixture). +- Add `bayes.update` to get a posterior distribution from a prior distribution and an evidence distribution. +- Add `bayes.average` to average distributions (via a mixture). #### New utility functions -* Add `laplace` to calculate Laplace's Law of Succession. If `s` and `n` are passed, it will calculate `(s+1)/(n+2)`. If `s`, `time_passed`, and `time_remaining` are passed, it will use the [time invariant version](https://www.lesswrong.com/posts/wE7SK8w8AixqknArs/a-time-invariant-version-of-laplace-s-rule). Use `time_fixed=True` for fixed time periods and `time_fixed=False` (default) otherwise. -* Add `geomean` to calculate the geometric mean. -* Add `p_to_odds` to convert probability to odds. Also `odds_to_p` to convert odds to probability. -* Add `geomean_odds` to calculate the geometric mean of odds, converted to and from probabilities. +- Add `laplace` to calculate Laplace's Law of Succession. If `s` and `n` are passed, it will calculate `(s+1)/(n+2)`. If `s`, `time_passed`, and `time_remaining` are passed, it will use the [time invariant version](https://www.lesswrong.com/posts/wE7SK8w8AixqknArs/a-time-invariant-version-of-laplace-s-rule). Use `time_fixed=True` for fixed time periods and `time_fixed=False` (default) otherwise. +- Add `geomean` to calculate the geometric mean. +- Add `p_to_odds` to convert probability to odds. Also `odds_to_p` to convert odds to probability. +- Add `geomean_odds` to calculate the geometric mean of odds, converted to and from probabilities. #### Other -* If a distribution is defined with `sd` but not `mean`, `mean` will be inferred to be 0. -* `sample` can now take `lclip` and `rclip` directly, in addition to defining `lclip` and `rclip` on the distribution itself. If both are defined, the most restrictive of the two bounds will be used. - +- If a distribution is defined with `sd` but not `mean`, `mean` will be inferred to be 0. +- `sample` can now take `lclip` and `rclip` directly, in addition to defining `lclip` and `rclip` on the distribution itself. If both are defined, the most restrictive of the two bounds will be used. ## v0.5 -* Fix critical bug to `tdist` and `log_tdist` introduced in v0.3. - +- Fix critical bug to `tdist` and `log_tdist` introduced in v0.3. ## v0.4 -* Fix critical bug introduced in v0.3. - +- Fix critical bug introduced in v0.3. ## v0.3 -* Be able to define distributions using `mean` and `sd` instead of defining the interval. - +- Be able to define distributions using `mean` and `sd` instead of defining the interval. ## v0.2 -* **[Breaking change]** Change `distributed_log` to `mixture` (to follow Squiggle) and allow it to implement any sub-distribution. -* **[Breaking change]** Changed library to single import. -* **[Breaking change]** Remove `weighted_log` as a distribution. - +- **[Breaking change]** Change `distributed_log` to `mixture` (to follow Squiggle) and allow it to implement any sub-distribution. +- **[Breaking change]** Changed library to single import. +- **[Breaking change]** Remove `weighted_log` as a distribution. ## v0.1 -* Initial library +- Initial library diff --git a/README.md b/README.md index e3d5011..a8e2919 100644 --- a/README.md +++ b/README.md @@ -438,9 +438,7 @@ You can see more examples of squigglepy in action [here](https://github.com/pete ## Run tests -Use `black .` for formatting. - -Run `ruff check . && pytest && pip3 install . && python3 tests/integration.py` +Run `black . && pyright . && ruff check . && pytest && pip3 install . && python3 tests/integration.py` ## Disclaimers diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/poetry.lock b/poetry.lock index 8ca1d79..2a7dc1c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,36 +2,33 @@ [[package]] name = "black" -version = "23.3.0" +version = "23.7.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, - {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, - {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, - {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, - {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, - {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, - {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, - {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, - {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, - {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, - {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, - {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, - {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, - {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, ] [package.dependencies] @@ -51,13 +48,13 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -76,77 +73,61 @@ files = [ [[package]] name = "contourpy" -version = "1.0.7" +version = "1.1.0" description = "Python library for calculating contours of 2D quadrilateral grids" optional = true python-versions = ">=3.8" files = [ - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:95c3acddf921944f241b6773b767f1cbce71d03307270e2d769fd584d5d1092d"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc1464c97579da9f3ab16763c32e5c5d5bb5fa1ec7ce509a4ca6108b61b84fab"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8acf74b5d383414401926c1598ed77825cd530ac7b463ebc2e4f46638f56cce6"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c71fdd8f1c0f84ffd58fca37d00ca4ebaa9e502fb49825484da075ac0b0b803"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f99e9486bf1bb979d95d5cffed40689cb595abb2b841f2991fc894b3452290e8"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f4d8941a9564cda3f7fa6a6cd9b32ec575830780677932abdec7bcb61717b0"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9e20e5a1908e18aaa60d9077a6d8753090e3f85ca25da6e25d30dc0a9e84c2c6"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a877ada905f7d69b2a31796c4b66e31a8068b37aa9b78832d41c82fc3e056ddd"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6381fa66866b0ea35e15d197fc06ac3840a9b2643a6475c8fff267db8b9f1e69"}, - {file = "contourpy-1.0.7-cp310-cp310-win32.whl", hash = "sha256:3c184ad2433635f216645fdf0493011a4667e8d46b34082f5a3de702b6ec42e3"}, - {file = "contourpy-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:3caea6365b13119626ee996711ab63e0c9d7496f65641f4459c60a009a1f3e80"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed33433fc3820263a6368e532f19ddb4c5990855e4886088ad84fd7c4e561c71"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38e2e577f0f092b8e6774459317c05a69935a1755ecfb621c0a98f0e3c09c9a5"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae90d5a8590e5310c32a7630b4b8618cef7563cebf649011da80874d0aa8f414"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130230b7e49825c98edf0b428b7aa1125503d91732735ef897786fe5452b1ec2"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58569c491e7f7e874f11519ef46737cea1d6eda1b514e4eb5ac7dab6aa864d02"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d43960d809c4c12508a60b66cb936e7ed57d51fb5e30b513934a4a23874fae"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:152fd8f730c31fd67fe0ffebe1df38ab6a669403da93df218801a893645c6ccc"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9056c5310eb1daa33fc234ef39ebfb8c8e2533f088bbf0bc7350f70a29bde1ac"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a9d7587d2fdc820cc9177139b56795c39fb8560f540bba9ceea215f1f66e1566"}, - {file = "contourpy-1.0.7-cp311-cp311-win32.whl", hash = "sha256:4ee3ee247f795a69e53cd91d927146fb16c4e803c7ac86c84104940c7d2cabf0"}, - {file = "contourpy-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:5caeacc68642e5f19d707471890f037a13007feba8427eb7f2a60811a1fc1350"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd7dc0e6812b799a34f6d12fcb1000539098c249c8da54f3566c6a6461d0dbad"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0f9d350b639db6c2c233d92c7f213d94d2e444d8e8fc5ca44c9706cf72193772"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e96a08b62bb8de960d3a6afbc5ed8421bf1a2d9c85cc4ea73f4bc81b4910500f"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:031154ed61f7328ad7f97662e48660a150ef84ee1bc8876b6472af88bf5a9b98"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e9ebb4425fc1b658e13bace354c48a933b842d53c458f02c86f371cecbedecc"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb8f6d08ca7998cf59eaf50c9d60717f29a1a0a09caa46460d33b2924839dbd"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6c180d89a28787e4b73b07e9b0e2dac7741261dbdca95f2b489c4f8f887dd810"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b8d587cc39057d0afd4166083d289bdeff221ac6d3ee5046aef2d480dc4b503c"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:769eef00437edf115e24d87f8926955f00f7704bede656ce605097584f9966dc"}, - {file = "contourpy-1.0.7-cp38-cp38-win32.whl", hash = "sha256:62398c80ef57589bdbe1eb8537127321c1abcfdf8c5f14f479dbbe27d0322e66"}, - {file = "contourpy-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:57119b0116e3f408acbdccf9eb6ef19d7fe7baf0d1e9aaa5381489bc1aa56556"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30676ca45084ee61e9c3da589042c24a57592e375d4b138bd84d8709893a1ba4"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e927b3868bd1e12acee7cc8f3747d815b4ab3e445a28d2e5373a7f4a6e76ba1"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:366a0cf0fc079af5204801786ad7a1c007714ee3909e364dbac1729f5b0849e5"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ba9bb365446a22411f0673abf6ee1fea3b2cf47b37533b970904880ceb72f3"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b0bf0c30d432278793d2141362ac853859e87de0a7dee24a1cea35231f0d50"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7281244c99fd7c6f27c1c6bfafba878517b0b62925a09b586d88ce750a016d2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6d0f9e1d39dbfb3977f9dd79f156c86eb03e57a7face96f199e02b18e58d32a"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f6979d20ee5693a1057ab53e043adffa1e7418d734c1532e2d9e915b08d8ec2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5dd34c1ae752515318224cba7fc62b53130c45ac6a1040c8b7c1a223c46e8967"}, - {file = "contourpy-1.0.7-cp39-cp39-win32.whl", hash = "sha256:c5210e5d5117e9aec8c47d9156d1d3835570dd909a899171b9535cb4a3f32693"}, - {file = "contourpy-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:60835badb5ed5f4e194a6f21c09283dd6e007664a86101431bf870d9e86266c4"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ce41676b3d0dd16dbcfabcc1dc46090aaf4688fd6e819ef343dbda5a57ef0161"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a011cf354107b47c58ea932d13b04d93c6d1d69b8b6dce885e642531f847566"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31a55dccc8426e71817e3fe09b37d6d48ae40aae4ecbc8c7ad59d6893569c436"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f8ff4db108815addd900a74df665e135dbbd6547a8a69333a68e1f6e368ac2"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efe99298ba37e37787f6a2ea868265465410822f7bea163edcc1bd3903354ea9"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a1e97b86f73715e8670ef45292d7cc033548266f07d54e2183ecb3c87598888f"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc331c13902d0f50845099434cd936d49d7a2ca76cb654b39691974cb1e4812d"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24847601071f740837aefb730e01bd169fbcaa610209779a78db7ebb6e6a7051"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abf298af1e7ad44eeb93501e40eb5a67abbf93b5d90e468d01fc0c4451971afa"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:64757f6460fc55d7e16ed4f1de193f362104285c667c112b50a804d482777edd"}, - {file = "contourpy-1.0.7.tar.gz", hash = "sha256:d8165a088d31798b59e91117d1f5fc3df8168d8b48c4acc10fc0df0d0bdbcc5e"}, + {file = "contourpy-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:89f06eff3ce2f4b3eb24c1055a26981bffe4e7264acd86f15b97e40530b794bc"}, + {file = "contourpy-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dffcc2ddec1782dd2f2ce1ef16f070861af4fb78c69862ce0aab801495dda6a3"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25ae46595e22f93592d39a7eac3d638cda552c3e1160255258b695f7b58e5655"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:17cfaf5ec9862bc93af1ec1f302457371c34e688fbd381f4035a06cd47324f48"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18a64814ae7bce73925131381603fff0116e2df25230dfc80d6d690aa6e20b37"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c81f22b4f572f8a2110b0b741bb64e5a6427e0a198b2cdc1fbaf85f352a3aa"}, + {file = "contourpy-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53cc3a40635abedbec7f1bde60f8c189c49e84ac180c665f2cd7c162cc454baa"}, + {file = "contourpy-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:1f795597073b09d631782e7245016a4323cf1cf0b4e06eef7ea6627e06a37ff2"}, + {file = "contourpy-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b7b04ed0961647691cfe5d82115dd072af7ce8846d31a5fac6c142dcce8b882"}, + {file = "contourpy-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27bc79200c742f9746d7dd51a734ee326a292d77e7d94c8af6e08d1e6c15d545"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052cc634bf903c604ef1a00a5aa093c54f81a2612faedaa43295809ffdde885e"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9382a1c0bc46230fb881c36229bfa23d8c303b889b788b939365578d762b5c18"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5cec36c5090e75a9ac9dbd0ff4a8cf7cecd60f1b6dc23a374c7d980a1cd710e"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0cbd657e9bde94cd0e33aa7df94fb73c1ab7799378d3b3f902eb8eb2e04a3a"}, + {file = "contourpy-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:181cbace49874f4358e2929aaf7ba84006acb76694102e88dd15af861996c16e"}, + {file = "contourpy-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb3b7d9e6243bfa1efb93ccfe64ec610d85cfe5aec2c25f97fbbd2e58b531256"}, + {file = "contourpy-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcb41692aa09aeb19c7c213411854402f29f6613845ad2453d30bf421fe68fed"}, + {file = "contourpy-1.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5d123a5bc63cd34c27ff9c7ac1cd978909e9c71da12e05be0231c608048bb2ae"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62013a2cf68abc80dadfd2307299bfa8f5aa0dcaec5b2954caeb5fa094171103"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b6616375d7de55797d7a66ee7d087efe27f03d336c27cf1f32c02b8c1a5ac70"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:317267d915490d1e84577924bd61ba71bf8681a30e0d6c545f577363157e5e94"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d551f3a442655f3dcc1285723f9acd646ca5858834efeab4598d706206b09c9f"}, + {file = "contourpy-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7a117ce7df5a938fe035cad481b0189049e8d92433b4b33aa7fc609344aafa1"}, + {file = "contourpy-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4f26b25b4f86087e7d75e63212756c38546e70f2a92d2be44f80114826e1cd4"}, + {file = "contourpy-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc00bb4225d57bff7ebb634646c0ee2a1298402ec10a5fe7af79df9a51c1bfd9"}, + {file = "contourpy-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:189ceb1525eb0655ab8487a9a9c41f42a73ba52d6789754788d1883fb06b2d8a"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f2931ed4741f98f74b410b16e5213f71dcccee67518970c42f64153ea9313b9"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f511c05fab7f12e0b1b7730ebdc2ec8deedcfb505bc27eb570ff47c51a8f15"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143dde50520a9f90e4a2703f367cf8ec96a73042b72e68fcd184e1279962eb6f"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e94bef2580e25b5fdb183bf98a2faa2adc5b638736b2c0a4da98691da641316a"}, + {file = "contourpy-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed614aea8462735e7d70141374bd7650afd1c3f3cb0c2dbbcbe44e14331bf002"}, + {file = "contourpy-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:438ba416d02f82b692e371858143970ed2eb6337d9cdbbede0d8ad9f3d7dd17d"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a698c6a7a432789e587168573a864a7ea374c6be8d4f31f9d87c001d5a843493"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b0ac8a12880412da3551a8cb5a187d3298a72802b45a3bd1805e204ad8439"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a67259c2b493b00e5a4d0f7bfae51fb4b3371395e47d079a4446e9b0f4d70e76"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2b836d22bd2c7bb2700348e4521b25e077255ebb6ab68e351ab5aa91ca27e027"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084eaa568400cfaf7179b847ac871582199b1b44d5699198e9602ecbbb5f6104"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:911ff4fd53e26b019f898f32db0d4956c9d227d51338fb3b03ec72ff0084ee5f"}, + {file = "contourpy-1.1.0.tar.gz", hash = "sha256:e53046c3863828d21d531cc3b53786e6580eb1ba02477e8681009b6aa0870b21"}, ] [package.dependencies] numpy = ">=1.16" [package.extras] -bokeh = ["bokeh", "chromedriver", "selenium"] +bokeh = ["bokeh", "selenium"] docs = ["furo", "sphinx-copybutton"] -mypy = ["contourpy[bokeh]", "docutils-stubs", "mypy (==0.991)", "types-Pillow"] -test = ["Pillow", "matplotlib", "pytest"] -test-no-images = ["pytest"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.2.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "wurlitzer"] [[package]] name = "cycler" @@ -161,13 +142,13 @@ files = [ [[package]] name = "dill" -version = "0.3.6" -description = "serialize all of python" +version = "0.3.7" +description = "serialize all of Python" optional = false python-versions = ">=3.7" files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, + {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, + {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] [package.extras] @@ -175,13 +156,13 @@ graph = ["objgraph (>=1.7.2)"] [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] [package.extras] @@ -189,45 +170,45 @@ test = ["pytest (>=6)"] [[package]] name = "fonttools" -version = "4.40.0" +version = "4.42.1" description = "Tools to manipulate font files" optional = true python-versions = ">=3.8" files = [ - {file = "fonttools-4.40.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b802dcbf9bcff74672f292b2466f6589ab8736ce4dcf36f48eb994c2847c4b30"}, - {file = "fonttools-4.40.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f6e3fa3da923063c286320e728ba2270e49c73386e3a711aa680f4b0747d692"}, - {file = "fonttools-4.40.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fdf60f8a5c6bcce7d024a33f7e4bc7921f5b74e8ea13bccd204f2c8b86f3470"}, - {file = "fonttools-4.40.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91784e21a1a085fac07c6a407564f4a77feb471b5954c9ee55a4f9165151f6c1"}, - {file = "fonttools-4.40.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:05171f3c546f64d78569f10adc0de72561882352cac39ec7439af12304d8d8c0"}, - {file = "fonttools-4.40.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7449e5e306f3a930a8944c85d0cbc8429cba13503372a1a40f23124d6fb09b58"}, - {file = "fonttools-4.40.0-cp310-cp310-win32.whl", hash = "sha256:bae8c13abbc2511e9a855d2142c0ab01178dd66b1a665798f357da0d06253e0d"}, - {file = "fonttools-4.40.0-cp310-cp310-win_amd64.whl", hash = "sha256:425b74a608427499b0e45e433c34ddc350820b6f25b7c8761963a08145157a66"}, - {file = "fonttools-4.40.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:00ab569b2a3e591e00425023ade87e8fef90380c1dde61be7691cb524ca5f743"}, - {file = "fonttools-4.40.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:18ea64ac43e94c9e0c23d7a9475f1026be0e25b10dda8f236fc956188761df97"}, - {file = "fonttools-4.40.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:022c4a16b412293e7f1ce21b8bab7a6f9d12c4ffdf171fdc67122baddb973069"}, - {file = "fonttools-4.40.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530c5d35109f3e0cea2535742d6a3bc99c0786cf0cbd7bb2dc9212387f0d908c"}, - {file = "fonttools-4.40.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5e00334c66f4e83535384cb5339526d01d02d77f142c23b2f97bd6a4f585497a"}, - {file = "fonttools-4.40.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb52c10fda31159c22c7ed85074e05f8b97da8773ea461706c273e31bcbea836"}, - {file = "fonttools-4.40.0-cp311-cp311-win32.whl", hash = "sha256:6a8d71b9a5c884c72741868e845c0e563c5d83dcaf10bb0ceeec3b4b2eb14c67"}, - {file = "fonttools-4.40.0-cp311-cp311-win_amd64.whl", hash = "sha256:15abb3d055c1b2dff9ce376b6c3db10777cb74b37b52b78f61657634fd348a0d"}, - {file = "fonttools-4.40.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14037c31138fbd21847ad5e5441dfdde003e0a8f3feb5812a1a21fd1c255ffbd"}, - {file = "fonttools-4.40.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:94c915f6716589f78bc00fbc14c5b8de65cfd11ee335d32504f1ef234524cb24"}, - {file = "fonttools-4.40.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37467cee0f32cada2ec08bc16c9c31f9b53ea54b2f5604bf25a1246b5f50593a"}, - {file = "fonttools-4.40.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56d4d85f5374b45b08d2f928517d1e313ea71b4847240398decd0ab3ebbca885"}, - {file = "fonttools-4.40.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8c4305b171b61040b1ee75d18f9baafe58bd3b798d1670078efe2c92436bfb63"}, - {file = "fonttools-4.40.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a954b90d1473c85a22ecf305761d9fd89da93bbd31dae86e7dea436ad2cb5dc9"}, - {file = "fonttools-4.40.0-cp38-cp38-win32.whl", hash = "sha256:1bc4c5b147be8dbc5df9cc8ac5e93ee914ad030fe2a201cc8f02f499db71011d"}, - {file = "fonttools-4.40.0-cp38-cp38-win_amd64.whl", hash = "sha256:8a917828dbfdb1cbe50cf40eeae6fbf9c41aef9e535649ed8f4982b2ef65c091"}, - {file = "fonttools-4.40.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:882983279bf39afe4e945109772c2ffad2be2c90983d6559af8b75c19845a80a"}, - {file = "fonttools-4.40.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c55f1b4109dbc3aeb496677b3e636d55ef46dc078c2a5e3f3db4e90f1c6d2907"}, - {file = "fonttools-4.40.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec468c022d09f1817c691cf884feb1030ef6f1e93e3ea6831b0d8144c06480d1"}, - {file = "fonttools-4.40.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d5adf4ba114f028fc3f5317a221fd8b0f4ef7a2e5524a2b1e0fd891b093791a"}, - {file = "fonttools-4.40.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa83b3f151bc63970f39b2b42a06097c5a22fd7ed9f7ba008e618de4503d3895"}, - {file = "fonttools-4.40.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97d95b8301b62bdece1af943b88bcb3680fd385f88346a4a899ee145913b414a"}, - {file = "fonttools-4.40.0-cp39-cp39-win32.whl", hash = "sha256:1a003608400dd1cca3e089e8c94973c6b51a4fb1ef00ff6d7641617b9242e637"}, - {file = "fonttools-4.40.0-cp39-cp39-win_amd64.whl", hash = "sha256:7961575221e3da0841c75da53833272c520000d76f7f71274dbf43370f8a1065"}, - {file = "fonttools-4.40.0-py3-none-any.whl", hash = "sha256:200729d12461e2038700d31f0d49ad5a7b55855dec7525074979a06b46f88505"}, - {file = "fonttools-4.40.0.tar.gz", hash = "sha256:337b6e83d7ee73c40ea62407f2ce03b07c3459e213b6f332b94a69923b9e1cb9"}, + {file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ed1a13a27f59d1fc1920394a7f596792e9d546c9ca5a044419dca70c37815d7c"}, + {file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9b1ce7a45978b821a06d375b83763b27a3a5e8a2e4570b3065abad240a18760"}, + {file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f720fa82a11c0f9042376fd509b5ed88dab7e3cd602eee63a1af08883b37342b"}, + {file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db55cbaea02a20b49fefbd8e9d62bd481aaabe1f2301dabc575acc6b358874fa"}, + {file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a35981d90feebeaef05e46e33e6b9e5b5e618504672ca9cd0ff96b171e4bfff"}, + {file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68a02bbe020dc22ee0540e040117535f06df9358106d3775e8817d826047f3fd"}, + {file = "fonttools-4.42.1-cp310-cp310-win32.whl", hash = "sha256:12a7c247d1b946829bfa2f331107a629ea77dc5391dfd34fdcd78efa61f354ca"}, + {file = "fonttools-4.42.1-cp310-cp310-win_amd64.whl", hash = "sha256:a398bdadb055f8de69f62b0fc70625f7cbdab436bbb31eef5816e28cab083ee8"}, + {file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:689508b918332fb40ce117131633647731d098b1b10d092234aa959b4251add5"}, + {file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e36344e48af3e3bde867a1ca54f97c308735dd8697005c2d24a86054a114a71"}, + {file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7db825c8adee96fac0692e6e1ecd858cae9affb3b4812cdb9d934a898b29e"}, + {file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113337c2d29665839b7d90b39f99b3cac731f72a0eda9306165a305c7c31d341"}, + {file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37983b6bdab42c501202500a2be3a572f50d4efe3237e0686ee9d5f794d76b35"}, + {file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6ed2662a3d9c832afa36405f8748c250be94ae5dfc5283d668308391f2102861"}, + {file = "fonttools-4.42.1-cp311-cp311-win32.whl", hash = "sha256:179737095eb98332a2744e8f12037b2977f22948cf23ff96656928923ddf560a"}, + {file = "fonttools-4.42.1-cp311-cp311-win_amd64.whl", hash = "sha256:f2b82f46917d8722e6b5eafeefb4fb585d23babd15d8246c664cd88a5bddd19c"}, + {file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:62f481ac772fd68901573956231aea3e4b1ad87b9b1089a61613a91e2b50bb9b"}, + {file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2f806990160d1ce42d287aa419df3ffc42dfefe60d473695fb048355fe0c6a0"}, + {file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db372213d39fa33af667c2aa586a0c1235e88e9c850f5dd5c8e1f17515861868"}, + {file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d18fc642fd0ac29236ff88ecfccff229ec0386090a839dd3f1162e9a7944a40"}, + {file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8708b98c278012ad267ee8a7433baeb809948855e81922878118464b274c909d"}, + {file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c95b0724a6deea2c8c5d3222191783ced0a2f09bd6d33f93e563f6f1a4b3b3a4"}, + {file = "fonttools-4.42.1-cp38-cp38-win32.whl", hash = "sha256:4aa79366e442dbca6e2c8595645a3a605d9eeabdb7a094d745ed6106816bef5d"}, + {file = "fonttools-4.42.1-cp38-cp38-win_amd64.whl", hash = "sha256:acb47f6f8680de24c1ab65ebde39dd035768e2a9b571a07c7b8da95f6c8815fd"}, + {file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb289b7a815638a7613d46bcf324c9106804725b2bb8ad913c12b6958ffc4ec"}, + {file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:53eb5091ddc8b1199330bb7b4a8a2e7995ad5d43376cadce84523d8223ef3136"}, + {file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46a0ec8adbc6ff13494eb0c9c2e643b6f009ce7320cf640de106fb614e4d4360"}, + {file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cc7d685b8eeca7ae69dc6416833fbfea61660684b7089bca666067cb2937dcf"}, + {file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:be24fcb80493b2c94eae21df70017351851652a37de514de553435b256b2f249"}, + {file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:515607ec756d7865f23070682622c49d922901943697871fc292277cf1e71967"}, + {file = "fonttools-4.42.1-cp39-cp39-win32.whl", hash = "sha256:0eb79a2da5eb6457a6f8ab904838454accc7d4cccdaff1fd2bd3a0679ea33d64"}, + {file = "fonttools-4.42.1-cp39-cp39-win_amd64.whl", hash = "sha256:7286aed4ea271df9eab8d7a9b29e507094b51397812f7ce051ecd77915a6e26b"}, + {file = "fonttools-4.42.1-py3-none-any.whl", hash = "sha256:9398f244e28e0596e2ee6024f808b06060109e33ed38dcc9bded452fd9bbb853"}, + {file = "fonttools-4.42.1.tar.gz", hash = "sha256:c391cd5af88aacaf41dd7cfb96eeedfad297b5899a39e12f4c2c3706d0a3329d"}, ] [package.extras] @@ -246,21 +227,21 @@ woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] [[package]] name = "importlib-resources" -version = "5.12.0" +version = "6.0.1" description = "Read resources from Python packages" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"}, - {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"}, + {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"}, + {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [[package]] name = "iniconfig" @@ -275,129 +256,165 @@ files = [ [[package]] name = "kiwisolver" -version = "1.4.4" +version = "1.4.5" description = "A fast implementation of the Cassowary constraint solver" optional = true python-versions = ">=3.7" files = [ - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win32.whl", hash = "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win32.whl", hash = "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win32.whl", hash = "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win32.whl", hash = "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win32.whl", hash = "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"}, - {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] [[package]] name = "matplotlib" -version = "3.7.1" +version = "3.7.2" description = "Python plotting package" optional = true python-versions = ">=3.8" files = [ - {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:95cbc13c1fc6844ab8812a525bbc237fa1470863ff3dace7352e910519e194b1"}, - {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:08308bae9e91aca1ec6fd6dda66237eef9f6294ddb17f0d0b3c863169bf82353"}, - {file = "matplotlib-3.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:544764ba51900da4639c0f983b323d288f94f65f4024dc40ecb1542d74dc0500"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56d94989191de3fcc4e002f93f7f1be5da476385dde410ddafbb70686acf00ea"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99bc9e65901bb9a7ce5e7bb24af03675cbd7c70b30ac670aa263240635999a4"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb7d248c34a341cd4c31a06fd34d64306624c8cd8d0def7abb08792a5abfd556"}, - {file = "matplotlib-3.7.1-cp310-cp310-win32.whl", hash = "sha256:ce463ce590f3825b52e9fe5c19a3c6a69fd7675a39d589e8b5fbe772272b3a24"}, - {file = "matplotlib-3.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:3d7bc90727351fb841e4d8ae620d2d86d8ed92b50473cd2b42ce9186104ecbba"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:770a205966d641627fd5cf9d3cb4b6280a716522cd36b8b284a8eb1581310f61"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f67bfdb83a8232cb7a92b869f9355d677bce24485c460b19d01970b64b2ed476"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2bf092f9210e105f414a043b92af583c98f50050559616930d884387d0772aba"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89768d84187f31717349c6bfadc0e0d8c321e8eb34522acec8a67b1236a66332"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83111e6388dec67822e2534e13b243cc644c7494a4bb60584edbff91585a83c6"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a867bf73a7eb808ef2afbca03bcdb785dae09595fbe550e1bab0cd023eba3de0"}, - {file = "matplotlib-3.7.1-cp311-cp311-win32.whl", hash = "sha256:fbdeeb58c0cf0595efe89c05c224e0a502d1aa6a8696e68a73c3efc6bc354304"}, - {file = "matplotlib-3.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:c0bd19c72ae53e6ab979f0ac6a3fafceb02d2ecafa023c5cca47acd934d10be7"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:6eb88d87cb2c49af00d3bbc33a003f89fd9f78d318848da029383bfc08ecfbfb"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:cf0e4f727534b7b1457898c4f4ae838af1ef87c359b76dcd5330fa31893a3ac7"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:46a561d23b91f30bccfd25429c3c706afe7d73a5cc64ef2dfaf2b2ac47c1a5dc"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8704726d33e9aa8a6d5215044b8d00804561971163563e6e6591f9dcf64340cc"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4cf327e98ecf08fcbb82685acaf1939d3338548620ab8dfa02828706402c34de"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:617f14ae9d53292ece33f45cba8503494ee199a75b44de7717964f70637a36aa"}, - {file = "matplotlib-3.7.1-cp38-cp38-win32.whl", hash = "sha256:7c9a4b2da6fac77bcc41b1ea95fadb314e92508bf5493ceff058e727e7ecf5b0"}, - {file = "matplotlib-3.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:14645aad967684e92fc349493fa10c08a6da514b3d03a5931a1bac26e6792bd1"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:81a6b377ea444336538638d31fdb39af6be1a043ca5e343fe18d0f17e098770b"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:28506a03bd7f3fe59cd3cd4ceb2a8d8a2b1db41afede01f66c42561b9be7b4b7"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c587963b85ce41e0a8af53b9b2de8dddbf5ece4c34553f7bd9d066148dc719c"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bf26ade3ff0f27668989d98c8435ce9327d24cffb7f07d24ef609e33d582439"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:def58098f96a05f90af7e92fd127d21a287068202aa43b2a93476170ebd99e87"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f883a22a56a84dba3b588696a2b8a1ab0d2c3d41be53264115c71b0a942d8fdb"}, - {file = "matplotlib-3.7.1-cp39-cp39-win32.whl", hash = "sha256:4f99e1b234c30c1e9714610eb0c6d2f11809c9c78c984a613ae539ea2ad2eb4b"}, - {file = "matplotlib-3.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:3ba2af245e36990facf67fde840a760128ddd71210b2ab6406e640188d69d136"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3032884084f541163f295db8a6536e0abb0db464008fadca6c98aaf84ccf4717"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a2cb34336110e0ed8bb4f650e817eed61fa064acbefeb3591f1b33e3a84fd96"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b867e2f952ed592237a1828f027d332d8ee219ad722345b79a001f49df0936eb"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:57bfb8c8ea253be947ccb2bc2d1bb3862c2bccc662ad1b4626e1f5e004557042"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:438196cdf5dc8d39b50a45cb6e3f6274edbcf2254f85fa9b895bf85851c3a613"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21e9cff1a58d42e74d01153360de92b326708fb205250150018a52c70f43c290"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75d4725d70b7c03e082bbb8a34639ede17f333d7247f56caceb3801cb6ff703d"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:97cc368a7268141afb5690760921765ed34867ffb9655dd325ed207af85c7529"}, - {file = "matplotlib-3.7.1.tar.gz", hash = "sha256:7b73305f25eab4541bd7ee0b96d87e53ae9c9f1823be5659b806cd85786fe882"}, + {file = "matplotlib-3.7.2-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:2699f7e73a76d4c110f4f25be9d2496d6ab4f17345307738557d345f099e07de"}, + {file = "matplotlib-3.7.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a8035ba590658bae7562786c9cc6ea1a84aa49d3afab157e414c9e2ea74f496d"}, + {file = "matplotlib-3.7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f8e4a49493add46ad4a8c92f63e19d548b2b6ebbed75c6b4c7f46f57d36cdd1"}, + {file = "matplotlib-3.7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71667eb2ccca4c3537d9414b1bc00554cb7f91527c17ee4ec38027201f8f1603"}, + {file = "matplotlib-3.7.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:152ee0b569a37630d8628534c628456b28686e085d51394da6b71ef84c4da201"}, + {file = "matplotlib-3.7.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:070f8dddd1f5939e60aacb8fa08f19551f4b0140fab16a3669d5cd6e9cb28fc8"}, + {file = "matplotlib-3.7.2-cp310-cp310-win32.whl", hash = "sha256:fdbb46fad4fb47443b5b8ac76904b2e7a66556844f33370861b4788db0f8816a"}, + {file = "matplotlib-3.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:23fb1750934e5f0128f9423db27c474aa32534cec21f7b2153262b066a581fd1"}, + {file = "matplotlib-3.7.2-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:30e1409b857aa8a747c5d4f85f63a79e479835f8dffc52992ac1f3f25837b544"}, + {file = "matplotlib-3.7.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:50e0a55ec74bf2d7a0ebf50ac580a209582c2dd0f7ab51bc270f1b4a0027454e"}, + {file = "matplotlib-3.7.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ac60daa1dc83e8821eed155796b0f7888b6b916cf61d620a4ddd8200ac70cd64"}, + {file = "matplotlib-3.7.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305e3da477dc8607336ba10bac96986d6308d614706cae2efe7d3ffa60465b24"}, + {file = "matplotlib-3.7.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c308b255efb9b06b23874236ec0f10f026673ad6515f602027cc8ac7805352d"}, + {file = "matplotlib-3.7.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60c521e21031632aa0d87ca5ba0c1c05f3daacadb34c093585a0be6780f698e4"}, + {file = "matplotlib-3.7.2-cp311-cp311-win32.whl", hash = "sha256:26bede320d77e469fdf1bde212de0ec889169b04f7f1179b8930d66f82b30cbc"}, + {file = "matplotlib-3.7.2-cp311-cp311-win_amd64.whl", hash = "sha256:af4860132c8c05261a5f5f8467f1b269bf1c7c23902d75f2be57c4a7f2394b3e"}, + {file = "matplotlib-3.7.2-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:a1733b8e84e7e40a9853e505fe68cc54339f97273bdfe6f3ed980095f769ddc7"}, + {file = "matplotlib-3.7.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d9881356dc48e58910c53af82b57183879129fa30492be69058c5b0d9fddf391"}, + {file = "matplotlib-3.7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f081c03f413f59390a80b3e351cc2b2ea0205839714dbc364519bcf51f4b56ca"}, + {file = "matplotlib-3.7.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1cd120fca3407a225168238b790bd5c528f0fafde6172b140a2f3ab7a4ea63e9"}, + {file = "matplotlib-3.7.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2c1590b90aa7bd741b54c62b78de05d4186271e34e2377e0289d943b3522273"}, + {file = "matplotlib-3.7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d2ff3c984b8a569bc1383cd468fc06b70d7b59d5c2854ca39f1436ae8394117"}, + {file = "matplotlib-3.7.2-cp38-cp38-win32.whl", hash = "sha256:5dea00b62d28654b71ca92463656d80646675628d0828e08a5f3b57e12869e13"}, + {file = "matplotlib-3.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:0f506a1776ee94f9e131af1ac6efa6e5bc7cb606a3e389b0ccb6e657f60bb676"}, + {file = "matplotlib-3.7.2-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:6515e878f91894c2e4340d81f0911857998ccaf04dbc1bba781e3d89cbf70608"}, + {file = "matplotlib-3.7.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:71f7a8c6b124e904db550f5b9fe483d28b896d4135e45c4ea381ad3b8a0e3256"}, + {file = "matplotlib-3.7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12f01b92ecd518e0697da4d97d163b2b3aa55eb3eb4e2c98235b3396d7dad55f"}, + {file = "matplotlib-3.7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7e28d6396563955f7af437894a36bf2b279462239a41028323e04b85179058b"}, + {file = "matplotlib-3.7.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbcf59334ff645e6a67cd5f78b4b2cdb76384cdf587fa0d2dc85f634a72e1a3e"}, + {file = "matplotlib-3.7.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:318c89edde72ff95d8df67d82aca03861240512994a597a435a1011ba18dbc7f"}, + {file = "matplotlib-3.7.2-cp39-cp39-win32.whl", hash = "sha256:ce55289d5659b5b12b3db4dc9b7075b70cef5631e56530f14b2945e8836f2d20"}, + {file = "matplotlib-3.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:2ecb5be2b2815431c81dc115667e33da0f5a1bcf6143980d180d09a717c4a12e"}, + {file = "matplotlib-3.7.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fdcd28360dbb6203fb5219b1a5658df226ac9bebc2542a9e8f457de959d713d0"}, + {file = "matplotlib-3.7.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c3cca3e842b11b55b52c6fb8bd6a4088693829acbfcdb3e815fa9b7d5c92c1b"}, + {file = "matplotlib-3.7.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebf577c7a6744e9e1bd3fee45fc74a02710b214f94e2bde344912d85e0c9af7c"}, + {file = "matplotlib-3.7.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:936bba394682049919dda062d33435b3be211dc3dcaa011e09634f060ec878b2"}, + {file = "matplotlib-3.7.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bc221ffbc2150458b1cd71cdd9ddd5bb37962b036e41b8be258280b5b01da1dd"}, + {file = "matplotlib-3.7.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35d74ebdb3f71f112b36c2629cf32323adfbf42679e2751252acd468f5001c07"}, + {file = "matplotlib-3.7.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:717157e61b3a71d3d26ad4e1770dc85156c9af435659a25ee6407dc866cb258d"}, + {file = "matplotlib-3.7.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:20f844d6be031948148ba49605c8b96dfe7d3711d1b63592830d650622458c11"}, + {file = "matplotlib-3.7.2.tar.gz", hash = "sha256:a8cdb91dddb04436bd2f098b8fdf4b81352e68cf4d2c6756fcc414791076569b"}, ] [package.dependencies] @@ -409,7 +426,7 @@ kiwisolver = ">=1.0.1" numpy = ">=1.20" packaging = ">=20.0" pillow = ">=6.2.0" -pyparsing = ">=2.3.1" +pyparsing = ">=2.3.1,<3.1" python-dateutil = ">=2.7" [[package]] @@ -459,29 +476,31 @@ yaml = ["pyyaml"] [[package]] name = "multiprocess" -version = "0.70.14" -description = "better multiprocessing and multithreading in python" +version = "0.70.15" +description = "better multiprocessing and multithreading in Python" optional = false python-versions = ">=3.7" files = [ - {file = "multiprocess-0.70.14-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:560a27540daef4ce8b24ed3cc2496a3c670df66c96d02461a4da67473685adf3"}, - {file = "multiprocess-0.70.14-pp37-pypy37_pp73-manylinux_2_24_i686.whl", hash = "sha256:bfbbfa36f400b81d1978c940616bc77776424e5e34cb0c94974b178d727cfcd5"}, - {file = "multiprocess-0.70.14-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:89fed99553a04ec4f9067031f83a886d7fdec5952005551a896a4b6a59575bb9"}, - {file = "multiprocess-0.70.14-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:40a5e3685462079e5fdee7c6789e3ef270595e1755199f0d50685e72523e1d2a"}, - {file = "multiprocess-0.70.14-pp38-pypy38_pp73-manylinux_2_24_i686.whl", hash = "sha256:44936b2978d3f2648727b3eaeab6d7fa0bedf072dc5207bf35a96d5ee7c004cf"}, - {file = "multiprocess-0.70.14-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:e628503187b5d494bf29ffc52d3e1e57bb770ce7ce05d67c4bbdb3a0c7d3b05f"}, - {file = "multiprocess-0.70.14-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d5da0fc84aacb0e4bd69c41b31edbf71b39fe2fb32a54eaedcaea241050855c"}, - {file = "multiprocess-0.70.14-pp39-pypy39_pp73-manylinux_2_24_i686.whl", hash = "sha256:6a7b03a5b98e911a7785b9116805bd782815c5e2bd6c91c6a320f26fd3e7b7ad"}, - {file = "multiprocess-0.70.14-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:cea5bdedd10aace3c660fedeac8b087136b4366d4ee49a30f1ebf7409bce00ae"}, - {file = "multiprocess-0.70.14-py310-none-any.whl", hash = "sha256:7dc1f2f6a1d34894c8a9a013fbc807971e336e7cc3f3ff233e61b9dc679b3b5c"}, - {file = "multiprocess-0.70.14-py37-none-any.whl", hash = "sha256:93a8208ca0926d05cdbb5b9250a604c401bed677579e96c14da3090beb798193"}, - {file = "multiprocess-0.70.14-py38-none-any.whl", hash = "sha256:6725bc79666bbd29a73ca148a0fb5f4ea22eed4a8f22fce58296492a02d18a7b"}, - {file = "multiprocess-0.70.14-py39-none-any.whl", hash = "sha256:63cee628b74a2c0631ef15da5534c8aedbc10c38910b9c8b18dcd327528d1ec7"}, - {file = "multiprocess-0.70.14.tar.gz", hash = "sha256:3eddafc12f2260d27ae03fe6069b12570ab4764ab59a75e81624fac453fbf46a"}, + {file = "multiprocess-0.70.15-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:aa36c7ed16f508091438687fe9baa393a7a8e206731d321e443745e743a0d4e5"}, + {file = "multiprocess-0.70.15-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:20e024018c46d0d1602024c613007ac948f9754659e3853b0aa705e83f6931d8"}, + {file = "multiprocess-0.70.15-pp37-pypy37_pp73-manylinux_2_24_i686.whl", hash = "sha256:e576062981c91f0fe8a463c3d52506e598dfc51320a8dd8d78b987dfca91c5db"}, + {file = "multiprocess-0.70.15-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:e73f497e6696a0f5433ada2b3d599ae733b87a6e8b008e387c62ac9127add177"}, + {file = "multiprocess-0.70.15-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:73db2e7b32dcc7f9b0f075c2ffa45c90b6729d3f1805f27e88534c8d321a1be5"}, + {file = "multiprocess-0.70.15-pp38-pypy38_pp73-manylinux_2_24_i686.whl", hash = "sha256:4271647bd8a49c28ecd6eb56a7fdbd3c212c45529ad5303b40b3c65fc6928e5f"}, + {file = "multiprocess-0.70.15-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:cf981fb998d6ec3208cb14f0cf2e9e80216e834f5d51fd09ebc937c32b960902"}, + {file = "multiprocess-0.70.15-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:18f9f2c7063346d1617bd1684fdcae8d33380ae96b99427260f562e1a1228b67"}, + {file = "multiprocess-0.70.15-pp39-pypy39_pp73-manylinux_2_24_i686.whl", hash = "sha256:0eac53214d664c49a34695e5824872db4006b1a465edd7459a251809c3773370"}, + {file = "multiprocess-0.70.15-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1a51dd34096db47fb21fa2b839e615b051d51b97af9a67afbcdaa67186b44883"}, + {file = "multiprocess-0.70.15-py310-none-any.whl", hash = "sha256:7dd58e33235e83cf09d625e55cffd7b0f0eede7ee9223cdd666a87624f60c21a"}, + {file = "multiprocess-0.70.15-py311-none-any.whl", hash = "sha256:134f89053d82c9ed3b73edd3a2531eb791e602d4f4156fc92a79259590bd9670"}, + {file = "multiprocess-0.70.15-py37-none-any.whl", hash = "sha256:f7d4a1629bccb433114c3b4885f69eccc200994323c80f6feee73b0edc9199c5"}, + {file = "multiprocess-0.70.15-py38-none-any.whl", hash = "sha256:bee9afba476c91f9ebee7beeee0601face9eff67d822e893f9a893725fbd6316"}, + {file = "multiprocess-0.70.15-py39-none-any.whl", hash = "sha256:3e0953f5d52b4c76f1c973eaf8214554d146f2be5decb48e928e55c7a2d19338"}, + {file = "multiprocess-0.70.15.tar.gz", hash = "sha256:f20eed3036c0ef477b07a4177cf7c1ba520d9a2677870a4f47fe026f0cd6787e"}, ] [package.dependencies] -dill = ">=0.3.6" +dill = ">=0.3.7" [[package]] name = "mypy-extensions" @@ -494,41 +513,52 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + [[package]] name = "numpy" -version = "1.24.3" +version = "1.25.2" description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, - {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, - {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, - {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, - {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, - {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, - {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, - {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, - {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, - {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, - {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, ] [[package]] @@ -544,36 +574,36 @@ files = [ [[package]] name = "pandas" -version = "2.0.2" +version = "2.0.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = true python-versions = ">=3.8" files = [ - {file = "pandas-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ebb9f1c22ddb828e7fd017ea265a59d80461d5a79154b49a4207bd17514d122"}, - {file = "pandas-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1eb09a242184092f424b2edd06eb2b99d06dc07eeddff9929e8667d4ed44e181"}, - {file = "pandas-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7319b6e68de14e6209460f72a8d1ef13c09fb3d3ef6c37c1e65b35d50b5c145"}, - {file = "pandas-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd46bde7309088481b1cf9c58e3f0e204b9ff9e3244f441accd220dd3365ce7c"}, - {file = "pandas-2.0.2-cp310-cp310-win32.whl", hash = "sha256:51a93d422fbb1bd04b67639ba4b5368dffc26923f3ea32a275d2cc450f1d1c86"}, - {file = "pandas-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:66d00300f188fa5de73f92d5725ced162488f6dc6ad4cecfe4144ca29debe3b8"}, - {file = "pandas-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02755de164da6827764ceb3bbc5f64b35cb12394b1024fdf88704d0fa06e0e2f"}, - {file = "pandas-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0a1e0576611641acde15c2322228d138258f236d14b749ad9af498ab69089e2d"}, - {file = "pandas-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6b5f14cd24a2ed06e14255ff40fe2ea0cfaef79a8dd68069b7ace74bd6acbba"}, - {file = "pandas-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50e451932b3011b61d2961b4185382c92cc8c6ee4658dcd4f320687bb2d000ee"}, - {file = "pandas-2.0.2-cp311-cp311-win32.whl", hash = "sha256:7b21cb72958fc49ad757685db1919021d99650d7aaba676576c9e88d3889d456"}, - {file = "pandas-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:c4af689352c4fe3d75b2834933ee9d0ccdbf5d7a8a7264f0ce9524e877820c08"}, - {file = "pandas-2.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:69167693cb8f9b3fc060956a5d0a0a8dbfed5f980d9fd2c306fb5b9c855c814c"}, - {file = "pandas-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:30a89d0fec4263ccbf96f68592fd668939481854d2ff9da709d32a047689393b"}, - {file = "pandas-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a18e5c72b989ff0f7197707ceddc99828320d0ca22ab50dd1b9e37db45b010c0"}, - {file = "pandas-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7376e13d28eb16752c398ca1d36ccfe52bf7e887067af9a0474de6331dd948d2"}, - {file = "pandas-2.0.2-cp38-cp38-win32.whl", hash = "sha256:6d6d10c2142d11d40d6e6c0a190b1f89f525bcf85564707e31b0a39e3b398e08"}, - {file = "pandas-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:e69140bc2d29a8556f55445c15f5794490852af3de0f609a24003ef174528b79"}, - {file = "pandas-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b42b120458636a981077cfcfa8568c031b3e8709701315e2bfa866324a83efa8"}, - {file = "pandas-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f908a77cbeef9bbd646bd4b81214cbef9ac3dda4181d5092a4aa9797d1bc7774"}, - {file = "pandas-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:713f2f70abcdade1ddd68fc91577cb090b3544b07ceba78a12f799355a13ee44"}, - {file = "pandas-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf3f0c361a4270185baa89ec7ab92ecaa355fe783791457077473f974f654df5"}, - {file = "pandas-2.0.2-cp39-cp39-win32.whl", hash = "sha256:598e9020d85a8cdbaa1815eb325a91cfff2bb2b23c1442549b8a3668e36f0f77"}, - {file = "pandas-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:77550c8909ebc23e56a89f91b40ad01b50c42cfbfab49b3393694a50549295ea"}, - {file = "pandas-2.0.2.tar.gz", hash = "sha256:dd5476b6c3fe410ee95926873f377b856dbc4e81a9c605a0dc05aaccc6a7c6c6"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, ] [package.dependencies] @@ -587,7 +617,7 @@ pytz = ">=2020.1" tzdata = ">=2022.1" [package.extras] -all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] aws = ["s3fs (>=2021.08.0)"] clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] @@ -606,110 +636,100 @@ plot = ["matplotlib (>=3.6.1)"] postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] spss = ["pyreadstat (>=1.1.2)"] sql-other = ["SQLAlchemy (>=1.4.16)"] -test = ["hypothesis (>=6.34.2)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.6.3)"] [[package]] name = "pathos" -version = "0.3.0" +version = "0.3.1" description = "parallel graph management and execution in heterogeneous computing" optional = false python-versions = ">=3.7" files = [ - {file = "pathos-0.3.0-py3-none-any.whl", hash = "sha256:b1f5a79b1c79a594330d451832642ee5bb61dd77dc75ba9e5c72087c77e8994c"}, - {file = "pathos-0.3.0.tar.gz", hash = "sha256:24fa8db51fbd9284da8e191794097c4bb2aa3fce411090e57af6385e61b97e09"}, + {file = "pathos-0.3.1-py3-none-any.whl", hash = "sha256:b1c7145e2adcc19c7e9cac48f110ea5a63e300c1cc10c2947d4857dc97a47b46"}, + {file = "pathos-0.3.1.tar.gz", hash = "sha256:c9a088021493c5cb627d4459bba6c0533c684199e271a5dc297d62be23d74019"}, ] [package.dependencies] -dill = ">=0.3.6" -multiprocess = ">=0.70.14" -pox = ">=0.3.2" -ppft = ">=1.7.6.6" +dill = ">=0.3.7" +multiprocess = ">=0.70.15" +pox = ">=0.3.3" +ppft = ">=1.7.6.7" [[package]] name = "pathspec" -version = "0.11.1" +version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.7" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] [[package]] name = "pillow" -version = "9.5.0" +version = "10.0.0" description = "Python Imaging Library (Fork)" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, - {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, - {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, - {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, - {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, - {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, - {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, - {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, - {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, - {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, - {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, - {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, - {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, - {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, - {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, - {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, - {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891"}, + {file = "Pillow-10.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1"}, + {file = "Pillow-10.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3"}, + {file = "Pillow-10.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992"}, + {file = "Pillow-10.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485"}, + {file = "Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd"}, + {file = "Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538"}, + {file = "Pillow-10.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d"}, + {file = "Pillow-10.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f"}, + {file = "Pillow-10.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883"}, + {file = "Pillow-10.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223"}, + {file = "Pillow-10.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551"}, + {file = "Pillow-10.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5"}, + {file = "Pillow-10.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199"}, + {file = "Pillow-10.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3"}, + {file = "Pillow-10.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530"}, + {file = "Pillow-10.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86"}, + {file = "Pillow-10.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7"}, + {file = "Pillow-10.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa"}, + {file = "Pillow-10.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3"}, + {file = "Pillow-10.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3"}, + {file = "Pillow-10.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017"}, + {file = "Pillow-10.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3"}, + {file = "Pillow-10.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684"}, + {file = "Pillow-10.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3"}, + {file = "Pillow-10.0.0.tar.gz", hash = "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396"}, ] [package.extras] @@ -718,28 +738,28 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "3.5.3" +version = "3.10.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.5.3-py3-none-any.whl", hash = "sha256:0ade98a4895e87dc51d47151f7d2ec290365a585151d97b4d8d6312ed6132fed"}, - {file = "platformdirs-3.5.3.tar.gz", hash = "sha256:e48fabd87db8f3a7df7150a4a5ea22c546ee8bc39bc2473244730d4b56d2cc4e"}, + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] [package.extras] -docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, ] [package.extras] @@ -748,28 +768,28 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pox" -version = "0.3.2" +version = "0.3.3" description = "utilities for filesystem exploration and automated builds" optional = false python-versions = ">=3.7" files = [ - {file = "pox-0.3.2-py3-none-any.whl", hash = "sha256:56fe2f099ecd8a557b8948082504492de90e8598c34733c9b1fdeca8f7b6de61"}, - {file = "pox-0.3.2.tar.gz", hash = "sha256:e825225297638d6e3d49415f8cfb65407a5d15e56f2fb7fe9d9b9e3050c65ee1"}, + {file = "pox-0.3.3-py3-none-any.whl", hash = "sha256:e95febf7401918478a3c1441a3630656d9a2049803889b4f589821372889d0ce"}, + {file = "pox-0.3.3.tar.gz", hash = "sha256:e1ced66f2a0c92a58cf3646bc7ccb8b4773d40884b76f85eeda0670474871667"}, ] [[package]] name = "ppft" -version = "1.7.6.6" -description = "distributed and parallel python" +version = "1.7.6.7" +description = "distributed and parallel Python" optional = false python-versions = ">=3.7" files = [ - {file = "ppft-1.7.6.6-py3-none-any.whl", hash = "sha256:f355d2caeed8bd7c9e4a860c471f31f7e66d1ada2791ab5458ea7dca15a51e41"}, - {file = "ppft-1.7.6.6.tar.gz", hash = "sha256:f933f0404f3e808bc860745acb3b79cd4fe31ea19a20889a645f900415be60f1"}, + {file = "ppft-1.7.6.7-py3-none-any.whl", hash = "sha256:fedb1b1253729d62483f2e1f36547fd50a5fc873ffbf9b78b48cfdc727d4180c"}, + {file = "ppft-1.7.6.7.tar.gz", hash = "sha256:ab34436814e2f18238f35688fd869b2641b2d2d8dca22b8d246f6701dfc954c8"}, ] [package.extras] -dill = ["dill (>=0.3.6)"] +dill = ["dill (>=0.3.7)"] [[package]] name = "pyparsing" @@ -785,15 +805,33 @@ files = [ [package.extras] diagrams = ["jinja2", "railroad-diagrams"] +[[package]] +name = "pyright" +version = "1.1.324" +description = "Command line wrapper for pyright" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyright-1.1.324-py3-none-any.whl", hash = "sha256:0edb712afbbad474e347de12ca1bd9368aa85d3365a1c7b795012e48e6a65111"}, + {file = "pyright-1.1.324.tar.gz", hash = "sha256:0c48e3bca3d081bba0dddd0c1f075aaa965c59bba691f7b9bd9d73a98e44e0cf"}, +] + +[package.dependencies] +nodeenv = ">=1.6.0" + +[package.extras] +all = ["twine (>=3.4.1)"] +dev = ["twine (>=3.4.1)"] + [[package]] name = "pytest" -version = "7.3.2" +version = "7.4.0" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.3.2-py3-none-any.whl", hash = "sha256:cdcbd012c9312258922f8cd3f1b62a6580fdced17db6014896053d47cddf9295"}, - {file = "pytest-7.3.2.tar.gz", hash = "sha256:ee990a3cc55ba808b80795a79944756f315c67c12b56abd3ac993a7b8c17030b"}, + {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, + {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, ] [package.dependencies] @@ -809,13 +847,13 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-mock" -version = "3.10.0" +version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, - {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, + {file = "pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f"}, + {file = "pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39"}, ] [package.dependencies] @@ -877,42 +915,62 @@ files = [ [[package]] name = "scipy" -version = "1.10.1" +version = "1.11.2" description = "Fundamental algorithms for scientific computing in Python" optional = false -python-versions = "<3.12,>=3.8" -files = [ - {file = "scipy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019"}, - {file = "scipy-1.10.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2"}, - {file = "scipy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d"}, - {file = "scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f"}, - {file = "scipy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601"}, - {file = "scipy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea"}, - {file = "scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5"}, +python-versions = "<3.13,>=3.9" +files = [ + {file = "scipy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2b997a5369e2d30c97995dcb29d638701f8000d04df01b8e947f206e5d0ac788"}, + {file = "scipy-1.11.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:95763fbda1206bec41157582bea482f50eb3702c85fffcf6d24394b071c0e87a"}, + {file = "scipy-1.11.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e367904a0fec76433bf3fbf3e85bf60dae8e9e585ffd21898ab1085a29a04d16"}, + {file = "scipy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d690e1ca993c8f7ede6d22e5637541217fc6a4d3f78b3672a6fe454dbb7eb9a7"}, + {file = "scipy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d2b813bfbe8dec6a75164523de650bad41f4405d35b0fa24c2c28ae07fcefb20"}, + {file = "scipy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:afdb0d983f6135d50770dd979df50bf1c7f58b5b33e0eb8cf5c73c70600eae1d"}, + {file = "scipy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d9886f44ef8c9e776cb7527fb01455bf4f4a46c455c4682edc2c2cc8cd78562"}, + {file = "scipy-1.11.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1342ca385c673208f32472830c10110a9dcd053cf0c4b7d4cd7026d0335a6c1d"}, + {file = "scipy-1.11.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b133f237bd8ba73bad51bc12eb4f2d84cbec999753bf25ba58235e9fc2096d80"}, + {file = "scipy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aeb87661de987f8ec56fa6950863994cd427209158255a389fc5aea51fa7055"}, + {file = "scipy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90d3b1364e751d8214e325c371f0ee0dd38419268bf4888b2ae1040a6b266b2a"}, + {file = "scipy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:f73102f769ee06041a3aa26b5841359b1a93cc364ce45609657751795e8f4a4a"}, + {file = "scipy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa4909c6c20c3d91480533cddbc0e7c6d849e7d9ded692918c76ce5964997898"}, + {file = "scipy-1.11.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ac74b1512d38718fb6a491c439aa7b3605b96b1ed3be6599c17d49d6c60fca18"}, + {file = "scipy-1.11.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8425fa963a32936c9773ee3ce44a765d8ff67eed5f4ac81dc1e4a819a238ee9"}, + {file = "scipy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:542a757e2a6ec409e71df3d8fd20127afbbacb1c07990cb23c5870c13953d899"}, + {file = "scipy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ea932570b1c2a30edafca922345854ff2cd20d43cd9123b6dacfdecebfc1a80b"}, + {file = "scipy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:4447ad057d7597476f9862ecbd9285bbf13ba9d73ce25acfa4e4b11c6801b4c9"}, + {file = "scipy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b0620240ef445b5ddde52460e6bc3483b7c9c750275369379e5f609a1050911c"}, + {file = "scipy-1.11.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:f28f1f6cfeb48339c192efc6275749b2a25a7e49c4d8369a28b6591da02fbc9a"}, + {file = "scipy-1.11.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:214cdf04bbae7a54784f8431f976704ed607c4bc69ba0d5d5d6a9df84374df76"}, + {file = "scipy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10eb6af2f751aa3424762948e5352f707b0dece77288206f227864ddf675aca0"}, + {file = "scipy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0f3261f14b767b316d7137c66cc4f33a80ea05841b9c87ad83a726205b901423"}, + {file = "scipy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:2c91cf049ffb5575917f2a01da1da082fd24ed48120d08a6e7297dfcac771dcd"}, + {file = "scipy-1.11.2.tar.gz", hash = "sha256:b29318a5e39bd200ca4381d80b065cdf3076c7d7281c5e36569e99273867f61d"}, ] [package.dependencies] -numpy = ">=1.19.5,<1.27.0" +numpy = ">=1.21.6,<1.28.0" [package.extras] -dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", "rich-click", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "setuptools" +version = "68.1.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"}, + {file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + [[package]] name = "six" version = "1.16.0" @@ -937,33 +995,33 @@ files = [ [[package]] name = "tqdm" -version = "4.65.0" +version = "4.66.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"}, - {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"}, + {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, + {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["py-make (>=0.1.0)", "twine", "wheel"] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] [[package]] name = "typing-extensions" -version = "4.6.3" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, ] [[package]] @@ -979,18 +1037,18 @@ files = [ [[package]] name = "zipp" -version = "3.15.0" +version = "3.16.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] all = [] @@ -1000,4 +1058,4 @@ plots = ["matplotlib"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "c08e85917917d22c840e121db13bdcdf32be455720eec35eee6299d378d645e0" +content-hash = "2aee5b08b431613a7a4b5fbee9ee4f50af7694c90b5eb2176942b5eecb196a38" diff --git a/pyproject.toml b/pyproject.toml index e62003e..b4c7b3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ ruff = "^0.0.272" pytest = "^7.3.2" pytest-mock = "^3.10.0" black = "^23.3.0" +pyright = "^1.1.324" [tool.poetry.extras] plots = ["matplotlib"] diff --git a/squigglepy/bayes.py b/squigglepy/bayes.py index 415f29a..33aade2 100644 --- a/squigglepy/bayes.py +++ b/squigglepy/bayes.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import time import math @@ -7,15 +9,24 @@ import pathos.multiprocessing as mp from datetime import datetime +from typing import Callable, Optional, Union -from .distributions import BetaDistribution, NormalDistribution, norm, beta, mixture -from .utils import _core_cuts, _init_tqdm, _tick_tqdm, _flush_tqdm +from .distributions import ( + BaseDistribution, + MixtureDistribution, + BetaDistribution, + NormalDistribution, + norm, + beta, + mixture, +) +from .utils import Weights, _core_cuts, _init_tqdm, _tick_tqdm, _flush_tqdm _squigglepy_internal_bayesnet_caches = {} -def simple_bayes(likelihood_h, likelihood_not_h, prior): +def simple_bayes(likelihood_h: float, likelihood_not_h: float, prior: float) -> float: """ Calculate Bayes rule. @@ -50,22 +61,23 @@ def simple_bayes(likelihood_h, likelihood_not_h, prior): return (likelihood_h * prior) / (likelihood_h * prior + likelihood_not_h * (1 - prior)) +# TODO: output type for bayesnet def bayesnet( - event_fn=None, - n=1, - find=None, - conditional_on=None, - reduce_fn=None, - raw=False, - memcache=True, - memcache_load=True, - memcache_save=True, - reload_cache=False, - dump_cache_file=None, - load_cache_file=None, - cache_file_primary=False, - verbose=False, - cores=1, + event_fn: Optional[Callable] = None, + n: int = 1, + find: Optional[Callable] = None, + conditional_on: Optional[Callable] = None, + reduce_fn: Optional[Callable] = None, + raw: bool = False, + memcache: bool = True, + memcache_load: bool = True, + memcache_save: bool = True, + reload_cache: bool = False, + dump_cache_file: str = "", + load_cache_file: str = "", + cache_file_primary: bool = False, + verbose: bool = False, + cores: int = 1, ): """ Calculate a Bayesian network. @@ -99,10 +111,10 @@ def bayesnet( is True. Cache will be matched based on the ``event_fn``. Default ``True``. reload_cache : bool If True, any existing cache will be ignored and recalculated. Default ``False``. - dump_cache_file : str or None + dump_cache_file : str If present, will write out the cache to a binary file with this path with ``.sqlcache`` appended to the file name. - load_cache_file : str or None + load_cache_file : str If present, will first attempt to load and use a cache from a file with this path with ``.sqlcache`` appended to the file name. cache_file_primary : bool @@ -141,7 +153,7 @@ def bayesnet( >> n=1*M) 0.07723995880535531 """ - events = None + events = {} if memcache is True: memcache_load = True memcache_save = True @@ -149,12 +161,10 @@ def bayesnet( memcache_load = False memcache_save = False has_in_mem_cache = event_fn in _squigglepy_internal_bayesnet_caches - cache_path = load_cache_file + ".sqcache" if load_cache_file else None - has_file_cache = os.path.exists(cache_path) if load_cache_file else False - - if load_cache_file or dump_cache_file or cores > 1: - encoder = msgspec.msgpack.Encoder() - decoder = msgspec.msgpack.Decoder() + cache_path = load_cache_file + ".sqcache" if load_cache_file != "" else "" + has_file_cache = os.path.exists(cache_path) if load_cache_file != "" else False + encoder = msgspec.msgpack.Encoder() + decoder = msgspec.msgpack.Decoder() if load_cache_file and not has_file_cache and verbose: print("Warning: cache file `{}.sqcache` not found.".format(load_cache_file)) @@ -172,21 +182,29 @@ def bayesnet( events = _squigglepy_internal_bayesnet_caches.get(event_fn) if events: - if events["metadata"]["n"] < n: - raise ValueError( - ("insufficient samples - {} results cached but " + "requested {}").format( - events["metadata"]["n"], n + n_ = events.get("metadata") + if n_ is not None: + n_ = n_.get("n") + if n_ is None: + raise ValueError("events is malformed") + elif n_ < n: + raise ValueError( + ("insufficient samples - {} results cached but " + "requested {}").format( + events["metadata"]["n"], n + ) ) - ) + else: + raise ValueError("events is malformed") - events = events["events"] + events = events.get("events", []) if verbose: print("...Loaded") elif verbose: print("Reloading cache...") - if events is None: + assert events is not None + if len(events) < 1: if event_fn is None: return None @@ -265,6 +283,7 @@ def multicore_event_fn(core, total_cores=1, verbose=False): if verbose: print("...Cached!") + assert events is not None if conditional_on is not None: if verbose: print("Filtering conditional...") @@ -300,7 +319,11 @@ def multicore_event_fn(core, total_cores=1, verbose=False): return events -def update(prior, evidence, evidence_weight=1): +def update( + prior: Union[NormalDistribution, BetaDistribution], + evidence: Union[NormalDistribution, BetaDistribution], + evidence_weight: float = 1, +) -> BaseDistribution: """ Update a distribution. @@ -358,7 +381,12 @@ def update(prior, evidence, evidence_weight=1): raise ValueError("type `{}` not supported.".format(prior.__class__.__name__)) -def average(prior, evidence, weights=[0.5, 0.5], relative_weights=None): +def average( + prior: BaseDistribution, + evidence: BaseDistribution, + weights: Optional[Weights] = [0.5, 0.5], + relative_weights: Optional[Weights] = None, +) -> MixtureDistribution: """ Average two distributions. @@ -378,14 +406,16 @@ def average(prior, evidence, weights=[0.5, 0.5], relative_weights=None): Returns ------- - Distribution + MixtureDistribution A mixture distribution that accords weights to ``prior`` and ``evidence``. Examples -------- - >> prior = sq.norm(1,5) - >> evidence = sq.norm(2,3) + >> prior = sq.norm(1, 5) + >> evidence = sq.norm(2, 3) >> bayes.average(prior, evidence) mixture + - 0.5 weight on norm(mean=3.0, sd=1.22) + - 0.5 weight on norm(mean=2.5, sd=0.3) """ return mixture(dists=[prior, evidence], weights=weights, relative_weights=relative_weights) diff --git a/squigglepy/distributions.py b/squigglepy/distributions.py index 6a1bc22..7846467 100644 --- a/squigglepy/distributions.py +++ b/squigglepy/distributions.py @@ -1,74 +1,50 @@ -import operator +from __future__ import annotations +from functools import partial +import functools + import math +import operator +from typing import Any, Callable, Optional, TypeAlias, TypeVar, Union + import numpy as np from scipy import stats -from .utils import _process_weights_values, _is_numpy, is_dist, _round +from .utils import ( + FloatArray, + Integer, + Weights, + _is_numpy, + _process_weights_values, + _round, + is_dist, + Number, + Float, +) from .version import __version__ +from typing import overload + +from numpy import ufunc, vectorize + class BaseDistribution: - def __init__(self): - self.x = None - self.y = None - self.n = None - self.p = None - self.t = None - self.a = None - self.b = None - self.shape = None - self.scale = None - self.credibility = None - self.mean = None - self.sd = None - self.left = None - self.mode = None - self.right = None - self.fn = None - self.fn_str = None - self.lclip = None - self.rclip = None - self.lam = None - self.df = None - self.items = None - self.dists = None - self.weights = None - self._version = __version__ + def __init__(self) -> None: + self.lclip: Optional[Number] = None + self.rclip: Optional[Number] = None + self._version: str = __version__ def __str__(self): return " base" - def __repr__(self): + def __repr__(self) -> str: return str(self) - def plot(self, num_samples=None, bins=None): - """ - Plot a histogram of the samples. - - Parameters - ---------- - num_samples : int - The number of samples to draw for plotting. Defaults to 1000 if not set. - bins : int - The number of bins to plot. Defaults to 200 if not set. - - Examples - -------- - >>> sq.norm(5, 10).plot() - """ - from matplotlib import pyplot as plt - - num_samples = 1000 if num_samples is None else num_samples - bins = 200 if bins is None else bins - - samples = self @ num_samples - plt.hist(samples, bins=bins) - plt.show() +OperationTarget: TypeAlias = Union[BaseDistribution, Number] class OperableDistribution(BaseDistribution): - def __init__(self): + def __init__(self) -> None: super().__init__() def __invert__(self): @@ -76,7 +52,7 @@ def __invert__(self): return sample(self) - def __matmul__(self, n): + def __matmul__(self, n: int): try: n = int(n) except ValueError: @@ -85,7 +61,9 @@ def __matmul__(self, n): return sample(self, n=n) - def __rshift__(self, fn): + def __rshift__( + self, fn: Union[Callable[[OperableDistribution], ComplexDistribution], ComplexDistribution] + ) -> Union[ComplexDistribution, int]: if callable(fn): return fn(self) elif isinstance(fn, ComplexDistribution): @@ -93,69 +71,101 @@ def __rshift__(self, fn): else: raise ValueError - def __rmatmul__(self, n): + def __rmatmul__(self, n: int): return self.__matmul__(n) - def __gt__(self, dist): + def __gt__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.gt, ">") - def __ge__(self, dist): + def __ge__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.ge, ">=") - def __lt__(self, dist): + def __lt__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.lt, "<") - def __le__(self, dist): + def __le__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.le, "<=") - def __eq__(self, dist): + def __eq__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.le, "==") - def __ne__(self, dist): + def __ne__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.le, "!=") - def __neg__(self): + def __neg__(self) -> "ComplexDistribution": return ComplexDistribution(self, None, operator.neg, "-") - def __add__(self, dist): + def __add__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.add, "+") - def __radd__(self, dist): + def __radd__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(dist, self, operator.add, "+") - def __sub__(self, dist): + def __sub__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.sub, "-") - def __rsub__(self, dist): + def __rsub__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(dist, self, operator.sub, "-") - def __mul__(self, dist): + def __mul__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.mul, "*") - def __rmul__(self, dist): + def __rmul__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(dist, self, operator.mul, "*") - def __truediv__(self, dist): + def __truediv__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.truediv, "/") - def __rtruediv__(self, dist): + def __rtruediv__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(dist, self, operator.truediv, "/") - def __floordiv__(self, dist): + def __floordiv__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.floordiv, "//") - def __rfloordiv__(self, dist): + def __rfloordiv__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(dist, self, operator.floordiv, "//") - def __pow__(self, dist): + def __pow__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(self, dist, operator.pow, "**") - def __rpow__(self, dist): + def __rpow__(self, dist: OperationTarget) -> "ComplexDistribution": return ComplexDistribution(dist, self, operator.pow, "**") + def plot(self, num_samples: int = 1000, bins: int = 200) -> None: + """ + Plot a histogram of the samples. + + Parameters + ---------- + num_samples : int + The number of samples to draw for plotting. Defaults to 1000 if not set. + bins : int + The number of bins to plot. Defaults to 200 if not set. + + Examples + -------- + >>> sq.norm(5, 10).plot() + """ + from matplotlib import pyplot as plt + + num_samples = 1000 if num_samples is None else num_samples + bins = 200 if bins is None else bins + + samples = self @ num_samples + + plt.hist(samples, bins=bins) + plt.show() + class ComplexDistribution(OperableDistribution): - def __init__(self, left, right=None, fn=operator.add, fn_str="+", infix=True): + def __init__( + self, + left: Any, + right: Optional[Any] = None, + fn: UFunction = operator.add, + fn_str: str = "+", + infix: bool = True, + ) -> None: super().__init__() self.left = left self.right = right @@ -163,36 +173,46 @@ def __init__(self, left, right=None, fn=operator.add, fn_str="+", infix=True): self.fn_str = fn_str self.infix = infix - def __str__(self): - if self.right is None and self.infix: + def __str__(self) -> str: + left, right, infix = self.left, self.right, self.infix + if isinstance(self.fn, functools.partial) and right is None and not infix: + # This prints the arguments when a partial function is being used + # this is useful for things like round, lclip, rclip, etc. + right = "".join(str(arg) for arg in self.fn.args) + for i, (k, v) in enumerate(self.fn.keywords.items()): + if i == 0 and right: + right += ", " + right += "{}={}".format(k, v) + + if right is None and infix: if self.fn_str == "-": out = " {}{}" else: out = " {} {}" - out = out.format(self.fn_str, str(self.left).replace(" ", "")) - elif self.right is None and not self.infix: + out = out.format(self.fn_str, str(left).replace(" ", "")) + elif right is None and not infix: out = " {}({})".format( - self.fn_str, str(self.left).replace(" ", "") + self.fn_str, str(left).replace(" ", "") ) - elif self.right is not None and self.infix: + elif right is not None and infix: out = " {} {} {}".format( - str(self.left).replace(" ", ""), + str(left).replace(" ", ""), self.fn_str, - str(self.right).replace(" ", ""), + str(right).replace(" ", ""), ) - elif self.right is not None and not self.infix: + elif right is not None and not infix: out = " {}({}, {})" out = out.format( self.fn_str, - str(self.left).replace(" ", ""), - str(self.right).replace(" ", ""), + str(left).replace(" ", ""), + str(right).replace(" ", ""), ) else: - raise ValueError + raise ValueError("The complex distribution is not properly defined") return out -def _get_fname(f, name): +def _get_fname(f: UFunction, name: Optional[str]) -> str: if name is None: if isinstance(f, np.vectorize): name = f.pyfunc.__name__ @@ -201,7 +221,21 @@ def _get_fname(f, name): return name -def dist_fn(dist1, dist2=None, fn=None, name=None): +# These are the types of functions that can be used in the dist_fn function +# We allow booleans for the case of the comparison operators +UScalar = TypeVar("UScalar", bound=Union[Number, bool]) +UFunction = Union[ + Callable[[UScalar], UScalar], + Callable[[UScalar, UScalar], UScalar], + ufunc, + vectorize, +] + + +@overload +def dist_fn( + dist: OperableDistribution, fn: Union[UFunction, list[UFunction]], name: Optional[str] = None +) -> ComplexDistribution: """ Initialize a distribution that has a custom function applied to the result. @@ -209,24 +243,19 @@ def dist_fn(dist1, dist2=None, fn=None, name=None): Parameters ---------- - dist1 : Distribution or function or list - Typically, the distribution to apply the function to. Could also be a function - or list of functions if ``dist_fn`` is being used in a pipe. - dist2 : Distribution or function or list or None - Typically, the second distribution to apply the function to if the function takes - two arguments. Could also be a function or list of functions if ``dist_fn`` is - being used in a pipe. - fn : function or None - The function to apply to the distribution(s). + dist : Distribution or function or list + The distribution to apply the function to. + fn : function or list of functions + The function(s) to apply to the distribution. name : str or None By default, ``fn.__name__`` will be used to name the function. But you can pass a custom name. Returns ------- - ComplexDistribution or function - This will be a lazy evaluation of the desired function that will then be calculated - when it is sampled. + ComplexDistribution + This distribution performs a lazy evaluation of the desired function that + will be calculated when it is sampled. Examples -------- @@ -234,42 +263,309 @@ def dist_fn(dist1, dist2=None, fn=None, name=None): >>> return x * 2 >>> dist_fn(norm(0, 1), double) double(norm(mean=0.5, sd=0.3)) + """ + # A unary function (or functions) was passed in + # The function is applied to each sample + ... + + +@overload +def dist_fn( + dist1: OperableDistribution, + dist2: OperableDistribution, + fn: Union[UFunction, list[UFunction]], + name: Optional[str] = None, +) -> ComplexDistribution: + """ + Apply a binary function to a pair of distributions. + + The function won't be applied until the returned distribution is sampled. + + Parameters + ---------- + dist1 : Distribution + The first distribution to apply the function to. + dist2 : Distribution + The second distribution to apply the function to. + fn : function or list of functions + The function(s) to apply to the distributions. Must take two arguments and + return a single value. + name : str or None + By default, ``fn.__name__`` will be used to name the function. But you can pass + a custom name. + + Returns + ------- + ComplexDistribution + This distribution performs a lazy evaluation of the desired function that + will be calculated when it is sampled. + + Examples + -------- + >>> def add(x, y): + >>> return x + y + >>> dist_fn(norm(0, 1), norm(1, 2), add) + add(norm(mean=0.5, sd=0.3), norm(mean=1.5, sd=0.3)) + """ + # A binary function (or function) passed was passed in + # The function is applied to pairs of samples, and returns the combined sample + ... + + +@overload +def dist_fn( + fn: Union[UFunction, list[UFunction]], + name: Optional[str] = None, +) -> Callable[[OperableDistribution], ComplexDistribution]: + """ + Lazily applies the given function to the previous distribution in a pipe. (Or, equivalently, + produces a partial of the function with the previous distribution as the first argument.) + + Parameters + ---------- + fn : function or list of functions + The function(s) to apply to the distributions. Each must take one argument and + return a single value. + name : str or None + By default, ``fn.__name__`` will be used to name the function. But you can pass + a custom name. + + Returns + ------- + function + A function that takes a distribution and returns a distribution. The returned distribution + performs a lazy evaluation of the desired function whenever it is sampled. + + Examples + -------- + >>> def double(x): + >>> return x * 2 >>> norm(0, 1) >> dist_fn(double) double(norm(mean=0.5, sd=0.3)) """ - if isinstance(dist1, list) and callable(dist1[0]) and dist2 is None and fn is None: - fn = dist1 + # Unary case of the pipe version + ... + + +@overload +def dist_fn( + dist: OperableDistribution, + fn: Union[UFunction, list[UFunction]], + name: Optional[str] = None, +) -> Callable[[OperableDistribution], ComplexDistribution]: + """ + Lazily applies the given binary function to the previous distribution in a pipe, with the given + distribution as the second argument. (Or, equivalently, produces a partial of the function with + the previous distribution passed as the second argument.) - def out_fn(d): - out = d - for f in fn: - out = ComplexDistribution(out, None, fn=f, fn_str=_get_fname(f, name), infix=False) - return out + Parameters + ---------- + dist : Distribution + The distribution to apply the function to. + fn : function or list of functions + The function(s) to apply to the distributions. Each must take two arguments and + return a single value. + name : str or None + By default, ``fn.__name__`` will be used to name the function. But you can pass + a custom name. + + Returns + ------- + function + A function that takes a distribution and returns a distribution. The returned distribution + performs a lazy evaluation of the desired function whenever it is sampled. + + Examples + -------- + >>> def add(x, y): + >>> return x + y + >>> norm(0, 1) >> dist_fn(norm(1, 2), add) + add(norm(mean=0.5, sd=0.3), norm(mean=1.5, sd=0.3)) + """ + # Binary case of the pipe version + ... + + +def dist_fn( + *args, + **kwargs, +) -> Union[ComplexDistribution, Callable[[OperableDistribution], ComplexDistribution]]: + """ + This is the dispatcher for the `dist_fn` function. It handles the different cases + of the function, which are then passed to the `_dist_fn` function to actually + create the respective distribution or partial function. - return out_fn + This handles both unary and binary functions, as well as the pipe versions of each. + The pipe version simply creates a partial of the inner `_dist_fn` function, and returns + that partial. + """ + # Get the arguments + p1: Union[OperableDistribution, Union[UFunction, list[UFunction]]] = ( + args[0] if len(args) > 0 else kwargs.get("dist1", None) + ) + p2: Optional[Union[OperableDistribution, Union[UFunction, list[UFunction]]]] = ( + args[1] if len(args) > 1 else kwargs.get("dist2", None) + ) + p3: Union[UFunction, list[UFunction]] = args[2] if len(args) > 2 else kwargs.get("fn", None) + name: str = kwargs.get("name", None) - if callable(dist1) and dist2 is None and fn is None: - return lambda d: dist_fn(d, fn=dist1) + # Dispatch to the proper form of the function + if ( + (isinstance(p1, OperableDistribution)) + and (not isinstance(p2, OperableDistribution) and p2 is not None) + and (p3 is None) + ): + # Simple case, unary function + p2 = p2 if isinstance(p2, list) else [p2] + return _dist_fn(dist1=p1, fn_list=p2, name=name) + elif ( + isinstance(p1, OperableDistribution) + and isinstance(p2, OperableDistribution) + and (p3 is not None) + ): + # Simple case, binary function + p3 = p3 if isinstance(p3, list) else [p3] + return _dist_fn(dist1=p1, dist2=p2, fn_list=p3, name=name) + elif p1 is not None and not isinstance(p1, OperableDistribution) and p2 is None and p3 is None: + # Pipe case, unary function + p1 = p1 if isinstance(p1, list) else [p1] + return lambda d: _dist_fn(dist1=d, fn_list=p1, name=name) + elif ( + p1 is not None + and not isinstance(p1, OperableDistribution) + and isinstance(p2, OperableDistribution) + and p3 is None + ): + p1 = p1 if isinstance(p1, list) else [p1] + # Pipe case, binary function + return lambda d: _dist_fn(dist1=d, dist2=p2, fn_list=p1, name=name) + else: + raise ValueError("Invalid arguments to dist_fn") - if isinstance(dist2, list) and callable(dist2[0]) and fn is None: - fn = dist2 - dist2 = None - if callable(dist2) and fn is None: - fn = dist2 - dist2 = None +def _dist_fn( + dist1: Optional[OperableDistribution] = None, + dist2: Optional[OperableDistribution] = None, + fn_list: Optional[list[UFunction]] = None, + name: Optional[str] = None, +) -> ComplexDistribution: + """ + This is the actual function that creates the complex distribution + whenever `dist_fn` is used. It handles the simple one function case, + as well as the case where multiple functions are being composed together. + """ + assert dist1 is not None and fn_list is not None + assert all(callable(f) for f in fn_list), "All functions provided must be callable" + assert len(fn_list) > 0, "Must provide at least one function to compose" - if not isinstance(fn, list): - fn = [fn] + if len(fn_list) == 1: + return ComplexDistribution( + dist1, dist2, fn=fn_list[0], fn_str=_get_fname(fn_list[0], name), infix=False + ) + else: + assert ( + dist2 is None + ), "Cannot provide a second distribution when composing multiple functions" - out = dist1 - for f in fn: - out = ComplexDistribution(out, dist2, fn=f, fn_str=_get_fname(f, name), infix=False) + out = ComplexDistribution( + dist1, None, fn=fn_list[0], fn_str=_get_fname(fn_list[0], name), infix=False + ) + for f in fn_list[1:]: + out = ComplexDistribution(out, None, fn=f, fn_str=_get_fname(f, name), infix=False) - return out + return out -def dist_max(dist1, dist2=None): +# def _dist_fn( +# dist1: Union[OperableDistribution, Callable, list[Callable]], +# dist2: Optional[Union[OperableDistribution, Callable, list[Callable]]] = None, +# fn: Optional[UFunction] = None, +# name: Optional[str] = None, +# ) -> Union[ComplexDistribution, Callable]: +# """ +# Initialize a distribution that has a custom function applied to the result. + +# The function won't be applied until the distribution is sampled. + +# Parameters +# ---------- +# dist1 : Distribution or function or list +# Typically, the distribution to apply the function to. Could also be a function +# or list of functions if ``dist_fn`` is being used in a pipe. +# dist2 : Distribution or function or list or None +# Typically, the second distribution to apply the function to if the function takes +# two arguments. Could also be a function or list of functions if ``dist_fn`` is +# being used in a pipe. +# fn : function or None +# The function to apply to the distribution(s). +# name : str or None +# By default, ``fn.__name__`` will be used to name the function. But you can pass +# a custom name. + +# Returns +# ------- +# ComplexDistribution or function +# This will be a lazy evaluation of the desired function that will then be calculated +# when it is sampled. + +# Examples +# -------- +# >>> def double(x): +# >>> return x * 2 +# >>> dist_fn(norm(0, 1), double) +# double(norm(mean=0.5, sd=0.3)) +# >>> norm(0, 1) >> dist_fn(double) +# double(norm(mean=0.5, sd=0.3)) +# """ + +# p1 = dist1 if isinstance(dist1, list) else [dist1] +# assert (p1 is None) or all(callable(f) for f in p1) +# p2 = dist2 if isinstance(dist2, list) else [dist2] +# assert (p2 is None) or all(callable(f) for f in p2) +# p3 = fn if isinstance(fn, list) else [fn] +# assert (p3 is None) or all(callable(f) for f in p3) + + +# if (p1 is not None and p2 is None and p3 is None) and (not ): +# # This is a simple pipe, +# # we compose the functions and return a partial of the composition + +# def out_fn(d): +# out = d +# for fn in p1: +# out = ComplexDistribution( +# out, None, fn=fn, fn_str=_get_fname(fn, name), infix=False +# ) +# return out + +# return out_fn + + +# if callable(dist1) and dist2 is None and fn is None: +# return lambda d: dist_fn(d, fn=dist1) + +# # These are cases where we're just applying function(s) to a distribution +# if isinstance(dist2, list) and callable(dist2[0]) and fn is None: +# # The user provided the functions through dist2 +# assert all(callable(f) for f in dist2) +# fn_list = dist2 + +# if callable(dist2) and fn is None: +# fn_list = [dist2] + +# if fn is not None and callable(fn): +# fn_list = [fn] + +# out = dist1 +# for f in fn_list: +# out = ComplexDistribution(out, dist2, fn=f, fn_str=_get_fname(f, name), infix=False) + +# return out + + +def dist_max( + dist1: OperableDistribution, dist2: Optional[OperableDistribution] = None +) -> Union[Callable, ComplexDistribution]: """ Initialize the calculation of the maximum value of two distributions. @@ -295,11 +591,16 @@ def dist_max(dist1, dist2=None): """ if is_dist(dist1) and dist2 is None: return lambda d: dist_fn(d, dist1, np.maximum, name="max") - else: + elif dist2 is not None: return dist_fn(dist1, dist2, np.maximum, name="max") + else: + raise ValueError("Invalid arguments to dist_max") -def dist_min(dist1, dist2=None): +def dist_min( + dist1: OperableDistribution, + dist2: Optional[OperableDistribution] = None, +) -> Union[Callable, ComplexDistribution]: """ Initialize the calculation of the minimum value of two distributions. @@ -324,11 +625,15 @@ def dist_min(dist1, dist2=None): """ if is_dist(dist1) and dist2 is None: return lambda d: dist_fn(d, dist1, np.minimum, name="min") - else: + elif dist2 is not None: return dist_fn(dist1, dist2, np.minimum, name="min") + else: + raise ValueError("Invalid arguments to dist_min") -def dist_round(dist1, digits=0): +def dist_round( + dist: OperableDistribution, digits: int = 0 +) -> Union[Callable, ComplexDistribution]: """ Initialize the rounding of the output of the distribution. @@ -351,13 +656,15 @@ def dist_round(dist1, digits=0): >>> dist_round(norm(0, 1)) round(norm(mean=0.5, sd=0.3), 0) """ - if isinstance(dist1, int) and digits == 0: - return lambda d: dist_round(d, digits=dist1) + if isinstance(dist, int) and digits == 0: + return lambda d: dist_round(d, digits=dist) else: - return dist_fn(dist1, digits, _round, name="round") + return dist_fn(dist, partial(_round, digits=digits), name="round") -def dist_ceil(dist1): +def dist_ceil( + dist1: OperableDistribution, +) -> Union[ComplexDistribution, Callable]: """ Initialize the ceiling rounding of the output of the distribution. @@ -370,7 +677,7 @@ def dist_ceil(dist1): Returns ------- - ComplexDistribution or function + ComplexDistribution This will be a lazy evaluation of the desired function that will then be calculated Examples @@ -378,10 +685,10 @@ def dist_ceil(dist1): >>> dist_ceil(norm(0, 1)) ceil(norm(mean=0.5, sd=0.3)) """ - return dist_fn(dist1, None, np.ceil) + return dist_fn(dist1, np.ceil) -def dist_floor(dist1): +def dist_floor(dist1: OperableDistribution): """ Initialize the floor rounding of the output of the distribution. @@ -394,7 +701,7 @@ def dist_floor(dist1): Returns ------- - ComplexDistribution or function + ComplexDistribution This will be a lazy evaluation of the desired function that will then be calculated Examples @@ -402,10 +709,12 @@ def dist_floor(dist1): >>> dist_floor(norm(0, 1)) floor(norm(mean=0.5, sd=0.3)) """ - return dist_fn(dist1, None, np.floor) + return dist_fn(dist1, np.floor) -def dist_log(dist1, base=math.e): +def dist_log( + dist1: OperableDistribution, base: Number = math.e +) -> Union[ComplexDistribution, Callable]: """ Initialize the log of the output of the distribution. @@ -429,7 +738,7 @@ def dist_log(dist1, base=math.e): return dist_fn(dist1, const(base), math.log) -def dist_exp(dist1): +def dist_exp(dist1: OperableDistribution): """ Initialize the exp of the output of the distribution. @@ -442,7 +751,7 @@ def dist_exp(dist1): Returns ------- - ComplexDistribution or function + ComplexDistribution This will be a lazy evaluation of the desired function that will then be calculated Examples @@ -450,18 +759,21 @@ def dist_exp(dist1): >>> dist_exp(norm(0, 1)) exp(norm(mean=0.5, sd=0.3)) """ - return dist_fn(dist1, None, math.exp) + return dist_fn(dist1, math.exp) @np.vectorize -def _lclip(n, val=None): +def _lclip(n: Number, val: Number) -> Number: if val is None: return n else: return val if n < val else n -def lclip(dist1, val=None): +def lclip( + dist1: Union[OperableDistribution, Callable], + val: Optional[Number] = None, +) -> Union[ComplexDistribution, Callable]: """ Initialize the clipping/bounding of the output of the distribution by the lower value. @@ -487,21 +799,24 @@ def lclip(dist1, val=None): """ if (isinstance(dist1, int) or isinstance(dist1, float)) and val is None: return lambda d: lclip(d, dist1) - elif is_dist(dist1): - return dist_fn(dist1, val, _lclip, name="lclip") + elif isinstance(dist1, OperableDistribution): + return dist_fn(dist1, partial(_lclip, val), name="lclip") else: return _lclip(dist1, val) @np.vectorize -def _rclip(n, val=None): +def _rclip(n: Number, val: Number) -> Number: if val is None: return n else: return val if n > val else n -def rclip(dist1, val=None): +def rclip( + dist1: Union[OperableDistribution, Callable], + val: Optional[Number] = None, +) -> Union[ComplexDistribution, Callable]: """ Initialize the clipping/bounding of the output of the distribution by the upper value. @@ -527,13 +842,17 @@ def rclip(dist1, val=None): """ if (isinstance(dist1, int) or isinstance(dist1, float)) and val is None: return lambda d: rclip(d, dist1) - elif is_dist(dist1): - return dist_fn(dist1, val, _rclip, name="rclip") + elif isinstance(dist1, OperableDistribution): + return dist_fn(dist1, partial(_rclip, val), name="rclip") else: return _rclip(dist1, val) -def clip(dist1, left, right=None): +def clip( + dist1: Union[OperableDistribution, Callable], + left: Optional[Number], + right: Optional[Number] = None, +) -> Union[ComplexDistribution, Callable]: """ Initialize the clipping/bounding of the output of the distribution. @@ -570,15 +889,15 @@ def clip(dist1, left, right=None): class ConstantDistribution(OperableDistribution): - def __init__(self, x): + def __init__(self, x: Any) -> None: super().__init__() self.x = x - def __str__(self): + def __str__(self) -> str: return " const({})".format(self.x) -def const(x): +def const(x: Any) -> ConstantDistribution: """ Initialize a constant distribution. @@ -602,16 +921,16 @@ def const(x): class UniformDistribution(OperableDistribution): - def __init__(self, x, y): + def __init__(self, x: Number, y: Number) -> None: super().__init__() self.x = x self.y = y - def __str__(self): + def __str__(self) -> str: return " uniform({}, {})".format(self.x, self.y) -def uniform(x, y): +def uniform(x: Number, y: Number) -> UniformDistribution: """ Initialize a uniform random distribution. @@ -635,33 +954,47 @@ def uniform(x, y): class NormalDistribution(OperableDistribution): - def __init__(self, x=None, y=None, mean=None, sd=None, credibility=90, lclip=None, rclip=None): + def __init__( + self, + x: Optional[Number] = None, + y: Optional[Number] = None, + mean: Optional[Number] = None, + sd: Optional[Number] = None, + credibility: Number = 90, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, + ) -> None: super().__init__() - self.x = x - self.y = y self.credibility = credibility - self.mean = mean - self.sd = sd self.lclip = lclip self.rclip = rclip - if self.x is not None and self.y is not None and self.x > self.y: - raise ValueError("`high value` cannot be lower than `low value`") - - if (self.x is None or self.y is None) and self.sd is None: - raise ValueError("must define either x/y or mean/sd") - elif (self.x is not None or self.y is not None) and self.sd is not None: - raise ValueError("must define either x/y or mean/sd -- cannot define both") - elif self.sd is not None and self.mean is None: - self.mean = 0 - - if self.mean is None and self.sd is None: + self.x: Optional[Number] + self.y: Optional[Number] + self.mean: Optional[Number] + self.sd: Optional[Number] + + # Define the complementary set of parameters + # x/y => mean/sd, mean/sd => x/y + if mean is None and sd is None and x is not None and y is not None: + if x > y: + raise ValueError("`high value` (y) cannot be lower than `low value` (x)") + self.x, self.y = x, y self.mean = (self.x + self.y) / 2 - cdf_value = 0.5 + 0.5 * (self.credibility / 100) - normed_sigma = stats.norm.ppf(cdf_value) + cdf_value: Float = 0.5 + 0.5 * (self.credibility / 100) + normed_sigma: np.float64 = stats.norm.ppf(cdf_value) # type: ignore + assert self.mean is not None self.sd = (self.y - self.mean) / normed_sigma + elif sd is not None and x is None and y is None: + self.sd = sd + self.mean = 0 if mean is None else mean + self.x = None + self.y = None + else: + raise ValueError("you must define either x/y or mean/sd") - def __str__(self): + def __str__(self) -> str: + assert self.mean is not None and self.sd is not None out = " norm(mean={}, sd={}".format(round(self.mean, 2), round(self.sd, 2)) if self.lclip is not None: out += ", lclip={}".format(self.lclip) @@ -671,7 +1004,15 @@ def __str__(self): return out -def norm(x=None, y=None, credibility=90, mean=None, sd=None, lclip=None, rclip=None): +def norm( + x: Optional[Number] = None, + y: Optional[Number] = None, + credibility: Integer = 90, + mean: Optional[Number] = None, + sd: Optional[Number] = None, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, +) -> NormalDistribution: """ Initialize a normal distribution. @@ -715,26 +1056,26 @@ def norm(x=None, y=None, credibility=90, mean=None, sd=None, lclip=None, rclip=N class LognormalDistribution(OperableDistribution): def __init__( self, - x=None, - y=None, - norm_mean=None, - norm_sd=None, - lognorm_mean=None, - lognorm_sd=None, - credibility=90, - lclip=None, - rclip=None, - ): + x: Optional[Number] = None, + y: Optional[Number] = None, + norm_mean: Optional[Number] = None, + norm_sd: Optional[Number] = None, + lognorm_mean: Optional[Number] = None, + lognorm_sd: Optional[Number] = None, + credibility: Integer = 90, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, + ) -> None: super().__init__() - self.x = x - self.y = y - self.credibility = credibility - self.norm_mean = norm_mean - self.norm_sd = norm_sd - self.lognorm_mean = lognorm_mean - self.lognorm_sd = lognorm_sd - self.lclip = lclip - self.rclip = rclip + self.x: Optional[Number] = x + self.y: Optional[Number] = y + self.credibility: Integer = credibility + self.norm_mean: Optional[Number] = norm_mean + self.norm_sd: Optional[Number] = norm_sd + self.lognorm_mean: Optional[Number] = lognorm_mean + self.lognorm_sd: Optional[Number] = lognorm_sd + self.lclip: Optional[Number] = lclip + self.rclip: Optional[Number] = rclip if self.x is not None and self.y is not None and self.x > self.y: raise ValueError("`high value` cannot be lower than `low value`") @@ -762,24 +1103,28 @@ def __init__( elif self.lognorm_sd is not None and self.lognorm_mean is None: self.lognorm_mean = 1 - if self.x is not None: + if self.x is not None and self.y is not None: self.norm_mean = (np.log(self.x) + np.log(self.y)) / 2 cdf_value = 0.5 + 0.5 * (self.credibility / 100) normed_sigma = stats.norm.ppf(cdf_value) self.norm_sd = (np.log(self.y) - self.norm_mean) / normed_sigma if self.lognorm_sd is None: + assert self.norm_sd is not None and self.norm_mean is not None self.lognorm_mean = np.exp(self.norm_mean + self.norm_sd**2 / 2) self.lognorm_sd = ( (np.exp(self.norm_sd**2) - 1) * np.exp(2 * self.norm_mean + self.norm_sd**2) ) ** 0.5 elif self.norm_sd is None: + assert self.lognorm_sd is not None and self.lognorm_mean is not None self.norm_mean = np.log( (self.lognorm_mean**2 / np.sqrt(self.lognorm_sd**2 + self.lognorm_mean**2)) ) self.norm_sd = np.sqrt(np.log(1 + self.lognorm_sd**2 / self.lognorm_mean**2)) - def __str__(self): + def __str__(self) -> str: + assert self.lognorm_mean is not None and self.lognorm_sd is not None + assert self.norm_mean is not None and self.norm_sd is not None out = " lognorm(lognorm_mean={}, lognorm_sd={}, norm_mean={}, norm_sd={}" out = out.format( round(self.lognorm_mean, 2), @@ -796,16 +1141,16 @@ def __str__(self): def lognorm( - x=None, - y=None, - credibility=90, - norm_mean=None, - norm_sd=None, - lognorm_mean=None, - lognorm_sd=None, - lclip=None, - rclip=None, -): + x: Optional[Number] = None, + y: Optional[Number] = None, + credibility: Integer = 90, + norm_mean: Optional[Number] = None, + norm_sd: Optional[Number] = None, + lognorm_mean: Optional[Number] = None, + lognorm_sd: Optional[Number] = None, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, +) -> LognormalDistribution: """ Initialize a lognormal distribution. @@ -862,7 +1207,13 @@ def lognorm( ) -def to(x, y, credibility=90, lclip=None, rclip=None): +def to( + x: Number, + y: Number, + credibility: Integer = 90, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, +) -> Union[LognormalDistribution, NormalDistribution]: """ Initialize a distribution from ``x`` to ``y``. @@ -903,18 +1254,18 @@ def to(x, y, credibility=90, lclip=None, rclip=None): class BinomialDistribution(OperableDistribution): - def __init__(self, n, p): + def __init__(self, n: int, p: Number) -> None: super().__init__() self.n = n self.p = p if self.p < 0 or self.p > 1: raise ValueError("p must be between 0 and 1") - def __str__(self): + def __str__(self) -> str: return " binomial(n={}, p={})".format(self.n, self.p) -def binomial(n, p): +def binomial(n: int, p: Number) -> BinomialDistribution: """ Initialize a binomial distribution. @@ -938,16 +1289,16 @@ def binomial(n, p): class BetaDistribution(OperableDistribution): - def __init__(self, a, b): + def __init__(self, a: Number, b: Number) -> None: super().__init__() self.a = a self.b = b - def __str__(self): + def __str__(self) -> str: return " beta(a={}, b={})".format(self.a, self.b) -def beta(a, b): +def beta(a: Number, b: Number) -> BetaDistribution: """ Initialize a beta distribution. @@ -973,7 +1324,7 @@ def beta(a, b): class BernoulliDistribution(OperableDistribution): - def __init__(self, p): + def __init__(self, p: Number) -> None: super().__init__() if not isinstance(p, float) or isinstance(p, int): raise ValueError("bernoulli p must be a float or int") @@ -981,11 +1332,11 @@ def __init__(self, p): raise ValueError("bernoulli p must be 0-1") self.p = p - def __str__(self): + def __str__(self) -> str: return " bernoulli(p={})".format(self.p) -def bernoulli(p): +def bernoulli(p: Number) -> BernoulliDistribution: """ Initialize a Bernoulli distribution. @@ -1007,17 +1358,19 @@ def bernoulli(p): class DiscreteDistribution(OperableDistribution): - def __init__(self, items): + def __init__(self, items: Any) -> None: super().__init__() if not isinstance(items, dict) and not isinstance(items, list) and not _is_numpy(items): raise ValueError("inputs to discrete must be a dict or list") self.items = list(items) if _is_numpy(items) else items - def __str__(self): + def __str__(self) -> str: return " discrete({})".format(self.items) -def discrete(items): +def discrete( + items: Union[dict[Any, Number], list[list[Number]], FloatArray] +) -> DiscreteDistribution: """ Initialize a discrete distribution (aka categorical distribution). @@ -1046,7 +1399,15 @@ def discrete(items): class TDistribution(OperableDistribution): - def __init__(self, x=None, y=None, t=20, credibility=90, lclip=None, rclip=None): + def __init__( + self, + x: Optional[Number] = None, + y: Optional[Number] = None, + t: Integer = 20, + credibility: Integer = 90, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, + ) -> None: super().__init__() self.x = x self.y = y @@ -1064,7 +1425,7 @@ def __init__(self, x=None, y=None, t=20, credibility=90, lclip=None, rclip=None) if self.x is None: self.credibility = None - def __str__(self): + def __str__(self) -> str: if self.x is not None: out = " tdist(x={}, y={}, t={}".format(self.x, self.y, self.t) else: @@ -1079,7 +1440,14 @@ def __str__(self): return out -def tdist(x=None, y=None, t=20, credibility=90, lclip=None, rclip=None): +def tdist( + x: Optional[Number] = None, + y: Optional[Number] = None, + t: Integer = 20, + credibility: Integer = 90, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, +) -> TDistribution: """ Initialize a t-distribution. @@ -1096,7 +1464,7 @@ def tdist(x=None, y=None, t=20, credibility=90, lclip=None, rclip=None): The low value of a credible interval defined by ``credibility``. Defaults to a 90% CI. y : float or None The high value of a credible interval defined by ``credibility``. Defaults to a 90% CI. - t : float + t : integer The number of degrees of freedom of the t-distribution. Defaults to 20. credibility : float The range of the credibility interval. Defaults to 90. @@ -1120,7 +1488,15 @@ def tdist(x=None, y=None, t=20, credibility=90, lclip=None, rclip=None): class LogTDistribution(OperableDistribution): - def __init__(self, x=None, y=None, t=1, credibility=90, lclip=None, rclip=None): + def __init__( + self, + x: Optional[Integer] = None, + y: Optional[Integer] = None, + t: int = 1, + credibility: int = 90, + lclip: Optional[Integer] = None, + rclip: Optional[Integer] = None, + ) -> None: super().__init__() self.x = x self.y = y @@ -1138,7 +1514,7 @@ def __init__(self, x=None, y=None, t=1, credibility=90, lclip=None, rclip=None): if self.x is None: self.credibility = None - def __str__(self): + def __str__(self) -> str: if self.x is not None: out = " log_tdist(x={}, y={}, t={}".format(self.x, self.y, self.t) else: @@ -1153,7 +1529,14 @@ def __str__(self): return out -def log_tdist(x=None, y=None, t=1, credibility=90, lclip=None, rclip=None): +def log_tdist( + x: Optional[Integer] = None, + y: Optional[Integer] = None, + t: int = 1, + credibility: int = 90, + lclip: Optional[Integer] = None, + rclip: Optional[Integer] = None, +) -> LogTDistribution: """ Initialize a log t-distribution, which is a t-distribution in log-space. @@ -1194,7 +1577,14 @@ def log_tdist(x=None, y=None, t=1, credibility=90, lclip=None, rclip=None): class TriangularDistribution(OperableDistribution): - def __init__(self, left, mode, right, lclip=None, rclip=None): + def __init__( + self, + left: int, + mode: int, + right: int, + lclip: Optional[Integer] = None, + rclip: Optional[Integer] = None, + ) -> None: super().__init__() self.left = left self.mode = mode @@ -1202,7 +1592,7 @@ def __init__(self, left, mode, right, lclip=None, rclip=None): self.lclip = lclip self.rclip = rclip - def __str__(self): + def __str__(self) -> str: out = " triangular({}, {}, {}".format(self.left, self.mode, self.right) if self.lclip is not None: out += ", lclip={}".format(self.lclip) @@ -1212,7 +1602,13 @@ def __str__(self): return out -def triangular(left, mode, right, lclip=None, rclip=None): +def triangular( + left: int, + mode: int, + right: int, + lclip: Optional[Integer] = None, + rclip: Optional[Integer] = None, +) -> TriangularDistribution: """ Initialize a triangular distribution. @@ -1242,13 +1638,15 @@ def triangular(left, mode, right, lclip=None, rclip=None): class PoissonDistribution(OperableDistribution): - def __init__(self, lam, lclip=None, rclip=None): + def __init__( + self, lam: Number, lclip: Optional[Integer] = None, rclip: Optional[Integer] = None + ) -> None: super().__init__() self.lam = lam self.lclip = lclip self.rclip = rclip - def __str__(self): + def __str__(self) -> str: out = " poisson({}".format(self.lam) if self.lclip is not None: out += ", lclip={}".format(self.lclip) @@ -1258,7 +1656,9 @@ def __str__(self): return out -def poisson(lam, lclip=None, rclip=None): +def poisson( + lam: Number, lclip: Optional[Integer] = None, rclip: Optional[Integer] = None +) -> PoissonDistribution: """ Initialize a poisson distribution. @@ -1284,17 +1684,17 @@ def poisson(lam, lclip=None, rclip=None): class ChiSquareDistribution(OperableDistribution): - def __init__(self, df): + def __init__(self, df: int) -> None: super().__init__() self.df = df if self.df <= 0: raise ValueError("df must be positive") - def __str__(self): + def __str__(self) -> str: return " chisquare({})".format(self.df) -def chisquare(df): +def chisquare(df: int) -> ChiSquareDistribution: """ Initialize a chi-square distribution. @@ -1316,13 +1716,15 @@ def chisquare(df): class ExponentialDistribution(OperableDistribution): - def __init__(self, scale, lclip=None, rclip=None): + def __init__( + self, scale: int, lclip: Optional[Integer] = None, rclip: Optional[Integer] = None + ) -> None: super().__init__() self.scale = scale self.lclip = lclip self.rclip = rclip - def __str__(self): + def __str__(self) -> str: out = " exponential({}".format(self.scale) if self.lclip is not None: out += ", lclip={}".format(self.lclip) @@ -1332,7 +1734,9 @@ def __str__(self): return out -def exponential(scale, lclip=None, rclip=None): +def exponential( + scale: int, lclip: Optional[Integer] = None, rclip: Optional[Integer] = None +) -> ExponentialDistribution: """ Initialize an exponential distribution. @@ -1358,14 +1762,20 @@ def exponential(scale, lclip=None, rclip=None): class GammaDistribution(OperableDistribution): - def __init__(self, shape, scale=1, lclip=None, rclip=None): + def __init__( + self, + shape: int, + scale: int = 1, + lclip: Optional[Integer] = None, + rclip: Optional[Integer] = None, + ) -> None: super().__init__() self.shape = shape self.scale = scale self.lclip = lclip self.rclip = rclip - def __str__(self): + def __str__(self) -> str: out = " gamma(shape={}, scale={}".format(self.shape, self.scale) if self.lclip is not None: out += ", lclip={}".format(self.lclip) @@ -1375,7 +1785,9 @@ def __str__(self): return out -def gamma(shape, scale=1, lclip=None, rclip=None): +def gamma( + shape: int, scale: int = 1, lclip: Optional[Integer] = None, rclip: Optional[Integer] = None +) -> GammaDistribution: """ Initialize a gamma distribution. @@ -1403,15 +1815,15 @@ def gamma(shape, scale=1, lclip=None, rclip=None): class ParetoDistribution(OperableDistribution): - def __init__(self, shape): + def __init__(self, shape: int) -> None: super().__init__() self.shape = shape - def __str__(self): + def __str__(self) -> str: return " pareto({})".format(self.shape) -def pareto(shape): +def pareto(shape: int) -> ParetoDistribution: """ Initialize a pareto distribution. @@ -1433,7 +1845,14 @@ def pareto(shape): class MixtureDistribution(OperableDistribution): - def __init__(self, dists, weights=None, relative_weights=None, lclip=None, rclip=None): + def __init__( + self, + dists: Any, + weights: Optional[Weights] = None, + relative_weights: Optional[Weights] = None, + lclip: Optional[Number] = None, + rclip: Optional[Number] = None, + ) -> None: super().__init__() weights, dists = _process_weights_values(weights, relative_weights, dists) self.dists = dists @@ -1441,14 +1860,21 @@ def __init__(self, dists, weights=None, relative_weights=None, lclip=None, rclip self.lclip = lclip self.rclip = rclip - def __str__(self): + def __str__(self) -> str: out = " mixture" + assert self.weights is not None for i in range(len(self.dists)): out += "\n - {} weight on {}".format(self.weights[i], self.dists[i]) return out -def mixture(dists, weights=None, relative_weights=None, lclip=None, rclip=None): +def mixture( + dists: Any, + weights: Optional[Weights] = None, + relative_weights: Optional[Weights] = None, + lclip: Optional[Integer] = None, + rclip: Optional[Integer] = None, +) -> MixtureDistribution: """ Initialize a mixture distribution, which is a combination of different distributions. @@ -1495,7 +1921,7 @@ def mixture(dists, weights=None, relative_weights=None, lclip=None, rclip=None): ) -def zero_inflated(p_zero, dist): +def zero_inflated(p_zero: float, dist: NormalDistribution) -> MixtureDistribution: """ Initialize an arbitrary zero-inflated distribution. @@ -1519,10 +1945,10 @@ def zero_inflated(p_zero, dist): """ if p_zero > 1 or p_zero < 0 or not isinstance(p_zero, float): raise ValueError("`p_zero` must be between 0 and 1") - return MixtureDistribution(dists=[0, dist], weights=p_zero) + return MixtureDistribution(dists=[0, dist], weights=[p_zero]) -def inf0(p_zero, dist): +def inf0(p_zero: float, dist: NormalDistribution) -> MixtureDistribution: """ Initialize an arbitrary zero-inflated distribution. diff --git a/squigglepy/rng.py b/squigglepy/rng.py index 2a6737a..82356a4 100644 --- a/squigglepy/rng.py +++ b/squigglepy/rng.py @@ -1,9 +1,10 @@ import numpy as np +from numpy.random import Generator _squigglepy_internal_rng = np.random.default_rng() -def set_seed(seed): +def set_seed(seed: int) -> Generator: """ Set the seed of the random number generator used by Squigglepy. diff --git a/squigglepy/samplers.py b/squigglepy/samplers.py index 4bb40a2..133b7a1 100644 --- a/squigglepy/samplers.py +++ b/squigglepy/samplers.py @@ -1,26 +1,16 @@ import os import time +from typing import Any, List, Optional, Tuple, TypeAlias, Union import numpy as np import pathos.multiprocessing as mp - +from numpy import float64 +from numpy.typing import NDArray +from numpy.random import Generator from scipy import stats -from .utils import ( - _process_weights_values, - _process_discrete_weights_values, - is_dist, - is_sampleable, - _simplify, - _enlist, - _safe_len, - _core_cuts, - _init_tqdm, - _tick_tqdm, - _flush_tqdm, -) - from .distributions import ( + BaseDistribution, BernoulliDistribution, BetaDistribution, BinomialDistribution, @@ -30,8 +20,8 @@ DiscreteDistribution, ExponentialDistribution, GammaDistribution, - LogTDistribution, LognormalDistribution, + LogTDistribution, MixtureDistribution, NormalDistribution, ParetoDistribution, @@ -41,17 +31,40 @@ UniformDistribution, const, ) +from .utils import ( + Float, + Integer, + Number, + Weights, + _core_cuts, + _enlist, + _flush_tqdm, + _init_tqdm, + _process_discrete_weights_values, + _process_weights_values, + _safe_len, + _simplify_numpy, + _simplify_list, + _tick_tqdm, + is_dist, + is_sampleable, +) _squigglepy_internal_sample_caches = {} -def _get_rng(): +def _get_rng() -> Generator: from .rng import _squigglepy_internal_rng return _squigglepy_internal_rng -def normal_sample(mean, sd, samples=1): +SampleFloatOutput: TypeAlias = NDArray[np.float64] | List[np.float64] | np.float64 +SampleIntOutput: TypeAlias = NDArray[np.integer] | List[np.integer] | np.integer +SampleNumberOutput: TypeAlias = SampleFloatOutput | SampleIntOutput + + +def normal_sample(mean: Number, sd: Number, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to a normal distribution. @@ -76,10 +89,10 @@ def normal_sample(mean, sd, samples=1): >>> normal_sample(0, 1) 0.30471707975443135 """ - return _simplify(_get_rng().normal(mean, sd, samples)) + return _simplify_numpy(_get_rng().normal(mean, sd, samples)) -def lognormal_sample(mean, sd, samples=1): +def lognormal_sample(mean: Number, sd: Number, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to a lognormal distribution. @@ -104,10 +117,16 @@ def lognormal_sample(mean, sd, samples=1): >>> lognormal_sample(0, 1) 1.3562412406168636 """ - return _simplify(_get_rng().lognormal(mean, sd, samples)) + return _simplify_numpy(_get_rng().lognormal(mean, sd, samples)) -def t_sample(low=None, high=None, t=20, samples=1, credibility=90): +def t_sample( + low: Optional[Number] = None, + high: Optional[Number] = None, + t: Integer = 20, + samples: int = 1, + credibility: int = 90, +) -> SampleFloatOutput: """ Sample a random number according to a t-distribution. @@ -124,7 +143,7 @@ def t_sample(low=None, high=None, t=20, samples=1, credibility=90): The low value of a credible interval defined by ``credibility``. Defaults to a 90% CI. high : float or None The high value of a credible interval defined by ``credibility``. Defaults to a 90% CI. - t : float + t : integer The number of degrees of freedom of the t-distribution. Defaults to 20. samples : int The number of samples to return. @@ -156,12 +175,18 @@ def t_sample(low=None, high=None, t=20, samples=1, credibility=90): cdf_value = 0.5 + 0.5 * (credibility / 100) normed_sigma = stats.norm.ppf(cdf_value) sigma = (high - mu) / normed_sigma - return _simplify( + return _simplify_numpy( normal_sample(mu, sigma, samples) / ((chi_square_sample(t, samples) / t) ** 0.5) ) -def log_t_sample(low=None, high=None, t=20, samples=1, credibility=90): +def log_t_sample( + low: Optional[int] = None, + high: Optional[int] = None, + t: int = 20, + samples: int = 1, + credibility: int = 90, +) -> SampleFloatOutput: """ Sample a random number according to a log-t-distribution. @@ -212,14 +237,14 @@ def log_t_sample(low=None, high=None, t=20, samples=1, credibility=90): cdf_value = 0.5 + 0.5 * (credibility / 100) normed_sigma = stats.norm.ppf(cdf_value) sigma = (log_high - mu) / normed_sigma - return _simplify( + return _simplify_numpy( np.exp( normal_sample(mu, sigma, samples) / ((chi_square_sample(t, samples) / t) ** 0.5) ) ) -def binomial_sample(n, p, samples=1): +def binomial_sample(n: int, p: float, samples: int = 1) -> SampleIntOutput: """ Sample a random number according to a binomial distribution. @@ -244,10 +269,10 @@ def binomial_sample(n, p, samples=1): >>> binomial_sample(10, 0.1) 2 """ - return _simplify(_get_rng().binomial(n, p, samples)) + return _simplify_numpy(_get_rng().binomial(n, p, samples)) -def beta_sample(a, b, samples=1): +def beta_sample(a: int, b: int, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to a beta distribution. @@ -274,10 +299,10 @@ def beta_sample(a, b, samples=1): >>> beta_sample(1, 1) 0.22145847498048798 """ - return _simplify(_get_rng().beta(a, b, samples)) + return _simplify_numpy(_get_rng().beta(a, b, samples)) -def bernoulli_sample(p, samples=1): +def bernoulli_sample(p: Float, samples: int = 1) -> SampleIntOutput: """ Sample 1 with probability ``p`` and 0 otherwise. @@ -300,13 +325,13 @@ def bernoulli_sample(p, samples=1): 0 """ a = uniform_sample(0, 1, samples) - if _safe_len(a) == 1: - return int(a < p) + if isinstance(a, Number): + return np.int64(a < p) else: - return (a < p).astype(int) + return (a < p).astype(np.int64) -def triangular_sample(left, mode, right, samples=1): +def triangular_sample(left: int, mode: int, right: int, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to a triangular distribution. @@ -332,10 +357,10 @@ def triangular_sample(left, mode, right, samples=1): >>> triangular_sample(1, 2, 3) 2.327625176788963 """ - return _simplify(_get_rng().triangular(left, mode, right, samples)) + return _simplify_numpy(_get_rng().triangular(left, mode, right, samples)) -def poisson_sample(lam, samples=1): +def poisson_sample(lam: Union[int, float], samples: int = 1) -> SampleIntOutput: """ Sample a random number according to a poisson distribution. @@ -357,10 +382,10 @@ def poisson_sample(lam, samples=1): >>> poisson_sample(10) 13 """ - return _simplify(_get_rng().poisson(lam, samples)) + return _simplify_numpy(_get_rng().poisson(lam, samples)) -def exponential_sample(scale, samples=1): +def exponential_sample(scale: int, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to an exponential distribution. @@ -382,10 +407,10 @@ def exponential_sample(scale, samples=1): >>> exponential_sample(10) 24.042086039659946 """ - return _simplify(_get_rng().exponential(scale, samples)) + return _simplify_numpy(_get_rng().exponential(scale, samples)) -def gamma_sample(shape, scale, samples=1): +def gamma_sample(shape: int, scale: int, samples: int = 1) -> SampleNumberOutput: """ Sample a random number according to a gamma distribution. @@ -409,10 +434,10 @@ def gamma_sample(shape, scale, samples=1): >>> gamma_sample(10, 2) 21.290716894247602 """ - return _simplify(_get_rng().gamma(shape, scale, samples)) + return _simplify_numpy(_get_rng().gamma(shape, scale, samples)) -def pareto_sample(shape, samples=1): +def pareto_sample(shape: int, samples: int = 1) -> SampleNumberOutput: """ Sample a random number according to a pareto distribution. @@ -432,10 +457,10 @@ def pareto_sample(shape, samples=1): >>> pareto_sample(1) 10.069666324736094 """ - return _simplify(_get_rng().pareto(shape, samples)) + return _simplify_numpy(_get_rng().pareto(shape, samples)) -def uniform_sample(low, high, samples=1): +def uniform_sample(low: int, high: int, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to a uniform distribution. @@ -460,10 +485,10 @@ def uniform_sample(low, high, samples=1): >>> uniform_sample(0, 1) 0.7739560485559633 """ - return _simplify(_get_rng().uniform(low, high, samples)) + return _simplify_numpy(_get_rng().uniform(low, high, samples)) -def chi_square_sample(df, samples=1): +def chi_square_sample(df: int, samples: int = 1) -> SampleFloatOutput: """ Sample a random number according to a chi-square distribution. @@ -485,10 +510,16 @@ def chi_square_sample(df, samples=1): >>> chi_square_sample(2) 4.808417207931989 """ - return _simplify(_get_rng().chisquare(df, samples)) + return _simplify_numpy(_get_rng().chisquare(df, samples)) -def discrete_sample(items, samples=1, verbose=False, _multicore_tqdm_n=1, _multicore_tqdm_cores=1): +def discrete_sample( + items: Any, + samples: int = 1, + verbose: bool = False, + _multicore_tqdm_n: int = 1, + _multicore_tqdm_cores: int = 1, +) -> Union[List[float], str, List[int], NormalDistribution, int]: """ Sample a random value from a discrete distribution (aka categorical distribution). @@ -543,14 +574,14 @@ def discrete_sample(items, samples=1, verbose=False, _multicore_tqdm_n=1, _multi def _mixture_sample_for_large_n( - values, - weights=None, - relative_weights=None, - samples=1, - verbose=False, - _multicore_tqdm_n=1, - _multicore_tqdm_cores=1, -): + values: List[Union[NormalDistribution, ConstantDistribution, float]], + weights: Optional[List[float]] = None, + relative_weights: None = None, + samples: int = 1, + verbose: bool = False, + _multicore_tqdm_n: int = 1, + _multicore_tqdm_cores: int = 1, +) -> Number | List[Number]: def _run_presample(dist, pbar): if is_dist(dist) and isinstance(dist, MixtureDistribution): raise ValueError( @@ -578,22 +609,22 @@ def _run_mixture(picker, i, pbar): picker = uniform_sample(0, 1, samples=samples) tqdm_samples = samples if _multicore_tqdm_cores == 1 else _multicore_tqdm_n - pbar = _init_tqdm(verbose=verbose, total=tqdm_samples) - out = _simplify([_run_mixture(p, i, pbar) for i, p in enumerate(_enlist(picker))]) + pbar: tqdm[NoReturn] | None = _init_tqdm(verbose=verbose, total=tqdm_samples) + out = _simplify_list([_run_mixture(p, i, pbar) for i, p in enumerate(_enlist(picker))]) _flush_tqdm(pbar) return out def _mixture_sample_for_small_n( - values, - weights=None, - relative_weights=None, - samples=1, - verbose=False, - _multicore_tqdm_n=1, - _multicore_tqdm_cores=1, -): + values: List[Any], + weights: Optional[List[float]] = None, + relative_weights: None = None, + samples: int = 1, + verbose: bool = False, + _multicore_tqdm_n: int = 1, + _multicore_tqdm_cores: int = 1, +) -> Number | List[Number]: def _run_mixture(values, weights, pbar=None, tick=1): r_ = uniform_sample(0, 1) _tick_tqdm(pbar, tick) @@ -606,7 +637,7 @@ def _run_mixture(values, weights, pbar=None, tick=1): weights = np.cumsum(weights) tqdm_samples = samples if _multicore_tqdm_cores == 1 else _multicore_tqdm_n pbar = _init_tqdm(verbose=verbose, total=tqdm_samples) - out = _simplify( + out = _simplify_list( [ _run_mixture(values=values, weights=weights, pbar=pbar, tick=_multicore_tqdm_cores) for _ in range(samples) @@ -617,14 +648,14 @@ def _run_mixture(values, weights, pbar=None, tick=1): def mixture_sample( - values, - weights=None, - relative_weights=None, - samples=1, - verbose=False, - _multicore_tqdm_n=1, - _multicore_tqdm_cores=1, -): + values: Union[dict, list], + weights: Optional[Weights] = None, + relative_weights: Optional[Weights] = None, + samples: int = 1, + verbose: bool = False, + _multicore_tqdm_n: int = 1, + _multicore_tqdm_cores: int = 1, +) -> Any: """ Sample a ranom number from a mixture distribution. @@ -692,20 +723,20 @@ def mixture_sample( def sample( - dist=None, - n=1, - lclip=None, - rclip=None, - memcache=False, - reload_cache=False, - dump_cache_file=None, - load_cache_file=None, - cache_file_primary=False, - verbose=None, - cores=1, - _multicore_tqdm_n=1, - _multicore_tqdm_cores=1, -): + dist: Optional[BaseDistribution | Number | str | bool] = None, + n: int = 1, + lclip: Optional[int] = None, + rclip: Optional[int] = None, + memcache: bool = False, + reload_cache: bool = False, + dump_cache_file: Optional[str] = None, + load_cache_file: Optional[str] = None, + cache_file_primary: bool = False, + verbose: Optional[bool] = None, + cores: int = 1, + _multicore_tqdm_n: int = 1, + _multicore_tqdm_cores: int = 1, +) -> Any: """ Sample random numbers from a given distribution. @@ -887,7 +918,7 @@ def run_dist(dist, pbar=None, tick=1): return samp pbar = _init_tqdm(verbose=verbose, total=len(out) * _multicore_tqdm_cores) - samples = _simplify( + samples = _simplify_numpy( np.array([run_dist(dist=o, pbar=pbar, tick=_multicore_tqdm_cores) for o in out]) ) _flush_tqdm(pbar) @@ -898,10 +929,10 @@ def run_dist(dist, pbar=None, tick=1): or isinstance(dist, str) or dist is None ): - samples = _simplify(np.array([dist for _ in range(n)])) + samples = _simplify_numpy(np.array([dist for _ in range(n)])) elif isinstance(dist, ConstantDistribution): - samples = _simplify(np.array([dist.x for _ in range(n)])) + samples = _simplify_numpy(np.array([dist.x for _ in range(n)])) elif isinstance(dist, UniformDistribution): samples = uniform_sample(dist.x, dist.y, samples=n) diff --git a/squigglepy/utils.py b/squigglepy/utils.py index f07e1da..11d2d79 100644 --- a/squigglepy/utils.py +++ b/squigglepy/utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import math import numpy as np @@ -5,11 +7,20 @@ from datetime import datetime from collections import Counter from collections.abc import Iterable +from typing import Any, Optional, Union, overload +from numpy.typing import NDArray +from typing import TypeVar, List import importlib import importlib.util import sys +Float = Union[float, np.floating] +Integer = Union[int, np.integer] +Number = Union[Float, Integer] +FloatArray = Union[list[Float], NDArray[np.floating]] +Weights = Union[list[Float], NDArray[np.floating], np.floating, float] + def _check_pandas_series(values): """Check if values is a pandas series. Only imports pandas if necessary.""" @@ -20,7 +31,12 @@ def _check_pandas_series(values): return isinstance(values, pd.core.series.Series) -def _process_weights_values(weights=None, relative_weights=None, values=None, drop_na=False): +def _process_weights_values( + weights: Optional[Weights] = None, + relative_weights: Optional[Weights] = None, + values=None, + drop_na: bool = False, +) -> tuple[list[Float], list[list]]: if weights is not None and relative_weights is not None: raise ValueError("can only pass either `weights` or `relative_weights`, not both.") if values is None or _safe_len(values) == 0: @@ -31,7 +47,7 @@ def _process_weights_values(weights=None, relative_weights=None, values=None, dr weights = relative_weights relative = True - if isinstance(weights, float): + if isinstance(weights, float) or isinstance(weights, np.floating): weights = [weights] elif isinstance(weights, np.ndarray): weights = list(weights) @@ -67,7 +83,7 @@ def _process_weights_values(weights=None, relative_weights=None, values=None, dr if any([_is_na_like(w) for w in weights]): raise ValueError("cannot handle NA-like values in weights") - sum_weights = sum(weights) + sum_weights = sum(weights) # type: ignore if relative: weights = normalize(weights) @@ -119,7 +135,22 @@ def _is_na_like(a): return a is None or np.isnan(a) -def _round(x, digits=0): +@overload +def _round(x: NDArray[np.floating], digits: Optional[int] = 0) -> NDArray[np.floating]: + ... + + +@overload +def _round(x: NDArray[np.integer], digits: Optional[int] = 0) -> NDArray[np.integer]: + ... + + +@overload +def _round(x: Number, digits: Optional[int] = 0) -> Number: + ... + + +def _round(x: Union[Number, np.ndarray], digits: Optional[int] = 0) -> Union[Number, np.ndarray]: if digits is None: return x @@ -131,13 +162,22 @@ def _round(x, digits=0): return int(x) if digits <= 0 else x -def _simplify(a): - if _is_numpy(a): - a = a.tolist() if a.size == 1 else a - if isinstance(a, list): - a = a[0] if len(a) == 1 else a +NumpyNumberVar = TypeVar("NumpyNumberVar", np.floating, np.integer) + +def _simplify_numpy( + a: Union[NumpyNumberVar, NDArray[NumpyNumberVar]] +) -> Union[NumpyNumberVar, NDArray[NumpyNumberVar]]: + if isinstance(a, np.ndarray): + a = a[0] if a.size == 1 and a.ndim == 1 else a + return a return a +NumberVar = TypeVar("NumberVar", bound=Number) + +def _simplify_list(a: list[NumberVar]) -> Union[NumberVar, list[NumberVar]]: + if len(a) == 1: + return a[0] + return a def _enlist(a): if _is_numpy(a) and isinstance(a, np.ndarray): @@ -384,11 +424,11 @@ def one_in(p, digits=0, verbose=True): def get_percentiles( - data, - percentiles=[1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99], - reverse=False, - digits=None, -): + data: Union[list[np.floating], NDArray[np.floating]], + percentiles: list[Number] = [1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99], + reverse: bool = False, + digits: Optional[int] = None, +) -> dict[Number, Number]: """ Print the percentiles of the data. @@ -416,20 +456,17 @@ def get_percentiles( """ percentiles = percentiles if isinstance(percentiles, list) else [percentiles] percentile_labels = list(reversed(percentiles)) if reverse else percentiles - percentiles = np.percentile(data, percentiles) - percentiles = [_round(p, digits) for p in percentiles] - if len(percentile_labels) == 1: - return percentiles[0] - else: - return dict(list(zip(percentile_labels, percentiles))) + computed_percentiles: NDArray[np.float64] = np.percentile(data, percentiles) # type: ignore + rounded_percentiles: list[Number] = [_round(p, digits) for p in computed_percentiles] + return dict(list(zip(percentile_labels, rounded_percentiles, strict=True))) def get_log_percentiles( - data, - percentiles=[1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99], - reverse=False, - display=True, - digits=1, + data: Union[list[np.floating], NDArray[np.floating]], + percentiles: list[Number] = [1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99], + reverse: bool = False, + display: bool = True, + digits: int = 1, ): """ Print the log (base 10) of the percentiles of the data. @@ -459,20 +496,15 @@ def get_log_percentiles( >>> get_percentiles(range(100), percentiles=[25, 50, 75]) {25: 24.75, 50: 49.5, 75: 74.25} """ - percentiles = get_percentiles(data, percentiles=percentiles, reverse=reverse, digits=digits) - if isinstance(percentiles, dict): - if display: - return dict( - [(k, ("{:." + str(digits) + "e}").format(v)) for k, v in percentiles.items()] - ) - else: - return dict([(k, _round(np.log10(v), digits)) for k, v in percentiles.items()]) + computed_percentiles = get_percentiles( + data, percentiles=percentiles, reverse=reverse, digits=digits + ) + if display: + return dict( + [(k, ("{:." + str(digits) + "e}").format(v)) for k, v in computed_percentiles.items()] + ) else: - if display: - digit_str = "{:." + str(digits) + "e}" - digit_str.format(percentiles) - else: - return _round(np.log10(percentiles), digits) + return dict([(k, _round(np.log10(v), digits)) for k, v in computed_percentiles.items()]) def get_mean_and_ci(data, credibility=90, digits=None): @@ -598,7 +630,7 @@ def _convert(p): raise ValueError("p must be between 0 and 1") return p / (1 - p) - return _simplify(np.array([_convert(p) for p in _enlist(p)])) + return _simplify_numpy(np.array([_convert(p) for p in _enlist(p)])) def odds_to_p(odds): @@ -628,7 +660,7 @@ def _convert(o): raise ValueError("odds must be greater than 0") return o / (1 + o) - return _simplify(np.array([_convert(o) for o in _enlist(odds)])) + return _simplify_numpy(np.array([_convert(o) for o in _enlist(odds)])) def geomean_odds(a, weights=None, relative_weights=None, drop_na=True): @@ -799,7 +831,7 @@ def doubling_time_to_growth_rate(doubling_time): return math.exp(math.log(2) / doubling_time) - 1 -def roll_die(sides, n=1): +def roll_die(sides: int, n: int=1) -> Union[int, list[int], None]: """ Roll a die. @@ -831,6 +863,8 @@ def roll_die(sides, n=1): raise ValueError("cannot roll less than a 2-sided die.") elif not isinstance(sides, int): raise ValueError("can only roll an integer number of sides") + elif n <= 0: + raise ValueError("cannot roll less than once") else: from .samplers import sample from .distributions import discrete @@ -859,13 +893,20 @@ def flip_coin(n=1): 'heads' """ rolls = roll_die(2, n=n) - if isinstance(rolls, int): - rolls = [rolls] + if isinstance(rolls, np.integer): + rolls: list[np.integer] = [rolls] flips = ["heads" if d == 2 else "tails" for d in rolls] return flips[0] if len(flips) == 1 else flips -def kelly(my_price, market_price, deference=0, bankroll=1, resolve_date=None, current=0): +def kelly( + my_price: Number, + market_price: Number, + deference: Number = 0, + bankroll: Number = 1, + resolve_date: Optional[str] = None, + current: Number = 0, +): """ Calculate the Kelly criterion. diff --git a/tests/test_bayes.py b/tests/test_bayes.py index 09c6323..a5783b9 100644 --- a/tests/test_bayes.py +++ b/tests/test_bayes.py @@ -1,11 +1,11 @@ import os import pytest -from ..squigglepy.bayes import simple_bayes, bayesnet, update, average -from ..squigglepy.samplers import sample -from ..squigglepy.distributions import discrete, norm, beta, gamma -from ..squigglepy.rng import set_seed -from ..squigglepy.distributions import BetaDistribution, MixtureDistribution, NormalDistribution +from squigglepy.bayes import simple_bayes, bayesnet, update, average +from squigglepy.samplers import sample +from squigglepy.distributions import discrete, norm, beta, gamma +from squigglepy.rng import set_seed +from squigglepy.distributions import BetaDistribution, MixtureDistribution, NormalDistribution def test_simple_bayes(): @@ -75,7 +75,7 @@ def test_bayesnet_raw(): def test_bayesnet_cache(): - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches = len(_squigglepy_internal_bayesnet_caches) @@ -83,19 +83,19 @@ def define_event(): return {"a": 1, "b": 2} bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches2 = len(_squigglepy_internal_bayesnet_caches) assert n_caches < n_caches2 bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches3 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 == n_caches3 bayesnet(define_event, find=lambda e: e["b"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches4 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 == n_caches4 @@ -103,7 +103,7 @@ def define_event(): def test_bayesnet_cache_multiple(): - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches = len(_squigglepy_internal_bayesnet_caches) @@ -111,13 +111,13 @@ def define_event(): return {"a": 1, "b": 2} bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches2 = len(_squigglepy_internal_bayesnet_caches) assert n_caches < n_caches2 bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches3 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 == n_caches3 @@ -126,7 +126,7 @@ def define_event2(): return {"a": 4, "b": 6} bayesnet(define_event2, find=lambda e: e["b"], n=1000) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches4 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 < n_caches4 @@ -134,20 +134,20 @@ def define_event2(): assert _squigglepy_internal_bayesnet_caches.get(define_event2)["metadata"]["n"] == 1000 bayesnet(define_event2, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches5 = len(_squigglepy_internal_bayesnet_caches) assert n_caches4 == n_caches5 bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches6 = len(_squigglepy_internal_bayesnet_caches) assert n_caches4 == n_caches6 def test_bayesnet_reload_cache(): - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches = len(_squigglepy_internal_bayesnet_caches) @@ -155,19 +155,19 @@ def define_event(): return {"a": 1, "b": 2} bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches2 = len(_squigglepy_internal_bayesnet_caches) assert n_caches < n_caches2 bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches3 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 == n_caches3 bayesnet(define_event, find=lambda e: e["b"], n=100, reload_cache=True) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches4 = len(_squigglepy_internal_bayesnet_caches) assert n_caches3 == n_caches4 @@ -175,7 +175,7 @@ def define_event(): def test_bayesnet_dont_use_cache(): - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches = len(_squigglepy_internal_bayesnet_caches) @@ -183,7 +183,7 @@ def define_event(): return {"a": 1, "b": 2} bayesnet(define_event, find=lambda e: e["a"], memcache=False, n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches2 = len(_squigglepy_internal_bayesnet_caches) assert n_caches == n_caches2 @@ -259,7 +259,7 @@ def define_event(): def test_bayesnet_cachefile_primary(cachefile): assert not os.path.exists(cachefile + ".sqcache") - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches = len(_squigglepy_internal_bayesnet_caches) @@ -268,7 +268,7 @@ def define_event(): bayesnet(define_event, find=lambda e: e["a"], n=100) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches2 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 == n_caches + 1 @@ -285,7 +285,7 @@ def define_event2(): n=100, ) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches3 = len(_squigglepy_internal_bayesnet_caches) assert n_caches3 == n_caches2 @@ -314,7 +314,7 @@ def define_event2(): ) assert set(out) == set([2]) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches4 = len(_squigglepy_internal_bayesnet_caches) assert n_caches4 == n_caches2 @@ -323,7 +323,7 @@ def define_event2(): def test_bayesnet_cachefile_will_also_memcache(cachefile): assert not os.path.exists(cachefile + ".sqcache") - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches = len(_squigglepy_internal_bayesnet_caches) @@ -341,7 +341,7 @@ def define_event(): assert os.path.exists(cachefile + ".sqcache") assert set(out) == set([1]) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches2 = len(_squigglepy_internal_bayesnet_caches) assert n_caches2 == n_caches @@ -357,7 +357,7 @@ def define_event(): assert os.path.exists(cachefile + ".sqcache") assert set(out) == set([1]) - from ..squigglepy.bayes import _squigglepy_internal_bayesnet_caches + from squigglepy.bayes import _squigglepy_internal_bayesnet_caches n_caches3 = len(_squigglepy_internal_bayesnet_caches) assert n_caches3 == n_caches + 1 diff --git a/tests/test_distributions.py b/tests/test_distributions.py index a0bf8fc..fe898c3 100644 --- a/tests/test_distributions.py +++ b/tests/test_distributions.py @@ -1,6 +1,6 @@ import pytest import numpy as np -from ..squigglepy.distributions import ( +from squigglepy.distributions import ( to, const, uniform, @@ -51,7 +51,7 @@ ParetoDistribution, UniformDistribution, ) -from ..squigglepy.version import __version__ +from squigglepy.version import __version__ def _mirror(x): @@ -118,7 +118,7 @@ def test_norm(): assert norm(1, 2).x == 1 assert norm(1, 2).y == 2 assert norm(1, 2).mean == 1.5 - assert round(norm(1, 2).sd, 2) == 0.3 + assert round(norm(1, 2).sd, 2) == 0.3 # type: ignore assert norm(1, 2).credibility == 90 assert norm(1, 2).lclip is None assert norm(1, 2).rclip is None @@ -169,7 +169,7 @@ def test_norm_overdefinition_value_error(): def test_norm_low_gt_high(): with pytest.raises(ValueError) as execinfo: norm(10, 5) - assert "`high value` cannot be lower than `low value`" in str(execinfo.value) + assert "`high value` (y) cannot be lower than `low value` (x)" in str(execinfo.value) def test_norm_passes_lclip_rclip(): @@ -210,10 +210,10 @@ def test_lognorm(): assert isinstance(lognorm(1, 2), LognormalDistribution) assert lognorm(1, 2).x == 1 assert lognorm(1, 2).y == 2 - assert round(lognorm(1, 2).norm_mean, 2) == 0.35 - assert round(lognorm(1, 2).norm_sd, 2) == 0.21 - assert round(lognorm(1, 2).lognorm_mean, 2) == 1.45 - assert round(lognorm(1, 2).lognorm_sd, 2) == 0.31 + assert round(lognorm(1, 2).norm_mean, 2) == 0.35 # type: ignore + assert round(lognorm(1, 2).norm_sd, 2) == 0.21 # type: ignore + assert round(lognorm(1, 2).lognorm_mean, 2) == 1.45 # type: ignore + assert round(lognorm(1, 2).lognorm_sd, 2) == 0.31 # type: ignore assert lognorm(1, 2).credibility == 90 assert lognorm(1, 2).lclip is None assert lognorm(1, 2).rclip is None @@ -1089,13 +1089,13 @@ def test_min(): def test_round(): obj = dist_round(norm(0, 1)) assert isinstance(obj, ComplexDistribution) - assert str(obj) == " round(norm(mean=0.5, sd=0.3), 0)" + assert str(obj) == " round(norm(mean=0.5, sd=0.3), digits=0)" def test_round_two_digits(): obj = dist_round(norm(0, 1), digits=2) assert isinstance(obj, ComplexDistribution) - assert str(obj) == " round(norm(mean=0.5, sd=0.3), 2)" + assert str(obj) == " round(norm(mean=0.5, sd=0.3), digits=2)" def test_ceil(): @@ -1198,10 +1198,10 @@ def test_min_pipe(): def test_round_pipe(): obj = norm(0, 1) >> dist_round assert isinstance(obj, ComplexDistribution) - assert str(obj) == " round(norm(mean=0.5, sd=0.3), 0)" + assert str(obj) == " round(norm(mean=0.5, sd=0.3), digits=0)" obj = norm(0, 1) >> dist_round(2) assert isinstance(obj, ComplexDistribution) - assert str(obj) == " round(norm(mean=0.5, sd=0.3), 2)" + assert str(obj) == " round(norm(mean=0.5, sd=0.3), digits=2)" def test_floor_pipe(): @@ -1219,7 +1219,7 @@ def test_ceil_pipe(): def test_two_pipes(): obj = norm(0, 1) >> lclip(2) >> dist_round assert isinstance(obj, ComplexDistribution) - assert str(obj) == " round(lclip(norm(mean=0.5, sd=0.3), 2), 0)" + assert str(obj) == " round(lclip(norm(mean=0.5, sd=0.3), 2), digits=0)" def test_dist_fn_list_pipe(): diff --git a/tests/test_numbers.py b/tests/test_numbers.py index 9d52027..fc3b5ad 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -1,4 +1,4 @@ -from ..squigglepy.numbers import K, M, B, T +from squigglepy.numbers import K, M, B, T def test_thousand(): diff --git a/tests/test_rng.py b/tests/test_rng.py index d2eb3cf..aef3a90 100644 --- a/tests/test_rng.py +++ b/tests/test_rng.py @@ -1,6 +1,6 @@ -from ..squigglepy.rng import set_seed -from ..squigglepy.samplers import sample -from ..squigglepy.distributions import norm +from squigglepy.rng import set_seed +from squigglepy.samplers import sample +from squigglepy.distributions import norm def test_seed(): diff --git a/tests/test_samplers.py b/tests/test_samplers.py index 8d884dd..d8ec18c 100644 --- a/tests/test_samplers.py +++ b/tests/test_samplers.py @@ -3,7 +3,7 @@ import numpy as np from unittest.mock import patch, Mock -from ..squigglepy.distributions import ( +from squigglepy.distributions import ( const, uniform, norm, @@ -33,9 +33,9 @@ clip, dist_fn, ) -from ..squigglepy import samplers -from ..squigglepy.utils import _is_numpy -from ..squigglepy.samplers import ( +from squigglepy import samplers +from squigglepy.utils import _is_numpy +from squigglepy.samplers import ( normal_sample, lognormal_sample, mixture_sample, @@ -44,7 +44,7 @@ t_sample, sample, ) -from ..squigglepy.distributions import NormalDistribution +from squigglepy.distributions import NormalDistribution class FakeRNG: @@ -934,61 +934,61 @@ def test_clip(): def test_sample_cache(): - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches = len(_squigglepy_internal_sample_caches) sample(norm(1, 2), memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches2 = len(_squigglepy_internal_sample_caches) assert n_caches < n_caches2 sample(norm(1, 2), memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches3 = len(_squigglepy_internal_sample_caches) assert n_caches2 == n_caches3 sample(norm(1, 2)) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches4 = len(_squigglepy_internal_sample_caches) assert n_caches2 == n_caches4 sample(norm(3, 4)) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches5 = len(_squigglepy_internal_sample_caches) assert n_caches2 == n_caches5 sample(norm(3, 4), memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches6 = len(_squigglepy_internal_sample_caches) assert n_caches6 > n_caches5 def test_sample_reload_cache(): - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches = len(_squigglepy_internal_sample_caches) out1 = sample(norm(5, 6), memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches2 = len(_squigglepy_internal_sample_caches) assert n_caches < n_caches2 out2 = sample(norm(5, 6), memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches3 = len(_squigglepy_internal_sample_caches) assert n_caches2 == n_caches3 assert out1 == out2 out3 = sample(norm(5, 6), memcache=True, reload_cache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches4 = len(_squigglepy_internal_sample_caches) assert n_caches3 == n_caches4 @@ -1014,13 +1014,13 @@ def test_sample_cachefile(cachefile): def test_sample_cachefile_primary(cachefile): assert not os.path.exists(cachefile + ".sqcache.npy") - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches = len(_squigglepy_internal_sample_caches) sample(norm(10, 20), dump_cache_file=cachefile, memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches2 = len(_squigglepy_internal_sample_caches) assert n_caches2 == n_caches + 1 @@ -1034,13 +1034,13 @@ def test_sample_cachefile_primary(cachefile): def test_sample_load_noop_cachefile(cachefile): assert not os.path.exists(cachefile + ".sqcache.npy") - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches = len(_squigglepy_internal_sample_caches) o1 = sample(norm(100, 200), dump_cache_file=cachefile, memcache=True) - from ..squigglepy.samplers import _squigglepy_internal_sample_caches + from squigglepy.samplers import _squigglepy_internal_sample_caches n_caches2 = len(_squigglepy_internal_sample_caches) assert n_caches2 == n_caches + 1 diff --git a/tests/test_utils.py b/tests/test_utils.py index f978f61..b59bd95 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,7 +2,7 @@ import numpy as np from datetime import datetime, timedelta -from ..squigglepy.utils import ( +from squigglepy.utils import ( _process_weights_values, _process_discrete_weights_values, event_occurs, @@ -29,8 +29,8 @@ extremize, normalize, ) -from ..squigglepy.rng import set_seed -from ..squigglepy.distributions import bernoulli, beta, norm, dist_round, const +from squigglepy.rng import set_seed +from squigglepy.distributions import bernoulli, beta, norm, dist_round, const def test_process_weights_values_simple_case(): @@ -280,9 +280,9 @@ def test_get_percentiles_digits(): def test_get_percentiles_length_one(): test = get_percentiles(range(1, 901), percentiles=[25], digits=1) - assert test == 225.8 + assert test == {25: 225.8} test = get_percentiles(range(1, 901), percentiles=25, digits=1) - assert test == 225.8 + assert test == {25: 225.8} def test_get_percentiles_zero_digits(): @@ -353,11 +353,11 @@ def test_get_log_percentiles_length_one(): test = get_log_percentiles( [10**x for x in range(1, 10)], percentiles=[20], display=False, digits=0 ) - assert test == 3 + assert test == {20: 3} test = get_log_percentiles( [10**x for x in range(1, 10)], percentiles=20, display=False, digits=0 ) - assert test == 3 + assert test == {20: 3} def test_get_mean_and_ci():