From af35d6d23ec1c415d52e158dc3ee3ab8457dd248 Mon Sep 17 00:00:00 2001
From: "Xu, He"
Date: Mon, 19 Jun 2023 07:31:47 +0000
Subject: [PATCH] Merge latest main to cpp_msglib
Signed-off-by: Xu, He
---
.github/ISSUE_TEMPLATE.md | 20 +-
.github/ISSUE_TEMPLATE/bug_report.md | 10 +-
.github/ISSUE_TEMPLATE/feature_request.md | 6 +-
.github/PULL_REQUEST_TEMPLATE.md | 32 +-
.github/workflows/cd.yml | 4 +-
.github/workflows/ci.yml | 15 +-
.../workflows/codacy_coverage_reporter.yml | 29 +
README.md | 34 +-
RELEASE.md | 106 +-
poetry.lock | 2012 ++++++++---------
pyproject.toml | 16 +-
.../compiler/builders/channel_builder.py | 1 -
.../magma/compiler/builders/interfaces.py | 2 -
.../magma/compiler/builders/py_builder.py | 7 +
src/lava/magma/compiler/channel_map.py | 5 +-
src/lava/magma/compiler/compiler.py | 2 +-
src/lava/magma/compiler/compiler_graphs.py | 1 -
src/lava/magma/compiler/mapper.py | 3 +-
src/lava/magma/compiler/node.py | 5 +-
.../subcompilers/channel_builders_factory.py | 4 +-
.../magma/compiler/subcompilers/interfaces.py | 2 -
src/lava/magma/compiler/utils.py | 2 -
src/lava/magma/compiler/var_model.py | 1 +
src/lava/magma/core/learning/constants.py | 11 +-
.../magma/core/learning/symbolic_equation.py | 12 +-
src/lava/magma/core/learning/utils.py | 1 -
src/lava/magma/core/model/interfaces.py | 1 -
src/lava/magma/core/model/py/connection.py | 150 +-
src/lava/magma/core/model/py/model.py | 48 +-
src/lava/magma/core/model/py/ports.py | 26 +-
src/lava/magma/core/process/ports/ports.py | 45 +-
.../magma/core/process/ports/reduce_ops.py | 4 -
src/lava/magma/core/process/process.py | 46 +-
src/lava/magma/core/process/variable.py | 26 +-
src/lava/magma/core/resources.py | 18 -
src/lava/magma/core/run_configs.py | 47 +-
.../runtime/message_infrastructure/factory.py | 5 +-
.../message_infrastructure_interface.py | 15 +-
.../runtime/message_infrastructure/nx.py | 4 -
.../message_infrastructure/pypychannel.py | 27 +-
src/lava/magma/runtime/mgmt_token_enums.py | 6 +-
src/lava/magma/runtime/runtime.py | 12 +-
.../channel_broker/channel_broker.py | 1 -
.../runtime_services/runtime_service.py | 55 +-
src/lava/proc/conv/utils.py | 20 +-
src/lava/proc/dense/models.py | 57 +-
src/lava/proc/dense/process.py | 5 +-
src/lava/proc/io/encoder.py | 1 -
src/lava/proc/lif/models.py | 68 +-
src/lava/proc/lif/process.py | 79 +-
src/lava/proc/monitor/process.py | 33 +-
src/lava/proc/sparse/models.py | 372 +++
src/lava/proc/sparse/process.py | 277 +++
src/lava/proc/spiker/models.py | 2 +-
src/lava/utils/dataloader/mnist.py | 3 +-
src/lava/utils/sparse.py | 32 +
src/lava/utils/weightutils.py | 67 +-
.../subcompilers/py/test_pyproc_compiler.py | 3 +-
.../test_channel_builders_factory.py | 13 +-
tests/lava/magma/compiler/test_channel_map.py | 1 -
tests/lava/magma/compiler/test_compiler.py | 4 -
tests/lava/magma/compiler/test_node.py | 2 -
.../magma/core/learning/test_learning_rule.py | 19 +-
tests/lava/magma/core/learning/test_random.py | 1 -
tests/lava/magma/core/model/py/test_model.py | 11 +-
.../lava/magma/core/model/test_decorators.py | 18 +-
.../magma/core/process/ports/test_ports.py | 21 +-
.../magma/core/process/test_lif_dense_lif.py | 16 +-
tests/lava/magma/core/process/test_process.py | 59 +-
.../lava/magma/runtime/test_async_protocol.py | 8 +-
.../runtime/test_get_set_non_determinism.py | 2 +-
.../runtime/test_loihi_with_async_protocol.py | 9 +-
tests/lava/proc/conv/test_utils.py | 8 +-
tests/lava/proc/dense/test_learning.py | 11 +-
tests/lava/proc/dense/test_models.py | 2 +-
tests/lava/proc/io/test_dataloader.py | 12 +-
tests/lava/proc/io/test_source_sink.py | 12 +-
tests/lava/proc/lif/test_models.py | 44 +-
tests/lava/proc/rf/test_models.py | 44 +-
tests/lava/proc/rf_iz/test_models.py | 22 +-
tests/lava/proc/sdn/test_models.py | 56 +-
tests/lava/proc/sparse/__init__.py | 0
tests/lava/proc/sparse/test_models.py | 1449 ++++++++++++
tests/lava/proc/sparse/test_process.py | 134 ++
tests/lava/proc/spiker/test_models.py | 4 +-
tests/lava/test_utils/utils.py | 10 +-
tests/lava/tutorials/test_tutorials.py | 5 +-
tests/lava/utils/test_plots.py | 10 +-
.../in_depth/three_factor_learning/utils.py | 34 +-
89 files changed, 4183 insertions(+), 1756 deletions(-)
create mode 100644 .github/workflows/codacy_coverage_reporter.yml
create mode 100644 src/lava/proc/sparse/models.py
create mode 100644 src/lava/proc/sparse/process.py
create mode 100644 src/lava/utils/sparse.py
create mode 100644 tests/lava/proc/sparse/__init__.py
create mode 100644 tests/lava/proc/sparse/test_models.py
create mode 100644 tests/lava/proc/sparse/test_process.py
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 4dbe39eb2..d96b923fc 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -17,19 +17,19 @@ Objective of issue:
**Lava version:**
-- [ ] **0.6.0** (feature release)
-- [ ] **0.5.1** (bug fixes)
-- [x] **0.5.0** (current version)
-- [ ] **0.4.1**
-- [ ] **0.4.0**
-- [ ] **0.3.0**
-- [ ] **0.1.2**
+- [ ] **0.6.0** (feature release)
+- [ ] **0.5.1** (bug fixes)
+- [x] **0.5.0** (current version)
+- [ ] **0.4.1**
+- [ ] **0.4.0**
+- [ ] **0.3.0**
+- [ ] **0.1.2**
**I'm submitting a ...**
-- [ ] bug report
-- [ ] feature request
-- [ ] documentation request
+- [ ] bug report
+- [ ] feature request
+- [ ] documentation request
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index ff3259a2e..49f097a3a 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -22,12 +22,12 @@ A clear and concise description of what the bug is.
**To reproduce current behavior**
Steps to reproduce the behavior:
-1. When I run this code (add code or minimum test case) ...
+1. When I run this code (add code or minimum test case) ...
```python
def my_code():
pass
```
-2. I get this error ...
+2. I get this error ...
```
Error...
```
@@ -39,9 +39,9 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem. Remove section otherwise.
**Environment (please complete the following information):**
- - Device: [e.g. Laptop, Intel cloud]
- - OS: [e.g. Linux]
- - Lava version [e.g. 0.6.1]
+- Device: [e.g. Laptop, Intel cloud]
+- OS: [e.g. Linux]
+- Lava version [e.g. 0.6.1]
**Additional context**
Add any other context about the problem here. Remove section otherwise.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 083147669..a0b34ba9d 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -11,8 +11,8 @@ assignees: ''
As a user, I want to [capability] to [benefit].
### Conditions of satisfaction
-- An optional list of conditions that have to be fulfilled for this feature to be complete.
-- For example: "Users can add both individual items and lists as parameters."
+- An optional list of conditions that have to be fulfilled for this feature to be complete.
+- For example: "Users can add both individual items and lists as parameters."
### Acceptance tests
-- An optional list of tests that should be written to automatically test the new feature.
+- An optional list of tests that should be written to automatically test the new feature.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index bc820529f..4eb543f72 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -12,13 +12,13 @@ Objective of pull request:
## Pull request checklist
Your PR fulfills the following requirements:
-- [ ] [Issue](https://github.com/lava-nc/lava/issues) created that explains the change and why it's needed
-- [ ] Tests are part of the PR (for bug fixes / features)
-- [ ] [Docs](https://github.com/lava-nc/docs) reviewed and added / updated if needed (for bug fixes / features)
-- [ ] PR conforms to [Coding Conventions](https://lava-nc.org/developer_guide.html#coding-conventions)
-- [ ] [PR applys BSD 3-clause or LGPL2.1+ Licenses](https://lava-nc.org/developer_guide.html#add-a-license) to all code files
-- [ ] Lint (`flakeheaven lint src/lava tests/`) and (`bandit -r src/lava/.`) pass locally
-- [ ] Build tests (`pytest`) passes locally
+- [ ] [Issue](https://github.com/lava-nc/lava/issues) created that explains the change and why it's needed
+- [ ] Tests are part of the PR (for bug fixes / features)
+- [ ] [Docs](https://github.com/lava-nc/docs) reviewed and added / updated if needed (for bug fixes / features)
+- [ ] PR conforms to [Coding Conventions](https://lava-nc.org/developer_guide.html#coding-conventions)
+- [ ] [PR applys BSD 3-clause or LGPL2.1+ Licenses](https://lava-nc.org/developer_guide.html#add-a-license) to all code files
+- [ ] Lint (`flakeheaven lint src/lava tests/`) and (`bandit -r src/lava/.`) pass locally
+- [ ] Build tests (`pytest`) passes locally
## Pull request type
@@ -30,13 +30,13 @@ Your PR fulfills the following requirements:
Please check your PR type:
-- [ ] Bugfix
-- [ ] Feature
-- [ ] Code style update (formatting, renaming)
-- [ ] Refactoring (no functional changes, no api changes)
-- [ ] Build related changes
-- [ ] Documentation changes
-- [ ] Other (please describe):
+- [ ] Bugfix
+- [ ] Feature
+- [ ] Code style update (formatting, renaming)
+- [ ] Refactoring (no functional changes, no api changes)
+- [ ] Build related changes
+- [ ] Documentation changes
+- [ ] Other (please describe):
## What is the current behavior?
@@ -50,8 +50,8 @@ Please check your PR type:
## Does this introduce a breaking change?
-- [ ] Yes
-- [ ] No
+- [ ] Yes
+- [ ] No
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index 6e38a44bc..a66ae8955 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -99,7 +99,7 @@ jobs:
python3.9 -m venv artifact-unittest
source artifact-unittest/bin/activate
pip install -U pip
- pip install nbconvert>=7.2.2 pytest>=7.2.0 matplotlib>=3.5.1 ipykernel>=6.15.0 nbformat>=5.3.0 nbconvert>=7.2.2
+ pip install "nbconvert>=7.2.10,<7.3" pytest>=7.2.0 matplotlib>=3.5.1 ipykernel>=6.15.0 nbformat>=5.3.0
artifact=$(ls | grep lava | grep tar)
pip install --no-input $artifact
tar -xvf $artifact
@@ -118,7 +118,7 @@ jobs:
python3.9 -m venv artifact-unittest
source artifact-unittest/bin/activate
pip install -U pip
- pip install nbconvert>=7.2.2 pytest>=7.2.0 matplotlib>=3.5.1 ipykernel>=6.15.0 nbformat>=5.3.0 nbconvert>=7.2.2
+ pip install "nbconvert>=7.2.10,<7.3" pytest>=7.2.0 matplotlib>=3.5.1 ipykernel>=6.15.0 nbformat>=5.3.0
artifact=$(ls | grep lava | grep whl)
pip install --no-input $artifact
# Change $artifact to tar.gz
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8ab7341eb..9d4ea435c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -81,8 +81,19 @@ jobs:
run: |
poetry run git lfs fetch
poetry run git lfs pull
- # poetry run pytest
- poetry run python -m unittest discover -s tests/ -t . -vv
+ poetry run coverage run -m unittest discover -s tests/ -t . -vv
+
+ - name: Generate coverage report
+ if: runner.os == 'Linux'
+ run: poetry run coverage xml
+
+ - name: Archive coverage report
+ if: runner.os == 'Linux'
+ uses: actions/upload-artifact@v3
+ with:
+ name: coverage
+ path: coverage.xml
+ retention-days: 30
msg-infr-unit-tests:
name: Message Infrastructure Unit Test
diff --git a/.github/workflows/codacy_coverage_reporter.yml b/.github/workflows/codacy_coverage_reporter.yml
new file mode 100644
index 000000000..a6826c9c5
--- /dev/null
+++ b/.github/workflows/codacy_coverage_reporter.yml
@@ -0,0 +1,29 @@
+name: Codacy Coverage Reporter
+
+on:
+ workflow_run:
+ workflows: ["Run CI"]
+ types: [completed]
+ branches: [main]
+ workflow_dispatch:
+
+jobs:
+ codacy-coverage-reporter:
+ runs-on: ubuntu-latest
+ if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
+ name: codacy-coverage-reporter
+ steps:
+ - name: Download artifact
+ uses: dawidd6/action-download-artifact@v2
+ with:
+ workflow: ci.yml
+ workflow_conclusion: "success"
+ branch: main
+ event: push
+ name: coverage
+
+ - name: Run codacy-coverage-reporter
+ uses: codacy/codacy-coverage-reporter-action@v1
+ with:
+ project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
+ coverage-reports: coverage.xml
diff --git a/README.md b/README.md
index b1b1ef9c5..c8a740275 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,11 @@
A Software Framework for Neuromorphic Computing
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/40792fa7db054279bdf7532e36f0cfab)](https://app.codacy.com/gh/lava-nc/lava/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
+[![Codacy Badge](https://app.codacy.com/project/badge/Coverage/40792fa7db054279bdf7532e36f0cfab)](https://app.codacy.com/gh/lava-nc/lava/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
+
+If you like lava and want to support it, the easiest way is to star our repo (click star in the upper right corner).
+
# Overview
Lava is an open source SW framework to develop applications for
@@ -35,22 +40,13 @@ supporting architectures like Intel Loihi may remain proprietary
to Intel and will be shared as extensions to eligible users.
>### Lava extension for Intel's Loihi
->The Lava extension for Loihi is available for members of the Intel
-Neuromorphic Research Community (INRC). The extension enables execution of
-Lava on Intel's Loihi hardware platform.
+>The Lava extension for Loihi is available for members of the Intel Neuromorphic Research Community (INRC). The extension enables execution of Lava on Intel's Loihi hardware platform.
>
->Developers interested in using Lava with Loihi systems need to join the
-INRC. Loihi 1 and 2 research systems are currently not available
-commercially. Once a member of the INRC, developers will gain access to
-cloud-hosted Loihi systems or may be able to obtain physical Loihi systems on a
-loan basis.
+>Developers interested in using Lava with Loihi systems need to join the INRC. Loihi 1 and 2 research systems are currently not available commercially. Once a member of the INRC, developers will gain access to cloud-hosted Loihi systems or may be able to obtain physical Loihi systems on a loan basis.
>
->To join the INRC, visit [http://neuromorphic.intel.com](http://neuromorphic.intel.com)
-or email at [inrc_interest@intel.com](mailto:inrc_interest@intel.com).
+>To join the INRC, visit [http://neuromorphic.intel.com](http://neuromorphic.intel.com) or email at [inrc_interest@intel.com](mailto:inrc_interest@intel.com).
>
-> If you are already a member of the INRC, please read how to [get
- started with the Lava extension for Loihi.](https://intel-ncl.atlassian.net/wiki/spaces/NAP/pages/1785856001/Get+started+with+the+Lava+extension+for+Loihi)
-> This page is **only** accessible to members of the INRC.
+> If you are already a member of the INRC, please read how to [get started with the Lava extension for Loihi](https://intel-ncl.atlassian.net/wiki/spaces/NAP/pages/1785856001/Get+started+with+the+Lava+extension+for+Loihi). This page is **only** accessible to members of the INRC.
# Getting started
@@ -70,7 +66,7 @@ will need to install the `poetry` Python package.
Open a **python 3** terminal and run based on the OS you are on:
-### [Linux/MacOS]
+### Linux/MacOS
```bash
cd $HOME
@@ -87,7 +83,7 @@ pytest
## See FAQ for more info: https://github.com/lava-nc/lava/wiki/Frequently-Asked-Questions-(FAQ)#install
```
-### [Windows]
+### Windows
```powershell
# Commands using PowerShell
@@ -140,7 +136,7 @@ Required test coverage of 85.0% reached. Total coverage: 88.81%
```
-## [Alternative] Installing Lava via Conda
+## Alternative: Installing Lava via Conda
If you use the Conda package manager, you can simply install the Lava package
via:
@@ -158,7 +154,7 @@ conda install -n lava -c intel numpy scipy
conda install -n lava -c conda-forge lava --freeze-installed
```
-## [Alternative] Installing Lava from binaries
+## Alternative: Installing Lava from binaries
If you only need to install Lava as a user in your python environment, we will
publish Lava releases via
@@ -167,7 +163,7 @@ the package and install it.
Open a Python terminal and run:
-### [Windows/MacOS/Linux]
+### Windows/MacOS/Linux
```bash
python -m venv .venv
@@ -203,7 +199,7 @@ bandit -r src/lava/.
bandit -r src/lava/. --format custom --msg-template '{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}'
```
##
-> Refer to the tutorials directory for in-depth as well as end-to-end tutorials on how to write Lava Processes, connect them, and execute the code.
+>Refer to the tutorials directory for in-depth as well as end-to-end tutorials on how to write Lava Processes, connect them, and execute the code.
# Stay in touch
diff --git a/RELEASE.md b/RELEASE.md
index 0493bdc4e..1852313be 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -4,79 +4,79 @@ While this release offers few high-level application examples, Lava v0.4.0 provi
## New Features and Improvements
Features marked with * are available as part of the Loihi 2 extension.
-- *Extended Process library including new ProcessModels and additional improvements:
- - LIF, Sigma-Delta, and Dense Processes execute on Loihi NeuroCores.
- - Prototype Convolutional Process added.
- - Sending and receiving spikes to NeuroCores via embedded processes that can be programmed in C with examples included.
- - All Lava Processes now list all constructor arguments explicitly with type annotations.
-- *Added high-level API to develop custom ProcessModels that use Loihi 2 features:
- - Loihi NeuroCores can be programmed in Python by allocating neural network resources like Axons, Synapses or Neurons. In particular, Loihi 2 NeuroCore Neurons can be configured by writing highly flexible assembly programs.
- - Loihi embedded processors can be programmed in C. But unlike the prior NxSDK, no knowledge of low-level registers details is required anymore. Instead, the C API mirrors the high-level Python API to interact with other processes via channels.
-- Compiler and Runtime support for Loihi 2:
- - General redesign of Compiler and Runtime architecture to support compilation of Processes that execute across a heterogenous backend of different compute resources. CPU and Loihi are supported via separate sub compilers.
- - *The Loihi NeuroCore sub compiler automatically distributes neural network resources across multiple cores.
- - *The Runtime supports direct channel-based communication between Processes running on Loihi NeuroCores, embedded CPUs or host CPUs written in Python or C. Of all combinations, only Python<->C and C<->NeuroCore are currently supported.
- - *Added support to access Process Variables on Loihi NeuroCores at runtime via Var.set and Var.get().
-- New tutorials and improved class and method docstrings explain how new Lava features can be used such as *NeuroCore and *embedded processor programming.
-- An extended suite of unit tests and new *integration tests validate the correctness of the Lava framework.
+- *Extended Process library including new ProcessModels and additional improvements:
+ - LIF, Sigma-Delta, and Dense Processes execute on Loihi NeuroCores.
+ - Prototype Convolutional Process added.
+ - Sending and receiving spikes to NeuroCores via embedded processes that can be programmed in C with examples included.
+ - All Lava Processes now list all constructor arguments explicitly with type annotations.
+- *Added high-level API to develop custom ProcessModels that use Loihi 2 features:
+ - Loihi NeuroCores can be programmed in Python by allocating neural network resources like Axons, Synapses or Neurons. In particular, Loihi 2 NeuroCore Neurons can be configured by writing highly flexible assembly programs.
+ - Loihi embedded processors can be programmed in C. But unlike the prior NxSDK, no knowledge of low-level registers details is required anymore. Instead, the C API mirrors the high-level Python API to interact with other processes via channels.
+- Compiler and Runtime support for Loihi 2:
+ - General redesign of Compiler and Runtime architecture to support compilation of Processes that execute across a heterogenous backend of different compute resources. CPU and Loihi are supported via separate sub compilers.
+ - *The Loihi NeuroCore sub compiler automatically distributes neural network resources across multiple cores.
+ - *The Runtime supports direct channel-based communication between Processes running on Loihi NeuroCores, embedded CPUs or host CPUs written in Python or C. Of all combinations, only Python<->C and C<->NeuroCore are currently supported.
+ - *Added support to access Process Variables on Loihi NeuroCores at runtime via Var.set and Var.get().
+- New tutorials and improved class and method docstrings explain how new Lava features can be used such as *NeuroCore and *embedded processor programming.
+- An extended suite of unit tests and new *integration tests validate the correctness of the Lava framework.
## Bug Fixes and Other Changes
-- Support for virtual ports on multiple incoming connections (Python Processes only) (Issue [#223](https://github.com/lava-nc/lava/issues/223), PR [#224](https://github.com/lava-nc/lava/pull/224))
-- Added conda install instructions (PR [#225](https://github.com/lava-nc/lava/pull/225))
-- Var.set/get() works when RunContinuous RunMode is used (Issue [#255](https://github.com/lava-nc/lava/issues/255), PR [#256](https://github.com/lava-nc/lava/pull/256))
-- Successful execution of tutorials now covered by unit tests (Issue [#243](https://github.com/lava-nc/lava/issues/243), PR [#244](https://github.com/lava-nc/lava/pull/244))
-- Fixed PYTHONPATH in tutorial_01 (Issue [#45](https://github.com/lava-nc/lava/issues/45), PR [#239](https://github.com/lava-nc/lava/pull/239))
-- Fixed output of tutorial_07 (Issue [#249](https://github.com/lava-nc/lava/issues/249), PR [#253](https://github.com/lava-nc/lava/pull/253))
+- Support for virtual ports on multiple incoming connections (Python Processes only) (Issue [#223](https://github.com/lava-nc/lava/issues/223), PR [#224](https://github.com/lava-nc/lava/pull/224))
+- Added conda install instructions (PR [#225](https://github.com/lava-nc/lava/pull/225))
+- Var.set/get() works when RunContinuous RunMode is used (Issue [#255](https://github.com/lava-nc/lava/issues/255), PR [#256](https://github.com/lava-nc/lava/pull/256))
+- Successful execution of tutorials now covered by unit tests (Issue [#243](https://github.com/lava-nc/lava/issues/243), PR [#244](https://github.com/lava-nc/lava/pull/244))
+- Fixed PYTHONPATH in tutorial_01 (Issue [#45](https://github.com/lava-nc/lava/issues/45), PR [#239](https://github.com/lava-nc/lava/pull/239))
+- Fixed output of tutorial_07 (Issue [#249](https://github.com/lava-nc/lava/issues/249), PR [#253](https://github.com/lava-nc/lava/pull/253))
## Breaking Changes
-- Process constructors for standard library processes now require explicit keyword/value pairs and do not accept arbitrary input arguments via **kwargs anymore. This might break some workloads.
-- use_graded_spike kwarg has been changed to num_message_bits for all the built-in processes.
-- shape kwarg has been removed from Dense process. It is automatically inferred from the weight parameter’s shape.
-- Conv Process has additional arguments weight_exp and num_weight_bits that are relevant for fixed-point implementations.
-- The sign_mode argument in the Dense Process is now an enum rather than an integer.
-- New parameters u and v in the LIF Process enable setting initial values for current and voltage.
-- The bias parameter in the LIF Process has been renamed to bias_mant.
+- Process constructors for standard library processes now require explicit keyword/value pairs and do not accept arbitrary input arguments via **kwargs anymore. This might break some workloads.
+- use_graded_spike kwarg has been changed to num_message_bits for all the built-in processes.
+- shape kwarg has been removed from Dense process. It is automatically inferred from the weight parameter’s shape.
+- Conv Process has additional arguments weight_exp and num_weight_bits that are relevant for fixed-point implementations.
+- The sign_mode argument in the Dense Process is now an enum rather than an integer.
+- New parameters u and v in the LIF Process enable setting initial values for current and voltage.
+- The bias parameter in the LIF Process has been renamed to bias_mant.
## Known Issues
-- Lava does currently not support on-chip learning, Loihi 1 and a variety of connectivity compression features such as convolutional encoding.
-- All Processes in a network must currently be connected via channels. Running unconnected Processes using NcProcessModels in parallel currently gives incorrect results.
-- Only one instance of a Process targeting an embedded processor (using CProcessModel) can currently be created. Creating multiple instances in a network, results in an error. As a workaround, the behavior of multiple Processes can be fused into a single CProcessModel.
-- Direct channel connections between Processes using a PyProcessModel and NcProcessModel are not supported.
-- In the scenario that InputAxons are duplicated across multiple cores and users expect to inject spikes based on the declared port size, then the current implementation leads to buffer overflows and memory corruption.
-- Channel communication between PyProcessModels is slow.
-- The Lava Compiler is still inefficient and in need of improvement to performance and memory utilization.
-- Virtual ports are only supported between Processes using PyProcModels, but not between Processes when CProcModels or NcProcModels are involved. In addition, VirtualPorts do not support concatenation yet.
-- Joining and forking of virtual ports is not supported.
-- The Monitor Process does currently only support probing of a single Var per Process implemented via a PyProcessModel. The Monitor Process does currently not support probing of Vars mapped to NeuroCores.
-- Despite new docstrings, type annotations, and parameter descriptions to most of the public user-facing API, some parts of the code still have limited documentation and are missing type annotations.
+- Lava does currently not support on-chip learning, Loihi 1 and a variety of connectivity compression features such as convolutional encoding.
+- All Processes in a network must currently be connected via channels. Running unconnected Processes using NcProcessModels in parallel currently gives incorrect results.
+- Only one instance of a Process targeting an embedded processor (using CProcessModel) can currently be created. Creating multiple instances in a network, results in an error. As a workaround, the behavior of multiple Processes can be fused into a single CProcessModel.
+- Direct channel connections between Processes using a PyProcessModel and NcProcessModel are not supported.
+- In the scenario that InputAxons are duplicated across multiple cores and users expect to inject spikes based on the declared port size, then the current implementation leads to buffer overflows and memory corruption.
+- Channel communication between PyProcessModels is slow.
+- The Lava Compiler is still inefficient and in need of improvement to performance and memory utilization.
+- Virtual ports are only supported between Processes using PyProcModels, but not between Processes when CProcModels or NcProcModels are involved. In addition, VirtualPorts do not support concatenation yet.
+- Joining and forking of virtual ports is not supported.
+- The Monitor Process does currently only support probing of a single Var per Process implemented via a PyProcessModel. The Monitor Process does currently not support probing of Vars mapped to NeuroCores.
+- Despite new docstrings, type annotations, and parameter descriptions to most of the public user-facing API, some parts of the code still have limited documentation and are missing type annotations.
## What's Changed
-* Virtual ports on multiple incoming connections by @mathisrichter in https://github.com/lava-nc/lava/pull/224
-* Add conda install to README by @Tobias-Fischer in https://github.com/lava-nc/lava/pull/225
-* PYTHONPATH fix in tutorial by @jlubo in https://github.com/lava-nc/lava/pull/239
-* Fix tutorial04_execution.ipynb by @mgkwill in https://github.com/lava-nc/lava/pull/241
-* Tutorial tests by @mgkwill in https://github.com/lava-nc/lava/pull/244
-* Update README.md remove vlab instructions by @mgkwill in https://github.com/lava-nc/lava/pull/248
-* Tutorial bug fix by @PhilippPlank in https://github.com/lava-nc/lava/pull/253
-* Fix get set var by @PhilippPlank in https://github.com/lava-nc/lava/pull/256
-* Update runtime_service.py by @PhilippPlank in https://github.com/lava-nc/lava/pull/258
-* Release/v0.4.0 by @mgkwill in https://github.com/lava-nc/lava/pull/265
+* Virtual ports on multiple incoming connections by @mathisrichter in https://github.com/lava-nc/lava/pull/224
+* Add conda install to README by @Tobias-Fischer in https://github.com/lava-nc/lava/pull/225
+* PYTHONPATH fix in tutorial by @jlubo in https://github.com/lava-nc/lava/pull/239
+* Fix tutorial04_execution.ipynb by @mgkwill in https://github.com/lava-nc/lava/pull/241
+* Tutorial tests by @mgkwill in https://github.com/lava-nc/lava/pull/244
+* Update README.md remove vlab instructions by @mgkwill in https://github.com/lava-nc/lava/pull/248
+* Tutorial bug fix by @PhilippPlank in https://github.com/lava-nc/lava/pull/253
+* Fix get set var by @PhilippPlank in https://github.com/lava-nc/lava/pull/256
+* Update runtime_service.py by @PhilippPlank in https://github.com/lava-nc/lava/pull/258
+* Release/v0.4.0 by @mgkwill in https://github.com/lava-nc/lava/pull/265
## Thanks to our Contributors
-- Intel Corporation: All contributing members of the Intel Neuromorphic Computing Lab
+- Intel Corporation: All contributing members of the Intel Neuromorphic Computing Lab
### Open-source community:
-- [Tobias-Fischer](https://github.com/Tobias-Fischer), Tobias Fischer
-- [jlubo](https://github.com/jlubo), Jannik Luboeinski
+- [Tobias-Fischer](https://github.com/Tobias-Fischer), Tobias Fischer
+- [jlubo](https://github.com/jlubo), Jannik Luboeinski
## New Contributors
-* @jlubo made their first contribution in https://github.com/lava-nc/lava/pull/239
+* @jlubo made their first contribution in https://github.com/lava-nc/lava/pull/239
**Full Changelog**: https://github.com/lava-nc/lava/compare/v0.3.0...v0.4.0
diff --git a/poetry.lock b/poetry.lock
index b50a855c7..6b539eae6 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,10 +1,9 @@
-# This file is automatically @generated by Poetry and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
[[package]]
name = "alabaster"
version = "0.7.13"
description = "A configurable sidebar-enabled Sphinx theme"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -16,7 +15,6 @@ files = [
name = "appnope"
version = "0.1.3"
description = "Disable App Nap on macOS >= 10.9"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -28,7 +26,6 @@ files = [
name = "argparse"
version = "1.4.0"
description = "Python command-line parsing library"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -40,7 +37,6 @@ files = [
name = "asteval"
version = "0.9.29"
description = "Safe, minimalistic evaluator of python expression using ast module"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -58,7 +54,6 @@ test = ["coverage", "pytest", "pytest-cov"]
name = "asttokens"
version = "2.2.1"
description = "Annotate AST trees with source code positions"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -74,28 +69,26 @@ test = ["astroid", "pytest"]
[[package]]
name = "attrs"
-version = "22.2.0"
+version = "23.1.0"
description = "Classes Without Boilerplate"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"},
- {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"},
+ {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
]
[package.extras]
-cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
-dev = ["attrs[docs,tests]"]
-docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"]
-tests = ["attrs[tests-no-zope]", "zope.interface"]
-tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
[[package]]
name = "autopep8"
version = "1.6.0"
description = "A tool that automatically formats Python code to conform to the PEP 8 style guide"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -109,24 +102,22 @@ toml = "*"
[[package]]
name = "babel"
-version = "2.11.0"
+version = "2.12.1"
description = "Internationalization utilities"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"},
- {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"},
+ {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
+ {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
]
[package.dependencies]
-pytz = ">=2015.7"
+pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
[[package]]
name = "backcall"
version = "0.2.0"
description = "Specifications for callback functions passed in to an API"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -138,7 +129,6 @@ files = [
name = "bandit"
version = "1.7.4"
description = "Security oriented static analyser for python code."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -159,14 +149,13 @@ yaml = ["PyYAML"]
[[package]]
name = "beautifulsoup4"
-version = "4.11.2"
+version = "4.12.2"
description = "Screen-scraping library"
-category = "dev"
optional = false
python-versions = ">=3.6.0"
files = [
- {file = "beautifulsoup4-4.11.2-py3-none-any.whl", hash = "sha256:0e79446b10b3ecb499c1556f7e228a53e64a2bfcebd455f370d8927cb5b59e39"},
- {file = "beautifulsoup4-4.11.2.tar.gz", hash = "sha256:bc4bdda6717de5a2987436fb8d72f45dc90dd856bdfd512a1314ce90349a0106"},
+ {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"},
+ {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"},
]
[package.dependencies]
@@ -180,7 +169,6 @@ lxml = ["lxml"]
name = "bleach"
version = "6.0.0"
description = "An easy safelist-based HTML-sanitizing tool."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -195,16 +183,38 @@ webencodings = "*"
[package.extras]
css = ["tinycss2 (>=1.1.0,<1.2)"]
+[[package]]
+name = "build"
+version = "0.10.0"
+description = "A simple, correct Python build frontend"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"},
+ {file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "os_name == \"nt\""}
+packaging = ">=19.0"
+pyproject_hooks = "*"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"]
+test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"]
+typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"]
+virtualenv = ["virtualenv (>=20.0.35)"]
+
[[package]]
name = "cachecontrol"
-version = "0.12.11"
+version = "0.12.14"
description = "httplib2 caching for requests"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "CacheControl-0.12.11-py2.py3-none-any.whl", hash = "sha256:2c75d6a8938cb1933c75c50184549ad42728a27e9f6b92fd677c3151aa72555b"},
- {file = "CacheControl-0.12.11.tar.gz", hash = "sha256:a5b9fcc986b184db101aa280b42ecdcdfc524892596f606858e0b7a8b4d9e144"},
+ {file = "CacheControl-0.12.14-py2.py3-none-any.whl", hash = "sha256:1c2939be362a70c4e5f02c6249462b3b7a24441e4f1ced5e9ef028172edf356a"},
+ {file = "CacheControl-0.12.14.tar.gz", hash = "sha256:d1087f45781c0e00616479bfd282c78504371ca71da017b49df9f5365a95feba"},
]
[package.dependencies]
@@ -218,21 +228,19 @@ redis = ["redis (>=2.10.5)"]
[[package]]
name = "certifi"
-version = "2022.12.7"
+version = "2023.5.7"
description = "Python package for providing Mozilla's CA Bundle."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
- {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
+ {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
+ {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
]
[[package]]
name = "cffi"
version = "1.15.1"
description = "Foreign Function Interface for Python calling C code."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -307,107 +315,92 @@ pycparser = "*"
[[package]]
name = "charset-normalizer"
-version = "3.0.1"
+version = "3.1.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.7.0"
files = [
- {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"},
- {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"},
- {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"},
- {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"},
- {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"},
- {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"},
- {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"},
- {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"},
+ {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
+ {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
]
[[package]]
name = "cleo"
version = "2.0.1"
description = "Cleo allows you to create beautiful and testable command-line interfaces."
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -423,7 +416,6 @@ rapidfuzz = ">=2.2.0,<3.0.0"
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
-category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -433,27 +425,27 @@ files = [
[[package]]
name = "comm"
-version = "0.1.2"
+version = "0.1.3"
description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "comm-0.1.2-py3-none-any.whl", hash = "sha256:9f3abf3515112fa7c55a42a6a5ab358735c9dccc8b5910a9d8e3ef5998130666"},
- {file = "comm-0.1.2.tar.gz", hash = "sha256:3e2f5826578e683999b93716285b3b1f344f157bf75fa9ce0a797564e742f062"},
+ {file = "comm-0.1.3-py3-none-any.whl", hash = "sha256:16613c6211e20223f215fc6d3b266a247b6e2641bf4e0a3ad34cb1aff2aa3f37"},
+ {file = "comm-0.1.3.tar.gz", hash = "sha256:a61efa9daffcfbe66fd643ba966f846a624e4e6d6767eda9cf6e993aadaab93e"},
]
[package.dependencies]
traitlets = ">=5.3"
[package.extras]
+lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"]
test = ["pytest"]
+typing = ["mypy (>=0.990)"]
[[package]]
name = "contourpy"
version = "1.0.7"
description = "Python library for calculating contours of 2D quadrilateral grids"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -528,7 +520,6 @@ test-no-images = ["pytest"]
name = "coverage"
version = "6.5.0"
description = "Code coverage measurement for Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -594,7 +585,6 @@ toml = ["tomli"]
name = "cpplint"
version = "1.6.1"
description = "Automated checker to ensure C++ files follow Google's style guide"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -610,7 +600,6 @@ test = ["configparser (<=3.7.4)", "pyparsing (<3)", "pytest (>=4.6,<5.0)", "pyte
name = "crashtest"
version = "0.4.1"
description = "Manage Python errors with ease"
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -620,35 +609,30 @@ files = [
[[package]]
name = "cryptography"
-version = "39.0.1"
+version = "41.0.1"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965"},
- {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc"},
- {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41"},
- {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505"},
- {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6"},
- {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502"},
- {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f"},
- {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106"},
- {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c"},
- {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4"},
- {file = "cryptography-39.0.1-cp36-abi3-win32.whl", hash = "sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8"},
- {file = "cryptography-39.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac"},
- {file = "cryptography-39.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad"},
- {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c5caeb8188c24888c90b5108a441c106f7faa4c4c075a2bcae438c6e8ca73cef"},
- {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4789d1e3e257965e960232345002262ede4d094d1a19f4d3b52e48d4d8f3b885"},
- {file = "cryptography-39.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388"},
- {file = "cryptography-39.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336"},
- {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2"},
- {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e"},
- {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0"},
- {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6"},
- {file = "cryptography-39.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a"},
- {file = "cryptography-39.0.1.tar.gz", hash = "sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695"},
+ {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"},
+ {file = "cryptography-41.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a"},
+ {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca"},
+ {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43"},
+ {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b"},
+ {file = "cryptography-41.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3"},
+ {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db"},
+ {file = "cryptography-41.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31"},
+ {file = "cryptography-41.0.1-cp37-abi3-win32.whl", hash = "sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5"},
+ {file = "cryptography-41.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c"},
+ {file = "cryptography-41.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb"},
+ {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3"},
+ {file = "cryptography-41.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039"},
+ {file = "cryptography-41.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc"},
+ {file = "cryptography-41.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485"},
+ {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c"},
+ {file = "cryptography-41.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a"},
+ {file = "cryptography-41.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5"},
+ {file = "cryptography-41.0.1.tar.gz", hash = "sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006"},
]
[package.dependencies]
@@ -657,18 +641,17 @@ cffi = ">=1.12"
[package.extras]
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
-pep8test = ["black", "check-manifest", "mypy", "ruff", "types-pytz", "types-requests"]
-sdist = ["setuptools-rust (>=0.11.4)"]
+nox = ["nox"]
+pep8test = ["black", "check-sdist", "mypy", "ruff"]
+sdist = ["build"]
ssh = ["bcrypt (>=3.1.5)"]
-test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist", "pytz"]
+test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
test-randomorder = ["pytest-randomly"]
-tox = ["tox"]
[[package]]
name = "cycler"
version = "0.11.0"
description = "Composable style cycles"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -680,7 +663,6 @@ files = [
name = "darglint"
version = "1.8.1"
description = "A utility for ensuring Google-style docstrings stay up to date with the source code."
-category = "dev"
optional = false
python-versions = ">=3.6,<4.0"
files = [
@@ -690,36 +672,35 @@ files = [
[[package]]
name = "debugpy"
-version = "1.6.6"
+version = "1.6.7"
description = "An implementation of the Debug Adapter Protocol for Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "debugpy-1.6.6-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:0ea1011e94416e90fb3598cc3ef5e08b0a4dd6ce6b9b33ccd436c1dffc8cd664"},
- {file = "debugpy-1.6.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dff595686178b0e75580c24d316aa45a8f4d56e2418063865c114eef651a982e"},
- {file = "debugpy-1.6.6-cp310-cp310-win32.whl", hash = "sha256:87755e173fcf2ec45f584bb9d61aa7686bb665d861b81faa366d59808bbd3494"},
- {file = "debugpy-1.6.6-cp310-cp310-win_amd64.whl", hash = "sha256:72687b62a54d9d9e3fb85e7a37ea67f0e803aaa31be700e61d2f3742a5683917"},
- {file = "debugpy-1.6.6-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:78739f77c58048ec006e2b3eb2e0cd5a06d5f48c915e2fc7911a337354508110"},
- {file = "debugpy-1.6.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23c29e40e39ad7d869d408ded414f6d46d82f8a93b5857ac3ac1e915893139ca"},
- {file = "debugpy-1.6.6-cp37-cp37m-win32.whl", hash = "sha256:7aa7e103610e5867d19a7d069e02e72eb2b3045b124d051cfd1538f1d8832d1b"},
- {file = "debugpy-1.6.6-cp37-cp37m-win_amd64.whl", hash = "sha256:f6383c29e796203a0bba74a250615ad262c4279d398e89d895a69d3069498305"},
- {file = "debugpy-1.6.6-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:23363e6d2a04d726bbc1400bd4e9898d54419b36b2cdf7020e3e215e1dcd0f8e"},
- {file = "debugpy-1.6.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b5d1b13d7c7bf5d7cf700e33c0b8ddb7baf030fcf502f76fc061ddd9405d16c"},
- {file = "debugpy-1.6.6-cp38-cp38-win32.whl", hash = "sha256:70ab53918fd907a3ade01909b3ed783287ede362c80c75f41e79596d5ccacd32"},
- {file = "debugpy-1.6.6-cp38-cp38-win_amd64.whl", hash = "sha256:c05349890804d846eca32ce0623ab66c06f8800db881af7a876dc073ac1c2225"},
- {file = "debugpy-1.6.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a771739902b1ae22a120dbbb6bd91b2cae6696c0e318b5007c5348519a4211c6"},
- {file = "debugpy-1.6.6-cp39-cp39-win32.whl", hash = "sha256:549ae0cb2d34fc09d1675f9b01942499751d174381b6082279cf19cdb3c47cbe"},
- {file = "debugpy-1.6.6-cp39-cp39-win_amd64.whl", hash = "sha256:de4a045fbf388e120bb6ec66501458d3134f4729faed26ff95de52a754abddb1"},
- {file = "debugpy-1.6.6-py2.py3-none-any.whl", hash = "sha256:be596b44448aac14eb3614248c91586e2bc1728e020e82ef3197189aae556115"},
- {file = "debugpy-1.6.6.zip", hash = "sha256:b9c2130e1c632540fbf9c2c88341493797ddf58016e7cba02e311de9b0a96b67"},
+ {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"},
+ {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"},
+ {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"},
+ {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"},
+ {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"},
+ {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"},
+ {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"},
+ {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"},
+ {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"},
+ {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"},
+ {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"},
+ {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"},
+ {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"},
+ {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"},
+ {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"},
+ {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"},
+ {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"},
+ {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"},
]
[[package]]
name = "decorator"
version = "5.1.1"
description = "Decorators for Humans"
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -731,7 +712,6 @@ files = [
name = "defusedxml"
version = "0.7.1"
description = "XML bomb protection for Python stdlib modules"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -743,7 +723,6 @@ files = [
name = "distlib"
version = "0.3.6"
description = "Distribution utilities"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -755,7 +734,6 @@ files = [
name = "docutils"
version = "0.17.1"
description = "Docutils -- Python Documentation Utilities"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -765,75 +743,67 @@ files = [
[[package]]
name = "dulwich"
-version = "0.20.50"
+version = "0.21.5"
description = "Python Git Library"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "dulwich-0.20.50-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:97f02f8d500d4af08dc022d697c56e8539171acc3f575c2fe9acf3b078e5c8c9"},
- {file = "dulwich-0.20.50-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7301773e5cc16d521bc6490e73772a86a4d1d0263de506f08b54678cc4e2f061"},
- {file = "dulwich-0.20.50-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b70106580ed11f45f4c32d2831d0c9c9f359bc2415fff4a6be443e3a36811398"},
- {file = "dulwich-0.20.50-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f9c4f2455f966cad94648278fa9972e4695b35d04f82792fa58e1ea15dd83f0"},
- {file = "dulwich-0.20.50-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9163fbb021a8ad9c35a0814a5eedf45a8eb3a0b764b865d7016d901fc5a947fc"},
- {file = "dulwich-0.20.50-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:322ff8ff6aa4d6d36294cd36de1c84767eb1903c7db3e7b4475ad091febf5363"},
- {file = "dulwich-0.20.50-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5d3290a45651c8e534f8e83ae2e30322aefdd162f0f338bae2e79a6ee5a87513"},
- {file = "dulwich-0.20.50-cp310-cp310-win32.whl", hash = "sha256:80ab07131a6e68594441f5c4767e9e44e87fceafc3e347e541c928a18c679bd8"},
- {file = "dulwich-0.20.50-cp310-cp310-win_amd64.whl", hash = "sha256:eefe786a6010f8546baac4912113eeed4e397ddb8c433a345b548a04d4176496"},
- {file = "dulwich-0.20.50-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df3562dde3079d57287c233d45b790bc967c5aae975c9a7b07ca30e60e055512"},
- {file = "dulwich-0.20.50-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1ae18d5805f0c0c5dac65795f8d48660437166b12ee2c0ffea95bfdbf9c1051"},
- {file = "dulwich-0.20.50-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2f7df39bd1378d3b0bfb3e7fc930fd0191924af1f0ef587bcd9946afe076c06"},
- {file = "dulwich-0.20.50-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:731e7f319b34251fadeb362ada1d52cc932369d9cdfa25c0e41150cda28773d0"},
- {file = "dulwich-0.20.50-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d11d44176e5d2fa8271fc86ad1e0a8731b9ad8f77df64c12846b30e16135eb"},
- {file = "dulwich-0.20.50-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7aaabb8e4beadd53f75f853a981caaadef3ef130e5645c902705704eaf136daa"},
- {file = "dulwich-0.20.50-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c3dc9f97ec8d3db08d9723b9fd06f3e52c15b84c800d153cfb59b0a3dc8b8d40"},
- {file = "dulwich-0.20.50-cp311-cp311-win32.whl", hash = "sha256:3b1964fa80cafd5a1fd71615b0313daf6f3295c6ab05656ea0c1d2423539904a"},
- {file = "dulwich-0.20.50-cp311-cp311-win_amd64.whl", hash = "sha256:a24a3893108f3b97beb958670d5f3f2a3bec73a1fe18637a572a85abd949a1c4"},
- {file = "dulwich-0.20.50-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6d409a282f8848fd6c8d7c7545ad2f75c16de5d5977de202642f1d50fdaac554"},
- {file = "dulwich-0.20.50-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5411d0f1092152e1c0bb916ae490fe181953ae1b8d13f4e68661253e10b78dbb"},
- {file = "dulwich-0.20.50-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6343569f998ce429e2a5d813c56768ac51b496522401db950f0aa44240bfa901"},
- {file = "dulwich-0.20.50-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a405cd236766060894411614a272cfb86fe86cde5ca73ef264fc4fa5a715fff4"},
- {file = "dulwich-0.20.50-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ee0f9b02019c0ea84cdd31c00a0c283669b771c85612997a911715cf84e33d99"},
- {file = "dulwich-0.20.50-cp36-cp36m-win32.whl", hash = "sha256:2644466270267270f2157ea6f1c0aa224f6f3bf06a307fc39954e6b4b3d82bae"},
- {file = "dulwich-0.20.50-cp36-cp36m-win_amd64.whl", hash = "sha256:d4629635a97e3af1b5da48071e00c8e70fad85f3266fadabe1f5a8f49172c507"},
- {file = "dulwich-0.20.50-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0e4862f318d99cc8a500e3622a89613a88c07d957a0f628cdc2ed86addff790f"},
- {file = "dulwich-0.20.50-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c96e3fb9d48c0454dc242c7accc7819780c9a7f29e441a9eff12361ed0fa35f9"},
- {file = "dulwich-0.20.50-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc6092a4f0bbbff2e553e87a9c6325955b64ea43fca21297c8182e19ae8a43c"},
- {file = "dulwich-0.20.50-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:519b627d49d273e2fd01c79d09e578675ca6cd05193c1787e9ef165c9a1d66ea"},
- {file = "dulwich-0.20.50-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a75cab01b909c4c683c2083e060e378bc01701b7366b5a7d9846ef6d3b9e3d5"},
- {file = "dulwich-0.20.50-cp37-cp37m-win32.whl", hash = "sha256:ea8ffe26d91dbcd5580dbd5a07270a12ea57b091604d77184da0a0d9fad50ed3"},
- {file = "dulwich-0.20.50-cp37-cp37m-win_amd64.whl", hash = "sha256:8f3af857f94021cae1322d86925bfc0dd31e501e885ab5db275473bfac0bb39d"},
- {file = "dulwich-0.20.50-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3fb35cedb1243bc420d885ef5b4afd642c6ac8f07ddfc7fdbca1becf9948bf7e"},
- {file = "dulwich-0.20.50-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4bb23a9cec63e16c0e432335f068169b73dd44fa9318dd7cd7a4ca83607ff367"},
- {file = "dulwich-0.20.50-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5267619b34ddaf8d9a6b841492cd17a971fd25bf9a5657f2de928385c3a08b94"},
- {file = "dulwich-0.20.50-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9091f1d53a3c0747cbf0bd127c64e7f09b770264d8fb53e284383fcdf69154e7"},
- {file = "dulwich-0.20.50-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ec7c8fea2b44187a3b545e6c11ab9947ffb122647b07abcdb7cc3aaa770c0e"},
- {file = "dulwich-0.20.50-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:11b180b80363b4fc70664197028181a17ae4c52df9965a29b62a6c52e40c2dbe"},
- {file = "dulwich-0.20.50-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c83e7840d9d0a94d7033bc109efe0c22dfcdcd816bcd4469085e42809e3bf5ba"},
- {file = "dulwich-0.20.50-cp38-cp38-win32.whl", hash = "sha256:c075f69c2de19d9fd97e3b70832d2b42c6a4a5d909b3ffd1963b67d86029f95f"},
- {file = "dulwich-0.20.50-cp38-cp38-win_amd64.whl", hash = "sha256:06775c5713cfeda778c7c67d4422b5e7554d3a7f644f1dde646cdf486a30285a"},
- {file = "dulwich-0.20.50-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:49f66f1c057c18d7d60363f461f4ab8329320fbe1f02a7a33c255864a7d3c942"},
- {file = "dulwich-0.20.50-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4e541cd690a5e3d55082ed51732d755917e933cddeb4b0204f2a5ec5d5d7b60b"},
- {file = "dulwich-0.20.50-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:80e8750ee2fa0ab2784a095956077758e5f6107de27f637c4b9d18406652c22c"},
- {file = "dulwich-0.20.50-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fbb6368f18451dc44c95c55e1a609d1a01d3821f7ed480b22b2aea1baca0f4a7"},
- {file = "dulwich-0.20.50-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3ee45001411b638641819b7b3b33f31f13467c84066e432256580fcab7d8815"},
- {file = "dulwich-0.20.50-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4842e22ed863a776b36ef8ffe9ed7b772eb452b42c8d02975c29d27e3bc50ab4"},
- {file = "dulwich-0.20.50-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:790e4a641284a7fb4d56ebdaf8b324a5826fbbb9c54307c06f586f9f6a5e56db"},
- {file = "dulwich-0.20.50-cp39-cp39-win32.whl", hash = "sha256:f08406b6b789dea5c95ba1130a0801d8748a67f18be940fe7486a8b481fde875"},
- {file = "dulwich-0.20.50-cp39-cp39-win_amd64.whl", hash = "sha256:78c388ad421199000fb7b5ed5f0c7b509b3e31bd7cad303786a4d0bf89b82f60"},
- {file = "dulwich-0.20.50-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:cb194c53109131bcbcd1ca430fcd437cdaf2d33e204e45fbe121c47eaa43e9af"},
- {file = "dulwich-0.20.50-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7542a72c5640dd0620862d6df8688f02a6c336359b5af9b3fcfe11b7fa6652f"},
- {file = "dulwich-0.20.50-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4aa1d0861517ebbbe0e0084cc9ab4f7ab720624a3eda2bd10e45f774ab858db8"},
- {file = "dulwich-0.20.50-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:583c6bbc27f13fe2e41a19f6987a42681c6e4f6959beae0a6e5bb033b8b081a8"},
- {file = "dulwich-0.20.50-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0c61c193d02c0e1e0d758cdd57ae76685c368d09a01f00d704ba88bd96767cfe"},
- {file = "dulwich-0.20.50-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2edbff3053251985f10702adfafbee118298d383ef5b5b432a5f22d1f1915df"},
- {file = "dulwich-0.20.50-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a344230cadfc5d315752add6ce9d4cfcfc6c85e36bbf57fce9444bcc7c6ea8fb"},
- {file = "dulwich-0.20.50-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:57bff9bde0b6b05b00c6acbb1a94357caddb2908ed7026a48c715ff50d220335"},
- {file = "dulwich-0.20.50-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e29a3c2037761fa816aa556e78364dfc8e3f44b873db2d17aed96f9b06ac83a3"},
- {file = "dulwich-0.20.50-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2aa2a4a84029625bf9c63771f8a628db1f3be2d2ea3cb8b17942cd4317797152"},
- {file = "dulwich-0.20.50-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd9fa00971ecf059bb358085a942ecac5be4ff71acdf299f44c8cbc45c18659f"},
- {file = "dulwich-0.20.50-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:af4adac92fb95671ea3a24f2f8e5e5e8f638711ce9c33a3ca6cd68bf1ff7d99f"},
- {file = "dulwich-0.20.50.tar.gz", hash = "sha256:50a941796b2c675be39be728d540c16b5b7ce77eb9e1b3f855650ece6832d2be"},
+ {file = "dulwich-0.21.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8864719bc176cdd27847332a2059127e2f7bab7db2ff99a999873cb7fff54116"},
+ {file = "dulwich-0.21.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3800cdc17d144c1f7e114972293bd6c46688f5bcc2c9228ed0537ded72394082"},
+ {file = "dulwich-0.21.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e2f676bfed8146966fe934ee734969d7d81548fbd250a8308582973670a9dab1"},
+ {file = "dulwich-0.21.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db330fb59fe3b9d253bdf0e49a521739db83689520c4921ab1c5242aaf77b82"},
+ {file = "dulwich-0.21.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e8f6d4f4f4d01dd1d3c968e486d4cd77f96f772da7265941bc506de0944ddb9"},
+ {file = "dulwich-0.21.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1cc0c9ba19ac1b2372598802bc9201a9c45e5d6f1f7a80ec40deeb10acc4e9ae"},
+ {file = "dulwich-0.21.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:61e10242b5a7a82faa8996b2c76239cfb633620b02cdd2946e8af6e7eb31d651"},
+ {file = "dulwich-0.21.5-cp310-cp310-win32.whl", hash = "sha256:7f357639b56146a396f48e5e0bc9bbaca3d6d51c8340bd825299272b588fff5f"},
+ {file = "dulwich-0.21.5-cp310-cp310-win_amd64.whl", hash = "sha256:891d5c73e2b66d05dbb502e44f027dc0dbbd8f6198bc90dae348152e69d0befc"},
+ {file = "dulwich-0.21.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45d6198e804b539708b73a003419e48fb42ff2c3c6dd93f63f3b134dff6dd259"},
+ {file = "dulwich-0.21.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c2a565d4e704d7f784cdf9637097141f6d47129c8fffc2fac699d57cb075a169"},
+ {file = "dulwich-0.21.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:823091d6b6a1ea07dc4839c9752198fb39193213d103ac189c7669736be2eaff"},
+ {file = "dulwich-0.21.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2c9931b657f2206abec0964ec2355ee2c1e04d05f8864e823ffa23c548c4548"},
+ {file = "dulwich-0.21.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dc358c2ee727322a09b7c6da43d47a1026049dbd3ad8d612eddca1f9074b298"},
+ {file = "dulwich-0.21.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6155ab7388ee01c670f7c5d8003d4e133eebebc7085a856c007989f0ba921b36"},
+ {file = "dulwich-0.21.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a605e10d72f90a39ea2e634fbfd80f866fc4df29a02ea6db52ae92e5fd4a2003"},
+ {file = "dulwich-0.21.5-cp311-cp311-win32.whl", hash = "sha256:daa607370722c3dce99a0022397c141caefb5ed32032a4f72506f4817ea6405b"},
+ {file = "dulwich-0.21.5-cp311-cp311-win_amd64.whl", hash = "sha256:5e56b2c1911c344527edb2bf1a4356e2fb7e086b1ba309666e1e5c2224cdca8a"},
+ {file = "dulwich-0.21.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:85d3401d08b1ec78c7d58ae987c4bb7b768a438f3daa74aeb8372bebc7fb16fa"},
+ {file = "dulwich-0.21.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90479608e49db93d8c9e4323bc0ec5496678b535446e29d8fd67dc5bbb5d51bf"},
+ {file = "dulwich-0.21.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9a6bf99f57bcac4c77fc60a58f1b322c91cc4d8c65dc341f76bf402622f89cb"},
+ {file = "dulwich-0.21.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3e68b162af2aae995355e7920f89d50d72b53d56021e5ac0a546d493b17cbf7e"},
+ {file = "dulwich-0.21.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0ab86d6d42e385bf3438e70f3c9b16de68018bd88929379e3484c0ef7990bd3c"},
+ {file = "dulwich-0.21.5-cp37-cp37m-win32.whl", hash = "sha256:f2eeca6d61366cf5ee8aef45bed4245a67d4c0f0d731dc2383eabb80fa695683"},
+ {file = "dulwich-0.21.5-cp37-cp37m-win_amd64.whl", hash = "sha256:1b20a3656b48c941d49c536824e1e5278a695560e8de1a83b53a630143c4552e"},
+ {file = "dulwich-0.21.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3932b5e17503b265a85f1eda77ede647681c3bab53bc9572955b6b282abd26ea"},
+ {file = "dulwich-0.21.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6616132d219234580de88ceb85dd51480dc43b1bdc05887214b8dd9cfd4a9d40"},
+ {file = "dulwich-0.21.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:eaf6c7fb6b13495c19c9aace88821c2ade3c8c55b4e216cd7cc55d3e3807d7fa"},
+ {file = "dulwich-0.21.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be12a46f73023970125808a4a78f610c055373096c1ecea3280edee41613eba8"},
+ {file = "dulwich-0.21.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baecef0d8b9199822c7912876a03a1af17833f6c0d461efb62decebd45897e49"},
+ {file = "dulwich-0.21.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:82f632afb9c7c341a875d46aaa3e6c5e586c7a64ce36c9544fa400f7e4f29754"},
+ {file = "dulwich-0.21.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82cdf482f8f51fcc965ffad66180b54a9abaea9b1e985a32e1acbfedf6e0e363"},
+ {file = "dulwich-0.21.5-cp38-cp38-win32.whl", hash = "sha256:c8ded43dc0bd2e65420eb01e778034be5ca7f72e397a839167eda7dcb87c4248"},
+ {file = "dulwich-0.21.5-cp38-cp38-win_amd64.whl", hash = "sha256:2aba0fdad2a19bd5bb3aad6882580cb33359c67b48412ccd4cfccd932012b35e"},
+ {file = "dulwich-0.21.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fd4ad079758514375f11469e081723ba8831ce4eaa1a64b41f06a3a866d5ac34"},
+ {file = "dulwich-0.21.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fe62685bf356bfb4d0738f84a3fcf0d1fc9e11fee152e488a20b8c66a52429e"},
+ {file = "dulwich-0.21.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aae448da7d80306dda4fc46292fed7efaa466294571ab3448be16714305076f1"},
+ {file = "dulwich-0.21.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b24cb1fad0525dba4872e9381bc576ea2a6dcdf06b0ed98f8e953e3b1d719b89"},
+ {file = "dulwich-0.21.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e39b7c2c9bda6acae83b25054650a8bb7e373e886e2334721d384e1479bf04b"},
+ {file = "dulwich-0.21.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26456dba39d1209fca17187db06967130e27eeecad2b3c2bbbe63467b0bf09d6"},
+ {file = "dulwich-0.21.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:281310644e02e3aa6d76bcaffe2063b9031213c4916b5f1a6e68c25bdecfaba4"},
+ {file = "dulwich-0.21.5-cp39-cp39-win32.whl", hash = "sha256:4814ca3209dabe0fe7719e9545fbdad7f8bb250c5a225964fe2a31069940c4cf"},
+ {file = "dulwich-0.21.5-cp39-cp39-win_amd64.whl", hash = "sha256:c922a4573267486be0ef85216f2da103fb38075b8465dc0e90457843884e4860"},
+ {file = "dulwich-0.21.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e52b20c4368171b7d32bd3ab0f1d2402e76ad4f2ea915ff9aa73bc9fa2b54d6d"},
+ {file = "dulwich-0.21.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeb736d777ee21f2117a90fc453ee181aa7eedb9e255b5ef07c51733f3fe5cb6"},
+ {file = "dulwich-0.21.5-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e8a79c1ed7166f32ad21974fa98d11bf6fd74e94a47e754c777c320e01257c6"},
+ {file = "dulwich-0.21.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b943517e30bd651fbc275a892bb96774f3893d95fe5a4dedd84496a98eaaa8ab"},
+ {file = "dulwich-0.21.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:32493a456358a3a6c15bbda07106fc3d4cc50834ee18bc7717968d18be59b223"},
+ {file = "dulwich-0.21.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0aa44b812d978fc22a04531f5090c3c369d5facd03fa6e0501d460a661800c7f"},
+ {file = "dulwich-0.21.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f46bcb6777e5f9f4af24a2bd029e88b77316269d24ce66be590e546a0d8f7b7"},
+ {file = "dulwich-0.21.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a917fd3b4493db3716da2260f16f6b18f68d46fbe491d851d154fc0c2d984ae4"},
+ {file = "dulwich-0.21.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:684c52cff867d10c75a7238151ca307582b3d251bbcd6db9e9cffbc998ef804e"},
+ {file = "dulwich-0.21.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9019189d7a8f7394df6a22cd5b484238c5776e42282ad5d6d6c626b4c5f43597"},
+ {file = "dulwich-0.21.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:494024f74c2eef9988adb4352b3651ac1b6c0466176ec62b69d3d3672167ba68"},
+ {file = "dulwich-0.21.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f9b6ac1b1c67fc6083c42b7b6cd3b211292c8a6517216c733caf23e8b103ab6d"},
+ {file = "dulwich-0.21.5.tar.gz", hash = "sha256:70955e4e249ddda6e34a4636b90f74e931e558f993b17c52570fa6144b993103"},
]
[package.dependencies]
@@ -849,7 +819,6 @@ pgp = ["gpg"]
name = "entrypoints"
version = "0.4"
description = "Discover and load entry points from installed packages."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -859,26 +828,24 @@ files = [
[[package]]
name = "eradicate"
-version = "2.1.0"
+version = "2.2.0"
description = "Removes commented-out code."
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "eradicate-2.1.0-py3-none-any.whl", hash = "sha256:8bfaca181db9227dc88bdbce4d051a9627604c2243e7d85324f6d6ce0fd08bb2"},
- {file = "eradicate-2.1.0.tar.gz", hash = "sha256:aac7384ab25b1bf21c4c012de9b4bf8398945a14c98c911545b2ea50ab558014"},
+ {file = "eradicate-2.2.0-py3-none-any.whl", hash = "sha256:751813c315a48ce7e3d0483410991015342d380a956e86e0265c61bfb875bcbc"},
+ {file = "eradicate-2.2.0.tar.gz", hash = "sha256:c329a05def6a4b558dab58bb1b694f5209706b7c99ba174d226dfdb69a5ba0da"},
]
[[package]]
name = "exceptiongroup"
-version = "1.1.0"
+version = "1.1.1"
description = "Backport of PEP 654 (exception groups)"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"},
- {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
+ {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
+ {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
]
[package.extras]
@@ -888,7 +855,6 @@ test = ["pytest (>=6)"]
name = "executing"
version = "1.2.0"
description = "Get the currently executing AST node of a frame, and other information"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -901,14 +867,13 @@ tests = ["asttokens", "littleutils", "pytest", "rich"]
[[package]]
name = "fastjsonschema"
-version = "2.16.2"
+version = "2.17.1"
description = "Fastest Python implementation of JSON schema"
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "fastjsonschema-2.16.2-py3-none-any.whl", hash = "sha256:21f918e8d9a1a4ba9c22e09574ba72267a6762d47822db9add95f6454e51cc1c"},
- {file = "fastjsonschema-2.16.2.tar.gz", hash = "sha256:01e366f25d9047816fe3d288cbfc3e10541daf0af2044763f3d0ade42476da18"},
+ {file = "fastjsonschema-2.17.1-py3-none-any.whl", hash = "sha256:4b90b252628ca695280924d863fe37234eebadc29c5360d322571233dc9746e0"},
+ {file = "fastjsonschema-2.17.1.tar.gz", hash = "sha256:f4eeb8a77cef54861dbf7424ac8ce71306f12cbb086c45131bcba2c6a4f726e3"},
]
[package.extras]
@@ -916,25 +881,23 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc
[[package]]
name = "filelock"
-version = "3.9.0"
+version = "3.12.0"
description = "A platform independent file lock."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "filelock-3.9.0-py3-none-any.whl", hash = "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"},
- {file = "filelock-3.9.0.tar.gz", hash = "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de"},
+ {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"},
+ {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"},
]
[package.extras]
-docs = ["furo (>=2022.12.7)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
-testing = ["covdefaults (>=2.2.2)", "coverage (>=7.0.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"]
+docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
[[package]]
name = "flake8"
version = "4.0.1"
description = "the modular source code checker: pep8 pyflakes and co"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -951,7 +914,6 @@ pyflakes = ">=2.4.0,<2.5.0"
name = "flake8-bandit"
version = "3.0.0"
description = "Automated security testing with bandit and flake8."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -969,7 +931,6 @@ pycodestyle = "*"
name = "flake8-bugbear"
version = "22.12.6"
description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -988,7 +949,6 @@ dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"]
name = "flake8-builtins"
version = "1.5.3"
description = "Check for python builtins being used as variables or parameters."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1004,14 +964,13 @@ test = ["coverage", "coveralls", "mock", "pytest", "pytest-cov"]
[[package]]
name = "flake8-comprehensions"
-version = "3.10.1"
+version = "3.12.0"
description = "A flake8 plugin to help you write better list/set/dict comprehensions."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "flake8-comprehensions-3.10.1.tar.gz", hash = "sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab"},
- {file = "flake8_comprehensions-3.10.1-py3-none-any.whl", hash = "sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e"},
+ {file = "flake8_comprehensions-3.12.0-py3-none-any.whl", hash = "sha256:013234637ec7dfcb7cd2900578fb53c512f81db909cefe371c019232695c362d"},
+ {file = "flake8_comprehensions-3.12.0.tar.gz", hash = "sha256:419ef1a6e8de929203791a5e8ff5e3906caeba13eb3290eebdbf88a9078d502e"},
]
[package.dependencies]
@@ -1021,7 +980,6 @@ flake8 = ">=3.0,<3.2.0 || >3.2.0"
name = "flake8-docstrings"
version = "1.7.0"
description = "Extension for flake8 which uses pydocstyle to check docstrings"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1037,7 +995,6 @@ pydocstyle = ">=2.1"
name = "flake8-eradicate"
version = "1.4.0"
description = "Flake8 plugin to find commented out code"
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@@ -1054,7 +1011,6 @@ flake8 = ">=3.5,<6"
name = "flake8-isort"
version = "4.2.0"
description = "flake8 plugin that integrates isort ."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1073,7 +1029,6 @@ test = ["pytest-cov"]
name = "flake8-mutable"
version = "1.2.0"
description = "mutable defaults flake8 extension"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1088,7 +1043,6 @@ flake8 = "*"
name = "flake8-plugin-utils"
version = "1.3.2"
description = "The package provides base classes and utils for flake8 plugin writing"
-category = "dev"
optional = false
python-versions = ">=3.6,<4.0"
files = [
@@ -1100,7 +1054,6 @@ files = [
name = "flake8-polyfill"
version = "1.0.2"
description = "Polyfill package for Flake8 plugins"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1115,7 +1068,6 @@ flake8 = "*"
name = "flake8-pytest-style"
version = "1.7.2"
description = "A flake8 plugin checking common style issues or inconsistencies with pytest-based tests."
-category = "dev"
optional = false
python-versions = ">=3.7.2,<4.0.0"
files = [
@@ -1130,7 +1082,6 @@ flake8-plugin-utils = ">=1.3.2,<2.0.0"
name = "flake8-spellcheck"
version = "0.25.0"
description = "Spellcheck variables, comments and docstrings"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1143,14 +1094,13 @@ flake8 = ">3.0.0"
[[package]]
name = "flakeheaven"
-version = "3.2.1"
+version = "3.3.0"
description = "FlakeHeaven is a [Flake8](https://gitlab.com/pycqa/flake8) wrapper to make it cool."
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
- {file = "flakeheaven-3.2.1-py3-none-any.whl", hash = "sha256:fdae542414a8cd327dbbc969bb18d5972379570f6562af21b4a83f67bdd6b87c"},
- {file = "flakeheaven-3.2.1.tar.gz", hash = "sha256:f2d54aedd98b817e94c8c0fcc0da1230b43dbf911ce38aa412d00eb5db6fb71d"},
+ {file = "flakeheaven-3.3.0-py3-none-any.whl", hash = "sha256:ae246197a178845b30b63fc03023f7ba925cc84cc96314ec19807dafcd6b39a3"},
+ {file = "flakeheaven-3.3.0.tar.gz", hash = "sha256:eb07860e028ff8dd56cce742c4766624a37a4ce397fd34300254ab623d13047b"},
]
[package.dependencies]
@@ -1166,18 +1116,17 @@ docs = ["alabaster", "myst-parser (>=0.18.0,<0.19.0)", "pygments-github-lexers",
[[package]]
name = "fonttools"
-version = "4.38.0"
+version = "4.39.4"
description = "Tools to manipulate font files"
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "fonttools-4.38.0-py3-none-any.whl", hash = "sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb"},
- {file = "fonttools-4.38.0.zip", hash = "sha256:2bb244009f9bf3fa100fc3ead6aeb99febe5985fa20afbfbaa2f8946c2fbdaf1"},
+ {file = "fonttools-4.39.4-py3-none-any.whl", hash = "sha256:106caf6167c4597556b31a8d9175a3fdc0356fdcd70ab19973c3b0d4c893c461"},
+ {file = "fonttools-4.39.4.zip", hash = "sha256:dba8d7cdb8e2bac1b3da28c5ed5960de09e59a2fe7e63bb73f5a59e57b0430d2"},
]
[package.extras]
-all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=14.0.0)", "xattr", "zopfli (>=0.1.4)"]
+all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"]
graphite = ["lz4 (>=1.7.4.2)"]
interpolatable = ["munkres", "scipy"]
lxml = ["lxml (>=4.0,<5)"]
@@ -1187,14 +1136,13 @@ repacker = ["uharfbuzz (>=0.23.0)"]
symfont = ["sympy"]
type1 = ["xattr"]
ufo = ["fs (>=2.2.0,<3)"]
-unicode = ["unicodedata2 (>=14.0.0)"]
+unicode = ["unicodedata2 (>=15.0.0)"]
woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"]
[[package]]
name = "gitdb"
version = "4.0.10"
description = "Git Object Database"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1209,7 +1157,6 @@ smmap = ">=3.0.1,<6"
name = "gitpython"
version = "3.1.31"
description = "GitPython is a Python library used to interact with Git repositories"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1224,7 +1171,6 @@ gitdb = ">=4.0.1,<5"
name = "html5lib"
version = "1.1"
description = "HTML parser based on the WHATWG HTML specification"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -1246,7 +1192,6 @@ lxml = ["lxml"]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -1258,7 +1203,6 @@ files = [
name = "imagesize"
version = "1.4.1"
description = "Getting image size from png/jpeg/jpeg2000/gif file"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -1268,34 +1212,32 @@ files = [
[[package]]
name = "importlib-metadata"
-version = "4.13.0"
+version = "6.6.0"
description = "Read metadata from Python packages"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "importlib_metadata-4.13.0-py3-none-any.whl", hash = "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116"},
- {file = "importlib_metadata-4.13.0.tar.gz", hash = "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d"},
+ {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
+ {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
[[package]]
name = "importlib-resources"
-version = "5.10.2"
+version = "5.12.0"
description = "Read resources from Python packages"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "importlib_resources-5.10.2-py3-none-any.whl", hash = "sha256:7d543798b0beca10b6a01ac7cafda9f822c54db9e8376a6bf57e0cbd74d486b6"},
- {file = "importlib_resources-5.10.2.tar.gz", hash = "sha256:e4a96c8cc0339647ff9a5e0550d9f276fc5a01ffa276012b58ec108cfd7b8484"},
+ {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"},
+ {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"},
]
[package.dependencies]
@@ -1309,7 +1251,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1317,16 +1258,26 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
+[[package]]
+name = "installer"
+version = "0.7.0"
+description = "A library for installing Python wheels."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "installer-0.7.0-py3-none-any.whl", hash = "sha256:05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53"},
+ {file = "installer-0.7.0.tar.gz", hash = "sha256:a26d3e3116289bb08216e0d0f7d925fcef0b0194eedfa0c944bcaaa106c4b631"},
+]
+
[[package]]
name = "ipykernel"
-version = "6.21.2"
+version = "6.23.1"
description = "IPython Kernel for Jupyter"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "ipykernel-6.21.2-py3-none-any.whl", hash = "sha256:430d00549b6aaf49bd0f5393150691edb1815afa62d457ee6b1a66b25cb17874"},
- {file = "ipykernel-6.21.2.tar.gz", hash = "sha256:6e9213484e4ce1fb14267ee435e18f23cc3a0634e635b9fb4ed4677b84e0fdf8"},
+ {file = "ipykernel-6.23.1-py3-none-any.whl", hash = "sha256:77aeffab056c21d16f1edccdc9e5ccbf7d96eb401bd6703610a21be8b068aadc"},
+ {file = "ipykernel-6.23.1.tar.gz", hash = "sha256:1aba0ae8453e15e9bc6b24e497ef6840114afcdb832ae597f32137fa19d42a6f"},
]
[package.dependencies]
@@ -1335,7 +1286,7 @@ comm = ">=0.1.1"
debugpy = ">=1.6.5"
ipython = ">=7.23.1"
jupyter-client = ">=6.1.12"
-jupyter-core = ">=4.12,<5.0.0 || >=5.1.0"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
matplotlib-inline = ">=0.1"
nest-asyncio = "*"
packaging = "*"
@@ -1353,14 +1304,13 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio"
[[package]]
name = "ipython"
-version = "8.10.0"
+version = "8.12.2"
description = "IPython: Productive Interactive Computing"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "ipython-8.10.0-py3-none-any.whl", hash = "sha256:b38c31e8fc7eff642fc7c597061fff462537cf2314e3225a19c906b7b0d8a345"},
- {file = "ipython-8.10.0.tar.gz", hash = "sha256:b13a1d6c1f5818bd388db53b7107d17454129a70de2b87481d555daede5eb49e"},
+ {file = "ipython-8.12.2-py3-none-any.whl", hash = "sha256:ea8801f15dfe4ffb76dea1b09b847430ffd70d827b41735c64a0638a04103bfc"},
+ {file = "ipython-8.12.2.tar.gz", hash = "sha256:c7b80eb7f5a855a88efc971fda506ff7a91c280b42cdae26643e0f601ea281ea"},
]
[package.dependencies]
@@ -1372,10 +1322,11 @@ jedi = ">=0.16"
matplotlib-inline = "*"
pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""}
pickleshare = "*"
-prompt-toolkit = ">=3.0.30,<3.1.0"
+prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0"
pygments = ">=2.4.0"
stack-data = "*"
traitlets = ">=5"
+typing-extensions = {version = "*", markers = "python_version < \"3.10\""}
[package.extras]
all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"]
@@ -1394,7 +1345,6 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa
name = "isort"
version = "5.12.0"
description = "A Python utility / library to sort Python imports."
-category = "dev"
optional = false
python-versions = ">=3.8.0"
files = [
@@ -1412,7 +1362,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]
name = "jaraco-classes"
version = "3.2.3"
description = "Utility functions for Python class constructs"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1431,7 +1380,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec
name = "jedi"
version = "0.18.2"
description = "An autocompletion tool for Python that can be used for text editors."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -1451,7 +1399,6 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
name = "jeepney"
version = "0.8.0"
description = "Low-level, pure Python DBus protocol wrapper."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1467,7 +1414,6 @@ trio = ["async_generator", "trio"]
name = "jinja2"
version = "3.0.3"
description = "A very fast and expressive template engine."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -1485,7 +1431,6 @@ i18n = ["Babel (>=2.7)"]
name = "jsonschema"
version = "4.17.3"
description = "An implementation of JSON Schema validation for Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1505,19 +1450,18 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-
[[package]]
name = "jupyter-client"
-version = "8.0.3"
+version = "8.2.0"
description = "Jupyter protocol implementation and client libraries"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "jupyter_client-8.0.3-py3-none-any.whl", hash = "sha256:be48ac6bd659cbbddb7a674cf06b3b8afbf53f228253cf58bde604c03bd487b0"},
- {file = "jupyter_client-8.0.3.tar.gz", hash = "sha256:ed65498bea6d876ef9d8da3e0db3dd33c5d129f5b2645f56ae03993782966bd0"},
+ {file = "jupyter_client-8.2.0-py3-none-any.whl", hash = "sha256:b18219aa695d39e2ad570533e0d71fb7881d35a873051054a84ee2a17c4b7389"},
+ {file = "jupyter_client-8.2.0.tar.gz", hash = "sha256:9fe233834edd0e6c0aa5f05ca2ab4bdea1842bfd2d8a932878212fc5301ddaf0"},
]
[package.dependencies]
importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""}
-jupyter-core = ">=4.12,<5.0.0 || >=5.1.0"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
python-dateutil = ">=2.8.2"
pyzmq = ">=23.0"
tornado = ">=6.2"
@@ -1525,23 +1469,22 @@ traitlets = ">=5.3"
[package.extras]
docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
-test = ["codecov", "coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"]
+test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"]
[[package]]
name = "jupyter-core"
-version = "5.2.0"
+version = "5.3.0"
description = "Jupyter core package. A base package on which Jupyter projects rely."
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "jupyter_core-5.2.0-py3-none-any.whl", hash = "sha256:4bdc2928c37f6917130c667d8b8708f20aee539d8283c6be72aabd2a4b4c83b0"},
- {file = "jupyter_core-5.2.0.tar.gz", hash = "sha256:1407cdb4c79ee467696c04b76633fc1884015fa109323365a6372c8e890cc83f"},
+ {file = "jupyter_core-5.3.0-py3-none-any.whl", hash = "sha256:d4201af84559bc8c70cead287e1ab94aeef3c512848dde077b7684b54d67730d"},
+ {file = "jupyter_core-5.3.0.tar.gz", hash = "sha256:6db75be0c83edbf1b7c9f91ec266a9a24ef945da630f3120e1a0046dc13713fc"},
]
[package.dependencies]
platformdirs = ">=2.5"
-pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""}
+pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""}
traitlets = ">=5.3"
[package.extras]
@@ -1552,7 +1495,6 @@ test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"]
name = "jupyterlab-pygments"
version = "0.2.2"
description = "Pygments theme using JupyterLab CSS variables"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1564,7 +1506,6 @@ files = [
name = "keyring"
version = "23.13.1"
description = "Store and access your passwords safely."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1589,7 +1530,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec
name = "kiwisolver"
version = "1.4.4"
description = "A fast implementation of the Cassowary constraint solver"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -1667,7 +1607,6 @@ files = [
name = "linecache2"
version = "1.0.0"
description = "Backports of the linecache module"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1679,7 +1618,6 @@ files = [
name = "lockfile"
version = "0.12.2"
description = "Platform-independent file locking module"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1689,113 +1627,111 @@ files = [
[[package]]
name = "markupsafe"
-version = "2.1.2"
+version = "2.1.3"
description = "Safely add untrusted strings to HTML/XML markup."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
- {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
]
[[package]]
name = "matplotlib"
-version = "3.7.0"
+version = "3.7.1"
description = "Python plotting package"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "matplotlib-3.7.0-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:3da8b9618188346239e51f1ea6c0f8f05c6e218cfcc30b399dd7dd7f52e8bceb"},
- {file = "matplotlib-3.7.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c0592ba57217c22987b7322df10f75ef95bc44dce781692b4b7524085de66019"},
- {file = "matplotlib-3.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:21269450243d6928da81a9bed201f0909432a74e7d0d65db5545b9fa8a0d0223"},
- {file = "matplotlib-3.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb2e76cd429058d8954121c334dddfcd11a6186c6975bca61f3f248c99031b05"},
- {file = "matplotlib-3.7.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de20eb1247725a2f889173d391a6d9e7e0f2540feda24030748283108b0478ec"},
- {file = "matplotlib-3.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5465735eaaafd1cfaec3fed60aee776aeb3fd3992aa2e49f4635339c931d443"},
- {file = "matplotlib-3.7.0-cp310-cp310-win32.whl", hash = "sha256:092e6abc80cdf8a95f7d1813e16c0e99ceda8d5b195a3ab859c680f3487b80a2"},
- {file = "matplotlib-3.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:4f640534ec2760e270801056bc0d8a10777c48b30966eef78a7c35d8590915ba"},
- {file = "matplotlib-3.7.0-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:f336e7014889c38c59029ebacc35c59236a852e4b23836708cfd3f43d1eaeed5"},
- {file = "matplotlib-3.7.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a10428d4f8d1a478ceabd652e61a175b2fdeed4175ab48da4a7b8deb561e3fa"},
- {file = "matplotlib-3.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46ca923e980f76d34c1c633343a72bb042d6ba690ecc649aababf5317997171d"},
- {file = "matplotlib-3.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c849aa94ff2a70fb71f318f48a61076d1205c6013b9d3885ade7f992093ac434"},
- {file = "matplotlib-3.7.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:827e78239292e561cfb70abf356a9d7eaf5bf6a85c97877f254009f20b892f89"},
- {file = "matplotlib-3.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:691ef1f15360e439886186d0db77b5345b24da12cbc4fc57b26c4826db4d6cab"},
- {file = "matplotlib-3.7.0-cp311-cp311-win32.whl", hash = "sha256:21a8aeac39b4a795e697265d800ce52ab59bdeb6bb23082e2d971f3041074f02"},
- {file = "matplotlib-3.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:01681566e95b9423021b49dea6a2395c16fa054604eacb87f0f4c439750f9114"},
- {file = "matplotlib-3.7.0-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:cf119eee4e57389fba5ac8b816934e95c256535e55f0b21628b4205737d1de85"},
- {file = "matplotlib-3.7.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:21bd4033c40b95abd5b8453f036ed5aa70856e56ecbd887705c37dce007a4c21"},
- {file = "matplotlib-3.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:111ef351f28fd823ed7177632070a6badd6f475607122bc9002a526f2502a0b5"},
- {file = "matplotlib-3.7.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f91d35b3ef51d29d9c661069b9e4ba431ce283ffc533b981506889e144b5b40e"},
- {file = "matplotlib-3.7.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a776462a4a63c0bfc9df106c15a0897aa2dbab6795c693aa366e8e283958854"},
- {file = "matplotlib-3.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0dfd4a0cbd151f6439e6d7f8dca5292839ca311e7e650596d073774847ca2e4f"},
- {file = "matplotlib-3.7.0-cp38-cp38-win32.whl", hash = "sha256:56b7b79488209041a9bf7ddc34f1b069274489ce69e34dc63ae241d0d6b4b736"},
- {file = "matplotlib-3.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:8665855f3919c80551f377bc16df618ceabf3ef65270bc14b60302dce88ca9ab"},
- {file = "matplotlib-3.7.0-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:f910d924da8b9fb066b5beae0b85e34ed1b6293014892baadcf2a51da1c65807"},
- {file = "matplotlib-3.7.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:cf6346644e8fe234dc847e6232145dac199a650d3d8025b3ef65107221584ba4"},
- {file = "matplotlib-3.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d1e52365d8d5af699f04581ca191112e1d1220a9ce4386b57d807124d8b55e6"},
- {file = "matplotlib-3.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c869b646489c6a94375714032e5cec08e3aa8d3f7d4e8ef2b0fb50a52b317ce6"},
- {file = "matplotlib-3.7.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4ddac5f59e78d04b20469bc43853a8e619bb6505c7eac8ffb343ff2c516d72f"},
- {file = "matplotlib-3.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb0304c1cd802e9a25743414c887e8a7cd51d96c9ec96d388625d2cd1c137ae3"},
- {file = "matplotlib-3.7.0-cp39-cp39-win32.whl", hash = "sha256:a06a6c9822e80f323549c6bc9da96d4f233178212ad9a5f4ab87fd153077a507"},
- {file = "matplotlib-3.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:cb52aa97b92acdee090edfb65d1cb84ea60ab38e871ba8321a10bbcebc2a3540"},
- {file = "matplotlib-3.7.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3493b48e56468c39bd9c1532566dff3b8062952721b7521e1f394eb6791495f4"},
- {file = "matplotlib-3.7.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d0dcd1a0bf8d56551e8617d6dc3881d8a1c7fb37d14e5ec12cbb293f3e6170a"},
- {file = "matplotlib-3.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51fb664c37714cbaac69c16d6b3719f517a13c96c3f76f4caadd5a0aa7ed0329"},
- {file = "matplotlib-3.7.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4497d88c559b76da320b7759d64db442178beeea06a52dc0c629086982082dcd"},
- {file = "matplotlib-3.7.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9d85355c48ef8b9994293eb7c00f44aa8a43cad7a297fbf0770a25cdb2244b91"},
- {file = "matplotlib-3.7.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03eb2c8ff8d85da679b71e14c7c95d16d014c48e0c0bfa14db85f6cdc5c92aad"},
- {file = "matplotlib-3.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71b751d06b2ed1fd017de512d7439c0259822864ea16731522b251a27c0b2ede"},
- {file = "matplotlib-3.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b51ab8a5d5d3bbd4527af633a638325f492e09e45e78afdf816ef55217a09664"},
- {file = "matplotlib-3.7.0.tar.gz", hash = "sha256:8f6efd313430d7ef70a38a3276281cb2e8646b3a22b3b21eb227da20e15e6813"},
+ {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"},
]
[package.dependencies]
@@ -1814,7 +1750,6 @@ python-dateutil = ">=2.7"
name = "matplotlib-inline"
version = "0.1.6"
description = "Inline Matplotlib backend for Jupyter"
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -1829,7 +1764,6 @@ traitlets = "*"
name = "mccabe"
version = "0.6.1"
description = "McCabe checker, plugin for flake8"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1841,7 +1775,6 @@ files = [
name = "mistune"
version = "2.0.5"
description = "A sane Markdown parser with useful plugins and renderers"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -1851,111 +1784,118 @@ files = [
[[package]]
name = "more-itertools"
-version = "9.0.0"
+version = "9.1.0"
description = "More routines for operating on iterables, beyond itertools"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "more-itertools-9.0.0.tar.gz", hash = "sha256:5a6257e40878ef0520b1803990e3e22303a41b5714006c32a3fd8304b26ea1ab"},
- {file = "more_itertools-9.0.0-py3-none-any.whl", hash = "sha256:250e83d7e81d0c87ca6bd942e6aeab8cc9daa6096d12c5308f3f92fa5e5c1f41"},
+ {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"},
+ {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"},
]
[[package]]
name = "msgpack"
-version = "1.0.4"
+version = "1.0.5"
description = "MessagePack serializer"
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"},
- {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88"},
- {file = "msgpack-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467"},
- {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6"},
- {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa"},
- {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6"},
- {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba"},
- {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e"},
- {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db"},
- {file = "msgpack-1.0.4-cp310-cp310-win32.whl", hash = "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef"},
- {file = "msgpack-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075"},
- {file = "msgpack-1.0.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52"},
- {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9"},
- {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9"},
- {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08"},
- {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8"},
- {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6"},
- {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae"},
- {file = "msgpack-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6"},
- {file = "msgpack-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661"},
- {file = "msgpack-1.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c"},
- {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0"},
- {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227"},
- {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff"},
- {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd"},
- {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e"},
- {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236"},
- {file = "msgpack-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44"},
- {file = "msgpack-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1"},
- {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d"},
- {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab"},
- {file = "msgpack-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb"},
- {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9"},
- {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e"},
- {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1"},
- {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e"},
- {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43"},
- {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243"},
- {file = "msgpack-1.0.4-cp38-cp38-win32.whl", hash = "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2"},
- {file = "msgpack-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6"},
- {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae"},
- {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55"},
- {file = "msgpack-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da"},
- {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f"},
- {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92"},
- {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f"},
- {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624"},
- {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8"},
- {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae"},
- {file = "msgpack-1.0.4-cp39-cp39-win32.whl", hash = "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c"},
- {file = "msgpack-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce"},
- {file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"},
+ {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:525228efd79bb831cf6830a732e2e80bc1b05436b086d4264814b4b2955b2fa9"},
+ {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f8d8b3bf1ff2672567d6b5c725a1b347fe838b912772aa8ae2bf70338d5a198"},
+ {file = "msgpack-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdc793c50be3f01106245a61b739328f7dccc2c648b501e237f0699fe1395b81"},
+ {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cb47c21a8a65b165ce29f2bec852790cbc04936f502966768e4aae9fa763cb7"},
+ {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e42b9594cc3bf4d838d67d6ed62b9e59e201862a25e9a157019e171fbe672dd3"},
+ {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:55b56a24893105dc52c1253649b60f475f36b3aa0fc66115bffafb624d7cb30b"},
+ {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1967f6129fc50a43bfe0951c35acbb729be89a55d849fab7686004da85103f1c"},
+ {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a97bf595a232c3ee6d57ddaadd5453d174a52594bf9c21d10407e2a2d9b3bd"},
+ {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d25dd59bbbbb996eacf7be6b4ad082ed7eacc4e8f3d2df1ba43822da9bfa122a"},
+ {file = "msgpack-1.0.5-cp310-cp310-win32.whl", hash = "sha256:382b2c77589331f2cb80b67cc058c00f225e19827dbc818d700f61513ab47bea"},
+ {file = "msgpack-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:4867aa2df9e2a5fa5f76d7d5565d25ec76e84c106b55509e78c1ede0f152659a"},
+ {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9f5ae84c5c8a857ec44dc180a8b0cc08238e021f57abdf51a8182e915e6299f0"},
+ {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e6ca5d5699bcd89ae605c150aee83b5321f2115695e741b99618f4856c50898"},
+ {file = "msgpack-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5494ea30d517a3576749cad32fa27f7585c65f5f38309c88c6d137877fa28a5a"},
+ {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ab2f3331cb1b54165976a9d976cb251a83183631c88076613c6c780f0d6e45a"},
+ {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28592e20bbb1620848256ebc105fc420436af59515793ed27d5c77a217477705"},
+ {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe5c63197c55bce6385d9aee16c4d0641684628f63ace85f73571e65ad1c1e8d"},
+ {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed40e926fa2f297e8a653c954b732f125ef97bdd4c889f243182299de27e2aa9"},
+ {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b2de4c1c0538dcb7010902a2b97f4e00fc4ddf2c8cda9749af0e594d3b7fa3d7"},
+ {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf22a83f973b50f9d38e55c6aade04c41ddda19b00c4ebc558930d78eecc64ed"},
+ {file = "msgpack-1.0.5-cp311-cp311-win32.whl", hash = "sha256:c396e2cc213d12ce017b686e0f53497f94f8ba2b24799c25d913d46c08ec422c"},
+ {file = "msgpack-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c4c68d87497f66f96d50142a2b73b97972130d93677ce930718f68828b382e2"},
+ {file = "msgpack-1.0.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a2b031c2e9b9af485d5e3c4520f4220d74f4d222a5b8dc8c1a3ab9448ca79c57"},
+ {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f837b93669ce4336e24d08286c38761132bc7ab29782727f8557e1eb21b2080"},
+ {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1d46dfe3832660f53b13b925d4e0fa1432b00f5f7210eb3ad3bb9a13c6204a6"},
+ {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:366c9a7b9057e1547f4ad51d8facad8b406bab69c7d72c0eb6f529cf76d4b85f"},
+ {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4c075728a1095efd0634a7dccb06204919a2f67d1893b6aa8e00497258bf926c"},
+ {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:f933bbda5a3ee63b8834179096923b094b76f0c7a73c1cfe8f07ad608c58844b"},
+ {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:36961b0568c36027c76e2ae3ca1132e35123dcec0706c4b7992683cc26c1320c"},
+ {file = "msgpack-1.0.5-cp36-cp36m-win32.whl", hash = "sha256:b5ef2f015b95f912c2fcab19c36814963b5463f1fb9049846994b007962743e9"},
+ {file = "msgpack-1.0.5-cp36-cp36m-win_amd64.whl", hash = "sha256:288e32b47e67f7b171f86b030e527e302c91bd3f40fd9033483f2cacc37f327a"},
+ {file = "msgpack-1.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:137850656634abddfb88236008339fdaba3178f4751b28f270d2ebe77a563b6c"},
+ {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c05a4a96585525916b109bb85f8cb6511db1c6f5b9d9cbcbc940dc6b4be944b"},
+ {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a62ec00b636583e5cb6ad313bbed36bb7ead5fa3a3e38938503142c72cba4f"},
+ {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef8108f8dedf204bb7b42994abf93882da1159728a2d4c5e82012edd92c9da9f"},
+ {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1835c84d65f46900920b3708f5ba829fb19b1096c1800ad60bae8418652a951d"},
+ {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e57916ef1bd0fee4f21c4600e9d1da352d8816b52a599c46460e93a6e9f17086"},
+ {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:17358523b85973e5f242ad74aa4712b7ee560715562554aa2134d96e7aa4cbbf"},
+ {file = "msgpack-1.0.5-cp37-cp37m-win32.whl", hash = "sha256:cb5aaa8c17760909ec6cb15e744c3ebc2ca8918e727216e79607b7bbce9c8f77"},
+ {file = "msgpack-1.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:ab31e908d8424d55601ad7075e471b7d0140d4d3dd3272daf39c5c19d936bd82"},
+ {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b72d0698f86e8d9ddf9442bdedec15b71df3598199ba33322d9711a19f08145c"},
+ {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:379026812e49258016dd84ad79ac8446922234d498058ae1d415f04b522d5b2d"},
+ {file = "msgpack-1.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:332360ff25469c346a1c5e47cbe2a725517919892eda5cfaffe6046656f0b7bb"},
+ {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:476a8fe8fae289fdf273d6d2a6cb6e35b5a58541693e8f9f019bfe990a51e4ba"},
+ {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9985b214f33311df47e274eb788a5893a761d025e2b92c723ba4c63936b69b1"},
+ {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48296af57cdb1d885843afd73c4656be5c76c0c6328db3440c9601a98f303d87"},
+ {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:addab7e2e1fcc04bd08e4eb631c2a90960c340e40dfc4a5e24d2ff0d5a3b3edb"},
+ {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:916723458c25dfb77ff07f4c66aed34e47503b2eb3188b3adbec8d8aa6e00f48"},
+ {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:821c7e677cc6acf0fd3f7ac664c98803827ae6de594a9f99563e48c5a2f27eb0"},
+ {file = "msgpack-1.0.5-cp38-cp38-win32.whl", hash = "sha256:1c0f7c47f0087ffda62961d425e4407961a7ffd2aa004c81b9c07d9269512f6e"},
+ {file = "msgpack-1.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:bae7de2026cbfe3782c8b78b0db9cbfc5455e079f1937cb0ab8d133496ac55e1"},
+ {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:20c784e66b613c7f16f632e7b5e8a1651aa5702463d61394671ba07b2fc9e025"},
+ {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:266fa4202c0eb94d26822d9bfd7af25d1e2c088927fe8de9033d929dd5ba24c5"},
+ {file = "msgpack-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18334484eafc2b1aa47a6d42427da7fa8f2ab3d60b674120bce7a895a0a85bdd"},
+ {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57e1f3528bd95cc44684beda696f74d3aaa8a5e58c816214b9046512240ef437"},
+ {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:586d0d636f9a628ddc6a17bfd45aa5b5efaf1606d2b60fa5d87b8986326e933f"},
+ {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a740fa0e4087a734455f0fc3abf5e746004c9da72fbd541e9b113013c8dc3282"},
+ {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3055b0455e45810820db1f29d900bf39466df96ddca11dfa6d074fa47054376d"},
+ {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a61215eac016f391129a013c9e46f3ab308db5f5ec9f25811e811f96962599a8"},
+ {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:362d9655cd369b08fda06b6657a303eb7172d5279997abe094512e919cf74b11"},
+ {file = "msgpack-1.0.5-cp39-cp39-win32.whl", hash = "sha256:ac9dd47af78cae935901a9a500104e2dea2e253207c924cc95de149606dc43cc"},
+ {file = "msgpack-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:06f5174b5f8ed0ed919da0e62cbd4ffde676a374aba4020034da05fab67b9164"},
+ {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"},
]
[[package]]
name = "nbclient"
-version = "0.7.2"
+version = "0.8.0"
description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor."
-category = "dev"
optional = false
-python-versions = ">=3.7.0"
+python-versions = ">=3.8.0"
files = [
- {file = "nbclient-0.7.2-py3-none-any.whl", hash = "sha256:d97ac6257de2794f5397609df754fcbca1a603e94e924eb9b99787c031ae2e7c"},
- {file = "nbclient-0.7.2.tar.gz", hash = "sha256:884a3f4a8c4fc24bb9302f263e0af47d97f0d01fe11ba714171b320c8ac09547"},
+ {file = "nbclient-0.8.0-py3-none-any.whl", hash = "sha256:25e861299e5303a0477568557c4045eccc7a34c17fc08e7959558707b9ebe548"},
+ {file = "nbclient-0.8.0.tar.gz", hash = "sha256:f9b179cd4b2d7bca965f900a2ebf0db4a12ebff2f36a711cb66861e4ae158e55"},
]
[package.dependencies]
jupyter-client = ">=6.1.12"
-jupyter-core = ">=4.12,<5.0.0 || >=5.1.0"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
nbformat = ">=5.1"
-traitlets = ">=5.3"
+traitlets = ">=5.4"
[package.extras]
dev = ["pre-commit"]
-docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme"]
-test = ["ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"]
+docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"]
+test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"]
[[package]]
name = "nbconvert"
-version = "7.2.9"
+version = "7.2.10"
description = "Converting Jupyter Notebooks"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "nbconvert-7.2.9-py3-none-any.whl", hash = "sha256:495638c5e06005f4a5ce828d8a81d28e34f95c20f4384d5d7a22254b443836e7"},
- {file = "nbconvert-7.2.9.tar.gz", hash = "sha256:a42c3ac137c64f70cbe4d763111bf358641ea53b37a01a5c202ed86374af5234"},
+ {file = "nbconvert-7.2.10-py3-none-any.whl", hash = "sha256:e41118f81698d3d59b3c7c2887937446048f741aba6c367c1c1a77810b3e2d08"},
+ {file = "nbconvert-7.2.10.tar.gz", hash = "sha256:8eed67bd8314f3ec87c4351c2f674af3a04e5890ab905d6bd927c05aec1cf27d"},
]
[package.dependencies]
@@ -1987,14 +1927,13 @@ webpdf = ["pyppeteer (>=1,<1.1)"]
[[package]]
name = "nbformat"
-version = "5.7.3"
+version = "5.9.0"
description = "The Jupyter Notebook format"
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "nbformat-5.7.3-py3-none-any.whl", hash = "sha256:22a98a6516ca216002b0a34591af5bcb8072ca6c63910baffc901cfa07fefbf0"},
- {file = "nbformat-5.7.3.tar.gz", hash = "sha256:4b021fca24d3a747bf4e626694033d792d594705829e5e35b14ee3369f9f6477"},
+ {file = "nbformat-5.9.0-py3-none-any.whl", hash = "sha256:8c8fa16d6d05062c26177754bfbfac22de644888e2ef69d27ad2a334cf2576e5"},
+ {file = "nbformat-5.9.0.tar.gz", hash = "sha256:e98ebb6120c3efbafdee2a40af2a140cadee90bb06dd69a2a63d9551fcc7f976"},
]
[package.dependencies]
@@ -2011,7 +1950,6 @@ test = ["pep440", "pre-commit", "pytest", "testpath"]
name = "nest-asyncio"
version = "1.5.6"
description = "Patch asyncio to allow nested event loops"
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -2023,7 +1961,6 @@ files = [
name = "networkx"
version = "2.8.7"
description = "Python package for creating and manipulating graphs and networks"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
@@ -2040,59 +1977,56 @@ test = ["codecov (>=2.1)", "pytest (>=7.1)", "pytest-cov (>=3.0)"]
[[package]]
name = "numpy"
-version = "1.24.2"
+version = "1.24.3"
description = "Fundamental package for array computing in Python"
-category = "main"
optional = false
python-versions = ">=3.8"
files = [
- {file = "numpy-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d"},
- {file = "numpy-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5"},
- {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253"},
- {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978"},
- {file = "numpy-1.24.2-cp310-cp310-win32.whl", hash = "sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9"},
- {file = "numpy-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0"},
- {file = "numpy-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a"},
- {file = "numpy-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0"},
- {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281"},
- {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910"},
- {file = "numpy-1.24.2-cp311-cp311-win32.whl", hash = "sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95"},
- {file = "numpy-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04"},
- {file = "numpy-1.24.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2"},
- {file = "numpy-1.24.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5"},
- {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a"},
- {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96"},
- {file = "numpy-1.24.2-cp38-cp38-win32.whl", hash = "sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d"},
- {file = "numpy-1.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756"},
- {file = "numpy-1.24.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a"},
- {file = "numpy-1.24.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f"},
- {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb"},
- {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780"},
- {file = "numpy-1.24.2-cp39-cp39-win32.whl", hash = "sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468"},
- {file = "numpy-1.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5"},
- {file = "numpy-1.24.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d"},
- {file = "numpy-1.24.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"},
- {file = "numpy-1.24.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f"},
- {file = "numpy-1.24.2.tar.gz", hash = "sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22"},
+ {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"},
]
[[package]]
name = "packaging"
-version = "23.0"
+version = "23.1"
description = "Core utilities for Python packages"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"},
- {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"},
+ {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
+ {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
]
[[package]]
name = "pandas"
version = "1.5.3"
description = "Powerful data structures for data analysis, time series, and statistics"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -2140,7 +2074,6 @@ test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"]
name = "pandocfilters"
version = "1.5.0"
description = "Utilities for writing pandoc filters in python"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -2152,7 +2085,6 @@ files = [
name = "parso"
version = "0.8.3"
description = "A Python Parser"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2168,7 +2100,6 @@ testing = ["docopt", "pytest (<6.0.0)"]
name = "pbr"
version = "5.11.1"
description = "Python Build Reasonableness"
-category = "dev"
optional = false
python-versions = ">=2.6"
files = [
@@ -2180,7 +2111,6 @@ files = [
name = "pep8-naming"
version = "0.12.1"
description = "Check PEP-8 naming conventions, plugin for flake8"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2196,7 +2126,6 @@ flake8-polyfill = ">=1.0.2,<2"
name = "pexpect"
version = "4.8.0"
description = "Pexpect allows easy control of interactive console applications."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2211,7 +2140,6 @@ ptyprocess = ">=0.5"
name = "pickleshare"
version = "0.7.5"
description = "Tiny 'shelve'-like database with concurrency support"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2221,100 +2149,87 @@ files = [
[[package]]
name = "pillow"
-version = "9.4.0"
+version = "9.5.0"
description = "Python Imaging Library (Fork)"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "Pillow-9.4.0-1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b4b4e9dda4f4e4c4e6896f93e84a8f0bcca3b059de9ddf67dac3c334b1195e1"},
- {file = "Pillow-9.4.0-1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fb5c1ad6bad98c57482236a21bf985ab0ef42bd51f7ad4e4538e89a997624e12"},
- {file = "Pillow-9.4.0-1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:f0caf4a5dcf610d96c3bd32932bfac8aee61c96e60481c2a0ea58da435e25acd"},
- {file = "Pillow-9.4.0-1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:3f4cc516e0b264c8d4ccd6b6cbc69a07c6d582d8337df79be1e15a5056b258c9"},
- {file = "Pillow-9.4.0-1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858"},
- {file = "Pillow-9.4.0-1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab"},
- {file = "Pillow-9.4.0-1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9"},
- {file = "Pillow-9.4.0-2-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0"},
- {file = "Pillow-9.4.0-2-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f"},
- {file = "Pillow-9.4.0-2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c"},
- {file = "Pillow-9.4.0-2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848"},
- {file = "Pillow-9.4.0-2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1"},
- {file = "Pillow-9.4.0-2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33"},
- {file = "Pillow-9.4.0-2-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9"},
- {file = "Pillow-9.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157"},
- {file = "Pillow-9.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47"},
- {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343"},
- {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d"},
- {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57"},
- {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5"},
- {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070"},
- {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28"},
- {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35"},
- {file = "Pillow-9.4.0-cp310-cp310-win32.whl", hash = "sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a"},
- {file = "Pillow-9.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391"},
- {file = "Pillow-9.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133"},
- {file = "Pillow-9.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132"},
- {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0"},
- {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35"},
- {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab"},
- {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4"},
- {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d"},
- {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8"},
- {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a"},
- {file = "Pillow-9.4.0-cp311-cp311-win32.whl", hash = "sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c"},
- {file = "Pillow-9.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee"},
- {file = "Pillow-9.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493"},
- {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327"},
- {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe"},
- {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57"},
- {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4"},
- {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5"},
- {file = "Pillow-9.4.0-cp37-cp37m-win32.whl", hash = "sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e"},
- {file = "Pillow-9.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6"},
- {file = "Pillow-9.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9"},
- {file = "Pillow-9.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011"},
- {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df"},
- {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837"},
- {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b"},
- {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d"},
- {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b"},
- {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f"},
- {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628"},
- {file = "Pillow-9.4.0-cp38-cp38-win32.whl", hash = "sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d"},
- {file = "Pillow-9.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a"},
- {file = "Pillow-9.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569"},
- {file = "Pillow-9.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed"},
- {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815"},
- {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264"},
- {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e"},
- {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503"},
- {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6"},
- {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2"},
- {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153"},
- {file = "Pillow-9.4.0-cp39-cp39-win32.whl", hash = "sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c"},
- {file = "Pillow-9.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b"},
- {file = "Pillow-9.4.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5"},
- {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286"},
- {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd"},
- {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df"},
- {file = "Pillow-9.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336"},
- {file = "Pillow-9.4.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3"},
- {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa"},
- {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb"},
- {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a"},
- {file = "Pillow-9.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9"},
- {file = "Pillow-9.4.0.tar.gz", hash = "sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e"},
-]
-
-[package.extras]
-docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"]
+ {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"},
+]
+
+[package.extras]
+docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
[[package]]
name = "pkginfo"
version = "1.9.6"
description = "Query metadata from sdists / bdists / installed packages."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2329,7 +2244,6 @@ testing = ["pytest", "pytest-cov"]
name = "pkgutil-resolve-name"
version = "1.3.10"
description = "Resolve a name to an object."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2339,25 +2253,23 @@ files = [
[[package]]
name = "platformdirs"
-version = "2.6.2"
+version = "3.5.1"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"},
- {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"},
+ {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"},
+ {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},
]
[package.extras]
-docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "pluggy"
version = "1.0.0"
description = "plugin and hook calling mechanisms for python"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2371,84 +2283,80 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "poetry"
-version = "1.3.2"
+version = "1.5.1"
description = "Python dependency management and packaging made easy."
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
- {file = "poetry-1.3.2-py3-none-any.whl", hash = "sha256:41980d557954b1418fa503de7a8fb25f19c03c0223a171666b305f05a45fc206"},
- {file = "poetry-1.3.2.tar.gz", hash = "sha256:26ded25f0cf67943243ca4f0aafd47ec4668bdb62845dbb8c2b0e3d9cd280bf4"},
+ {file = "poetry-1.5.1-py3-none-any.whl", hash = "sha256:dfc7ce3a38ae216c0465694e2e674bef6eb1a2ba81aa47a26f9dc03362fe2f5f"},
+ {file = "poetry-1.5.1.tar.gz", hash = "sha256:cc7ea4524d1a11558006224bfe8ba8ed071417d4eb5ef6c89decc6a37d437eeb"},
]
[package.dependencies]
+build = ">=0.10.0,<0.11.0"
cachecontrol = {version = ">=0.12.9,<0.13.0", extras = ["filecache"]}
cleo = ">=2.0.0,<3.0.0"
crashtest = ">=0.4.1,<0.5.0"
-dulwich = ">=0.20.46,<0.21.0"
+dulwich = ">=0.21.2,<0.22.0"
filelock = ">=3.8.0,<4.0.0"
html5lib = ">=1.0,<2.0"
-importlib-metadata = {version = ">=4.4,<5.0", markers = "python_version < \"3.10\""}
+importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
+installer = ">=0.7.0,<0.8.0"
jsonschema = ">=4.10.0,<5.0.0"
keyring = ">=23.9.0,<24.0.0"
lockfile = ">=0.12.2,<0.13.0"
packaging = ">=20.4"
pexpect = ">=4.7.0,<5.0.0"
-pkginfo = ">=1.5,<2.0"
-platformdirs = ">=2.5.2,<3.0.0"
-poetry-core = "1.4.0"
-poetry-plugin-export = ">=1.2.0,<2.0.0"
+pkginfo = ">=1.9.4,<2.0.0"
+platformdirs = ">=3.0.0,<4.0.0"
+poetry-core = "1.6.1"
+poetry-plugin-export = ">=1.4.0,<2.0.0"
+pyproject-hooks = ">=1.0.0,<2.0.0"
requests = ">=2.18,<3.0"
-requests-toolbelt = ">=0.9.1,<0.11.0"
+requests-toolbelt = ">=0.9.1,<2"
shellingham = ">=1.5,<2.0"
tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""}
-tomlkit = ">=0.11.1,<0.11.2 || >0.11.2,<0.11.3 || >0.11.3,<1.0.0"
+tomlkit = ">=0.11.4,<1.0.0"
trove-classifiers = ">=2022.5.19"
urllib3 = ">=1.26.0,<2.0.0"
-virtualenv = [
- {version = ">=20.4.3,<20.4.5 || >20.4.5,<20.4.6 || >20.4.6,<21.0.0", markers = "sys_platform != \"win32\" or python_version != \"3.9\""},
- {version = ">=20.4.3,<20.4.5 || >20.4.5,<20.4.6 || >20.4.6,<20.16.6", markers = "sys_platform == \"win32\" and python_version == \"3.9\""},
-]
+virtualenv = ">=20.22.0,<21.0.0"
xattr = {version = ">=0.10.0,<0.11.0", markers = "sys_platform == \"darwin\""}
[[package]]
name = "poetry-core"
-version = "1.4.0"
+version = "1.6.1"
description = "Poetry PEP 517 Build Backend"
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
- {file = "poetry_core-1.4.0-py3-none-any.whl", hash = "sha256:5559ab80384ac021db329ef317086417e140ee1176bcfcb3a3838b544e213c8e"},
- {file = "poetry_core-1.4.0.tar.gz", hash = "sha256:514bd33c30e0bf56b0ed44ee15e120d7e47b61ad908b2b1011da68c48a84ada9"},
+ {file = "poetry_core-1.6.1-py3-none-any.whl", hash = "sha256:70707340447dee0e7f334f9495ae652481c67b32d8d218f296a376ac2ed73573"},
+ {file = "poetry_core-1.6.1.tar.gz", hash = "sha256:0f9b0de39665f36d6594657e7d57b6f463cc10f30c28e6d1c3b9ff54c26c9ac3"},
]
[[package]]
name = "poetry-plugin-export"
-version = "1.3.0"
+version = "1.4.0"
description = "Poetry plugin to export the dependencies to various formats"
-category = "dev"
optional = false
python-versions = ">=3.7,<4.0"
files = [
- {file = "poetry_plugin_export-1.3.0-py3-none-any.whl", hash = "sha256:6e5919bf84afcb08cdd419a03f909f490d8671f00633a3c6df8ba09b0820dc2f"},
- {file = "poetry_plugin_export-1.3.0.tar.gz", hash = "sha256:61ae5ec1db233aba947a48e1ce54c6ff66afd0e1c87195d6bce64c73a5ae658c"},
+ {file = "poetry_plugin_export-1.4.0-py3-none-any.whl", hash = "sha256:5d9186d6f77cf2bf35fc96bd11fe650cc7656e515b17d99cb65018d50ba22589"},
+ {file = "poetry_plugin_export-1.4.0.tar.gz", hash = "sha256:f16974cd9f222d4ef640fa97a8d661b04d4fb339e51da93973f1bc9d578e183f"},
]
[package.dependencies]
-poetry = ">=1.3.0,<2.0.0"
-poetry-core = ">=1.3.0,<2.0.0"
+poetry = ">=1.5.0,<2.0.0"
+poetry-core = ">=1.6.0,<2.0.0"
[[package]]
name = "prompt-toolkit"
-version = "3.0.36"
+version = "3.0.38"
description = "Library for building powerful interactive command lines in Python"
-category = "dev"
optional = false
-python-versions = ">=3.6.2"
+python-versions = ">=3.7.0"
files = [
- {file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"},
- {file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"},
+ {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"},
+ {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"},
]
[package.dependencies]
@@ -2456,26 +2364,25 @@ wcwidth = "*"
[[package]]
name = "psutil"
-version = "5.9.4"
+version = "5.9.5"
description = "Cross-platform lib for process and system monitoring in Python."
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
- {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"},
- {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"},
- {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"},
- {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"},
- {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"},
- {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"},
- {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"},
- {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"},
- {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"},
- {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"},
- {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"},
- {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"},
- {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"},
- {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"},
+ {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"},
+ {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"},
+ {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"},
+ {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"},
+ {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"},
+ {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"},
+ {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"},
+ {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"},
+ {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"},
+ {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"},
+ {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"},
+ {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"},
+ {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"},
+ {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"},
]
[package.extras]
@@ -2485,7 +2392,6 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
name = "ptyprocess"
version = "0.7.0"
description = "Run a subprocess in a pseudo terminal"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2497,7 +2403,6 @@ files = [
name = "pure-eval"
version = "0.2.2"
description = "Safely evaluate AST nodes without side effects"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2510,39 +2415,36 @@ tests = ["pytest"]
[[package]]
name = "pybind11"
-version = "2.10.3"
+version = "2.10.4"
description = "Seamless operability between C++11 and Python"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
- {file = "pybind11-2.10.3-py3-none-any.whl", hash = "sha256:123e303f39ad5de97ddfa4f1f473cb85881a0a94ee5714eb3c37e2405371fc12"},
- {file = "pybind11-2.10.3.tar.gz", hash = "sha256:08cfe6d4f73746447cc85a400c8169a91608b8a00c5feecd8ff251a70565d12f"},
+ {file = "pybind11-2.10.4-py3-none-any.whl", hash = "sha256:ec9be0c45061c829648d7e8c98a7d041768b768c934acd15196e0f1943d9a818"},
+ {file = "pybind11-2.10.4.tar.gz", hash = "sha256:0bb621d3c45a049aa5923debb87c5c0e2668227905c55ebe8af722608d8ed927"},
]
[package.dependencies]
-pybind11-global = {version = "2.10.3", optional = true, markers = "extra == \"global\""}
+pybind11-global = {version = "2.10.4", optional = true, markers = "extra == \"global\""}
[package.extras]
-global = ["pybind11-global (==2.10.3)"]
+global = ["pybind11-global (==2.10.4)"]
[[package]]
name = "pybind11-global"
-version = "2.10.3"
+version = "2.10.4"
description = "Seamless operability between C++11 and Python"
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
- {file = "pybind11_global-2.10.3-py3-none-any.whl", hash = "sha256:0185118804f11349007989e9fab9d346b2d9997166b8ff90915419c528ba8690"},
- {file = "pybind11_global-2.10.3.tar.gz", hash = "sha256:9982149e0859e7a8496397b7dcdf083a37b87cbc1cac6e5dbe453eb3f3f22db1"},
+ {file = "pybind11_global-2.10.4-py3-none-any.whl", hash = "sha256:2e8fef06c6f238ff437745221850047d9f987343c4a502b753a9fbd25215912e"},
+ {file = "pybind11_global-2.10.4.tar.gz", hash = "sha256:210fbae7e0b1f02f137abf90fe3992b26b3eb173b91d5a892fc13c79f6fd54f4"},
]
[[package]]
name = "pycodestyle"
version = "2.8.0"
description = "Python style guide checker"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
@@ -2554,7 +2456,6 @@ files = [
name = "pycparser"
version = "2.21"
description = "C parser in Python"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -2566,7 +2467,6 @@ files = [
name = "pydocstyle"
version = "6.3.0"
description = "Python docstring style checker"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2584,7 +2484,6 @@ toml = ["tomli (>=1.2.3)"]
name = "pyflakes"
version = "2.4.0"
description = "passive checker of Python programs"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
@@ -2594,14 +2493,13 @@ files = [
[[package]]
name = "pygments"
-version = "2.14.0"
+version = "2.15.1"
description = "Pygments is a syntax highlighting package written in Python."
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"},
- {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"},
+ {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
+ {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
]
[package.extras]
@@ -2611,7 +2509,6 @@ plugins = ["importlib-metadata"]
name = "pyparsing"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
-category = "dev"
optional = false
python-versions = ">=3.6.8"
files = [
@@ -2622,11 +2519,24 @@ files = [
[package.extras]
diagrams = ["jinja2", "railroad-diagrams"]
+[[package]]
+name = "pyproject-hooks"
+version = "1.0.0"
+description = "Wrappers to call pyproject.toml-based build backend hooks."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"},
+ {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"},
+]
+
+[package.dependencies]
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
[[package]]
name = "pyrsistent"
version = "0.19.3"
description = "Persistent/Functional/Immutable data structures"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -2661,18 +2571,16 @@ files = [
[[package]]
name = "pytest"
-version = "7.2.1"
+version = "7.3.1"
description = "pytest: simple powerful testing with Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.2.1-py3-none-any.whl", hash = "sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5"},
- {file = "pytest-7.2.1.tar.gz", hash = "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"},
+ {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
+ {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
]
[package.dependencies]
-attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
@@ -2681,13 +2589,12 @@ pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
[[package]]
name = "pytest-cov"
version = "3.0.0"
description = "Pytest plugin for measuring coverage."
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2706,7 +2613,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
-category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [
@@ -2719,45 +2625,42 @@ six = ">=1.5"
[[package]]
name = "pytz"
-version = "2022.7.1"
+version = "2023.3"
description = "World timezone definitions, modern and historical"
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"},
- {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"},
+ {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
+ {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
]
[[package]]
name = "pywin32"
-version = "305"
+version = "306"
description = "Python for Window Extensions"
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "pywin32-305-cp310-cp310-win32.whl", hash = "sha256:421f6cd86e84bbb696d54563c48014b12a23ef95a14e0bdba526be756d89f116"},
- {file = "pywin32-305-cp310-cp310-win_amd64.whl", hash = "sha256:73e819c6bed89f44ff1d690498c0a811948f73777e5f97c494c152b850fad478"},
- {file = "pywin32-305-cp310-cp310-win_arm64.whl", hash = "sha256:742eb905ce2187133a29365b428e6c3b9001d79accdc30aa8969afba1d8470f4"},
- {file = "pywin32-305-cp311-cp311-win32.whl", hash = "sha256:19ca459cd2e66c0e2cc9a09d589f71d827f26d47fe4a9d09175f6aa0256b51c2"},
- {file = "pywin32-305-cp311-cp311-win_amd64.whl", hash = "sha256:326f42ab4cfff56e77e3e595aeaf6c216712bbdd91e464d167c6434b28d65990"},
- {file = "pywin32-305-cp311-cp311-win_arm64.whl", hash = "sha256:4ecd404b2c6eceaca52f8b2e3e91b2187850a1ad3f8b746d0796a98b4cea04db"},
- {file = "pywin32-305-cp36-cp36m-win32.whl", hash = "sha256:48d8b1659284f3c17b68587af047d110d8c44837736b8932c034091683e05863"},
- {file = "pywin32-305-cp36-cp36m-win_amd64.whl", hash = "sha256:13362cc5aa93c2beaf489c9c9017c793722aeb56d3e5166dadd5ef82da021fe1"},
- {file = "pywin32-305-cp37-cp37m-win32.whl", hash = "sha256:a55db448124d1c1484df22fa8bbcbc45c64da5e6eae74ab095b9ea62e6d00496"},
- {file = "pywin32-305-cp37-cp37m-win_amd64.whl", hash = "sha256:109f98980bfb27e78f4df8a51a8198e10b0f347257d1e265bb1a32993d0c973d"},
- {file = "pywin32-305-cp38-cp38-win32.whl", hash = "sha256:9dd98384da775afa009bc04863426cb30596fd78c6f8e4e2e5bbf4edf8029504"},
- {file = "pywin32-305-cp38-cp38-win_amd64.whl", hash = "sha256:56d7a9c6e1a6835f521788f53b5af7912090674bb84ef5611663ee1595860fc7"},
- {file = "pywin32-305-cp39-cp39-win32.whl", hash = "sha256:9d968c677ac4d5cbdaa62fd3014ab241718e619d8e36ef8e11fb930515a1e918"},
- {file = "pywin32-305-cp39-cp39-win_amd64.whl", hash = "sha256:50768c6b7c3f0b38b7fb14dd4104da93ebced5f1a50dc0e834594bff6fbe1271"},
+ {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
+ {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
+ {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
+ {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
+ {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
+ {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
+ {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
+ {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
+ {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
+ {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
+ {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
+ {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
+ {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
+ {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
]
[[package]]
name = "pywin32-ctypes"
version = "0.2.0"
description = ""
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -2769,7 +2672,6 @@ files = [
name = "pyyaml"
version = "6.0"
description = "YAML parser and emitter for Python"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -2817,89 +2719,88 @@ files = [
[[package]]
name = "pyzmq"
-version = "25.0.0"
+version = "25.1.0"
description = "Python bindings for 0MQ"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
- {file = "pyzmq-25.0.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:2d05d904f03ddf1e0d83d97341354dfe52244a619b5a1440a5f47a5b3451e84e"},
- {file = "pyzmq-25.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a154ef810d44f9d28868be04641f837374a64e7449df98d9208e76c260c7ef1"},
- {file = "pyzmq-25.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:487305c2a011fdcf3db1f24e8814bb76d23bc4d2f46e145bc80316a59a9aa07d"},
- {file = "pyzmq-25.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e7b87638ee30ab13230e37ce5331b3e730b1e0dda30120b9eeec3540ed292c8"},
- {file = "pyzmq-25.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75243e422e85a62f0ab7953dc315452a56b2c6a7e7d1a3c3109ac3cc57ed6b47"},
- {file = "pyzmq-25.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:31e523d067ce44a04e876bed3ff9ea1ff8d1b6636d16e5fcace9d22f8c564369"},
- {file = "pyzmq-25.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8539216173135e9e89f6b1cc392e74e6b935b91e8c76106cf50e7a02ab02efe5"},
- {file = "pyzmq-25.0.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2754fa68da08a854f4816e05160137fa938a2347276471103d31e04bcee5365c"},
- {file = "pyzmq-25.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1bc30f0c18444d51e9b0d0dd39e3a4e7c53ee74190bebef238cd58de577ea9"},
- {file = "pyzmq-25.0.0-cp310-cp310-win32.whl", hash = "sha256:01d53958c787cfea34091fcb8ef36003dbb7913b8e9f8f62a0715234ebc98b70"},
- {file = "pyzmq-25.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:58fc3ad5e1cfd2e6d24741fbb1e216b388115d31b0ca6670f894187f280b6ba6"},
- {file = "pyzmq-25.0.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:e4bba04ea779a3d7ef25a821bb63fd0939142c88e7813e5bd9c6265a20c523a2"},
- {file = "pyzmq-25.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:af1fbfb7ad6ac0009ccee33c90a1d303431c7fb594335eb97760988727a37577"},
- {file = "pyzmq-25.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85456f0d8f3268eecd63dede3b99d5bd8d3b306310c37d4c15141111d22baeaf"},
- {file = "pyzmq-25.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0645b5a2d2a06fd8eb738018490c514907f7488bf9359c6ee9d92f62e844b76f"},
- {file = "pyzmq-25.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f72ea279b2941a5203e935a4588b9ba8a48aeb9a926d9dfa1986278bd362cb8"},
- {file = "pyzmq-25.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:4e295f7928a31ae0f657e848c5045ba6d693fe8921205f408ca3804b1b236968"},
- {file = "pyzmq-25.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ac97e7d647d5519bcef48dd8d3d331f72975afa5c4496c95f6e854686f45e2d9"},
- {file = "pyzmq-25.0.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:656281d496aaf9ca4fd4cea84e6d893e3361057c4707bd38618f7e811759103c"},
- {file = "pyzmq-25.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f6116991568aac48b94d6d8aaed6157d407942ea385335a6ed313692777fb9d"},
- {file = "pyzmq-25.0.0-cp311-cp311-win32.whl", hash = "sha256:0282bba9aee6e0346aa27d6c69b5f7df72b5a964c91958fc9e0c62dcae5fdcdc"},
- {file = "pyzmq-25.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:526f884a27e8bba62fe1f4e07c62be2cfe492b6d432a8fdc4210397f8cf15331"},
- {file = "pyzmq-25.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ccb3e1a863222afdbda42b7ca8ac8569959593d7abd44f5a709177d6fa27d266"},
- {file = "pyzmq-25.0.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4046d03100aca266e70d54a35694cb35d6654cfbef633e848b3c4a8d64b9d187"},
- {file = "pyzmq-25.0.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3100dddcada66ec5940ed6391ebf9d003cc3ede3d320748b2737553019f58230"},
- {file = "pyzmq-25.0.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7877264aa851c19404b1bb9dbe6eed21ea0c13698be1eda3784aab3036d1c861"},
- {file = "pyzmq-25.0.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5049e75cc99db65754a3da5f079230fb8889230cf09462ec972d884d1704a3ed"},
- {file = "pyzmq-25.0.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:81f99fb1224d36eb91557afec8cdc2264e856f3464500b55749020ce4c848ef2"},
- {file = "pyzmq-25.0.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a1cd4a95f176cdc0ee0a82d49d5830f13ae6015d89decbf834c273bc33eeb3d3"},
- {file = "pyzmq-25.0.0-cp36-cp36m-win32.whl", hash = "sha256:926236ca003aec70574754f39703528947211a406f5c6c8b3e50eca04a9e87fc"},
- {file = "pyzmq-25.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:94f0a7289d0f5c80807c37ebb404205e7deb737e8763eb176f4770839ee2a287"},
- {file = "pyzmq-25.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f3f96d452e9580cb961ece2e5a788e64abaecb1232a80e61deffb28e105ff84a"},
- {file = "pyzmq-25.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:930e6ad4f2eaac31a3d0c2130619d25db754b267487ebc186c6ad18af2a74018"},
- {file = "pyzmq-25.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1081d7030a1229c8ff90120346fb7599b54f552e98fcea5170544e7c6725aab"},
- {file = "pyzmq-25.0.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:531866c491aee5a1e967c286cfa470dffac1e2a203b1afda52d62b58782651e9"},
- {file = "pyzmq-25.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fc7c1421c5b1c916acf3128bf3cc7ea7f5018b58c69a6866d70c14190e600ce9"},
- {file = "pyzmq-25.0.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9a2d5e419bd39a1edb6cdd326d831f0120ddb9b1ff397e7d73541bf393294973"},
- {file = "pyzmq-25.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:183e18742be3621acf8908903f689ec520aee3f08449bfd29f583010ca33022b"},
- {file = "pyzmq-25.0.0-cp37-cp37m-win32.whl", hash = "sha256:02f5cb60a7da1edd5591a15efa654ffe2303297a41e1b40c3c8942f8f11fc17c"},
- {file = "pyzmq-25.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:cac602e02341eaaf4edfd3e29bd3fdef672e61d4e6dfe5c1d065172aee00acee"},
- {file = "pyzmq-25.0.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:e14df47c1265356715d3d66e90282a645ebc077b70b3806cf47efcb7d1d630cb"},
- {file = "pyzmq-25.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:293a7c2128690f496057f1f1eb6074f8746058d13588389981089ec45d8fdc77"},
- {file = "pyzmq-25.0.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:731b208bc9412deeb553c9519dca47136b5a01ca66667cafd8733211941b17e4"},
- {file = "pyzmq-25.0.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b055a1cddf8035966ad13aa51edae5dc8f1bba0b5d5e06f7a843d8b83dc9b66b"},
- {file = "pyzmq-25.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17e1cb97d573ea84d7cd97188b42ca6f611ab3ee600f6a75041294ede58e3d20"},
- {file = "pyzmq-25.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:60ecbfe7669d3808ffa8a7dd1487d6eb8a4015b07235e3b723d4b2a2d4de7203"},
- {file = "pyzmq-25.0.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4c25c95416133942280faaf068d0fddfd642b927fb28aaf4ab201a738e597c1e"},
- {file = "pyzmq-25.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:be05504af0619d1cffa500af1e0ede69fb683f301003851f5993b5247cc2c576"},
- {file = "pyzmq-25.0.0-cp38-cp38-win32.whl", hash = "sha256:6bf3842af37af43fa953e96074ebbb5315f6a297198f805d019d788a1021dbc8"},
- {file = "pyzmq-25.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:b90bb8dfbbd138558f1f284fecfe328f7653616ff9a972433a00711d9475d1a9"},
- {file = "pyzmq-25.0.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:62b9e80890c0d2408eb42d5d7e1fc62a5ce71be3288684788f74cf3e59ffd6e2"},
- {file = "pyzmq-25.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:484c2c4ee02c1edc07039f42130bd16e804b1fe81c4f428e0042e03967f40c20"},
- {file = "pyzmq-25.0.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9ca6db34b26c4d3e9b0728841ec9aa39484eee272caa97972ec8c8e231b20c7e"},
- {file = "pyzmq-25.0.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:610d2d112acd4e5501fac31010064a6c6efd716ceb968e443cae0059eb7b86de"},
- {file = "pyzmq-25.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3594c0ff604e685d7e907860b61d0e10e46c74a9ffca168f6e9e50ea934ee440"},
- {file = "pyzmq-25.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c21a5f4e54a807df5afdef52b6d24ec1580153a6bcf0607f70a6e1d9fa74c5c3"},
- {file = "pyzmq-25.0.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4725412e27612f0d7d7c2f794d89807ad0227c2fc01dd6146b39ada49c748ef9"},
- {file = "pyzmq-25.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d3d604fe0a67afd1aff906e54da557a5203368a99dcc50a70eef374f1d2abef"},
- {file = "pyzmq-25.0.0-cp39-cp39-win32.whl", hash = "sha256:3670e8c5644768f214a3b598fe46378a4a6f096d5fb82a67dfd3440028460565"},
- {file = "pyzmq-25.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:e99629a976809fe102ef73e856cf4b2660acd82a412a51e80ba2215e523dfd0a"},
- {file = "pyzmq-25.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:66509c48f7446b640eeae24b60c9c1461799a27b1b0754e438582e36b5af3315"},
- {file = "pyzmq-25.0.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c464cc508177c09a5a6122b67f978f20e2954a21362bf095a0da4647e3e908"},
- {file = "pyzmq-25.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:28bcb2e66224a7ac2843eb632e4109d6b161479e7a2baf24e37210461485b4f1"},
- {file = "pyzmq-25.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0e7ef9ac807db50b4eb6f534c5dcc22f998f5dae920cc28873d2c1d080a4fc9"},
- {file = "pyzmq-25.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:5050f5c50b58a6e38ccaf9263a356f74ef1040f5ca4030225d1cb1a858c5b7b6"},
- {file = "pyzmq-25.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2a73af6504e0d2805e926abf136ebf536735a13c22f709be7113c2ec65b4bec3"},
- {file = "pyzmq-25.0.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0e8d00228db627ddd1b418c7afd81820b38575f237128c9650365f2dd6ac3443"},
- {file = "pyzmq-25.0.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5605621f2181f20b71f13f698944deb26a0a71af4aaf435b34dd90146092d530"},
- {file = "pyzmq-25.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6136bfb0e5a9cf8c60c6ac763eb21f82940a77e6758ea53516c8c7074f4ff948"},
- {file = "pyzmq-25.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0a90b2480a26aef7c13cff18703ba8d68e181facb40f78873df79e6d42c1facc"},
- {file = "pyzmq-25.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00c94fd4c9dd3c95aace0c629a7fa713627a5c80c1819326b642adf6c4b8e2a2"},
- {file = "pyzmq-25.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20638121b0bdc80777ce0ec8c1f14f1ffec0697a1f88f0b564fa4a23078791c4"},
- {file = "pyzmq-25.0.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6f75b4b8574f3a8a0d6b4b52606fc75b82cb4391471be48ab0b8677c82f9ed4"},
- {file = "pyzmq-25.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cbb885f347eba7ab7681c450dee5b14aed9f153eec224ec0c3f299273d9241f"},
- {file = "pyzmq-25.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c48f257da280b3be6c94e05bd575eddb1373419dbb1a72c3ce64e88f29d1cd6d"},
- {file = "pyzmq-25.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:866eabf7c1315ef2e93e34230db7cbf672e0d7c626b37c11f7e870c8612c3dcc"},
- {file = "pyzmq-25.0.0.tar.gz", hash = "sha256:f330a1a2c7f89fd4b0aa4dcb7bf50243bf1c8da9a2f1efc31daf57a2046b31f2"},
+ {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:1a6169e69034eaa06823da6a93a7739ff38716142b3596c180363dee729d713d"},
+ {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:19d0383b1f18411d137d891cab567de9afa609b214de68b86e20173dc624c101"},
+ {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1e931d9a92f628858a50f5bdffdfcf839aebe388b82f9d2ccd5d22a38a789dc"},
+ {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d984b1b2f574bc1bb58296d3c0b64b10e95e7026f8716ed6c0b86d4679843f"},
+ {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:154bddda2a351161474b36dba03bf1463377ec226a13458725183e508840df89"},
+ {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cb6d161ae94fb35bb518b74bb06b7293299c15ba3bc099dccd6a5b7ae589aee3"},
+ {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:90146ab578931e0e2826ee39d0c948d0ea72734378f1898939d18bc9c823fcf9"},
+ {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:831ba20b660b39e39e5ac8603e8193f8fce1ee03a42c84ade89c36a251449d80"},
+ {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a522510e3434e12aff80187144c6df556bb06fe6b9d01b2ecfbd2b5bfa5c60c"},
+ {file = "pyzmq-25.1.0-cp310-cp310-win32.whl", hash = "sha256:be24a5867b8e3b9dd5c241de359a9a5217698ff616ac2daa47713ba2ebe30ad1"},
+ {file = "pyzmq-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:5693dcc4f163481cf79e98cf2d7995c60e43809e325b77a7748d8024b1b7bcba"},
+ {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:13bbe36da3f8aaf2b7ec12696253c0bf6ffe05f4507985a8844a1081db6ec22d"},
+ {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:69511d604368f3dc58d4be1b0bad99b61ee92b44afe1cd9b7bd8c5e34ea8248a"},
+ {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a983c8694667fd76d793ada77fd36c8317e76aa66eec75be2653cef2ea72883"},
+ {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:332616f95eb400492103ab9d542b69d5f0ff628b23129a4bc0a2fd48da6e4e0b"},
+ {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58416db767787aedbfd57116714aad6c9ce57215ffa1c3758a52403f7c68cff5"},
+ {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cad9545f5801a125f162d09ec9b724b7ad9b6440151b89645241d0120e119dcc"},
+ {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d6128d431b8dfa888bf51c22a04d48bcb3d64431caf02b3cb943269f17fd2994"},
+ {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b15247c49d8cbea695b321ae5478d47cffd496a2ec5ef47131a9e79ddd7e46c"},
+ {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:442d3efc77ca4d35bee3547a8e08e8d4bb88dadb54a8377014938ba98d2e074a"},
+ {file = "pyzmq-25.1.0-cp311-cp311-win32.whl", hash = "sha256:65346f507a815a731092421d0d7d60ed551a80d9b75e8b684307d435a5597425"},
+ {file = "pyzmq-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b45d722046fea5a5694cba5d86f21f78f0052b40a4bbbbf60128ac55bfcc7b6"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f45808eda8b1d71308c5416ef3abe958f033fdbb356984fabbfc7887bed76b3f"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b697774ea8273e3c0460cf0bba16cd85ca6c46dfe8b303211816d68c492e132"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b324fa769577fc2c8f5efcd429cef5acbc17d63fe15ed16d6dcbac2c5eb00849"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:5873d6a60b778848ce23b6c0ac26c39e48969823882f607516b91fb323ce80e5"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f0d9e7ba6a815a12c8575ba7887da4b72483e4cfc57179af10c9b937f3f9308f"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:414b8beec76521358b49170db7b9967d6974bdfc3297f47f7d23edec37329b00"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:01f06f33e12497dca86353c354461f75275a5ad9eaea181ac0dc1662da8074fa"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-win32.whl", hash = "sha256:b5a07c4f29bf7cb0164664ef87e4aa25435dcc1f818d29842118b0ac1eb8e2b5"},
+ {file = "pyzmq-25.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:968b0c737797c1809ec602e082cb63e9824ff2329275336bb88bd71591e94a90"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47b915ba666c51391836d7ed9a745926b22c434efa76c119f77bcffa64d2c50c"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af31493663cf76dd36b00dafbc839e83bbca8a0662931e11816d75f36155897"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5489738a692bc7ee9a0a7765979c8a572520d616d12d949eaffc6e061b82b4d1"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1fc56a0221bdf67cfa94ef2d6ce5513a3d209c3dfd21fed4d4e87eca1822e3a3"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:75217e83faea9edbc29516fc90c817bc40c6b21a5771ecb53e868e45594826b0"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3830be8826639d801de9053cf86350ed6742c4321ba4236e4b5568528d7bfed7"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3575699d7fd7c9b2108bc1c6128641a9a825a58577775ada26c02eb29e09c517"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-win32.whl", hash = "sha256:95bd3a998d8c68b76679f6b18f520904af5204f089beebb7b0301d97704634dd"},
+ {file = "pyzmq-25.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dbc466744a2db4b7ca05589f21ae1a35066afada2f803f92369f5877c100ef62"},
+ {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:3bed53f7218490c68f0e82a29c92335daa9606216e51c64f37b48eb78f1281f4"},
+ {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eb52e826d16c09ef87132c6e360e1879c984f19a4f62d8a935345deac43f3c12"},
+ {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ddbef8b53cd16467fdbfa92a712eae46dd066aa19780681a2ce266e88fbc7165"},
+ {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9301cf1d7fc1ddf668d0abbe3e227fc9ab15bc036a31c247276012abb921b5ff"},
+ {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e23a8c3b6c06de40bdb9e06288180d630b562db8ac199e8cc535af81f90e64b"},
+ {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4a82faae00d1eed4809c2f18b37f15ce39a10a1c58fe48b60ad02875d6e13d80"},
+ {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c8398a1b1951aaa330269c35335ae69744be166e67e0ebd9869bdc09426f3871"},
+ {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d40682ac60b2a613d36d8d3a0cd14fbdf8e7e0618fbb40aa9fa7b796c9081584"},
+ {file = "pyzmq-25.1.0-cp38-cp38-win32.whl", hash = "sha256:33d5c8391a34d56224bccf74f458d82fc6e24b3213fc68165c98b708c7a69325"},
+ {file = "pyzmq-25.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:c66b7ff2527e18554030319b1376d81560ca0742c6e0b17ff1ee96624a5f1afd"},
+ {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:af56229ea6527a849ac9fb154a059d7e32e77a8cba27e3e62a1e38d8808cb1a5"},
+ {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdca18b94c404af6ae5533cd1bc310c4931f7ac97c148bbfd2cd4bdd62b96253"},
+ {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b6b42f7055bbc562f63f3df3b63e3dd1ebe9727ff0f124c3aa7bcea7b3a00f9"},
+ {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c2fc7aad520a97d64ffc98190fce6b64152bde57a10c704b337082679e74f67"},
+ {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86a26415a8b6af02cd8d782e3a9ae3872140a057f1cadf0133de685185c02b"},
+ {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:851fb2fe14036cfc1960d806628b80276af5424db09fe5c91c726890c8e6d943"},
+ {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2a21fec5c3cea45421a19ccbe6250c82f97af4175bc09de4d6dd78fb0cb4c200"},
+ {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bad172aba822444b32eae54c2d5ab18cd7dee9814fd5c7ed026603b8cae2d05f"},
+ {file = "pyzmq-25.1.0-cp39-cp39-win32.whl", hash = "sha256:4d67609b37204acad3d566bb7391e0ecc25ef8bae22ff72ebe2ad7ffb7847158"},
+ {file = "pyzmq-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:71c7b5896e40720d30cd77a81e62b433b981005bbff0cb2f739e0f8d059b5d99"},
+ {file = "pyzmq-25.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cb27ef9d3bdc0c195b2dc54fcb8720e18b741624686a81942e14c8b67cc61a6"},
+ {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0c4fc2741e0513b5d5a12fe200d6785bbcc621f6f2278893a9ca7bed7f2efb7d"},
+ {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fc34fdd458ff77a2a00e3c86f899911f6f269d393ca5675842a6e92eea565bae"},
+ {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8751f9c1442624da391bbd92bd4b072def6d7702a9390e4479f45c182392ff78"},
+ {file = "pyzmq-25.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6581e886aec3135964a302a0f5eb68f964869b9efd1dbafdebceaaf2934f8a68"},
+ {file = "pyzmq-25.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5482f08d2c3c42b920e8771ae8932fbaa0a67dff925fc476996ddd8155a170f3"},
+ {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7fbcafa3ea16d1de1f213c226005fea21ee16ed56134b75b2dede5a2129e62"},
+ {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adecf6d02b1beab8d7c04bc36f22bb0e4c65a35eb0b4750b91693631d4081c70"},
+ {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6d39e42a0aa888122d1beb8ec0d4ddfb6c6b45aecb5ba4013c27e2f28657765"},
+ {file = "pyzmq-25.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7018289b402ebf2b2c06992813523de61d4ce17bd514c4339d8f27a6f6809492"},
+ {file = "pyzmq-25.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9e68ae9864d260b18f311b68d29134d8776d82e7f5d75ce898b40a88df9db30f"},
+ {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e21cc00e4debe8f54c3ed7b9fcca540f46eee12762a9fa56feb8512fd9057161"},
+ {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f666ae327a6899ff560d741681fdcdf4506f990595201ed39b44278c471ad98"},
+ {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f5efcc29056dfe95e9c9db0dfbb12b62db9c4ad302f812931b6d21dd04a9119"},
+ {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:48e5e59e77c1a83162ab3c163fc01cd2eebc5b34560341a67421b09be0891287"},
+ {file = "pyzmq-25.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:108c96ebbd573d929740d66e4c3d1bdf31d5cde003b8dc7811a3c8c5b0fc173b"},
+ {file = "pyzmq-25.1.0.tar.gz", hash = "sha256:80c41023465d36280e801564a69cbfce8ae85ff79b080e1913f6e90481fb8957"},
]
[package.dependencies]
@@ -2907,101 +2808,103 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""}
[[package]]
name = "rapidfuzz"
-version = "2.13.7"
+version = "2.15.1"
description = "rapid fuzzy string matching"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "rapidfuzz-2.13.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b75dd0928ce8e216f88660ab3d5c5ffe990f4dd682fd1709dba29d5dafdde6de"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:24d3fea10680d085fd0a4d76e581bfb2b1074e66e78fd5964d4559e1fcd2a2d4"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8109e0324d21993d5b2d111742bf5958f3516bf8c59f297c5d1cc25a2342eb66"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f705652360d520c2de52bee11100c92f59b3e3daca308ebb150cbc58aecdad"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7496e8779905b02abc0ab4ba2a848e802ab99a6e20756ffc967a0de4900bd3da"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:24eb6b843492bdc63c79ee4b2f104059b7a2201fef17f25177f585d3be03405a"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:467c1505362823a5af12b10234cb1c4771ccf124c00e3fc9a43696512bd52293"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53dcae85956853b787c27c1cb06f18bb450e22cf57a4ad3444cf03b8ff31724a"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46b9b8aa09998bc48dd800854e8d9b74bc534d7922c1d6e1bbf783e7fa6ac29c"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1fbad8fb28d98980f5bff33c7842efef0315d42f0cd59082108482a7e6b61410"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:43fb8cb030f888c3f076d40d428ed5eb4331f5dd6cf1796cfa39c67bf0f0fc1e"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:b6bad92de071cbffa2acd4239c1779f66851b60ffbbda0e4f4e8a2e9b17e7eef"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d00df2e4a81ffa56a6b1ec4d2bc29afdcb7f565e0b8cd3092fece2290c4c7a79"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-win32.whl", hash = "sha256:2c836f0f2d33d4614c3fbaf9a1eb5407c0fe23f8876f47fd15b90f78daa64c34"},
- {file = "rapidfuzz-2.13.7-cp310-cp310-win_amd64.whl", hash = "sha256:c36fd260084bb636b9400bb92016c6bd81fd80e59ed47f2466f85eda1fc9f782"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b34e8c0e492949ecdd5da46a1cfc856a342e2f0389b379b1a45a3cdcd3176a6e"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:875d51b3497439a72e2d76183e1cb5468f3f979ab2ddfc1d1f7dde3b1ecfb42f"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae33a72336059213996fe4baca4e0e4860913905c2efb7c991eab33b95a98a0a"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5585189b3d90d81ccd62d4f18530d5ac8972021f0aaaa1ffc6af387ff1dce75"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42085d4b154a8232767de8296ac39c8af5bccee6b823b0507de35f51c9cbc2d7"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:585206112c294e335d84de5d5f179c0f932837752d7420e3de21db7fdc476278"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f891b98f8bc6c9d521785816085e9657212621e93f223917fb8e32f318b2957e"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08590905a95ccfa43f4df353dcc5d28c15d70664299c64abcad8721d89adce4f"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b5dd713a1734574c2850c566ac4286594bacbc2d60b9170b795bee4b68656625"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:988f8f6abfba7ee79449f8b50687c174733b079521c3cc121d65ad2d38831846"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b3210869161a864f3831635bb13d24f4708c0aa7208ef5baac1ac4d46e9b4208"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f6fe570e20e293eb50491ae14ddeef71a6a7e5f59d7e791393ffa99b13f1f8c2"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6120f2995f5154057454c5de99d86b4ef3b38397899b5da1265467e8980b2f60"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-win32.whl", hash = "sha256:b20141fa6cee041917801de0bab503447196d372d4c7ee9a03721b0a8edf5337"},
- {file = "rapidfuzz-2.13.7-cp311-cp311-win_amd64.whl", hash = "sha256:ec55a81ac2b0f41b8d6fb29aad16e55417036c7563bad5568686931aa4ff08f7"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d005e058d86f2a968a8d28ca6f2052fab1f124a39035aa0523261d6baf21e1f"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe59a0c21a032024edb0c8e43f5dee5623fef0b65a1e3c1281836d9ce199af3b"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfc04f7647c29fb48da7a04082c34cdb16f878d3c6d098d62d5715c0ad3000c"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68a89bb06d5a331511961f4d3fa7606f8e21237467ba9997cae6f67a1c2c2b9e"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:effe182767d102cb65dfbbf74192237dbd22d4191928d59415aa7d7c861d8c88"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25b4cedf2aa19fb7212894ce5f5219010cce611b60350e9a0a4d492122e7b351"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3a9bd02e1679c0fd2ecf69b72d0652dbe2a9844eaf04a36ddf4adfbd70010e95"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5e2b3d020219baa75f82a4e24b7c8adcb598c62f0e54e763c39361a9e5bad510"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:cf62dacb3f9234f3fddd74e178e6d25c68f2067fde765f1d95f87b1381248f58"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:fa263135b892686e11d5b84f6a1892523123a00b7e5882eff4fbdabb38667347"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa4c598ed77f74ec973247ca776341200b0f93ec3883e34c222907ce72cb92a4"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-win32.whl", hash = "sha256:c2523f8180ebd9796c18d809e9a19075a1060b1a170fde3799e83db940c1b6d5"},
- {file = "rapidfuzz-2.13.7-cp37-cp37m-win_amd64.whl", hash = "sha256:5ada0a14c67452358c1ee52ad14b80517a87b944897aaec3e875279371a9cb96"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ca8a23097c1f50e0fdb4de9e427537ca122a18df2eead06ed39c3a0bef6d9d3a"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9be02162af0376d64b840f2fc8ee3366794fc149f1e06d095a6a1d42447d97c5"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af4f7c3c904ca709493eb66ca9080b44190c38e9ecb3b48b96d38825d5672559"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f50d1227e6e2a0e3ae1fb1c9a2e1c59577d3051af72c7cab2bcc430cb5e18da"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c71d9d512b76f05fa00282227c2ae884abb60e09f08b5ca3132b7e7431ac7f0d"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b52ac2626945cd21a2487aeefed794c14ee31514c8ae69b7599170418211e6f6"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca00fafd2756bc9649bf80f1cf72c647dce38635f0695d7ce804bc0f759aa756"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d248a109699ce9992304e79c1f8735c82cc4c1386cd8e27027329c0549f248a2"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c88adbcb933f6b8612f6c593384bf824e562bb35fc8a0f55fac690ab5b3486e5"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c8601a66fbfc0052bb7860d2eacd303fcde3c14e87fdde409eceff516d659e77"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:27be9c63215d302ede7d654142a2e21f0d34ea6acba512a4ae4cfd52bbaa5b59"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3dcffe1f3cbda0dc32133a2ae2255526561ca594f15f9644384549037b355245"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8450d15f7765482e86ef9be2ad1a05683cd826f59ad236ef7b9fb606464a56aa"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-win32.whl", hash = "sha256:460853983ab88f873173e27cc601c5276d469388e6ad6e08c4fd57b2a86f1064"},
- {file = "rapidfuzz-2.13.7-cp38-cp38-win_amd64.whl", hash = "sha256:424f82c35dbe4f83bdc3b490d7d696a1dc6423b3d911460f5493b7ffae999fd2"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c3fbe449d869ea4d0909fc9d862007fb39a584fb0b73349a6aab336f0d90eaed"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:16080c05a63d6042643ae9b6cfec1aefd3e61cef53d0abe0df3069b9d4b72077"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dbcf5371ea704759fcce772c66a07647751d1f5dbdec7818331c9b31ae996c77"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:114810491efb25464016fd554fdf1e20d390309cecef62587494fc474d4b926f"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a84ab9ac9a823e7e93b4414f86344052a5f3e23b23aa365cda01393ad895bd"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81642a24798851b118f82884205fc1bd9ff70b655c04018c467824b6ecc1fabc"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3741cb0bf9794783028e8b0cf23dab917fa5e37a6093b94c4c2f805f8e36b9f"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:759a3361711586a29bc753d3d1bdb862983bd9b9f37fbd7f6216c24f7c972554"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1333fb3d603d6b1040e365dca4892ba72c7e896df77a54eae27dc07db90906e3"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:916bc2e6cf492c77ad6deb7bcd088f0ce9c607aaeabc543edeb703e1fbc43e31"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:23524635840500ce6f4d25005c9529a97621689c85d2f727c52eed1782839a6a"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:ebe303cd9839af69dd1f7942acaa80b1ba90bacef2e7ded9347fbed4f1654672"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fe56659ccadbee97908132135de4b875543353351e0c92e736b7c57aee298b5a"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-win32.whl", hash = "sha256:3f11a7eff7bc6301cd6a5d43f309e22a815af07e1f08eeb2182892fca04c86cb"},
- {file = "rapidfuzz-2.13.7-cp39-cp39-win_amd64.whl", hash = "sha256:e8914dad106dacb0775718e54bf15e528055c4e92fb2677842996f2d52da5069"},
- {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f7930adf84301797c3f09c94b9c5a9ed90a9e8b8ed19b41d2384937e0f9f5bd"},
- {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c31022d9970177f6affc6d5dd757ed22e44a10890212032fabab903fdee3bfe7"},
- {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f42b82f268689f429def9ecfb86fa65ceea0eaf3fed408b570fe113311bf5ce7"},
- {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b477b43ced896301665183a5e0faec0f5aea2373005648da8bdcb3c4b73f280"},
- {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d63def9bbc6b35aef4d76dc740301a4185867e8870cbb8719ec9de672212fca8"},
- {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c66546e30addb04a16cd864f10f5821272a1bfe6462ee5605613b4f1cb6f7b48"},
- {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f799d1d6c33d81e983d3682571cc7d993ae7ff772c19b3aabb767039c33f6d1e"},
- {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82f20c0060ffdaadaf642b88ab0aa52365b56dffae812e188e5bdb998043588"},
- {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:042644133244bfa7b20de635d500eb9f46af7097f3d90b1724f94866f17cb55e"},
- {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:75c45dcd595f8178412367e302fd022860ea025dc4a78b197b35428081ed33d5"},
- {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3d8b081988d0a49c486e4e845a547565fee7c6e7ad8be57ff29c3d7c14c6894c"},
- {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16ffad751f43ab61001187b3fb4a9447ec2d1aedeff7c5bac86d3b95f9980cc3"},
- {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:020858dd89b60ce38811cd6e37875c4c3c8d7fcd8bc20a0ad2ed1f464b34dc4e"},
- {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cda1e2f66bb4ba7261a0f4c2d052d5d909798fca557cbff68f8a79a87d66a18f"},
- {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b6389c50d8d214c9cd11a77f6d501529cb23279a9c9cafe519a3a4b503b5f72a"},
- {file = "rapidfuzz-2.13.7.tar.gz", hash = "sha256:8d3e252d4127c79b4d7c2ae47271636cbaca905c8bb46d80c7930ab906cf4b5c"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fc0bc259ebe3b93e7ce9df50b3d00e7345335d35acbd735163b7c4b1957074d3"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d59fb3a410d253f50099d7063855c2b95df1ef20ad93ea3a6b84115590899f25"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c525a3da17b6d79d61613096c8683da86e3573e807dfaecf422eea09e82b5ba6"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4deae6a918ecc260d0c4612257be8ba321d8e913ccb43155403842758c46fbe"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2577463d10811386e704a3ab58b903eb4e2a31b24dfd9886d789b0084d614b01"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f67d5f56aa48c0da9de4ab81bffb310683cf7815f05ea38e5aa64f3ba4368339"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7927722ff43690e52b3145b5bd3089151d841d350c6f8378c3cfac91f67573a"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6534afc787e32c4104f65cdeb55f6abe4d803a2d0553221d00ef9ce12788dcde"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d0ae6ec79a1931929bb9dd57bc173eb5ba4c7197461bf69e3a34b6dd314feed2"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be7ccc45c4d1a7dfb595f260e8022a90c6cb380c2a346ee5aae93f85c96d362b"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:8ba013500a2b68c64b2aecc5fb56a2dad6c2872cf545a0308fd044827b6e5f6a"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4d9f7d10065f657f960b48699e7dddfce14ab91af4bab37a215f0722daf0d716"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7e24a1b802cea04160b3fccd75d2d0905065783ebc9de157d83c14fb9e1c6ce2"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-win32.whl", hash = "sha256:dffdf03499e0a5b3442951bb82b556333b069e0661e80568752786c79c5b32de"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d150d90a7c6caae7962f29f857a4e61d42038cfd82c9df38508daf30c648ae7"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-win_arm64.whl", hash = "sha256:87c30e9184998ff6eb0fa9221f94282ce7c908fd0da96a1ef66ecadfaaa4cdb7"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6986413cb37035eb796e32f049cbc8c13d8630a4ac1e0484e3e268bb3662bd1b"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a72f26e010d4774b676f36e43c0fc8a2c26659efef4b3be3fd7714d3491e9957"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5cd54c98a387cca111b3b784fc97a4f141244bbc28a92d4bde53f164464112e"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7fac7c3da39f93e6b2ebe386ed0ffe1cefec91509b91857f6e1204509e931f"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f976e76ac72f650790b3a5402431612175b2ac0363179446285cb3c901136ca9"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:abde47e1595902a490ed14d4338d21c3509156abb2042a99e6da51f928e0c117"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca8f1747007a3ce919739a60fa95c5325f7667cccf6f1c1ef18ae799af119f5e"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c35da09ab9797b020d0d4f07a66871dfc70ea6566363811090353ea971748b5a"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a3a769ca7580686a66046b77df33851b3c2d796dc1eb60c269b68f690f3e1b65"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d50622efefdb03a640a51a6123748cd151d305c1f0431af762e833d6ffef71f0"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b7461b0a7651d68bc23f0896bffceea40f62887e5ab8397bf7caa883592ef5cb"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:074ee9e17912e025c72a5780ee4c7c413ea35cd26449719cc399b852d4e42533"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7025fb105a11f503943f17718cdb8241ea3bb4d812c710c609e69bead40e2ff0"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-win32.whl", hash = "sha256:2084d36b95139413cef25e9487257a1cc892b93bd1481acd2a9656f7a1d9930c"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:5a738fcd24e34bce4b19126b92fdae15482d6d3a90bd687fd3d24ce9d28ce82d"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-win_arm64.whl", hash = "sha256:dc3cafa68cfa54638632bdcadf9aab89a3d182b4a3f04d2cad7585ed58ea8731"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c53d57ba7a88f7bf304d4ea5a14a0ca112db0e0178fff745d9005acf2879f7d"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6ee758eec4cf2215dc8d8eafafcea0d1f48ad4b0135767db1b0f7c5c40a17dd"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d93ba3ae59275e7a3a116dac4ffdb05e9598bf3ee0861fecc5b60fb042d539e"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c3ff75e647908ddbe9aa917fbe39a112d5631171f3fcea5809e2363e525a59d"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d89c421702474c6361245b6b199e6e9783febacdbfb6b002669e6cb3ef17a09"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f69e6199fec0f58f9a89afbbaea78d637c7ce77f656a03a1d6ea6abdc1d44f8"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:41dfea282844d0628279b4db2929da0dacb8ac317ddc5dcccc30093cf16357c1"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2dd03477feefeccda07b7659dd614f6738cfc4f9b6779dd61b262a73b0a9a178"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5efe035aa76ff37d1b5fa661de3c4b4944de9ff227a6c0b2e390a95c101814c0"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ed2cf7c69102c7a0a06926d747ed855bc836f52e8d59a5d1e3adfd980d1bd165"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a0e441d4c2025110ec3eba5d54f11f78183269a10152b3a757a739ffd1bb12bf"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-win32.whl", hash = "sha256:a4a54efe17cc9f53589c748b53f28776dfdfb9bc83619685740cb7c37985ac2f"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:bb8318116ecac4dfb84841d8b9b461f9bb0c3be5b616418387d104f72d2a16d1"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e9296c530e544f68858c3416ad1d982a1854f71e9d2d3dcedb5b216e6d54f067"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:49c4bcdb9238f11f8c4eba1b898937f09b92280d6f900023a8216008f299b41a"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebb40a279e134bb3fef099a8b58ed5beefb201033d29bdac005bddcdb004ef71"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7381c11cb590bbd4e6f2d8779a0b34fdd2234dfa13d0211f6aee8ca166d9d05"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfdcdedfd12a0077193f2cf3626ff6722c5a184adf0d2d51f1ec984bf21c23c3"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85bece1ec59bda8b982bd719507d468d4df746dfb1988df11d916b5e9fe19e8"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1b393f4a1eaa6867ffac6aef58cfb04bab2b3d7d8e40b9fe2cf40dd1d384601"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53de456ef020a77bf9d7c6c54860a48e2e902584d55d3001766140ac45c54bc7"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2492330bc38b76ed967eab7bdaea63a89b6ceb254489e2c65c3824efcbf72993"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:099e4c6befaa8957a816bdb67ce664871f10aaec9bebf2f61368cf7e0869a7a1"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:46599b2ad4045dd3f794a24a6db1e753d23304699d4984462cf1ead02a51ddf3"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:591f19d16758a3c55c9d7a0b786b40d95599a5b244d6eaef79c7a74fcf5104d8"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed17359061840eb249f8d833cb213942e8299ffc4f67251a6ed61833a9f2ea20"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-win32.whl", hash = "sha256:aa1e5aad325168e29bf8e17006479b97024aa9d2fdbe12062bd2f8f09080acf8"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:c2bb68832b140c551dbed691290bef4ee6719d4e8ce1b7226a3736f61a9d1a83"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fac40972cf7b6c14dded88ae2331eb50dfbc278aa9195473ef6fc6bfe49f686"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0e456cbdc0abf39352800309dab82fd3251179fa0ff6573fa117f51f4e84be8"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:22b9d22022b9d09fd4ece15102270ab9b6a5cfea8b6f6d1965c1df7e3783f5ff"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46754fe404a9a6f5cbf7abe02d74af390038d94c9b8c923b3f362467606bfa28"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91abb8bf7610efe326394adc1d45e1baca8f360e74187f3fa0ef3df80cdd3ba6"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e40a2f60024f9d3c15401e668f732800114a023f3f8d8c40f1521a62081ff054"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a48ee83916401ac73938526d7bd804e01d2a8fe61809df7f1577b0b3b31049a3"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71580052f9dbac443c02f60484e5a2e5f72ad4351b84b2009fbe345b1f38422"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:82b86d5b8c1b9bcbc65236d75f81023c78d06a721c3e0229889ff4ed5c858169"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fc4528b7736e5c30bc954022c2cf410889abc19504a023abadbc59cdf9f37cae"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e1e0e569108a5760d8f01d0f2148dd08cc9a39ead79fbefefca9e7c7723c7e88"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:94e1c97f0ad45b05003806f8a13efc1fc78983e52fa2ddb00629003acf4676ef"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47e81767a962e41477a85ad7ac937e34d19a7d2a80be65614f008a5ead671c56"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-win32.whl", hash = "sha256:79fc574aaf2d7c27ec1022e29c9c18f83cdaf790c71c05779528901e0caad89b"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:f3dd4bcef2d600e0aa121e19e6e62f6f06f22a89f82ef62755e205ce14727874"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-win_arm64.whl", hash = "sha256:cac095cbdf44bc286339a77214bbca6d4d228c9ebae3da5ff6a80aaeb7c35634"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b89d1126be65c85763d56e3b47d75f1a9b7c5529857b4d572079b9a636eaa8a7"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7460e91168229768be882ea365ba0ac7da43e57f9416e2cfadc396a7df3c2"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c33c03e7092642c38f8a15ca2d8fc38da366f2526ec3b46adf19d5c7aa48ba"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040faca2e26d9dab5541b45ce72b3f6c0e36786234703fc2ac8c6f53bb576743"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6e2a3b23e1e9aa13474b3c710bba770d0dcc34d517d3dd6f97435a32873e3f28"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e597b9dfd6dd180982684840975c458c50d447e46928efe3e0120e4ec6f6686"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14752c9dd2036c5f36ebe8db5f027275fa7d6b3ec6484158f83efb674bab84e"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558224b6fc6124d13fa32d57876f626a7d6188ba2a97cbaea33a6ee38a867e31"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c89cfa88dc16fd8c9bcc0c7f0b0073f7ef1e27cceb246c9f5a3f7004fa97c4d"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:509c5b631cd64df69f0f011893983eb15b8be087a55bad72f3d616b6ae6a0f96"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0f73a04135a03a6e40393ecd5d46a7a1049d353fc5c24b82849830d09817991f"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c99d53138a2dfe8ada67cb2855719f934af2733d726fbf73247844ce4dd6dd5"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f01fa757f0fb332a1f045168d29b0d005de6c39ee5ce5d6c51f2563bb53c601b"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60368e1add6e550faae65614844c43f8a96e37bf99404643b648bf2dba92c0fb"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785744f1270828cc632c5a3660409dee9bcaac6931a081bae57542c93e4d46c4"},
+ {file = "rapidfuzz-2.15.1.tar.gz", hash = "sha256:d62137c2ca37aea90a11003ad7dc109c8f1739bfbe5a9a217f3cdb07d7ac00f6"},
]
[package.extras]
@@ -3009,21 +2912,20 @@ full = ["numpy"]
[[package]]
name = "requests"
-version = "2.28.2"
+version = "2.31.0"
description = "Python HTTP for Humans."
-category = "dev"
optional = false
-python-versions = ">=3.7, <4"
+python-versions = ">=3.7"
files = [
- {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
- {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
+ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
+ {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<1.27"
+urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
@@ -3031,14 +2933,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "requests-toolbelt"
-version = "0.10.1"
+version = "1.0.0"
description = "A utility belt for advanced users of python-requests"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
- {file = "requests-toolbelt-0.10.1.tar.gz", hash = "sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d"},
- {file = "requests_toolbelt-0.10.1-py2.py3-none-any.whl", hash = "sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7"},
+ {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"},
+ {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"},
]
[package.dependencies]
@@ -3046,33 +2947,32 @@ requests = ">=2.0.1,<3.0.0"
[[package]]
name = "scipy"
-version = "1.10.0"
+version = "1.10.1"
description = "Fundamental algorithms for scientific computing in Python"
-category = "main"
optional = false
python-versions = "<3.12,>=3.8"
files = [
- {file = "scipy-1.10.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b901b423c91281a974f6cd1c36f5c6c523e665b5a6d5e80fcb2334e14670eefd"},
- {file = "scipy-1.10.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:16ba05d3d1b9f2141004f3f36888e05894a525960b07f4c2bfc0456b955a00be"},
- {file = "scipy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:151f066fe7d6653c3ffefd489497b8fa66d7316e3e0d0c0f7ff6acca1b802809"},
- {file = "scipy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f9ea0a37aca111a407cb98aa4e8dfde6e5d9333bae06dfa5d938d14c80bb5c3"},
- {file = "scipy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:27e548276b5a88b51212b61f6dda49a24acf5d770dff940bd372b3f7ced8c6c2"},
- {file = "scipy-1.10.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:42ab8b9e7dc1ebe248e55f54eea5307b6ab15011a7883367af48dd781d1312e4"},
- {file = "scipy-1.10.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e096b062d2efdea57f972d232358cb068413dc54eec4f24158bcbb5cb8bddfd8"},
- {file = "scipy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4df25a28bd22c990b22129d3c637fd5c3be4b7c94f975dca909d8bab3309b694"},
- {file = "scipy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ad449db4e0820e4b42baccefc98ec772ad7818dcbc9e28b85aa05a536b0f1a2"},
- {file = "scipy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:6faf86ef7717891195ae0537e48da7524d30bc3b828b30c9b115d04ea42f076f"},
- {file = "scipy-1.10.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:4bd0e3278126bc882d10414436e58fa3f1eca0aa88b534fcbf80ed47e854f46c"},
- {file = "scipy-1.10.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:38bfbd18dcc69eeb589811e77fae552fa923067fdfbb2e171c9eac749885f210"},
- {file = "scipy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ab2a58064836632e2cec31ca197d3695c86b066bc4818052b3f5381bfd2a728"},
- {file = "scipy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cd7a30970c29d9768a7164f564d1fbf2842bfc77b7d114a99bc32703ce0bf48"},
- {file = "scipy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:9b878c671655864af59c108c20e4da1e796154bd78c0ed6bb02bc41c84625686"},
- {file = "scipy-1.10.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:3afcbddb4488ac950ce1147e7580178b333a29cd43524c689b2e3543a080a2c8"},
- {file = "scipy-1.10.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:6e4497e5142f325a5423ff5fda2fff5b5d953da028637ff7c704378c8c284ea7"},
- {file = "scipy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:441cab2166607c82e6d7a8683779cb89ba0f475b983c7e4ab88f3668e268c143"},
- {file = "scipy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0490dc499fe23e4be35b8b6dd1e60a4a34f0c4adb30ac671e6332446b3cbbb5a"},
- {file = "scipy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:954ff69d2d1bf666b794c1d7216e0a746c9d9289096a64ab3355a17c7c59db54"},
- {file = "scipy-1.10.0.tar.gz", hash = "sha256:c8b3cbc636a87a89b770c6afc999baa6bcbb01691b5ccbbc1b1791c7c0a07540"},
+ {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"},
]
[package.dependencies]
@@ -3087,7 +2987,6 @@ test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeo
name = "secretstorage"
version = "3.3.3"
description = "Python bindings to FreeDesktop.org Secret Service API"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -3099,28 +2998,10 @@ files = [
cryptography = ">=2.0"
jeepney = ">=0.6"
-[[package]]
-name = "setuptools"
-version = "67.3.2"
-description = "Easily download, build, install, upgrade, and uninstall Python packages"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "setuptools-67.3.2-py3-none-any.whl", hash = "sha256:bb6d8e508de562768f2027902929f8523932fcd1fb784e6d573d2cafac995a48"},
- {file = "setuptools-67.3.2.tar.gz", hash = "sha256:95f00380ef2ffa41d9bba85d95b27689d923c93dfbafed4aecd7cf988a25e012"},
-]
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "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 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "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 = "shellingham"
version = "1.5.0.post1"
description = "Tool to Detect Surrounding Shell"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -3132,7 +3013,6 @@ files = [
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -3144,7 +3024,6 @@ files = [
name = "smmap"
version = "5.0.0"
description = "A pure Python implementation of a sliding window memory map manager"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -3156,7 +3035,6 @@ files = [
name = "snowballstemmer"
version = "2.2.0"
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3166,21 +3044,19 @@ files = [
[[package]]
name = "soupsieve"
-version = "2.4"
+version = "2.4.1"
description = "A modern CSS selector implementation for Beautiful Soup."
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "soupsieve-2.4-py3-none-any.whl", hash = "sha256:49e5368c2cda80ee7e84da9dbe3e110b70a4575f196efb74e51b94549d921955"},
- {file = "soupsieve-2.4.tar.gz", hash = "sha256:e28dba9ca6c7c00173e34e4ba57448f0688bb681b7c5e8bf4971daafc093d69a"},
+ {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"},
+ {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"},
]
[[package]]
name = "sphinx"
version = "4.5.0"
description = "Python documentation generator"
-category = "dev"
optional = false
python-versions = ">=3.6"
files = [
@@ -3214,14 +3090,13 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"]
[[package]]
name = "sphinx-rtd-theme"
-version = "1.2.0"
+version = "1.2.1"
description = "Read the Docs theme for Sphinx"
-category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
- {file = "sphinx_rtd_theme-1.2.0-py2.py3-none-any.whl", hash = "sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2"},
- {file = "sphinx_rtd_theme-1.2.0.tar.gz", hash = "sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8"},
+ {file = "sphinx_rtd_theme-1.2.1-py2.py3-none-any.whl", hash = "sha256:2cc9351176cbf91944ce44cefd4fab6c3b76ac53aa9e15d6db45a3229ad7f866"},
+ {file = "sphinx_rtd_theme-1.2.1.tar.gz", hash = "sha256:cf9a7dc0352cf179c538891cb28d6fad6391117d4e21c891776ab41dd6c8ff70"},
]
[package.dependencies]
@@ -3236,7 +3111,6 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
name = "sphinx-tabs"
version = "3.4.0"
description = "Tabbed views for Sphinx"
-category = "dev"
optional = false
python-versions = "~=3.7"
files = [
@@ -3258,7 +3132,6 @@ testing = ["bs4", "coverage", "pygments", "pytest (>=7.1,<8)", "pytest-cov", "py
name = "sphinxcontrib-applehelp"
version = "1.0.4"
description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -3274,7 +3147,6 @@ test = ["pytest"]
name = "sphinxcontrib-devhelp"
version = "1.0.2"
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -3290,7 +3162,6 @@ test = ["pytest"]
name = "sphinxcontrib-htmlhelp"
version = "2.0.1"
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
@@ -3304,24 +3175,22 @@ test = ["html5lib", "pytest"]
[[package]]
name = "sphinxcontrib-jquery"
-version = "2.0.0"
+version = "4.1"
description = "Extension to include jQuery on newer Sphinx releases"
-category = "dev"
optional = false
python-versions = ">=2.7"
files = [
- {file = "sphinxcontrib-jquery-2.0.0.tar.gz", hash = "sha256:8fb65f6dba84bf7bcd1aea1f02ab3955ac34611d838bcc95d4983b805b234daa"},
- {file = "sphinxcontrib_jquery-2.0.0-py3-none-any.whl", hash = "sha256:ed47fa425c338ffebe3c37e1cdb56e30eb806116b85f01055b158c7057fdb995"},
+ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"},
+ {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"},
]
[package.dependencies]
-setuptools = "*"
+Sphinx = ">=1.8"
[[package]]
name = "sphinxcontrib-jsmath"
version = "1.0.1"
description = "A sphinx extension which renders display math in HTML via JavaScript"
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -3336,7 +3205,6 @@ test = ["flake8", "mypy", "pytest"]
name = "sphinxcontrib-qthelp"
version = "1.0.3"
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -3352,7 +3220,6 @@ test = ["pytest"]
name = "sphinxcontrib-serializinghtml"
version = "1.1.5"
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
-category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@@ -3368,7 +3235,6 @@ test = ["pytest"]
name = "stack-data"
version = "0.6.2"
description = "Extract data from python stack frames and tracebacks for informative displays"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3386,14 +3252,13 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
[[package]]
name = "stevedore"
-version = "5.0.0"
+version = "5.1.0"
description = "Manage dynamic plugins for Python applications"
-category = "dev"
optional = false
python-versions = ">=3.8"
files = [
- {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"},
- {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"},
+ {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"},
+ {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"},
]
[package.dependencies]
@@ -3403,7 +3268,6 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0"
name = "tinycss2"
version = "1.2.1"
description = "A tiny CSS parser"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -3422,7 +3286,6 @@ test = ["flake8", "isort", "pytest"]
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
-category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
@@ -3434,7 +3297,6 @@ files = [
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -3444,42 +3306,39 @@ files = [
[[package]]
name = "tomlkit"
-version = "0.11.6"
+version = "0.11.8"
description = "Style preserving TOML library"
-category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"},
- {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"},
+ {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"},
+ {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},
]
[[package]]
name = "tornado"
-version = "6.2"
+version = "6.3.2"
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
-category = "dev"
optional = false
-python-versions = ">= 3.7"
+python-versions = ">= 3.8"
files = [
- {file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"},
- {file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"},
- {file = "tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"},
- {file = "tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"},
- {file = "tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"},
- {file = "tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"},
- {file = "tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"},
- {file = "tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"},
- {file = "tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"},
- {file = "tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"},
- {file = "tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"},
+ {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"},
+ {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"},
+ {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"},
+ {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"},
+ {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"},
+ {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"},
+ {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"},
+ {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"},
+ {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"},
+ {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"},
+ {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"},
]
[[package]]
name = "traceback2"
version = "1.4.0"
description = "Backports of the traceback module"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3494,7 +3353,6 @@ linecache2 = "*"
name = "traitlets"
version = "5.9.0"
description = "Traitlets Python configuration system"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -3508,21 +3366,30 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
[[package]]
name = "trove-classifiers"
-version = "2023.2.8"
+version = "2023.5.24"
description = "Canonical source for classifiers on PyPI (pypi.org)."
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "trove-classifiers-2023.2.8.tar.gz", hash = "sha256:3b6960fb96c1d4cc9988bdc1b90bcd65fcf5d9843d884dfc86bd674ff81a4dea"},
- {file = "trove_classifiers-2023.2.8-py3-none-any.whl", hash = "sha256:3aff899dd9792c4d095740980a5967eb98094ff881faf0b29afc775b75aaaac6"},
+ {file = "trove-classifiers-2023.5.24.tar.gz", hash = "sha256:fd5a1546283be941f47540a135bdeae8fb261380a6a204d9c18012f2a1b0ceae"},
+ {file = "trove_classifiers-2023.5.24-py3-none-any.whl", hash = "sha256:d9d7ae14fb90bf3d50bef99c3941b176b5326509e6e9037e622562d6352629d0"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.6.3"
+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"},
]
[[package]]
name = "unittest2"
version = "1.1.0"
description = "The new features in unittest backported to Python 2.4+."
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3537,14 +3404,13 @@ traceback2 = "*"
[[package]]
name = "urllib3"
-version = "1.26.14"
+version = "1.26.16"
description = "HTTP library with thread-safe connection pooling, file post, and more."
-category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"},
- {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"},
+ {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
+ {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
]
[package.extras]
@@ -3554,51 +3420,28 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "virtualenv"
-version = "20.16.5"
-description = "Virtual Python Environment builder"
-category = "dev"
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "virtualenv-20.16.5-py3-none-any.whl", hash = "sha256:d07dfc5df5e4e0dbc92862350ad87a36ed505b978f6c39609dc489eadd5b0d27"},
- {file = "virtualenv-20.16.5.tar.gz", hash = "sha256:227ea1b9994fdc5ea31977ba3383ef296d7472ea85be9d6732e42a91c04e80da"},
-]
-
-[package.dependencies]
-distlib = ">=0.3.5,<1"
-filelock = ">=3.4.1,<4"
-platformdirs = ">=2.4,<3"
-
-[package.extras]
-docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"]
-testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"]
-
-[[package]]
-name = "virtualenv"
-version = "20.19.0"
+version = "20.23.0"
description = "Virtual Python Environment builder"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.19.0-py3-none-any.whl", hash = "sha256:54eb59e7352b573aa04d53f80fc9736ed0ad5143af445a1e539aada6eb947dd1"},
- {file = "virtualenv-20.19.0.tar.gz", hash = "sha256:37a640ba82ed40b226599c522d411e4be5edb339a0c0de030c0dc7b646d61590"},
+ {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"},
+ {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"},
]
[package.dependencies]
distlib = ">=0.3.6,<1"
-filelock = ">=3.4.1,<4"
-platformdirs = ">=2.4,<4"
+filelock = ">=3.11,<4"
+platformdirs = ">=3.2,<4"
[package.extras]
-docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
-test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23)", "pytest (>=7.2.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"]
+docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"]
[[package]]
name = "wcwidth"
version = "0.2.6"
description = "Measures the displayed width of unicode strings in a terminal"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3610,7 +3453,6 @@ files = [
name = "webencodings"
version = "0.5.1"
description = "Character encoding aliases for legacy web content"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3622,7 +3464,6 @@ files = [
name = "xattr"
version = "0.10.1"
description = "Python wrapper for extended filesystem attributes"
-category = "dev"
optional = false
python-versions = "*"
files = [
@@ -3705,21 +3546,20 @@ cffi = ">=1.0"
[[package]]
name = "zipp"
-version = "3.13.0"
+version = "3.15.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "zipp-3.13.0-py3-none-any.whl", hash = "sha256:e8b2a36ea17df80ffe9e2c4fda3f693c3dad6df1697d3cd3af232db680950b0b"},
- {file = "zipp-3.13.0.tar.gz", hash = "sha256:23f70e964bc11a34cef175bc90ba2914e1e4545ea1e3e2f67c079671883f9cb6"},
+ {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
+ {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["flake8 (<5)", "func-timeout", "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)"]
+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)"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8, <3.11"
-content-hash = "1c0d6bce699c6702d5b43f9987307e8cb6e415dc2340deaddb89606108e3a094"
+content-hash = "1ddc2df45b167c409828188c9353936aec9c5738befb6bf612ff4f0a5d1a200e"
diff --git a/pyproject.toml b/pyproject.toml
index 45f2bfe4f..f1ef8af88 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,7 +13,7 @@ packages = [
include = ["tutorials",
"src/lava/magma/runtime/message_infrastructure/*.so",
"src/lava/magma/runtime/message_infrastructure/install/lib/lib*"]
-version = "0.6.0"
+version = "0.7.0"
description = "A Software Framework for Neuromorphic Computing"
homepage = "https://lava-nc.org/"
@@ -21,7 +21,7 @@ repository = "https://github.com/lava-nc/lava"
authors = [
"Intel's Neuromorphic Computing Lab and the open source community "
]
-license = "Lava uses multiple licenses and is licensed under BSD-3-Clause or LGPL-2.1-or-later"
+license = "(BSD-3-Clause), (LGPL-2.1-or-later)"
keywords = [
"neuromorphic",
"ai",
@@ -37,8 +37,8 @@ classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
- "License :: OSI Approved :: The 3-Clause BSD License (BSD-3-Clause)",
- "License :: OSI Approved :: GNU Lesser General Public License v2.1 or later (LGPL-2.1-or-later)",
+ "License :: OSI Approved :: BSD License",
+ "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)",
"Operating System :: OS Independent"
]
@@ -86,7 +86,7 @@ sphinx_rtd_theme = { extras = ["toml"], version = "^1.0.0" }
autopep8 = "^1.6.0"
ipykernel = "^6.15.0"
nbformat = "^5.3.0"
-nbconvert = "^7.2.0"
+nbconvert = ">=7.2.10, <7.3"
cpplint = "^1.6.0"
psutil = "^5.9.4"
@@ -181,11 +181,11 @@ pep8-naming = ["-*"]
# mccabe = ["+*"]
# pep8-naming = ["+*"]
# pyflakes = ["+*"]
-# pylint = ["+*"]
+pylint = ["+*"]
pycodestyle = ["+*", "-W503", "-E203"]
-pyflakes = ["-*"] # Disable temporarily until lint fix is pushed
-pylint = ["-*"] # Disable temporarily until lint fix is pushed
+# pyflakes = ["-*"] # Disable temporarily until lint fix is pushed
+# pylint = ["-*"] # Disable temporarily until lint fix is pushed
[tool.flakeheaven.exceptions."tests/"]
pycodestyle = ["-F401"] # Disable a check
diff --git a/src/lava/magma/compiler/builders/channel_builder.py b/src/lava/magma/compiler/builders/channel_builder.py
index d6db0366d..21d1d1a58 100644
--- a/src/lava/magma/compiler/builders/channel_builder.py
+++ b/src/lava/magma/compiler/builders/channel_builder.py
@@ -174,4 +174,3 @@ def build(
Exception
Can't build channel of type specified
"""
- pass
diff --git a/src/lava/magma/compiler/builders/interfaces.py b/src/lava/magma/compiler/builders/interfaces.py
index eed2c90fc..5c78fbf01 100644
--- a/src/lava/magma/compiler/builders/interfaces.py
+++ b/src/lava/magma/compiler/builders/interfaces.py
@@ -14,7 +14,6 @@ class AbstractBuilder(ABC):
@abstractmethod
def build(self):
"""Build the actual process."""
- pass
class ResourceAddress(ABC):
@@ -24,7 +23,6 @@ class ResourceAddress(ABC):
class Resource(ABC):
def write(self, hw: ty.Any):
"""Given hw, write this compiled resource"""
- pass
class CompiledResource(Resource):
diff --git a/src/lava/magma/compiler/builders/py_builder.py b/src/lava/magma/compiler/builders/py_builder.py
index afb67ec23..785f591cd 100644
--- a/src/lava/magma/compiler/builders/py_builder.py
+++ b/src/lava/magma/compiler/builders/py_builder.py
@@ -5,6 +5,7 @@
import typing as ty
import numpy as np
+from scipy.sparse import csr_matrix
from lava.magma.compiler.builders.interfaces import AbstractProcessBuilder
from lava.magma.runtime.message_infrastructure import (
@@ -392,6 +393,12 @@ def build(self):
var[:] = v.value
elif issubclass(lt.cls, (int, float, str)):
var = v.value
+ elif issubclass(lt.cls, (csr_matrix)):
+ if isinstance(v.value, int):
+ var = csr_matrix(v.shape, dtype=lt.d_type)
+ var[:] = v.value
+ else:
+ var = v.value
else:
raise NotImplementedError(
"Cannot initiliaze variable "
diff --git a/src/lava/magma/compiler/channel_map.py b/src/lava/magma/compiler/channel_map.py
index 79039cd0a..2eadd52cc 100644
--- a/src/lava/magma/compiler/channel_map.py
+++ b/src/lava/magma/compiler/channel_map.py
@@ -85,8 +85,9 @@ def from_proc_groups(self,
the list of process groups given as input.
"""
port_pairs = self._get_port_pairs_from_proc_groups(proc_groups)
- default_payload = Payload(multiplicity=1)
- channel_map = ChannelMap.fromkeys(port_pairs, default_payload)
+ channel_map = ChannelMap()
+ for port_pair in port_pairs:
+ channel_map[port_pair] = Payload(multiplicity=1)
return channel_map
@classmethod
diff --git a/src/lava/magma/compiler/compiler.py b/src/lava/magma/compiler/compiler.py
index ae2e0f628..bc09e3bb0 100644
--- a/src/lava/magma/compiler/compiler.py
+++ b/src/lava/magma/compiler/compiler.py
@@ -132,7 +132,7 @@ def compile(
proc_builders, channel_map = self._compile_proc_groups(
proc_groups, channel_map
)
- py_builders, c_builders, nc_builders = split_proc_builders_by_type(
+ _, c_builders, nc_builders = split_proc_builders_by_type(
proc_builders
)
diff --git a/src/lava/magma/compiler/compiler_graphs.py b/src/lava/magma/compiler/compiler_graphs.py
index 7d36fc140..75a112e62 100644
--- a/src/lava/magma/compiler/compiler_graphs.py
+++ b/src/lava/magma/compiler/compiler_graphs.py
@@ -8,7 +8,6 @@
import itertools
import os
import pkgutil
-import re
import sys
import types
import typing as ty
diff --git a/src/lava/magma/compiler/mapper.py b/src/lava/magma/compiler/mapper.py
index 2f570877f..d0d957faf 100644
--- a/src/lava/magma/compiler/mapper.py
+++ b/src/lava/magma/compiler/mapper.py
@@ -76,7 +76,7 @@ def map_cores(self, executable: Executable,
executable: Compiled Executable
"""
- py_builders, c_builders, nc_builders = split_proc_builders_by_type(
+ _, c_builders, nc_builders = split_proc_builders_by_type(
executable.proc_builders)
# Iterate over all the ncbuilder and map them
for ncb in nc_builders.values():
@@ -124,7 +124,6 @@ def map_cores(self, executable: Executable,
# src or dst and its initializers
for port_pair in channel_map:
src = port_pair.src
- dst = port_pair.dst
# Checking if the initializers are same
if channel_map[port_pair].src_port_initializer == ports[
port]:
diff --git a/src/lava/magma/compiler/node.py b/src/lava/magma/compiler/node.py
index 20e0c7261..88a9d5647 100644
--- a/src/lava/magma/compiler/node.py
+++ b/src/lava/magma/compiler/node.py
@@ -4,7 +4,6 @@
from __future__ import annotations
-import typing
import typing as ty
from collections import UserList, OrderedDict
@@ -27,7 +26,7 @@ def __init__(
processes: ty.List[AbstractProcess],
):
self.id: int = -1
- self.node_type: typing.Type[AbstractNode] = node_type
+ self.node_type: ty.Type[AbstractNode] = node_type
self.processes = processes
def add_process(self, process: AbstractProcess):
@@ -57,7 +56,7 @@ def __str__(self):
result.append(str(self.node_map))
return "\n".join(result)
- def append(self, node: Node):
+ def append(self, node: Node): # pylint: disable=arguments-renamed
"""Appends a new node to the NodeConfig."""
node.id = self._node_ctr
self._node_ctr += 1
diff --git a/src/lava/magma/compiler/subcompilers/channel_builders_factory.py b/src/lava/magma/compiler/subcompilers/channel_builders_factory.py
index a2e04671c..a47c4777f 100644
--- a/src/lava/magma/compiler/subcompilers/channel_builders_factory.py
+++ b/src/lava/magma/compiler/subcompilers/channel_builders_factory.py
@@ -106,10 +106,10 @@ def from_channel_map(
src_pt_init.connected_port_type = LoihiConnectedPortType.C_PY
dst_pt_init.connected_port_type = LoihiConnectedPortType.C_PY
if ch_type is ChannelType.PyC:
- p_port, c_port = src_port, dst_port
+ p_port = src_port
pi = dst_pt_init
else:
- c_port, p_port = src_port, dst_port
+ p_port = dst_port
pi = src_pt_init
lt = getattr(p_port.process.model_class, p_port.name).cls
if lt in [PyInPort.VEC_DENSE, PyOutPort.VEC_DENSE]:
diff --git a/src/lava/magma/compiler/subcompilers/interfaces.py b/src/lava/magma/compiler/subcompilers/interfaces.py
index 067c6da02..63147ca30 100644
--- a/src/lava/magma/compiler/subcompilers/interfaces.py
+++ b/src/lava/magma/compiler/subcompilers/interfaces.py
@@ -20,14 +20,12 @@ class AbstractSubCompiler(ABC):
def compile(self, channel_map: ChannelMap) -> ChannelMap:
"""Partitions all Processes in the SubCompiler's ProcGroup onto the
available resources."""
- pass
@abstractmethod
def get_builders(
self, channel_map: ChannelMap
) -> ty.Tuple[ty.Dict[AbstractProcess, AbstractProcessBuilder], ChannelMap]:
"""After compilation, creates and returns builders for all Processes."""
- pass
class SubCompiler(AbstractSubCompiler):
diff --git a/src/lava/magma/compiler/utils.py b/src/lava/magma/compiler/utils.py
index 8070683f9..994b2aeb0 100644
--- a/src/lava/magma/compiler/utils.py
+++ b/src/lava/magma/compiler/utils.py
@@ -142,7 +142,6 @@ class LoihiIOPortInitializer(LoihiPortInitializer):
@dataclass
class LoihiInPortInitializer(LoihiIOPortInitializer):
"""Port Initializer for a InPort for C/NC Models"""
- pass
@dataclass
@@ -154,7 +153,6 @@ class LoihiCInPortInitializer(LoihiIOPortInitializer):
@dataclass
class LoihiOutPortInitializer(LoihiIOPortInitializer):
"""Port Initializer for a OutPort for C/NC Models"""
- pass
@dataclass
diff --git a/src/lava/magma/compiler/var_model.py b/src/lava/magma/compiler/var_model.py
index eff1af8f2..805ed5b14 100644
--- a/src/lava/magma/compiler/var_model.py
+++ b/src/lava/magma/compiler/var_model.py
@@ -68,6 +68,7 @@ def __post_init__(self, var: Var) -> None:
self.name: str = var.name
self.shape: ty.Tuple[int, ...] = var.shape
self.proc_id: int = var.process.id
+ self.dtype = type(var.init)
@dataclass
diff --git a/src/lava/magma/core/learning/constants.py b/src/lava/magma/core/learning/constants.py
index 0ec3bdbb2..ab34c9cb9 100644
--- a/src/lava/magma/core/learning/constants.py
+++ b/src/lava/magma/core/learning/constants.py
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
-from enum import IntEnum, auto
+from enum import IntEnum
import lava.magma.core.learning.string_symbols as str_symbols
# ---------------------------------------------------------------------------
@@ -89,7 +89,8 @@
class GradedSpikeCfg(IntEnum):
- USE_REGULAR_IMPULSE = auto()
- OVERWRITE = auto()
- ADD_WITH_SATURATION = auto()
- ADD_WITHOUT_SATURATION = auto()
+ # Do not change the values below as they determine hardware behavior
+ USE_REGULAR_IMPULSE = 0
+ OVERWRITE = 1
+ ADD_WITH_SATURATION = 2
+ ADD_WITHOUT_SATURATION = 3
diff --git a/src/lava/magma/core/learning/symbolic_equation.py b/src/lava/magma/core/learning/symbolic_equation.py
index d3d72a78c..1ccbc9fe0 100644
--- a/src/lava/magma/core/learning/symbolic_equation.py
+++ b/src/lava/magma/core/learning/symbolic_equation.py
@@ -3,14 +3,14 @@
# See: https://spdx.org/licenses/
import re
-from abc import abstractmethod
+from abc import ABC, abstractmethod
import typing as ty
import ast
import lava.magma.core.learning.string_symbols as str_symbols
-class Symbol(object):
+class Symbol(ABC):
"""Super class for all possible symbols."""
def __init__(self, expr: ty.Optional[str] = "") -> None:
@@ -50,8 +50,9 @@ def __str__(self):
pass
@staticmethod
- def find_expr(expr: str, reg_expr: str, symbol: "Symbol") \
- -> ty.Tuple[ty.Optional["Symbol"], str]:
+ def find_expr(expr: str,
+ reg_expr: str,
+ symbol: "Symbol") -> ty.Tuple[ty.Optional["Symbol"], str]:
"""Factory method for creating symbols.
Matches an expression to a regular expression and if there is a match,
@@ -132,7 +133,6 @@ def __str__(self) -> str:
class Operator(Symbol):
"""Abstract super class for operator Symbols."""
- pass
class Addition(Operator):
@@ -231,8 +231,6 @@ def __str__(self):
class FactorSym(Symbol):
"""Abstract super class for factor Symbols."""
- pass
-
class Dependency(FactorSym):
"""Abstract super class for dependency Symbols."""
diff --git a/src/lava/magma/core/learning/utils.py b/src/lava/magma/core/learning/utils.py
index 5b7d6998c..480860397 100644
--- a/src/lava/magma/core/learning/utils.py
+++ b/src/lava/magma/core/learning/utils.py
@@ -4,7 +4,6 @@
import numpy as np
import typing as ty
-import struct
def stochastic_round(values: np.ndarray,
diff --git a/src/lava/magma/core/model/interfaces.py b/src/lava/magma/core/model/interfaces.py
index f878a02b0..cf00a438a 100644
--- a/src/lava/magma/core/model/interfaces.py
+++ b/src/lava/magma/core/model/interfaces.py
@@ -27,7 +27,6 @@ def shape(self) -> ty.Tuple[int, ...]:
@abstractmethod
def csp_ports(self) -> ty.List[AbstractTransferPort]:
"""Returns all csp ports of the port."""
- pass
def start(self):
"""Start all csp ports."""
diff --git a/src/lava/magma/core/model/py/connection.py b/src/lava/magma/core/model/py/connection.py
index 5c59dea96..dfa33c440 100644
--- a/src/lava/magma/core/model/py/connection.py
+++ b/src/lava/magma/core/model/py/connection.py
@@ -3,8 +3,10 @@
# See: https://spdx.org/licenses/
from abc import abstractmethod
+from lava.utils.sparse import find
import numpy as np
import typing
+from scipy.sparse import csr_matrix
from lava.magma.core.learning.learning_rule import (
LoihiLearningRule,
@@ -305,7 +307,7 @@ def _create_learning_rule_applier(
pass
@abstractmethod
- def _init_randoms(self):
+ def _init_randoms(self) -> None:
pass
@property
@@ -827,11 +829,12 @@ def _compute_trace_histories(self) -> typing.Tuple[np.ndarray, np.ndarray]:
t_spike_y = self.ty
# most naive algorithm to decay traces
- x_traces_history = np.full((t_epoch + 1,) + x_traces.shape, np.nan,
+ x_traces_history = np.full((t_epoch + 1,) + x_traces.shape, 0,
dtype=int)
x_traces_history[0] = x_traces
- y_traces_history = np.full((t_epoch + 1,) + y_traces.shape, np.nan,
+ y_traces_history = np.full((t_epoch + 1,) + y_traces.shape, 0,
dtype=int)
+
y_traces_history[0] = y_traces
for t in range(1, t_epoch + 1):
@@ -942,10 +945,16 @@ def _apply_learning_rules(
for syn_var_name, lr_applier in self._learning_rule_appliers.items():
syn_var = getattr(self, syn_var_name).copy()
- syn_var = np.left_shift(
- syn_var, W_ACCUMULATOR_S - W_SYN_VAR_S[syn_var_name]
- )
- syn_var = lr_applier.apply(syn_var, **applier_args)
+ shift = W_ACCUMULATOR_S - W_SYN_VAR_S[syn_var_name]
+ if isinstance(syn_var, csr_matrix):
+ syn_var.data = syn_var.data << shift
+ dst, src, _ = find(syn_var, explicit_zeros=True)
+ syn_var[dst, src] = lr_applier.apply(syn_var,
+ **applier_args)[dst, src]
+ else:
+ syn_var = syn_var << shift
+ syn_var = lr_applier.apply(syn_var, **applier_args)
+
syn_var = self._saturate_synaptic_variable_accumulator(
syn_var_name, syn_var
)
@@ -954,9 +963,11 @@ def _apply_learning_rules(
syn_var,
self._conn_var_random.random_stochastic_round,
)
- syn_var = np.right_shift(
- syn_var, W_ACCUMULATOR_S - W_SYN_VAR_S[syn_var_name]
- )
+
+ if isinstance(syn_var, csr_matrix):
+ syn_var.data = syn_var.data >> shift
+ else:
+ syn_var = syn_var >> shift
syn_var = self._saturate_synaptic_variable(syn_var_name, syn_var)
setattr(self, syn_var_name, syn_var)
@@ -1015,83 +1026,93 @@ def _extract_applier_args(
return applier_args
def _saturate_synaptic_variable_accumulator(
- self, synaptic_variable_name: str,
- synaptic_variable_values: np.ndarray
- ) -> np.ndarray:
+ self, syn_var_name: str,
+ syn_var_values: typing.Union[np.ndarray, csr_matrix]
+ ) -> typing.Union[np.ndarray, csr_matrix]:
"""Saturate synaptic variable accumulator.
Checks that sign is valid.
Parameters
----------
- synaptic_variable_name: str
+ syn_var_name: str
Synaptic variable name.
- synaptic_variable_values: ndarray
+ syn_var_values: ndarray, csr_matrix
Synaptic variable values to saturate.
Returns
----------
- result : ndarray
+ result : ndarray, csr_matrix
Saturated synaptic variable values.
"""
# Weights
- if synaptic_variable_name == "weights":
+ if syn_var_name == "weights":
if self.sign_mode == SignMode.MIXED:
- return synaptic_variable_values
+ return syn_var_values
elif self.sign_mode == SignMode.EXCITATORY:
- return np.maximum(0, synaptic_variable_values)
+ return np.maximum(0, syn_var_values)
elif self.sign_mode == SignMode.INHIBITORY:
- return np.minimum(0, synaptic_variable_values)
+ return np.minimum(0, syn_var_values)
# Delays
- elif synaptic_variable_name == "tag_2":
- return np.maximum(0, synaptic_variable_values)
+ elif syn_var_name == "tag_2":
+ if isinstance(syn_var_values, csr_matrix):
+ syn_var_values.data[syn_var_values.data < 0] = 0
+ return syn_var_values
+ return np.maximum(0, syn_var_values)
# Tags
- elif synaptic_variable_name == "tag_1":
- return synaptic_variable_values
+ elif syn_var_name == "tag_1":
+ return syn_var_values
else:
raise ValueError(
- f"synaptic_variable_name can be 'weights', "
+ f"syn_var_name can be 'weights', "
f"'tag_1', or 'tag_2'."
- f"Got {synaptic_variable_name=}."
+ f"Got {syn_var_name=}."
)
@staticmethod
def _stochastic_round_synaptic_variable(
- synaptic_variable_name: str,
- synaptic_variable_values: np.ndarray,
+ syn_var_name: str,
+ syn_var_values: typing.Union[np.ndarray, csr_matrix],
random: float,
- ) -> np.ndarray:
+ ) -> typing.Union[np.ndarray, csr_matrix]:
"""Stochastically round synaptic variable after learning rule
application.
Parameters
----------
- synaptic_variable_name: str
+ syn_var_name: str
Synaptic variable name.
- synaptic_variable_values: ndarray
+ syn_var_values: ndarray, csr_matrix
Synaptic variable values to stochastically round.
Returns
----------
- result : ndarray
+ result : ndarray, csr_matrix
Stochastically rounded synaptic variable values.
"""
- exp_mant = 2 ** (W_ACCUMULATOR_U - W_SYN_VAR_U[synaptic_variable_name])
+ exp_mant = 2 ** (W_ACCUMULATOR_U - W_SYN_VAR_U[syn_var_name])
- integer_part = synaptic_variable_values / exp_mant
+ if isinstance(syn_var_values, csr_matrix):
+ integer_part = syn_var_values.data / exp_mant
+ else:
+ integer_part = syn_var_values / exp_mant
fractional_part = integer_part % 1
integer_part = np.floor(integer_part)
integer_part = stochastic_round(integer_part, random, fractional_part)
- result = (integer_part * exp_mant).astype(
- synaptic_variable_values.dtype
- )
- return result
+ if isinstance(syn_var_values, csr_matrix):
+ syn_var_values.data = (integer_part
+ * exp_mant).astype(syn_var_values.dtype)
+ return syn_var_values
+ else:
+ return (integer_part * exp_mant).astype(
+ syn_var_values.dtype
+ )
def _saturate_synaptic_variable(
- self, synaptic_variable_name: str,
- synaptic_variable_values: np.ndarray
+ self, syn_var_name: str,
+ syn_var_val: typing.Union[np.ndarray, csr_matrix]
) -> np.ndarray:
"""Saturate synaptic variable.
@@ -1100,40 +1121,54 @@ def _saturate_synaptic_variable(
Parameters
----------
- synaptic_variable_name: str
+ syn_var_name: str
Synaptic variable name.
- synaptic_variable_values: ndarray
+ syn_var_val: ndarray, csr_matrix
Synaptic variable values to saturate.
Returns
----------
- result : ndarray
+ result : ndarray, csr_matrix
Saturated synaptic variable values.
"""
+
# Weights
- if synaptic_variable_name == "weights":
+ if syn_var_name == "weights":
return clip_weights(
- synaptic_variable_values,
+ syn_var_val,
sign_mode=self.sign_mode,
num_bits=W_WEIGHTS_U,
)
# Delays
- elif synaptic_variable_name == "tag_2":
+ elif syn_var_name == "tag_2":
+ if isinstance(syn_var_val, csr_matrix):
+ _min = -(2 ** W_TAG_2_U) - 1
+ _max = (2 ** W_TAG_2_U) - 1
+ syn_var_val.data[syn_var_val.data < _min] = _min
+ syn_var_val.data[syn_var_val.data > _max] = _max
+ return syn_var_val
+
return np.clip(
- synaptic_variable_values, a_min=0, a_max=2 ** W_TAG_2_U - 1
+ syn_var_val, a_min=0, a_max=2 ** W_TAG_2_U - 1
)
# Tags
- elif synaptic_variable_name == "tag_1":
+ elif syn_var_name == "tag_1":
+ if isinstance(syn_var_val, csr_matrix):
+ _min = -(2 ** W_TAG_1_U) - 1
+ _max = (2 ** W_TAG_1_U) - 1
+ syn_var_val.data[syn_var_val.data < _min] = _min
+ syn_var_val.data[syn_var_val.data > _max] = _max
+ return syn_var_val
return np.clip(
- synaptic_variable_values,
+ syn_var_val,
a_min=-(2 ** W_TAG_1_U) - 1,
a_max=2 ** W_TAG_1_U - 1,
)
else:
raise ValueError(
- f"synaptic_variable_name can be 'weights', "
+ f"syn_var_name can be 'weights', "
f"'tag_1', or 'tag_2'."
- f"Got {synaptic_variable_name=}."
+ f"Got {syn_var_name=}."
)
@@ -1423,7 +1458,12 @@ def _apply_learning_rules(
for syn_var_name, lr_applier in self._learning_rule_appliers.items():
syn_var = getattr(self, syn_var_name).copy()
- syn_var = lr_applier.apply(syn_var, **applier_args)
+ if (isinstance(syn_var, csr_matrix)):
+ dst, src, _ = find(syn_var, explicit_zeros=True)
+ syn_var[dst, src] = lr_applier.apply(syn_var,
+ **applier_args)[dst, src]
+ else:
+ syn_var = lr_applier.apply(syn_var, **applier_args)
syn_var = self._saturate_synaptic_variable(syn_var_name, syn_var)
setattr(self, syn_var_name, syn_var)
@@ -1511,6 +1551,9 @@ def _saturate_synaptic_variable(
elif synaptic_variable_name == "tag_1":
return synaptic_variable_values
elif synaptic_variable_name == "tag_2":
+ if isinstance(synaptic_variable_values, csr_matrix):
+ synaptic_variable_values[synaptic_variable_values < 0] = 0
+ return synaptic_variable_values
return np.maximum(0, synaptic_variable_values)
else:
raise ValueError(
@@ -1518,3 +1561,6 @@ def _saturate_synaptic_variable(
f"'tag_1', or 'tag_2'."
f"Got {synaptic_variable_name=}."
)
+
+ def _init_randoms(self) -> None:
+ pass
diff --git a/src/lava/magma/core/model/py/model.py b/src/lava/magma/core/model/py/model.py
index fb2623d29..443e317bb 100644
--- a/src/lava/magma/core/model/py/model.py
+++ b/src/lava/magma/core/model/py/model.py
@@ -6,7 +6,9 @@
from abc import ABC, abstractmethod
# from functools import partial
import logging
+from lava.utils.sparse import find
import numpy as np
+from scipy.sparse import csr_matrix
import platform
from lava.magma.runtime.message_infrastructure import (SendPort,
@@ -77,10 +79,9 @@ def __setattr__(self, key: str, value: ty.Any):
"""
self.__dict__[key] = value
- if isinstance(value, AbstractPyPort):
+ if isinstance(value, AbstractPyPort) and value not in self.py_ports:
self.py_ports.append(value)
- # Store all VarPorts for efficient RefPort -> VarPort handling
- if isinstance(value, PyVarPort):
+ if isinstance(value, PyVarPort) and value not in self.var_ports:
self.var_ports.append(value)
def start(self):
@@ -120,11 +121,14 @@ def _get_var(self):
addr_path = self.service_to_process.recv()
data_port = getTempSendPort(str(addr_path[0]))
data_port.start()
- if isinstance(var, int) or isinstance(var, np.integer):
+ if isinstance(var, int) or isinstance(var, np.int32):
data_port.send(enum_to_np(var))
elif isinstance(var, np.ndarray):
# FIXME: send a whole vector (also runtime_service.py)
data_port.send(var)
+ elif isinstance(var, csr_matrix):
+ _, _, data = find(var, explicit_zeros=True)
+ data_port.send(data)
elif isinstance(var, str):
data_port.send(np.array(var, dtype=str))
data_port.join()
@@ -132,7 +136,7 @@ def _get_var(self):
data_port = self.process_to_service
# Header corresponds to number of values
# Data is either send once (for int) or one by one (array)
- if isinstance(var, int) or isinstance(var, np.integer):
+ if isinstance(var, int) or isinstance(var, np.int32):
data_port.send(enum_to_np(1))
data_port.send(enum_to_np(var))
elif isinstance(var, np.ndarray):
@@ -142,6 +146,12 @@ def _get_var(self):
data_port.send(enum_to_np(num_items))
for value in var_iter:
data_port.send(enum_to_np(value, np.float64))
+ elif isinstance(var, csr_matrix):
+ _, _, values = find(var, explicit_zeros=True)
+ num_items = var.data.size
+ data_port.send(enum_to_np(num_items))
+ for value in values:
+ data_port.send(enum_to_np(value, np.float64))
elif isinstance(var, str):
encoded_str = list(var.encode("ascii"))
data_port.send(enum_to_np(len(encoded_str)))
@@ -162,7 +172,7 @@ def _set_var(self):
self.process_to_service.send(np.array([addr_path]))
buffer = data_port.recv()
data_port.join()
- if isinstance(var, int) or isinstance(var, np.integer):
+ if isinstance(var, int) or isinstance(var, np.int32):
buffer = buffer[0]
if isinstance(var, int):
setattr(self, var_name, buffer.item())
@@ -173,6 +183,11 @@ def _set_var(self):
var_iter = np.nditer(var, op_flags=['readwrite'])
setattr(self, var_name, buffer.astype(var.dtype))
self.process_to_service.send(MGMT_RESPONSE.SET_COMPLETE)
+ elif isinstance(var, csr_matrix):
+ dst, src, _ = find(var)
+ var = csr_matrix((buffer, (dst, src)), var.shape)
+ setattr(self, var_name, var)
+ self.process_to_service.send(MGMT_RESPONSE.SET_COMPLETE)
elif isinstance(var, str):
setattr(self, var_name, np.array_str(buffer))
self.process_to_service.send(MGMT_RESPONSE.SET_COMPLETE)
@@ -181,7 +196,7 @@ def _set_var(self):
raise RuntimeError("Unsupported type")
else:
data_port = self.service_to_process
- if isinstance(var, int) or isinstance(var, np.integer):
+ if isinstance(var, int) or isinstance(var, np.int32):
# First item is number of items (1) - not needed
data_port.recv()
# Data to set
@@ -202,6 +217,18 @@ def _set_var(self):
num_items -= 1
i[...] = data_port.recv()[0]
self.process_to_service.send(MGMT_RESPONSE.SET_COMPLETE)
+ elif isinstance(var, csr_matrix):
+ # First item is number of items
+ num_items = int(data_port.recv()[0])
+
+ buffer = np.empty(num_items)
+ # Set data one by one
+ for i in range(num_items):
+ buffer[i] = data_port.recv()[0]
+ dst, src, _ = find(var)
+ var = csr_matrix((buffer, (dst, src)), var.shape)
+ setattr(self, var_name, var)
+ self.process_to_service.send(MGMT_RESPONSE.SET_COMPLETE)
elif isinstance(var, str):
# First item is number of items
num_items = int(data_port.recv()[0])
@@ -221,9 +248,6 @@ def _set_var(self):
# notify PM that Vars have been changed
self.on_var_update()
- # notify PM that Vars have been changed
- self.on_var_update()
-
def _handle_var_port(self, var_port):
"""Handles read/write requests on the given VarPort."""
var_port.service()
@@ -241,7 +265,7 @@ def run(self):
if cmd in self._cmd_handlers:
self._cmd_handlers[cmd]()
if cmd == MGMT_COMMAND.STOP[0] or self._stopped:
- break
+ return
else:
raise ValueError(
f"Illegal RuntimeService command! ProcessModels of "
@@ -264,7 +288,6 @@ def add_ports_for_polling(self):
"""
Add various ports to poll for communication on ports
"""
- pass
def join(self):
"""
@@ -279,7 +302,6 @@ def on_var_update(self):
"""This method is called if a Var is updated. It
can be used as callback function to calculate dependent
changes."""
- pass
class PyLoihiProcessModel(AbstractPyProcessModel):
diff --git a/src/lava/magma/core/model/py/ports.py b/src/lava/magma/core/model/py/ports.py
index 8d83d8429..933eeaef2 100644
--- a/src/lava/magma/core/model/py/ports.py
+++ b/src/lava/magma/core/model/py/ports.py
@@ -55,7 +55,6 @@ def csp_ports(self) -> ty.List[AbstractTransferPort]:
-------
A list of all CSP Ports connected to the PyPort.
"""
- pass
class AbstractPyIOPort(AbstractPyPort):
@@ -703,13 +702,19 @@ def read(self) -> np.ndarray:
The value of the referenced Var.
"""
if self._csp_send_port and self._csp_recv_port:
- header = np.ones(self._shape, dtype=self._d_type) * \
- VarPortCmd.GET.astype(self._d_type)
- self._csp_send_port.send(header)
+ if not hasattr(self, 'get_header'):
+ # pylint: disable=W0201
+ self.get_header = (np.ones(self._csp_send_port.shape,
+ dtype=self._d_type)
+ * VarPortCmd.GET.astype(self._d_type))
+ self._csp_send_port.send(self.get_header)
return self._transformer.transform(self._csp_recv_port.recv(),
self._csp_recv_port)
-
- return np.zeros(self._shape, self._d_type)
+ else:
+ if not hasattr(self, 'get_zeros'):
+ # pylint: disable=W0201
+ self.get_zeros = np.zeros(self._shape, self._d_type)
+ return self.get_zeros
def write(self, data: np.ndarray):
"""Abstract method to write data to a VarPort to set the value of the
@@ -721,9 +726,12 @@ def write(self, data: np.ndarray):
The data to send via _csp_send_port.
"""
if self._csp_send_port:
- header = np.ones(self._shape, dtype=data.dtype) * \
- VarPortCmd.SET.astype(self._d_type)
- self._csp_send_port.send(header)
+ if not hasattr(self, 'set_header'):
+ # pylint: disable=W0201
+ self.set_header = (np.ones(self._csp_send_port.shape,
+ dtype=data.dtype)
+ * VarPortCmd.SET.astype(self._d_type))
+ self._csp_send_port.send(self.set_header)
self._csp_send_port.send(data)
diff --git a/src/lava/magma/core/process/ports/ports.py b/src/lava/magma/core/process/ports/ports.py
index 083394d9f..d0094adf3 100644
--- a/src/lava/magma/core/process/ports/ports.py
+++ b/src/lava/magma/core/process/ports/ports.py
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
+from __future__ import annotations
import typing as ty
from abc import ABC, abstractmethod
import math
@@ -383,8 +384,6 @@ class AbstractIOPort(AbstractPort):
type hierarchy needed for validating connections.
"""
- pass
-
class AbstractRVPort(AbstractPort):
"""Abstract base class for RefPorts and VarPorts.
@@ -392,8 +391,6 @@ class AbstractRVPort(AbstractPort):
type hierarchy needed for validating connections.
"""
- pass
-
class AbstractSrcPort(ABC):
"""Interface for source ports such as OutPorts and RefPorts from which
@@ -402,8 +399,6 @@ class AbstractSrcPort(ABC):
type hierarchy needed for validating connections.
"""
- pass
-
class AbstractDstPort(ABC):
"""Interface for destination ports such as InPorts and VarPorts in which
@@ -412,8 +407,6 @@ class AbstractDstPort(ABC):
type hierarchy needed for validating connections.
"""
- pass
-
class OutPort(AbstractIOPort, AbstractSrcPort):
"""Output ports are members of a Lava Process and can be connected to
@@ -635,7 +628,7 @@ def get_dst_vars(self) -> ty.List[Var]:
return [ty.cast(VarPort, p).var for p in self.get_dst_ports()]
@staticmethod
- def create_implicit_var_port(var: Var) -> "ImplicitVarPort":
+ def create_implicit_var_port(var: Var) -> ImplicitVarPort:
"""Creates and returns an ImplicitVarPort for the given Var."""
# Create a VarPort to wrap Var
vp = ImplicitVarPort(var)
@@ -646,9 +639,12 @@ def create_implicit_var_port(var: Var) -> "ImplicitVarPort":
vp.process = var.process
# VarPort name could shadow existing attribute
if hasattr(var.process, vp.name):
- raise AssertionError(
- "Name of implicit VarPort might conflict"
- " with existing attribute.")
+ name = str(vp.name)
+ name_suffix = 1
+ while hasattr(var.process, vp.name):
+ # pylint: disable=W0201
+ vp.name = name + "_" + str(name_suffix)
+ name_suffix += 1
setattr(var.process, vp.name, vp)
var.process.var_ports.add_members({vp.name: vp})
@@ -749,7 +745,9 @@ def connect_from(
class ImplicitVarPort(VarPort):
"""Sub class for VarPort to identify implicitly created VarPorts when
a RefPort connects directly to a Var."""
- pass
+
+ def __init__(self, var: Var) -> None:
+ super().__init__(var)
class AbstractVirtualPort(AbstractPort):
@@ -826,7 +824,7 @@ class ReshapePort(AbstractVirtualPort):
def __init__(self,
new_shape: ty.Tuple[int, ...],
old_shape: ty.Tuple[int, ...]):
- AbstractPort.__init__(self, new_shape)
+ super().__init__(new_shape)
self.old_shape = old_shape
def get_transform_func_fwd(self) -> ft.partial:
@@ -861,7 +859,7 @@ class ConcatPort(AbstractVirtualPort):
tensor-valued data array from the derived to the new shape."""
def __init__(self, ports: ty.List[AbstractPort], axis: int):
- AbstractPort.__init__(self, self._get_new_shape(ports, axis))
+ super().__init__(self._get_new_shape(ports, axis))
self._connect_backward(
ports, AbstractPort, assert_same_shape=False, assert_same_type=True
)
@@ -916,7 +914,7 @@ def __init__(self,
new_shape: ty.Tuple[int, ...],
axes: ty.Tuple[int, ...]):
self.axes = axes
- AbstractPort.__init__(self, new_shape)
+ super().__init__(new_shape)
def get_transform_func_fwd(self) -> ft.partial:
"""Returns a function pointer that implements the forward (fwd)
@@ -941,18 +939,3 @@ def get_transform_func_bwd(self) -> ft.partial:
function_pointer : functools.partial
a function pointer that can be applied to incoming data"""
return ft.partial(np.transpose, axes=np.argsort(self.axes))
-
-
-class ReIndexPort(AbstractVirtualPort):
- """A ReIndexPort is a virtual port that allows to re-index the elements
- of a port before connecting to another port.
- It is used by the compiler to map the indices of the underlying
- tensor-valued data array from the derived to the new shape.
-
- Example:
- out_port = OutPort((2, 2))
- in_port = InPort((2, 2))
- out_port.reindex([3, 1, 0, 2]).connect(in_port)
- """
-
- pass
diff --git a/src/lava/magma/core/process/ports/reduce_ops.py b/src/lava/magma/core/process/ports/reduce_ops.py
index 4d9e99ad7..709d77367 100644
--- a/src/lava/magma/core/process/ports/reduce_ops.py
+++ b/src/lava/magma/core/process/ports/reduce_ops.py
@@ -9,11 +9,7 @@ class AbstractReduceOp(ABC):
"""Reduce operations are required by InPorts to specify how date from
multiple OutPorts connected to the same InPorts gets integrated."""
- pass
-
class ReduceSum(AbstractReduceOp):
"""ReduceOp to indicate that multiple inputs to same InPort should be
added."""
-
- pass
diff --git a/src/lava/magma/core/process/process.py b/src/lava/magma/core/process/process.py
index 808df52b7..51047b5cc 100644
--- a/src/lava/magma/core/process/process.py
+++ b/src/lava/magma/core/process/process.py
@@ -19,7 +19,6 @@
from lava.magma.core.run_conditions import AbstractRunCondition
from lava.magma.core.run_configs import RunConfig
from lava.magma.runtime.runtime import Runtime
-from lava.magma.runtime.runtime_services.enums import LoihiVersion
if ty.TYPE_CHECKING:
from lava.magma.core.model.model import AbstractProcessModel
@@ -224,7 +223,6 @@ def __del__(self):
def __enter__(self):
"""Executed when Process enters a "with" block of a context manager."""
- pass
def __exit__(self, exc_type, exc_val, exc_tb):
"""Stop the runtime when exiting "with" block of a context manager."""
@@ -284,7 +282,7 @@ def runtime(self, value):
def register_sub_procs(self, procs: ty.Dict[str, AbstractProcess]):
"""Registers other processes as sub processes of this process."""
- for name, p in procs.items():
+ for p in procs.values():
if not isinstance(p, AbstractProcess):
raise AssertionError
p.parent_proc = self
@@ -331,6 +329,9 @@ def run(self,
being no longer satisfied, run() can be called again to resume
execution from the current state.
+ NOTE: run_cfg will be ignored when re-running a previously compiled
+ process.
+
Parameters
----------
condition : AbstractRunCondition
@@ -344,18 +345,37 @@ def run(self,
"""
if not self._runtime:
if not run_cfg:
- raise ValueError("The Processes that are to be executed have "
- "not been compiled yet. This requires that a"
- "RunConfig is passed to the run() method.")
+ raise ValueError("run_cfg must not be None when calling"
+ " Process.run() unless the process has already"
+ " been compiled.")
+ self.create_runtime(run_cfg, compile_config)
+ self._runtime.start(condition)
- executable = self.compile(run_cfg, compile_config)
- self._runtime = Runtime(executable,
- ActorType.MultiProcessing,
- loglevel=self._log_config.level)
- executable.assign_runtime_to_all_processes(self._runtime)
- self._runtime.initialize()
+ def create_runtime(self, run_cfg: RunConfig,
+ compile_config:
+ ty.Optional[ty.Dict[str, ty.Any]] = None):
+ """Creates a runtime for this process and all connected processes by
+ compiling the process to an executable and assigning that executable to
+ the process and connected processes.
- self._runtime.start(condition)
+ See Process.run() for information on Process blocking, which must be
+ specified in the run_cfg passed to create_runtime.
+
+ Parameters
+ ----------
+ run_cfg : RunConfig, optional
+ Used by the compiler to select a ProcessModel for each Process.
+ Must be provided when Processes have to be compiled, can be
+ omitted otherwise.
+ compile_config: Dict[str, Any], optional
+ Configuration options for the Compiler and SubCompilers.
+ """
+ executable = self.compile(run_cfg, compile_config)
+ self._runtime = Runtime(executable,
+ ActorType.MultiProcessing,
+ loglevel=self._log_config.level)
+ executable.assign_runtime_to_all_processes(self._runtime)
+ self._runtime.initialize()
def compile(self,
run_cfg: RunConfig,
diff --git a/src/lava/magma/core/process/variable.py b/src/lava/magma/core/process/variable.py
index e8457d1b1..aed95a66d 100644
--- a/src/lava/magma/core/process/variable.py
+++ b/src/lava/magma/core/process/variable.py
@@ -4,7 +4,8 @@
import typing as ty
import numpy as np
-
+from scipy.sparse import csr_matrix, spmatrix
+from lava.utils.sparse import find
from lava.magma.core.process.interfaces import (
AbstractProcessMember,
IdGeneratorSingleton,
@@ -127,7 +128,9 @@ def validate_alias(self):
f"."
)
- def set(self, value: ty.Union[np.ndarray, str], idx: np.ndarray = None):
+ def set(self,
+ value: ty.Union[np.ndarray, str, spmatrix],
+ idx: np.ndarray = None):
"""Sets value of Var. If this Var aliases another Var, then set(..) is
delegated to aliased Var."""
if self.aliased_var is not None:
@@ -142,6 +145,19 @@ def set(self, value: ty.Union[np.ndarray, str], idx: np.ndarray = None):
value = np.array(
list(value.encode("ascii")), dtype=np.int32
)
+ elif isinstance(value, spmatrix):
+ value = value.tocsr()
+ init_dst, init_src, init_val = find(self.init,
+ explicit_zeros=True)
+ dst, src, val = find(value, explicit_zeros=True)
+ if value.shape != self.init.shape or \
+ np.any(init_dst != dst) or \
+ np.any(init_src != src) or \
+ len(val) != len(init_val):
+ raise ValueError("Indices and number of non-zero "
+ "elements must stay equal when using"
+ "set on a sparse matrix.")
+ value = val
self.process.runtime.set_var(self.id, value, idx)
else:
raise ValueError(
@@ -155,7 +171,7 @@ def get(self, idx: np.ndarray = None) -> np.ndarray:
if self.aliased_var is not None:
return self.aliased_var.get(idx)
else:
- if self.process.runtime:
+ if self.process and self.process.runtime:
buffer = self.process.runtime.get_var(self.id, idx)
if isinstance(self.init, str):
if SupportTempChannel:
@@ -164,6 +180,10 @@ def get(self, idx: np.ndarray = None) -> np.ndarray:
# decode if var is string
return bytes(buffer.astype(int).tolist()). \
decode("ascii")
+ if isinstance(self.init, csr_matrix):
+ dst, src, _ = find(self.init)
+ ret = csr_matrix((buffer, (dst, src)), self.init.shape)
+ return ret
else:
return buffer
else:
diff --git a/src/lava/magma/core/resources.py b/src/lava/magma/core/resources.py
index 28bc102e7..3419ae1b8 100644
--- a/src/lava/magma/core/resources.py
+++ b/src/lava/magma/core/resources.py
@@ -13,89 +13,73 @@ class AbstractResource(ABC):
Each ProcessModel lists its required hardware resources with the
@requires decorator.
"""
- pass
# Compute resources ------------------------------------------------------------
class AbstractComputeResource(AbstractResource):
"""A compute resource, for example a particular type of neuromorphic
processor or CPU."""
- pass
class CPU(AbstractComputeResource):
"""A central processing unit on a regular computer or laptop."""
- pass
class HostCPU(AbstractComputeResource):
"""A central processing unit on a special host system that holds
neuromorphic devices."""
- pass
class GPU(AbstractComputeResource):
"""A graphical processing unit."""
- pass
class ECPU(AbstractComputeResource):
"""An embedded central processing unit that is part of a neuromorphic
chip."""
- pass
class LMT(ECPU):
"""A Lakemont embedded central processing unit."""
- pass
class PB(ECPU):
"""A Powell Bute embedded central processing unit."""
- pass
class NeuroCore(AbstractComputeResource):
"""A neuromorphic core."""
- pass
class Loihi1NeuroCore(NeuroCore):
"""A neuromorphic core on a Loihi 1 chip."""
- pass
class Loihi2NeuroCore(NeuroCore):
"""A neuromorphic core on a Loihi 2 chip."""
- pass
# Peripheral resources ---------------------------------------------------------
class AbstractPeripheralResource(AbstractResource):
"""A hardware resource that is a peripheral device."""
- pass
class DVS(AbstractPeripheralResource):
"""An event-based dynamic vision sensor (DVS)."""
- pass
class HardDrive(AbstractPeripheralResource):
"""A hard drive in a computer."""
- pass
class HeadNodeHardDrive(AbstractPeripheralResource):
"""A hard drive attached to a HeadNode (the node on which a user executes
code)."""
- pass
# Nodes ------------------------------------------------------------------------
class AbstractNode(ABC):
"""A node is a resource that has other compute or peripheral resources."""
- pass
class GenericNode(AbstractNode):
@@ -112,7 +96,6 @@ class HeadNode(GenericNode):
class Loihi1System(AbstractNode):
"""A neuromorphic system that carries Loihi 1 chips."""
- pass
class KapohoBay(Loihi1System):
@@ -133,7 +116,6 @@ class Pohoiki(Loihi1System):
class Loihi2System(AbstractNode):
"""A neuromorphic system that carries Loihi 2 chips."""
- pass
class OheoGulch(Loihi2System):
diff --git a/src/lava/magma/core/run_configs.py b/src/lava/magma/core/run_configs.py
index f7144ce4d..1bf6ffda0 100644
--- a/src/lava/magma/core/run_configs.py
+++ b/src/lava/magma/core/run_configs.py
@@ -79,11 +79,9 @@ def __init__(self,
def exclude_nodes(self, nodes: ty.List[AbstractNode]):
"""Excludes given nodes from consideration by compiler."""
- pass
def require_nodes(self, nodes: ty.List[AbstractNode]):
"""Requires that compiler maps processes to given nodes."""
- pass
def select(self,
process: AbstractProcess,
@@ -168,7 +166,7 @@ def __init__(self,
self.exception_proc_model_map = {}
def select(self,
- proc: AbstractProcess,
+ process: AbstractProcess,
proc_models: ty.List[ty.Type[AbstractProcessModel]]) \
-> ty.Type[AbstractProcessModel]:
"""
@@ -177,7 +175,7 @@ def select(self,
Parameters
----------
- proc: AbstractProcess
+ process: AbstractProcess
Process for which ProcessModel is selected
proc_models: List[AbstractProcessModel]
List of ProcessModels to select from
@@ -191,9 +189,10 @@ def select(self,
# ------------------------------
# Raise error
if num_pm == 0:
- raise AssertionError(f"[{self.__class__.__qualname__}]: No "
- f"ProcessModels exist for Process "
- f"{proc.name}::{proc.__class__.__qualname__}.")
+ raise AssertionError(
+ f"[{self.__class__.__qualname__}]: No ProcessModels exist for "
+ f"Process {process.name}::{process.__class__.__qualname__}."
+ )
# Required modules and helper functions
from lava.magma.core.model.sub.model import AbstractSubProcessModel
@@ -206,8 +205,8 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
# ----------------------------
# We will simply return the ProcessModel class associated with a
# Process class in the exceptions dictionary
- if proc.__class__ in self.exception_proc_model_map:
- return self.exception_proc_model_map[proc.__class__]
+ if process.__class__ in self.exception_proc_model_map:
+ return self.exception_proc_model_map[process.__class__]
# Case 2: Only 1 PM found:
# -----------------------
@@ -247,8 +246,8 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
f"[{self.__class__.__qualname__}]: No "
f"ProcessModels found with tag "
f"'{self.select_tag}' for Process "
- f"{proc.name}::"
- f"{proc.__class__.__qualname__}.")
+ f"{process.name}::"
+ f"{process.__class__.__qualname__}.")
# Case 3: Multiple PMs exist:
# --------------------------
@@ -269,11 +268,13 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
# Assumption: User doesn't care about tags. We return the first
# SubProcessModel found
if self.select_tag is None:
- self.log.info(f"[{self.__class__.__qualname__}]: Using the"
- f" first SubProcessModel "
- f"{proc_models[sub_pm_idxs[0]].__qualname__} "
- f"available for Process "
- f"{proc.name}::{proc.__class__.__qualname__}.")
+ self.log.info(
+ f"[{self.__class__.__qualname__}]: Using the first "
+ f"SubProcessModel "
+ f"{proc_models[sub_pm_idxs[0]].__qualname__} "
+ f"available for Process "
+ f"{process.name}::{process.__class__.__qualname__}."
+ )
return proc_models[sub_pm_idxs[0]]
# Case 3a(iii): User asked for a specific tag:
# -------------------------------------------
@@ -286,8 +287,8 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
raise AssertionError(f"[{self.__class__.__qualname__}]: No "
f"ProcessModels found with tag "
f"{self.select_tag} for Process "
- f"{proc.name}::"
- f"{proc.__class__.__qualname__}.")
+ f"{process.name}::"
+ f"{process.__class__.__qualname__}.")
return proc_models[valid_sub_pm_idxs[0]]
# Case 3b: User didn't ask for SubProcessModel:
# --------------------------------------------
@@ -295,8 +296,8 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
if len(leaf_pm_idxs) == 0:
raise AssertionError(f"[{self.__class__.__qualname__}]: "
f"No hardware-specific ProcessModels were "
- f"found for Process {proc.name}::"
- f"{proc.__class__.__qualname__}. "
+ f"found for Process {process.name}::"
+ f"{process.__class__.__qualname__}. "
f"Try setting select_sub_proc_model=True.")
# Case 3b(i): User didn't provide select_tag:
# ------------------------------------------
@@ -307,7 +308,7 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
f"Hardware-specific ProcessModel "
f"{proc_models[leaf_pm_idxs[0]].__qualname__} "
f"available for Process "
- f"{proc.name}::{proc.__class__.__qualname__}.")
+ f"{process.name}::{process.__class__.__qualname__}.")
return proc_models[leaf_pm_idxs[0]]
# Case 3b(ii): User asked for a specific tag:
# ------------------------------------------
@@ -320,8 +321,8 @@ def _issubpm(pm: ty.Type[AbstractProcessModel]) -> bool:
raise AssertionError(f"[{self.__class__.__qualname__}]: No "
f"ProcessModels found with tag "
f"'{self.select_tag}' for Process "
- f"{proc.name}::"
- f"{proc.__class__.__qualname__}.")
+ f"{process.name}::"
+ f"{process.__class__.__qualname__}.")
return proc_models[valid_leaf_pm_idxs[0]]
def _is_hw_supported(self, pm: ty.Type[AbstractProcessModel]) -> bool:
diff --git a/src/lava/magma/runtime/message_infrastructure/factory.py b/src/lava/magma/runtime/message_infrastructure/factory.py
index 750b029db..362a37e12 100644
--- a/src/lava/magma/runtime/message_infrastructure/factory.py
+++ b/src/lava/magma/runtime/message_infrastructure/factory.py
@@ -6,14 +6,13 @@
from lava.magma.runtime.message_infrastructure import PURE_PYTHON_VERSION
-"""Factory class to create the messaging infrastructure"""
-
-
class MessageInfrastructureFactory:
"""Creates the message infrastructure instance based on type"""
@staticmethod
def create(factory_type: ActorType):
+ """Creates the message infrastructure instance based on type
+ of actor framework being chosen."""
if PURE_PYTHON_VERSION:
factory_type = ActorType.PyMultiProcessing
"""type of actor framework being chosen"""
diff --git a/src/lava/magma/runtime/message_infrastructure/message_infrastructure_interface.py b/src/lava/magma/runtime/message_infrastructure/message_infrastructure_interface.py
index 7d83169f4..f68a52428 100644
--- a/src/lava/magma/runtime/message_infrastructure/message_infrastructure_interface.py
+++ b/src/lava/magma/runtime/message_infrastructure/message_infrastructure_interface.py
@@ -7,15 +7,12 @@
from lava.magma.runtime.message_infrastructure import Channel
from lava.magma.runtime.message_infrastructure.interfaces import ChannelType
-"""A Message Infrastructure Interface which can create actors which would
-participate in message passing/exchange, start and stop them as well as
-declare the underlying Channel Infrastructure Class to be used for message
-passing implementation."""
-
class MessageInfrastructureInterface(ABC):
- """Interface to provide the ability to create actors which can
- communicate via message passing"""
+ """A Message Infrastructure Interface which can create actors which would
+ participate in message passing/exchange, start and stop them as well as
+ declare the underlying Channel Infrastructure Class to be used for message
+ passing implementation."""
@abstractmethod
def init(self):
@@ -25,7 +22,6 @@ def init(self):
@abstractmethod
def start(self):
"""Starts the messaging infrastructure"""
- pass
def pre_stop(self):
"""Stop MessageInfrastructure before join ports"""
@@ -38,7 +34,6 @@ def stop(self):
@abstractmethod
def build_actor(self, target_fn: ty.Callable, builder):
"""Given a target_fn starts a system process"""
- pass
def cleanup(self, block=False):
"""Close all resources"""
@@ -52,11 +47,9 @@ def trace(self, logger) -> int:
@abstractmethod
def actors(self) -> ty.List[ty.Any]:
"""Returns a list of actors"""
- pass
@abstractmethod
def channel(self, channel_type: ChannelType, src_name, dst_name,
shape, dtype, size, sync=False) -> Channel:
"""Given the Channel Type, Return the Channel Implementation to
be used during execution"""
- pass
diff --git a/src/lava/magma/runtime/message_infrastructure/nx.py b/src/lava/magma/runtime/message_infrastructure/nx.py
index 0d52f5145..604358785 100644
--- a/src/lava/magma/runtime/message_infrastructure/nx.py
+++ b/src/lava/magma/runtime/message_infrastructure/nx.py
@@ -27,21 +27,17 @@ class NxBoardMsgInterface(MessageInfrastructureInterface):
@property
def actors(self):
"""Returns a list of actors"""
- pass
def start(self):
"""Starts the shared memory manager"""
- pass
def build_actor(self, target_fn: ty.Callable, builder: ty.Union[
ty.Dict['AbstractProcess', 'PyProcessBuilder'], ty.Dict[
SyncDomain, 'RuntimeServiceBuilder']]) -> ty.Any:
"""Given a target_fn starts a system (os) process"""
- pass
def stop(self):
"""Stops the shared memory manager"""
- pass
def channel_class(self, channel_type: ChannelType) -> ty.Type[Channel]:
"""Given a channel type, returns the shared memory based class
diff --git a/src/lava/magma/runtime/message_infrastructure/pypychannel.py b/src/lava/magma/runtime/message_infrastructure/pypychannel.py
index 16906590b..1d5bd8601 100644
--- a/src/lava/magma/runtime/message_infrastructure/pypychannel.py
+++ b/src/lava/magma/runtime/message_infrastructure/pypychannel.py
@@ -8,6 +8,9 @@
from queue import Queue, Empty
from threading import BoundedSemaphore, Condition, Thread
from time import time
+from scipy.sparse import csr_matrix
+from lava.utils.sparse import find
+
import numpy as np
from lava.magma.runtime.message_infrastructure import Channel
@@ -61,7 +64,7 @@ def __init__(self, name, shm, proto, size, req, ack):
self._done = False
self._array = []
self._semaphore = None
- self.observer = None
+ self.observer: ty.Optional[ty.Callable[[], ty.Any]] = None
self.thread = None
@property
@@ -125,6 +128,10 @@ def send(self, data):
"""
if data.shape != self._shape:
raise AssertionError(f"{data.shape=} {self._shape=} Mismatch")
+
+ if isinstance(data, csr_matrix):
+ data = find(data, explicit_zeros=True)[2]
+
self._semaphore.acquire()
self._array[self._idx][:] = data[:]
self._idx = (self._idx + 1) % self._size
@@ -203,7 +210,7 @@ def __init__(self, name, shm, proto, size, req, ack):
self._done = False
self._array = []
self._queue = None
- self.observer = None
+ self.observer: ty.Optional[ty.Callable[[], ty.Any]] = None
self.thread = None
@property
@@ -279,7 +286,6 @@ def recv(self):
result = self._array[self._idx].copy()
self._idx = (self._idx + 1) % self._size
self._ack.release()
-
return result
def join(self):
@@ -304,26 +310,29 @@ def _changed(self):
with self._cv:
self._cv.notify_all()
- def _set_observer(self, channel_actions, observer):
+ @staticmethod
+ def _set_observer(
+ channel_actions: ty.Tuple,
+ observer: ty.Union[ty.Callable[[], ty.Any], None]) -> None:
for channel, _ in channel_actions:
channel.observer = observer
def select(
self,
- *args: ty.Tuple[
+ *channel_actions: ty.Tuple[
ty.Union[SendPort, RecvPort], ty.Callable[[], ty.Any]
],
- ):
+ ) -> None:
"""
Wait for any channel to become ready, then execute the corresponding
callable and return the result.
"""
with self._cv:
- self._set_observer(args, self._changed)
+ self._set_observer(channel_actions, self._changed)
while True:
- for channel, action in args:
+ for channel, action in channel_actions:
if channel.probe():
- self._set_observer(args, None)
+ self._set_observer(channel_actions, None)
return action()
self._cv.wait()
diff --git a/src/lava/magma/runtime/mgmt_token_enums.py b/src/lava/magma/runtime/mgmt_token_enums.py
index 3c789cd74..bb0795fdf 100644
--- a/src/lava/magma/runtime/mgmt_token_enums.py
+++ b/src/lava/magma/runtime/mgmt_token_enums.py
@@ -2,12 +2,12 @@
# SPDX-License-Identifier: LGPL 2.1 or later
# See: https://spdx.org/licenses/
+"""Defines message tokens for Actions (Commands) and Responses. Also defines
+helper functions to convert scalar values to these message tokens."""
+
import typing as ty
import numpy as np
-"""Defines message tokens for Actions (Commands) and Responses. Also defines
-helper functions to convert scalar values to these message tokens"""
-
def enum_to_np(value: ty.Union[int, float],
d_type: type = np.float64) -> np.array:
diff --git a/src/lava/magma/runtime/runtime.py b/src/lava/magma/runtime/runtime.py
index 95e007704..4c31bd093 100644
--- a/src/lava/magma/runtime/runtime.py
+++ b/src/lava/magma/runtime/runtime.py
@@ -7,7 +7,6 @@
import logging
import sys
import traceback
-import typing
import typing as ty
import numpy as np
from lava.magma.runtime.message_infrastructure import (RecvPort,
@@ -19,6 +18,7 @@
getTempRecvPort,
AbstractTransferPort)
+from scipy.sparse import csr_matrix
from lava.magma.compiler.var_model import AbstractVarModel, LoihiSynapseVarModel
from lava.magma.runtime.message_infrastructure.message_interface_enum import \
ActorType
@@ -119,7 +119,7 @@ def __init__(self,
loglevel: int = logging.WARNING):
self.log = logging.getLogger(__name__)
self.log.setLevel(loglevel)
- self._run_cond: typing.Optional[AbstractRunCondition] = None
+ self._run_cond: ty.Optional[AbstractRunCondition] = None
self._executable: Executable = exe
self._messaging_infrastructure_type: ActorType = \
@@ -134,6 +134,7 @@ def __init__(self,
self.runtime_to_service: ty.Iterable[SendPort] = []
self.service_to_runtime: ty.Iterable[RecvPort] = []
self._open_ports: ty.List[AbstractTransferPort] = []
+ self.num_steps: int = 0
def __del__(self):
"""On destruction, terminate Runtime automatically to
@@ -523,6 +524,8 @@ def get_var(self, var_id: int, idx: np.ndarray = None) -> np.ndarray:
req_port.send(np.array([addr_path]))
buffer = recv_port.recv()
recv_port.join()
+ if ev.dtype == csr_matrix:
+ return buffer[idx] if idx else buffer
if buffer.dtype.type != np.str_:
reshape_order = 'F' \
if isinstance(ev, LoihiSynapseVarModel) else 'C'
@@ -531,6 +534,11 @@ def get_var(self, var_id: int, idx: np.ndarray = None) -> np.ndarray:
# 2. Receive Data [NUM_ITEMS, DATA1, DATA2, ...]
data_port: RecvPort = self.service_to_runtime[runtime_srv_id]
num_items: int = int(data_port.recv()[0].item())
+ if ev.dtype == csr_matrix:
+ buffer = np.zeros(num_items)
+ for i in range(num_items):
+ buffer[i] = data_port.recv()[0]
+ return buffer[idx] if idx else buffer
buffer: np.ndarray = np.zeros((1, np.prod(ev.shape)))
for i in range(num_items):
buffer[0, i] = data_port.recv()[0]
diff --git a/src/lava/magma/runtime/runtime_services/channel_broker/channel_broker.py b/src/lava/magma/runtime/runtime_services/channel_broker/channel_broker.py
index 05e8f59ce..0a439a5b7 100644
--- a/src/lava/magma/runtime/runtime_services/channel_broker/channel_broker.py
+++ b/src/lava/magma/runtime/runtime_services/channel_broker/channel_broker.py
@@ -22,7 +22,6 @@
try:
from nxcore.arch.base.nxboard import NxBoard
from nxcore.graph.channel import Channel
- from nxcore.graph.processes.phase_enums import Phase
from nxcore.graph.processes.embedded.embedded_snip import EmbeddedSnip
except ImportError:
class NxBoard:
diff --git a/src/lava/magma/runtime/runtime_services/runtime_service.py b/src/lava/magma/runtime/runtime_services/runtime_service.py
index fcbcd8ba1..481abf6ed 100644
--- a/src/lava/magma/runtime/runtime_services/runtime_service.py
+++ b/src/lava/magma/runtime/runtime_services/runtime_service.py
@@ -2,6 +2,28 @@
# SPDX-License-Identifier: LGPL 2.1 or later
# See: https://spdx.org/licenses/
+"""The RuntimeService interface is responsible for
+coordinating the execution of a group of process models belonging to a common
+synchronization domain. The domain will follow a SyncProtocol or will be
+asynchronous. The processes and their corresponding process models are
+selected by the Runtime dependent on the RunConfiguration assigned at the
+start of execution. For each group of processes which follow the same
+protocol and execute on the same node, the Runtime creates a RuntimeService.
+Each RuntimeService coordinates all actions and commands from the Runtime,
+transmitting them to the processes under its management and
+returning action and command responses back to Runtime.
+
+RuntimeService Types:
+
+PyRuntimeService: (Abstract Class) Coordinates process models executing on
+ the CPU and written in Python.
+ Concrete Implementations:
+ a. LoihiPyRuntimeService: Coordinates process models executing on
+ the CPU and written in Python and following the LoihiProtocol.
+ b. AsyncPyRuntimeService: Coordinates process models executing on
+ the CPU and written in Python and following the AsyncProtocol.
+"""
+
import logging
import typing as ty
from abc import abstractmethod
@@ -27,28 +49,6 @@
from lava.magma.runtime.runtime_services.interfaces import \
AbstractRuntimeService
-"""The RuntimeService interface is responsible for
-coordinating the execution of a group of process models belonging to a common
-synchronization domain. The domain will follow a SyncProtocol or will be
-asynchronous. The processes and their corresponding process models are
-selected by the Runtime dependent on the RunConfiguration assigned at the
-start of execution. For each group of processes which follow the same
-protocol and execute on the same node, the Runtime creates a RuntimeService.
-Each RuntimeService coordinates all actions and commands from the Runtime,
- transmitting them to the the processes under it's managment and
-returning action and command responses back to Runtime.
-
-RuntimeService Types:
-
-PyRuntimeService: (Abstract Class) Coordinates process models executing on
- the CPU and written in Python.
- Concrete Implementations:
- a. LoihiPyRuntimeService: Coordinates process models executing on
- the CPU and written in Python and following the LoihiProtocol.
- b. AsyncPyRuntimeService: Coordinates process models executing on
- the CPU and written in Python and following the AsyncProtocol.
-"""
-
class PyRuntimeService(AbstractRuntimeService):
"""Abstract RuntimeService for Python, it provides base methods
@@ -80,7 +80,6 @@ def run(self):
"""Override this method to implement the runtime service. The run
method is invoked upon start which called when the execution is
started by the runtime."""
- pass
def join(self):
"""Stop the necessary channels to coordinate with runtime and group
@@ -106,7 +105,7 @@ def _relay_to_runtime_data_given_model_id(self, model_id: int):
data_relay_port = self.service_to_runtime
num_items = data_recv_port.recv()
data_relay_port.send(num_items)
- for i in range(int(num_items[0])):
+ for _ in range(int(num_items[0])):
value = data_recv_port.recv()
data_relay_port.send(value)
@@ -128,7 +127,7 @@ def _relay_to_pm_data_given_model_id(self, model_id: int) -> MGMT_RESPONSE:
num_items = data_recv_port.recv()
data_relay_port.send(num_items)
# Receive and relay data1, data2, ...
- for i in range(int(num_items[0].item())):
+ for _ in range(int(num_items[0].item())):
data_relay_port.send(data_recv_port.recv())
rsp = resp_port.recv()
return rsp
@@ -212,12 +211,12 @@ def _next_phase(self, is_last_time_step: bool):
if self.req_pre_lrn_mgmt:
self.req_pre_lrn_mgmt = False
return LoihiPyRuntimeService.Phase.PRE_MGMT
- if self.req_post_lrn_mgmt:
- self.req_post_lrn_mgmt = False
- return LoihiPyRuntimeService.Phase.POST_MGMT
if self.req_lrn:
self.req_lrn = False
return LoihiPyRuntimeService.Phase.LRN
+ if self.req_post_lrn_mgmt:
+ self.req_post_lrn_mgmt = False
+ return LoihiPyRuntimeService.Phase.POST_MGMT
if self.req_pause:
self.req_pause = False
return MGMT_COMMAND.PAUSE
diff --git a/src/lava/proc/conv/utils.py b/src/lava/proc/conv/utils.py
index c47e9c5b6..73572af8f 100644
--- a/src/lava/proc/conv/utils.py
+++ b/src/lava/proc/conv/utils.py
@@ -157,7 +157,7 @@ def output_shape(input_shape: Tuple[int, int, int],
return x_out, y_out, out_channels
-def conv(input: np.ndarray,
+def conv(input_: np.ndarray,
weight: np.ndarray,
kernel_size: Tuple[int, int],
stride: Tuple[int, int],
@@ -168,7 +168,7 @@ def conv(input: np.ndarray,
Parameters
----------
- input : 3 dimensional np array
+ input_ : 3 dimensional np array
convolution input.
weight : 4 dimensional np array
convolution kernel weight.
@@ -192,7 +192,7 @@ def conv(input: np.ndarray,
# with torch.no_grad(): # this seems to cause problems
output = F.conv2d(
torch.unsqueeze( # torch expects a batch dimension NCHW
- torch.FloatTensor(input.transpose([2, 1, 0])),
+ torch.FloatTensor(input_.transpose([2, 1, 0])),
dim=0,
),
torch.FloatTensor(
@@ -209,13 +209,13 @@ def conv(input: np.ndarray,
)[0].cpu().data.numpy().transpose([2, 1, 0])
else:
output = conv_scipy(
- input, weight, kernel_size, stride, padding, dilation, groups
+ input_, weight, kernel_size, stride, padding, dilation, groups
)
return output.astype(weight.dtype)
-def conv_scipy(input: np.ndarray,
+def conv_scipy(input_: np.ndarray,
weight: np.ndarray,
kernel_size: Tuple[int, int],
stride: Tuple[int, int],
@@ -226,7 +226,7 @@ def conv_scipy(input: np.ndarray,
Parameters
----------
- input : 3 dimensional np array
+ input_ : 3 dimensional np array
convolution input.
weight : 4 dimensional np array
convolution kernel weight.
@@ -246,7 +246,7 @@ def conv_scipy(input: np.ndarray,
3 dimensional np array
convolution output
"""
- input_shape = input.shape
+ input_shape = input_.shape
output = np.zeros(
output_shape(
input_shape, weight.shape[0],
@@ -263,12 +263,12 @@ def conv_scipy(input: np.ndarray,
dilated_weight[:, ::dilation[0], ::dilation[1], :] = weight
input_padded = np.pad(
- input,
+ input_,
((padding[0], padding[0]), (padding[1], padding[1]), (0, 0)),
mode='constant',
)
- if input.shape[-1] % groups != 0:
+ if input_.shape[-1] % groups != 0:
raise Exception(
f'Expected number of in_channels to be divisible by group.'
f'Found {weight.shape[3] = } and {groups = }.'
@@ -280,7 +280,7 @@ def conv_scipy(input: np.ndarray,
)
k_grp = output.shape[2] // groups
- c_grp = input.shape[2] // groups
+ c_grp = input_.shape[2] // groups
for g in range(groups):
for k in range(k_grp):
for c in range(c_grp):
diff --git a/src/lava/proc/dense/models.py b/src/lava/proc/dense/models.py
index b14588b2c..1761110dd 100644
--- a/src/lava/proc/dense/models.py
+++ b/src/lava/proc/dense/models.py
@@ -72,9 +72,10 @@ def __init__(self, proc_params):
super().__init__(proc_params)
# Flag to determine whether weights have already been scaled.
self.weights_set = False
+ self.weight_exp: int = self.proc_params.get("weight_exp", 0)
def run_spk(self):
- self.weight_exp: int = self.proc_params.get("weight_exp", 0)
+ self.weight_exp = self.proc_params.get("weight_exp", 0)
# Since this Process has no learning, weights are assumed to be static
# and only require scaling on the first timestep of run_spk().
@@ -148,9 +149,9 @@ def run_spk(self):
@tag("bit_approximate_loihi", "fixed_pt")
class PyLearningDenseModelBitApproximate(
LearningConnectionModelBitApproximate, AbstractPyDenseModelBitAcc):
- """Implementation of Conn Process with Dense synaptic connections that is
- bit-accurate with Loihi's hardware implementation of Dense, which means,
- it mimics Loihi behaviour bit-by-bit.
+ """Implementation of Conn Process with Dense synaptic connections that
+ uses similar constraints as Loihi's hardware implementation of dense
+ connectivity but does not reproduce Loihi bit-by-bit.
"""
def __init__(self, proc_params):
@@ -347,14 +348,38 @@ class AbstractPyDelayDenseModel(PyLoihiProcessModel):
"""Abstract Conn Process with Dense synaptic connections which incorporates
delays into the Conn Process.
"""
+ weights: np.ndarray = None
+ delays: np.ndarray = None
+ a_buff: np.ndarray = None
+
+ def calc_act(self, s_in) -> np.ndarray:
+ """
+ Calculate the activation matrix based on s_in by performing
+ delay_wgts * s_in.
+ """
+ # First calculating the activations through delay_wgts * s_in
+ # This matrix is then summed across each row to get the
+ # activations to the output neurons for different delays.
+ # This activation vector is reshaped to a matrix of the form
+ # (n_flat_output_neurons * (max_delay + 1), n_flat_output_neurons)
+ # which is then transposed to get the activation matrix.
+ return np.reshape(
+ np.sum(self.get_delay_wgts_mat(self.weights,
+ self.delays) * s_in, axis=1),
+ (np.max(self.delays) + 1, self.weights.shape[0])).T
@staticmethod
- def get_del_wgts(weights, delays) -> np.ndarray:
+ def get_delay_wgts_mat(weights, delays) -> np.ndarray:
"""
- Use self.weights and self.delays to create a matrix where the
- weights are separated by delay. Returns 2D matrix of form
+ Create a matrix where the synaptic weights are separated
+ by their corresponding delays. The first matrix contains all the
+ weights, where the delay is equal to zero. The second matrix
+ contains all the weights, where the delay is equal to one and so on.
+ These matrices are then stacked together vertically.
+
+ Returns 2D matrix of form
(num_flat_output_neurons * max_delay + 1, num_flat_input_neurons) where
- del_wgts[
+ delay_wgts[
k * num_flat_output_neurons : (k + 1) * num_flat_output_neurons, :
]
contains the weights for all connections with a delay equal to k.
@@ -366,20 +391,6 @@ def get_del_wgts(weights, delays) -> np.ndarray:
for k in range(np.max(delays) + 1)
])
- def calc_act(self, s_in) -> np.ndarray:
- """
- Calculate the activations by performing del_wgts * s_in. This matrix
- is then summed across each row to get the activations to the output
- neurons for different delays. This activation vector is reshaped to a
- matrix of the form
- (n_flat_output_neurons * (max_delay + 1), n_flat_output_neurons)
- which is then transposed to get the activation matrix.
- """
- return np.reshape(
- np.sum(self.get_del_wgts(self.weights,
- self.delays) * s_in, axis=1),
- (np.max(self.delays) + 1, self.weights.shape[0])).T
-
def update_act(self, s_in):
"""
Updates the activations for the connection.
@@ -416,7 +427,7 @@ class PyDelayDenseModelFloat(AbstractPyDelayDenseModel):
num_message_bits: np.ndarray = LavaPyType(np.ndarray, int, precision=5)
def run_spk(self):
- # The a_out sent on a each timestep is a buffered value from dendritic
+ # The a_out sent on each timestep is a buffered value from dendritic
# accumulation at timestep t-1. This prevents deadlocking in
# networks with recurrent connectivity structures.
self.a_out.send(self.a_buff[:, 0])
diff --git a/src/lava/proc/dense/process.py b/src/lava/proc/dense/process.py
index 89d58c3ba..c2c0baf7e 100644
--- a/src/lava/proc/dense/process.py
+++ b/src/lava/proc/dense/process.py
@@ -232,17 +232,18 @@ def __init__(self,
spikes as binary spikes (num_message_bits = 0) or as graded
spikes (num_message_bits > 0). Default is 0.
"""
+ if max_delay == 0:
+ max_delay = int(np.max(delays))
super().__init__(weights=weights,
num_message_bits=num_message_bits,
name=name,
log_config=log_config,
+ max_delay=max_delay,
**kwargs)
self._validate_delays(weights, delays)
shape = weights.shape
- if max_delay == 0:
- max_delay = int(np.max(delays))
# Variables
self.delays = Var(shape=shape, init=delays)
diff --git a/src/lava/proc/io/encoder.py b/src/lava/proc/io/encoder.py
index 6a2fe39e7..3e284ce85 100644
--- a/src/lava/proc/io/encoder.py
+++ b/src/lava/proc/io/encoder.py
@@ -15,7 +15,6 @@
from lava.magma.core.resources import HostCPU
from lava.magma.core.decorator import implements, requires, tag
from lava.magma.core.model.py.model import PyLoihiProcessModel
-from lava.proc.sdn.models import AbstractDeltaModel
@unique
diff --git a/src/lava/proc/lif/models.py b/src/lava/proc/lif/models.py
index 1d7bd3a75..b58ffe7db 100644
--- a/src/lava/proc/lif/models.py
+++ b/src/lava/proc/lif/models.py
@@ -1,7 +1,11 @@
-# Copyright (C) 2021-22 Intel Corporation
+# Copyright (C) 2021-23 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
+from lava.magma.core.model.py.neuron import (
+ LearningNeuronModelFloat,
+ LearningNeuronModelFixed,
+)
import numpy as np
from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
from lava.magma.core.model.py.ports import PyInPort, PyOutPort
@@ -9,12 +13,8 @@
from lava.magma.core.resources import CPU
from lava.magma.core.decorator import implements, requires, tag
from lava.magma.core.model.py.model import PyLoihiProcessModel
-from lava.proc.lif.process import LIF, LIFReset, TernaryLIF, LearningLIF
-
-from lava.magma.core.model.py.neuron import (
- LearningNeuronModelFloat,
- LearningNeuronModelFixed,
-)
+from lava.proc.lif.process import (LIF, LIFReset, TernaryLIF, LearningLIF,
+ LIFRefractory)
class AbstractPyLifModelFloat(PyLoihiProcessModel):
@@ -449,6 +449,60 @@ def run_spk(self):
self.s_out.send(s_out)
+@implements(proc=LIFRefractory, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("floating_pt")
+class PyLifRefractoryModelFloat(AbstractPyLifModelFloat):
+ """Implementation of Leaky-Integrate-and-Fire neural process with
+ refractory period in floating point precision.
+ """
+
+ s_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, float)
+ vth: float = LavaPyType(float, float)
+ refractory_period_end: np.ndarray = LavaPyType(np.ndarray, int)
+
+ def __init__(self, proc_params):
+ super(PyLifRefractoryModelFloat, self).__init__(proc_params)
+ self.refractory_period = proc_params["refractory_period"]
+
+ def spiking_activation(self):
+ """Spiking activation function for LIF Refractory."""
+ return self.v > self.vth
+
+ def subthr_dynamics(self, activation_in: np.ndarray):
+ """Sub-threshold dynamics of current and voltage variables for
+ all refractory LIF models. This is where the 'leaky integration'
+ happens.
+ """
+ self.u[:] = self.u * (1 - self.du)
+ self.u[:] += activation_in
+ non_refractory = self.refractory_period_end < self.time_step
+ self.v[non_refractory] = (self.v[non_refractory] * (
+ (1 - self.dv) + self.u[non_refractory])
+ + self.bias_mant[non_refractory])
+
+ def process_spikes(self, spike_vector: np.ndarray):
+ self.refractory_period_end[spike_vector] = (self.time_step
+ + self.refractory_period)
+ super().reset_voltage(spike_vector)
+
+ def run_spk(self):
+ """The run function that performs the actual computation during
+ execution orchestrated by a PyLoihiProcessModel using the
+ LoihiProtocol.
+ """
+ # Receive synaptic input
+ a_in_data = self.a_in.recv()
+
+ self.subthr_dynamics(activation_in=a_in_data)
+
+ s_out = self.spiking_activation()
+
+ # Reset voltage of spiked neurons to 0
+ self.process_spikes(spike_vector=s_out)
+ self.s_out.send(s_out)
+
+
@implements(proc=LearningLIF, protocol=LoihiProtocol)
@requires(CPU)
@tag("bit_accurate_loihi", "fixed_pt")
diff --git a/src/lava/proc/lif/process.py b/src/lava/proc/lif/process.py
index 426f9b216..d658755b8 100644
--- a/src/lava/proc/lif/process.py
+++ b/src/lava/proc/lif/process.py
@@ -1,14 +1,11 @@
-# Copyright (C) 2022 Intel Corporation
+# Copyright (C) 2022-23 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
import numpy as np
import typing as ty
-from lava.magma.core.learning.learning_rule import (
- LoihiLearningRule,
- Loihi2FLearningRule,
-)
+from lava.magma.core.learning.learning_rule import Loihi2FLearningRule
from lava.magma.core.process.process import LogConfig, AbstractProcess
from lava.magma.core.process.variable import Var
from lava.magma.core.process.ports.ports import InPort, OutPort
@@ -347,3 +344,75 @@ def __init__(
self.proc_params["reset_interval"] = reset_interval
self.proc_params["reset_offset"] = reset_offset
+
+
+class LIFRefractory(LIF):
+
+ """Leaky-Integrate-and-Fire (LIF) process with refractory period.
+
+ Parameters
+ ----------
+ shape : tuple(int)
+ Number and topology of LIF neurons.
+ u : float, list, numpy.ndarray, optional
+ Initial value of the neurons' current.
+ v : float, list, numpy.ndarray, optional
+ Initial value of the neurons' voltage (membrane potential).
+ du : float, optional
+ Inverse of decay time-constant for current decay. Currently, only a
+ single decay can be set for the entire population of neurons.
+ dv : float, optional
+ Inverse of decay time-constant for voltage decay. Currently, only a
+ single decay can be set for the entire population of neurons.
+ bias_mant : float, list, numpy.ndarray, optional
+ Mantissa part of neuron bias.
+ bias_exp : float, list, numpy.ndarray, optional
+ Exponent part of neuron bias, if needed. Mostly for fixed point
+ implementations. Ignored for floating point implementations.
+ vth : float, optional
+ Neuron threshold voltage, exceeding which, the neuron will spike.
+ Currently, only a single threshold can be set for the entire
+ population of neurons.
+ refractory_period : int, optional
+ The interval of the refractory period. 1 timestep by default.
+
+
+ See Also
+ --------
+ lava.proc.lif.process.LIF: 'Regular' leaky-integrate-and-fire neuron for
+ documentation on rest of the behavior.
+ """
+
+ def __init__(
+ self,
+ *,
+ shape: ty.Tuple[int, ...],
+ u: ty.Optional[ty.Union[float, list, np.ndarray]] = 0,
+ v: ty.Optional[ty.Union[float, list, np.ndarray]] = 0,
+ du: ty.Optional[float] = 0,
+ dv: ty.Optional[float] = 0,
+ bias_mant: ty.Optional[ty.Union[float, list, np.ndarray]] = 0,
+ bias_exp: ty.Optional[ty.Union[float, list, np.ndarray]] = 0,
+ vth: ty.Optional[float] = 10,
+ refractory_period: ty.Optional[int] = 1,
+ name: ty.Optional[str] = None,
+ log_config: ty.Optional[LogConfig] = None,
+ ) -> None:
+ super().__init__(
+ shape=shape,
+ u=u,
+ v=v,
+ du=du,
+ dv=dv,
+ bias_mant=bias_mant,
+ bias_exp=bias_exp,
+ vth=vth,
+ name=name,
+ log_config=log_config,
+ )
+
+ if refractory_period < 1:
+ raise ValueError("Refractory period must be > 0.")
+
+ self.proc_params["refractory_period"] = refractory_period
+ self.refractory_period_end = Var(shape=shape, init=0)
diff --git a/src/lava/proc/monitor/process.py b/src/lava/proc/monitor/process.py
index b907c4103..0c8b4d17a 100644
--- a/src/lava/proc/monitor/process.py
+++ b/src/lava/proc/monitor/process.py
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
-import matplotlib.pyplot as plt
from lava.magma.core.process.process import AbstractProcess
from lava.magma.core.process.variable import Var
from lava.magma.core.process.ports.ports import InPort, OutPort, RefPort
@@ -131,23 +130,19 @@ def probe(self, target, num_steps):
# Create names for Ports/Vars to be created in Monitor process for
# probing purposes. Names are given incrementally each time probe(..)
# method is called.
- self.new_ref_port_name = "ref_port_" + \
- str(self.proc_params["n_ref_ports"])
- self.new_var_read_name = "var_read_" + \
- str(self.proc_params["n_ref_ports"])
- self.new_in_port_name = "in_port_" + \
- str(self.proc_params["n_in_ports"])
- self.new_out_read_name = "out_read_" + \
- str(self.proc_params["n_in_ports"])
+ new_ref_port_name = f"ref_port_{self.proc_params['n_ref_ports']}"
+ new_var_read_name = f"var_read_{self.proc_params['n_ref_ports']}"
+ new_in_port_name = f"in_port_{self.proc_params['n_in_ports']}"
+ new_out_read_name = f"out_read_{self.proc_params['n_in_ports']}"
# Create and set new Refport and corresponding Var to store data
- setattr(self, self.new_ref_port_name, RefPort(shape=target.shape))
- setattr(self, self.new_var_read_name,
+ setattr(self, new_ref_port_name, RefPort(shape=target.shape))
+ setattr(self, new_var_read_name,
Var(shape=(num_steps,) + target.shape, init=0))
# Create and set new InPort and corresponding Var to store data
- setattr(self, self.new_in_port_name, InPort(shape=target.shape))
- setattr(self, self.new_out_read_name,
+ setattr(self, new_in_port_name, InPort(shape=target.shape))
+ setattr(self, new_out_read_name,
Var(shape=(num_steps,) + target.shape, init=0))
# Add the names of new RefPort and Var_read name to proc_params dict
@@ -179,11 +174,11 @@ def probe(self, target, num_steps):
self.proc_params.overwrite("n_ref_ports", n_ref_ports + 1)
# Connect newly created Refport to the var to be monitored
- getattr(self, self.new_ref_port_name).connect_var(target)
+ getattr(self, new_ref_port_name).connect_var(target)
# Add the name of probed Var and its process to the target_names
- self.target_names[self.new_var_read_name] = [target.process.name,
- target.name]
+ self.target_names[new_var_read_name] = [target.process.name,
+ target.name]
# If target to be monitored is an OutPort
elif isinstance(target, OutPort):
@@ -192,11 +187,11 @@ def probe(self, target, num_steps):
self.proc_params.overwrite("n_in_ports", n_in_ports + 1)
# Connect newly created InPort from the OutPort to be monitored
- getattr(self, self.new_in_port_name).connect_from(target)
+ getattr(self, new_in_port_name).connect_from(target)
# Add the name of OutPort and its process to the target_names
- self.target_names[self.new_out_read_name] = [target.process.name,
- target.name]
+ self.target_names[new_out_read_name] = [target.process.name,
+ target.name]
# If target is an InPort raise a Type error, as monitoring InPorts is
# not supported yet
diff --git a/src/lava/proc/sparse/models.py b/src/lava/proc/sparse/models.py
new file mode 100644
index 000000000..cd7b4abc3
--- /dev/null
+++ b/src/lava/proc/sparse/models.py
@@ -0,0 +1,372 @@
+# Copyright (C) 2023 Intel Corporation
+# SPDX-License-Identifier: BSD-3-Clause
+# See: https://spdx.org/licenses/
+
+import numpy as np
+from scipy.sparse import csr_matrix, spmatrix, vstack, find
+from lava.magma.core.model.py.connection import (
+ LearningConnectionModelFloat,
+ LearningConnectionModelBitApproximate,
+)
+from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
+from lava.magma.core.model.py.ports import PyInPort, PyOutPort
+from lava.magma.core.model.py.type import LavaPyType
+from lava.magma.core.resources import CPU
+from lava.magma.core.decorator import implements, requires, tag
+from lava.magma.core.model.py.model import PyLoihiProcessModel
+from lava.proc.sparse.process import Sparse, DelaySparse, LearningSparse
+from lava.utils.weightutils import SignMode, determine_sign_mode,\
+ truncate_weights, clip_weights
+
+
+class AbstractPySparseModelFloat(PyLoihiProcessModel):
+ """Implementation of Conn Process with Sparse synaptic connections in
+ floating point precision. This short and simple ProcessModel can be used
+ for quick algorithmic prototyping, without engaging with the nuances of a
+ fixed point implementation.
+ """
+
+ s_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, bool, precision=1)
+ a_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, float)
+ a_buff: np.ndarray = LavaPyType(np.ndarray, float)
+ # weights is a 2D matrix of form (num_flat_output_neurons,
+ # num_flat_input_neurons) in C-order (row major).
+ weights: csr_matrix = LavaPyType(csr_matrix, float)
+ num_message_bits: np.ndarray = LavaPyType(np.ndarray, int, precision=5)
+
+ def run_spk(self):
+ # The a_out sent on each timestep is a buffered value from dendritic
+ # accumulation at timestep t-1. This prevents deadlocking in
+ # networks with recurrent connectivity structures.
+ self.a_out.send(self.a_buff)
+ if self.num_message_bits.item() > 0:
+ s_in = self.s_in.recv()
+ self.a_buff = self.weights.dot(s_in)
+ else:
+ s_in = self.s_in.recv().astype(bool)
+ # A1: return as flattend array
+ self.a_buff = self.weights[:, s_in].sum(axis=1).A1
+
+
+@implements(proc=Sparse, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("floating_pt")
+class PySparseModelFloat(AbstractPySparseModelFloat):
+ pass
+
+
+class AbstractPySparseModelBitAcc(PyLoihiProcessModel):
+ """Implementation of Conn Process with Sparse synaptic connections that is
+ bit-accurate with Loihi's hardware implementation of Sparse, which means,
+ it reproduces Loihi behavior bit-by-bit.
+ """
+
+ s_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, bool, precision=1)
+ a_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, np.int32, precision=16)
+ a_buff: np.ndarray = LavaPyType(np.ndarray, np.int32, precision=16)
+ # weights is a 2D matrix of form (num_flat_output_neurons,
+ # num_flat_input_neurons) in C-order (row major).
+ weights: np.ndarray = LavaPyType(csr_matrix, np.int32, precision=8)
+ num_message_bits: np.ndarray = LavaPyType(np.ndarray, int, precision=5)
+
+ def __init__(self, proc_params):
+ super().__init__(proc_params)
+ # Flag to determine whether weights have already been scaled.
+ self.weights_set = False
+
+ def run_spk(self):
+ # pylint: disable=W0201
+ self.weight_exp: int = self.proc_params.get("weight_exp", 0)
+
+ # Since this Process has no learning, weights are assumed to be static
+ # and only require scaling on the first timestep of run_spk().
+ if not self.weights_set:
+ num_weight_bits: int = self.proc_params.get("num_weight_bits", 8)
+ sign_mode: SignMode = self.proc_params.get("sign_mode") \
+ or determine_sign_mode(self.weights)
+
+ self.weights = clip_weights(self.weights, sign_mode, num_bits=8)
+ self.weights = truncate_weights(self.weights,
+ sign_mode,
+ num_weight_bits)
+ self.weights_set = True
+
+ # The a_out sent at each timestep is a buffered value from dendritic
+ # accumulation at timestep t-1. This prevents deadlocking in
+ # networks with recurrent connectivity structures.
+ self.a_out.send(self.a_buff)
+ if self.num_message_bits.item() > 0:
+ s_in = self.s_in.recv()
+ a_accum = self.weights.dot(s_in)
+ else:
+ s_in = self.s_in.recv().astype(bool)
+ a_accum = self.weights[:, s_in].sum(axis=1).A1
+ self.a_buff = (
+ np.left_shift(a_accum, self.weight_exp)
+ if self.weight_exp > 0
+ else np.right_shift(a_accum, -self.weight_exp)
+ )
+
+
+@implements(proc=Sparse, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("bit_accurate_loihi", "fixed_pt")
+class PySparseModelBitAcc(AbstractPySparseModelBitAcc):
+ pass
+
+
+@implements(proc=LearningSparse, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("floating_pt")
+class PyLearningSparseModelFloat(
+ LearningConnectionModelFloat, AbstractPySparseModelFloat):
+ """Implementation of Conn Process with Sparse synaptic connections in
+ floating point precision. This short and simple ProcessModel can be used
+ for quick algorithmic prototyping, without engaging with the nuances of a
+ fixed point implementation.
+
+ Warning: LearningSparse on CPU is not offering any memory usage benefits
+ over using LearningDense.
+ """
+
+ # Overwrite dense PyTypes with sparse
+ tag_1: csr_matrix = LavaPyType(csr_matrix, float)
+ tag_2: csr_matrix = LavaPyType(csr_matrix, float)
+
+ def __init__(self, proc_params):
+ super().__init__(proc_params)
+
+ def run_spk(self):
+ # The a_out sent at each timestep is a buffered value from dendritic
+ # accumulation at timestep t-1. This prevents deadlocking in
+ # networks with recurrent connectivity structures.
+ self.a_out.send(self.a_buff)
+ if self.num_message_bits.item() > 0:
+ s_in = self.s_in.recv()
+ self.a_buff = self.weights.dot(s_in)
+ else:
+ s_in = self.s_in.recv().astype(bool)
+ self.a_buff = self.weights[:, s_in].sum(axis=1).A1
+
+ self.recv_traces(s_in)
+
+
+@implements(proc=LearningSparse, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("bit_approximate_loihi", "fixed_pt")
+class PyLearningSparseModelBitApproximate(
+ LearningConnectionModelBitApproximate, AbstractPySparseModelBitAcc):
+ """Implementation of Conn Process with Sparse synaptic connections that
+ uses similar constraints as Loihi's hardware implementation of sparse
+ connectivity but does not reproduce Loihi bit-by-bit.
+
+ Warning: LearningSparse on CPU is not offering any memory usage benefits
+ over using LearningDense.
+ """
+ # Overwrite dense PyTypes with sparse
+ tag_1: csr_matrix = LavaPyType(csr_matrix, int, precision=8)
+ tag_2: csr_matrix = LavaPyType(csr_matrix, int, precision=6)
+
+ def __init__(self, proc_params):
+ super().__init__(proc_params)
+ # Flag to determine whether weights have already been scaled.
+ self.num_weight_bits: int = self.proc_params.get("num_weight_bits", 8)
+
+ def run_spk(self):
+ self.weight_exp: int = self.proc_params.get("weight_exp", 0)
+
+ # Since this Process has no learning, weights are assumed to be static
+ # and only require scaling on the first timestep of run_spk().
+ if not self.weights_set:
+ self.weights = truncate_weights(
+ self.weights,
+ sign_mode=self.sign_mode,
+ num_weight_bits=self.num_weight_bits
+ )
+ self.weights_set = True
+
+ # The a_out sent at each timestep is a buffered value from dendritic
+ # accumulation at timestep t-1. This prevents deadlocking in
+ # networks with recurrent connectivity structures.
+ self.a_out.send(self.a_buff)
+ if self.num_message_bits.item() > 0:
+ s_in = self.s_in.recv()
+ a_accum = self.weights.dot(s_in)
+ else:
+ s_in = self.s_in.recv().astype(bool)
+ a_accum = self.weights[:, s_in].sum(axis=1).A1
+
+ self.a_buff = (
+ np.left_shift(a_accum, self.weight_exp)
+ if self.weight_exp > 0
+ else np.right_shift(a_accum, -self.weight_exp)
+ )
+
+ self.recv_traces(s_in)
+
+
+class AbstractPyDelaySparseModel(PyLoihiProcessModel):
+ """Abstract Conn Process with Sparse synaptic connections which incorporates
+ delays into the Conn Process.
+ """
+ weights: csr_matrix = None
+ delays: csr_matrix = None
+ a_buff: np.ndarray = None
+
+ def calc_act(self, s_in) -> np.ndarray:
+ """
+ Calculate the activation matrix based on s_in by performing
+ delay_wgts * s_in.
+ """
+ # First calculating the activations through delay_wgts * s_in
+ # This matrix is then summed across each row to get the
+ # activations to the output neurons for different delays.
+ # This activation vector is reshaped to a matrix of the form
+ # (n_flat_output_neurons * (max_delay + 1), n_flat_output_neurons)
+ # which is then transposed to get the activation matrix.
+ return np.reshape(self.get_delay_wgts_mat(self.weights,
+ self.delays).dot(s_in),
+ (np.max(self.delays) + 1,
+ self.weights.shape[0])).T
+
+ @staticmethod
+ def get_delay_wgts_mat(weights, delays) -> spmatrix:
+ """
+ Create a matrix where the synaptic weights are separated
+ by their corresponding delays. The first matrix contains all the
+ weights, where the delay is equal to zero. The second matrix
+ contains all the weights, where the delay is equal to one and so on.
+ These matrices are then stacked together vertically.
+
+ Returns 2D matrix of form
+ (num_flat_output_neurons * max_delay + 1, num_flat_input_neurons) where
+ delay_wgts[
+ k * num_flat_output_neurons : (k + 1) * num_flat_output_neurons, :
+ ]
+ contains the weights for all connections with a delay equal to k.
+ This allows for the updating of the activation buffer and updating
+ weights.
+ """
+ # Can only start at 1, as delays==0 raises inefficiency warning
+ if np.max(delays) == 0:
+ return weights
+
+ weight_delay_from_1 = vstack([weights.multiply(delays == k)
+ for k in range(1, np.max(delays) + 1)])
+ # Create weight matrix at delays == 0
+ r, c, _ = find(delays)
+ weight_delay_zeros = weights.copy()
+ weight_delay_zeros[r, c] = 0
+ weight_delay_zeros.eliminate_zeros()
+ return vstack([weight_delay_zeros, weight_delay_from_1])
+
+ def update_act(self, s_in):
+ """
+ Updates the activations for the connection.
+ Clears first column of a_buff and rolls them to the last column.
+ Finally, calculates the activations for the current time step and adds
+ them to a_buff.
+ This order of operations ensures that delays of 0 correspond to
+ the next time step.
+ """
+ self.a_buff[:, 0] = 0
+ self.a_buff = np.roll(self.a_buff, -1)
+ self.a_buff += self.calc_act(s_in)
+
+
+@implements(proc=DelaySparse, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("floating_pt")
+class PyDelaySparseModelFloat(AbstractPyDelaySparseModel):
+ """Implementation of Conn Process with Sparse synaptic connections in
+ floating point precision. This short and simple ProcessModel can be used
+ for quick algorithmic prototyping, without engaging with the nuances of a
+ fixed point implementation. DelaySparse incorporates delays into the Conn
+ Process.
+ """
+ s_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, bool, precision=1)
+ a_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, float)
+ a_buff: np.ndarray = LavaPyType(np.ndarray, float)
+ # weights is a 2D matrix of form (num_flat_output_neurons,
+ # num_flat_input_neurons) in C-order (row major).
+ weights: np.ndarray = LavaPyType(csr_matrix, float)
+ # delays is a 2D matrix of form (num_flat_output_neurons,
+ # num_flat_input_neurons) in C-order (row major).
+ delays: np.ndarray = LavaPyType(csr_matrix, int)
+ num_message_bits: np.ndarray = LavaPyType(np.ndarray, int, precision=5)
+
+ def run_spk(self):
+ # The a_out sent on each timestep is a buffered value from dendritic
+ # accumulation at timestep t-1; this prevents deadlocking in
+ # networks with recurrent connectivity structures.
+ self.a_out.send(self.a_buff[:, 0])
+ if self.num_message_bits.item() > 0:
+ s_in = self.s_in.recv()
+ else:
+ s_in = self.s_in.recv().astype(bool)
+ self.update_act(s_in)
+
+
+@implements(proc=DelaySparse, protocol=LoihiProtocol)
+@requires(CPU)
+@tag("bit_accurate_loihi", "fixed_pt")
+class PyDelaySparseModelBitAcc(AbstractPyDelaySparseModel):
+ """Implementation of Conn Process with Sparse synaptic connections that is
+ bit-accurate with Loihi's hardware implementation of Sparse, which means,
+ it mimics Loihi behaviour bit-by-bit. DelaySparse incorporates delays into
+ the Conn Process. Loihi 2 has a maximum of 6 bits for delays, meaning a
+ spike can be delayed by 0 to 63 time steps."""
+
+ s_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, bool, precision=1)
+ a_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, np.int32, precision=16)
+ a_buff: np.ndarray = LavaPyType(np.ndarray, np.int32, precision=16)
+ # weights is a 2D matrix of form (num_flat_output_neurons,
+ # num_flat_input_neurons) in C-order (row major).
+ weights: csr_matrix = LavaPyType(csr_matrix, np.int32, precision=8)
+ delays: csr_matrix = LavaPyType(csr_matrix, np.int32, precision=6)
+ num_message_bits: np.ndarray = LavaPyType(np.ndarray, int, precision=5)
+
+ def __init__(self, proc_params):
+ super().__init__(proc_params)
+ # Flag to determine whether weights have already been scaled.
+ self.weights_set = False
+
+ def run_spk(self):
+ self.weight_exp: int = self.proc_params.get("weight_exp", 0)
+
+ # Since this Process has no learning, weights are assumed to be static
+ # and only require scaling on the first timestep of run_spk().
+ if not self.weights_set:
+ num_weight_bits: int = self.proc_params.get("num_weight_bits", 8)
+ sign_mode: SignMode = self.proc_params.get("sign_mode") \
+ or determine_sign_mode(self.weights)
+
+ self.weights = clip_weights(self.weights, sign_mode, num_bits=8)
+ self.weights = truncate_weights(self.weights,
+ sign_mode,
+ num_weight_bits)
+ self.weights_set = True
+
+ # Check if delays are within Loihi 2 constraints
+ if np.max(self.delays) > 63:
+ raise ValueError("DelaySparse Process 'delays' expects values "
+ f"between 0 and 63 for Loihi, got "
+ f"{self.delays}.")
+
+ # The a_out sent at each timestep is a buffered value from dendritic
+ # accumulation at timestep t-1. This prevents deadlocking in
+ # networks with recurrent connectivity structures.
+ self.a_out.send(self.a_buff[:, 0])
+ if self.num_message_bits.item() > 0:
+ s_in = self.s_in.recv()
+ else:
+ s_in = self.s_in.recv().astype(bool)
+
+ a_accum = self.calc_act(s_in)
+ self.a_buff[:, 0] = 0
+ self.a_buff = np.roll(self.a_buff, -1)
+ self.a_buff += (
+ np.left_shift(a_accum, self.weight_exp)
+ if self.weight_exp > 0
+ else np.right_shift(a_accum, -self.weight_exp)
+ )
diff --git a/src/lava/proc/sparse/process.py b/src/lava/proc/sparse/process.py
new file mode 100644
index 000000000..d8c52c7ce
--- /dev/null
+++ b/src/lava/proc/sparse/process.py
@@ -0,0 +1,277 @@
+# Copyright (C) 2021-23 Intel Corporation
+# SPDX-License-Identifier: BSD-3-Clause
+# See: https://spdx.org/licenses/
+
+import numpy as np
+from scipy.sparse import spmatrix
+import typing as ty
+
+from lava.magma.core.process.process import AbstractProcess, LogConfig
+from lava.magma.core.process.variable import Var
+from lava.magma.core.process.ports.ports import InPort, OutPort
+from lava.magma.core.process.connection import LearningConnectionProcess
+from lava.magma.core.learning.constants import GradedSpikeCfg
+from lava.magma.core.learning.learning_rule import LoihiLearningRule
+
+
+class Sparse(AbstractProcess):
+ """Sparse connections between neurons. Realizes the following abstract
+ behavior: a_out = weights * s_in. The weights are stored as
+ scipy.sparse.csr_matrix.
+
+ Parameters
+ ----------
+ weights : scipy.sparse.spmatrix
+ 2D connection weight matrix as sparse matrix of form
+ (num_flat_output_neurons, num_flat_input_neurons).
+
+ weight_exp : int, optional
+ Shared weight exponent of base 2 used to scale magnitude of
+ weights, if needed. Mostly for fixed point implementations.
+ Unnecessary for floating point implementations.
+ Default value is 0.
+
+ num_weight_bits : int, optional
+ Shared weight width/precision used by weight. Mostly for fixed
+ point implementations. Unnecessary for floating point
+ implementations.
+ Default is for weights to use full 8 bit precision.
+
+ sign_mode : SignMode, optional
+ Shared indicator whether synapse is of type SignMode.NULL,
+ SignMode.MIXED, SignMode.EXCITATORY, or SignMode.INHIBITORY. If
+ SignMode.MIXED, the sign of the weight is
+ included in the weight bits and the fixed point weight used for
+ inference is scaled by 2.
+ Unnecessary for floating point implementations.
+
+ In the fixed point implementation, weights are scaled according to
+ the following equations:
+ w_scale = 8 - num_weight_bits + weight_exp + isMixed()
+ weights = weights * (2 ** w_scale)
+
+ num_message_bits : int, optional
+ Determines whether the Sparse Process deals with the incoming
+ spikes as binary spikes (num_message_bits = 0) or as graded
+ spikes (num_message_bits > 0). Default is 0.
+ """
+ def __init__(self,
+ *,
+ weights: spmatrix,
+ name: ty.Optional[str] = None,
+ num_message_bits: ty.Optional[int] = 0,
+ log_config: ty.Optional[LogConfig] = None,
+ **kwargs) -> None:
+
+ super().__init__(num_message_bits=num_message_bits,
+ name=name,
+ log_config=log_config,
+ **kwargs)
+
+ # Transform weights to csr matrix
+ weights = weights.tocsr()
+
+ shape = weights.shape
+
+ # Ports
+ self.s_in = InPort(shape=(shape[1],))
+ self.a_out = OutPort(shape=(shape[0],))
+
+ # Variables
+ self.weights = Var(shape=shape, init=weights)
+ self.a_buff = Var(shape=(shape[0],), init=0)
+ self.num_message_bits = Var(shape=(1,), init=num_message_bits)
+
+
+class LearningSparse(LearningConnectionProcess, Sparse):
+ """Sparse connections between neurons. Realizes the following abstract
+ behavior: a_out = weights * s_in. The weights are stored as
+ scipy.sparse.csr_matrix.
+
+ Parameters
+ ----------
+ weights : scipy.sparse.spmatrix
+ 2D connection weight matrix as sparse matrix of form
+ (num_flat_output_neurons, num_flat_input_neurons).
+
+ weight_exp : int, optional
+ Shared weight exponent of base 2 used to scale magnitude of
+ weights, if needed. Mostly for fixed point implementations.
+ Unnecessary for floating point implementations.
+ Default value is 0.
+
+ num_weight_bits : int, optional
+ Shared weight width/precision used by weight. Mostly for fixed
+ point implementations. Unnecessary for floating point
+ implementations.
+ Default is for weights to use full 8 bit precision.
+
+ sign_mode : SignMode, optional
+ Shared indicator whether synapse is of type SignMode.NULL,
+ SignMode.MIXED, SignMode.EXCITATORY, or SignMode.INHIBITORY. If
+ SignMode.MIXED, the sign of the weight is
+ included in the weight bits and the fixed point weight used for
+ inference is scaled by 2.
+ Unnecessary for floating point implementations.
+
+ In the fixed point implementation, weights are scaled according to
+ the following equations:
+ w_scale = 8 - num_weight_bits + weight_exp + isMixed()
+ weights = weights * (2 ** w_scale)
+
+ num_message_bits : int, optional
+ Determines whether the Sparse Process deals with the incoming
+ spikes as binary spikes (num_message_bits = 0) or as graded
+ spikes (num_message_bits > 0). Default is 0.
+
+ learning_rule: LoihiLearningRule
+ Learning rule which determines the parameters for online learning.
+
+ graded_spike_cfg: GradedSpikeCfg
+ Indicates how to use incoming graded spike to update pre-synaptic
+ traces.
+
+ (0) GradedSpikeCfg.USE_REGULAR_IMPULSE interprets the spike as a
+ binary spike, adds regular impulses to pre-synaptic traces, at the end
+ of the epoch.
+ (1) GradedSpikeCfg.OVERWRITE interprets the spike as a graded spike,
+ overwrites the value of the pre-synaptic trace x1 by payload/2,
+ upon spiking.
+ (2) GradedSpikeCfg.ADD_WITH_SATURATION interprets the spike as a graded
+ spike, adds payload/2 to the pre-synaptic trace x1, upon spiking,
+ saturates x1 to 127 (fixed-pt/hw only).
+ (3) GradedSpikeCfg.ADD_WITHOUT_SATURATION interprets the spike as a
+ graded spike, adds payload/2 to the pre-synaptic trace x1, upon spiking,
+ keeps only overflow above 127 in x1 (fixed-pt/hw only), adds regular
+ impulse to x2 on overflow.
+ In addition, only pre-synaptic graded spikes that trigger overflow in
+ x1 and regular impulse addition to x2 will be considered by the
+ learning rule Products conditioned on x0.
+ """
+ def __init__(self,
+ *,
+ weights: spmatrix,
+ name: ty.Optional[str] = None,
+ num_message_bits: ty.Optional[int] = 0,
+ log_config: ty.Optional[LogConfig] = None,
+ learning_rule: LoihiLearningRule = None,
+ graded_spike_cfg: GradedSpikeCfg =
+ GradedSpikeCfg.USE_REGULAR_IMPULSE,
+ **kwargs) -> None:
+
+ if graded_spike_cfg != GradedSpikeCfg.USE_REGULAR_IMPULSE:
+ learning_rule.x1_impulse = 0
+
+ super().__init__(weights=weights,
+ shape=weights.shape,
+ num_message_bits=num_message_bits,
+ name=name,
+ log_config=log_config,
+ learning_rule=learning_rule,
+ graded_spike_cfg=graded_spike_cfg,
+ **kwargs)
+
+ # Transform weights to csr matrix
+ weights = weights.tocsr()
+
+ shape = weights.shape
+
+ # Ports
+ self.s_in = InPort(shape=(shape[1],))
+ self.a_out = OutPort(shape=(shape[0],))
+
+ # Variables
+ self.weights = Var(shape=shape, init=weights)
+ self.a_buff = Var(shape=(shape[0],), init=0)
+ self.num_message_bits = Var(shape=(1,), init=num_message_bits)
+
+
+class DelaySparse(Sparse):
+ def __init__(self,
+ *,
+ weights: spmatrix,
+ delays: ty.Union[spmatrix, int],
+ max_delay: ty.Optional[int] = 0,
+ name: ty.Optional[str] = None,
+ num_message_bits: ty.Optional[int] = 0,
+ log_config: ty.Optional[LogConfig] = None,
+ **kwargs) -> None:
+ """Sparse, delayed connections between neurons. Realizes the following
+ abstract behavior: a_out = weights * s_in
+
+ Parameters
+ ----------
+ weights : spmatrix
+ 2D connection weight matrix of form (num_flat_output_neurons,
+ num_flat_input_neurons) in C-order (row major).
+
+ delays : spmatrix, int
+ 2D connection delay matrix of form (num_flat_output_neurons,
+ num_flat_input_neurons) in C-order (row major) or integer value if
+ the same delay should be used for all synapses.
+
+ max_delay: int, optional
+ Maximum expected delay. Should be set if delays change during
+ execution. Default value is 0, in this case the maximum delay
+ will be determined from the values given in 'delays'.
+
+ weight_exp : int, optional
+ Shared weight exponent of base 2 used to scale magnitude of
+ weights, if needed. Mostly for fixed point implementations.
+ Unnecessary for floating point implementations.
+ Default value is 0.
+
+ num_weight_bits : int, optional
+ Shared weight width/precision used by weight. Mostly for fixed
+ point implementations. Unnecessary for floating point
+ implementations.
+ Default is for weights to use full 8 bit precision.
+
+ sign_mode : SignMode, optional
+ Shared indicator whether synapse is of type SignMode.NULL,
+ SignMode.MIXED, SignMode.EXCITATORY, or SignMode.INHIBITORY. If
+ SignMode.MIXED, the sign of the weight is
+ included in the weight bits and the fixed point weight used for
+ inference is scaled by 2.
+ Unnecessary for floating point implementations.
+
+ In the fixed point implementation, weights are scaled according to
+ the following equations:
+ w_scale = 8 - num_weight_bits + weight_exp + isMixed()
+ weights = weights * (2 ** w_scale)
+
+ num_message_bits : int, optional
+ Determines whether the Sparse Process deals with the incoming
+ spikes as binary spikes (num_message_bits = 0) or as graded
+ spikes (num_message_bits > 0). Default is 0.
+ """
+ if max_delay == 0:
+ max_delay = int(np.max(delays))
+
+ super().__init__(weights=weights,
+ num_message_bits=num_message_bits,
+ name=name,
+ log_config=log_config,
+ max_delay=max_delay,
+ **kwargs)
+
+ self._validate_delays(weights, delays)
+ shape = weights.shape
+
+ # Variables
+ self.delays = Var(shape=shape, init=delays)
+ self.a_buff = Var(shape=(shape[0], max_delay + 1), init=0)
+
+ @staticmethod
+ def _validate_delays(weights: spmatrix, delays: spmatrix) -> None:
+ if np.min(delays) < 0:
+ raise ValueError("DelaySparse Process 'delays' expects only "
+ f"positive values, got {delays}.")
+ if not isinstance(delays, int):
+ if weights.shape != delays.shape:
+ raise ValueError("DelaySparse Process 'delays' expects same "
+ f"shape as the weight matrix or int, got "
+ f"{delays}.")
+ if delays.dtype != int:
+ raise ValueError("DelaySparse Process 'delays' expects integer "
+ f"value(s), got {delays}.")
diff --git a/src/lava/proc/spiker/models.py b/src/lava/proc/spiker/models.py
index 17352767f..af5b7d5d9 100644
--- a/src/lava/proc/spiker/models.py
+++ b/src/lava/proc/spiker/models.py
@@ -5,7 +5,7 @@
import numpy as np
from lava.magma.core.decorator import implements, requires
from lava.magma.core.model.py.model import PyLoihiProcessModel
-from lava.magma.core.model.py.ports import PyInPort, PyOutPort
+from lava.magma.core.model.py.ports import PyOutPort
from lava.magma.core.model.py.type import LavaPyType
from lava.magma.core.resources import CPU
from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
diff --git a/src/lava/utils/dataloader/mnist.py b/src/lava/utils/dataloader/mnist.py
index c7b9e4eaa..724b25a34 100644
--- a/src/lava/utils/dataloader/mnist.py
+++ b/src/lava/utils/dataloader/mnist.py
@@ -56,7 +56,8 @@ def download_mnist(path=os.path.join(os.path.dirname(__file__), 'temp')):
f.write(res.read())
break
else:
- raise "Url does not start with http"
+ raise ValueError(f"Specified URL ({url}) does not "
+ "start with 'http'.")
except urllib.error.URLError as exception:
err = exception
continue
diff --git a/src/lava/utils/sparse.py b/src/lava/utils/sparse.py
new file mode 100644
index 000000000..8abb8ab59
--- /dev/null
+++ b/src/lava/utils/sparse.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2023 Intel Corporation
+# SPDX-License-Identifier: BSD-3-Clause
+# See: https://spdx.org/licenses/
+
+import typing as ty
+
+from scipy.sparse import csr_matrix, find as scipy_find
+
+
+def find(mat: csr_matrix,
+ explicit_zeros: bool = False) -> ty.Tuple:
+ """Behaves like scipy.sparse.find but also returns explict zeros.
+
+ Parameters
+ ==========
+ mat: csr_matrix
+ Return col, row and values of this sparse matrix.
+ explicit_zeros: bool
+ Include explicit zeros
+ """
+ if not explicit_zeros:
+ return scipy_find(mat)
+
+ idx = mat.data == 0
+
+ mat.data[idx] = 1
+ dst, src, _ = scipy_find(mat)
+ mat.data[idx] = 0
+
+ vals = mat[dst, src].A1 # A1 returns values in flattened array
+
+ return dst, src, vals
diff --git a/src/lava/utils/weightutils.py b/src/lava/utils/weightutils.py
index 587bf9282..0230da93e 100644
--- a/src/lava/utils/weightutils.py
+++ b/src/lava/utils/weightutils.py
@@ -3,6 +3,7 @@
# See: https://spdx.org/licenses/
import numpy as np
+from scipy.sparse import spmatrix
import typing as ty
from enum import Enum, unique
from dataclasses import dataclass
@@ -44,20 +45,20 @@ def determine_sign_mode(weights: np.ndarray) -> SignMode:
@dataclass
class OptimizedWeights:
- weights: np.ndarray
+ weights: ty.Union[np.ndarray, spmatrix]
num_weight_bits: int
weight_exp: int
def optimize_weight_bits(
- weights: np.ndarray,
+ weights: ty.Union[np.ndarray, spmatrix],
sign_mode: SignMode,
loihi2: ty.Optional[bool] = False) -> OptimizedWeights:
"""Optimizes the weight matrix to best fit in Loihi's synapse.
Parameters
----------
- weights : np.ndarray
+ weights : np.ndarray, spmatrix
Standard 8-bit signed weight matrix.
sign_mode : SignMode
Determines whether the weights are purely excitatory, inhibitory,
@@ -75,26 +76,29 @@ def optimize_weight_bits(
weight_exp = _determine_weight_exp(weights, sign_mode)
num_weight_bits = _determine_num_weight_bits(weights, weight_exp, sign_mode)
- weights = np.left_shift(weights.astype(np.int32), int(-weight_exp))
+ if isinstance(weights, np.ndarray):
+ weights = weights.astype(np.int32) << int(-weight_exp)
+ elif isinstance(weights, spmatrix):
+ weights.data = weights.data.astype(np.int32) << int(-weight_exp)
if loihi2:
- weights = weights // (1 << (8 - num_weight_bits))
+ weights = (weights / (1 << (8 - num_weight_bits))).astype(np.int32)
if sign_mode == SignMode.MIXED:
- weights = weights // 2
+ weights = (weights / 2).astype(np.int32)
- optimized_weights = OptimizedWeights(weights=weights.astype(int),
+ optimized_weights = OptimizedWeights(weights=weights,
num_weight_bits=num_weight_bits,
weight_exp=weight_exp)
return optimized_weights
-def _validate_weights(weights: np.ndarray,
+def _validate_weights(weights: ty.Union[np.ndarray, spmatrix],
sign_mode: SignMode) -> None:
"""Validate the weight values against the given sign mode.
Parameters
----------
- weights : numpy.ndarray
+ weights : numpy.ndarray, spmatrix
Weight matrix
sign_mode : SignMode
Sign mode specified for the weight matrix
@@ -107,11 +111,11 @@ def _validate_weights(weights: np.ndarray,
min_weight += inhibitory_flag
max_weight = (2 ** 8 - 1) * (mixed_flag + excitatory_flag)
- if np.any(weights > max_weight) or np.any(weights < min_weight):
+ if weights.max() > max_weight or weights.min() < min_weight:
raise ValueError(f"weights have to be between {min_weight} and "
f"{max_weight} for {sign_mode=}. Got "
- f"weights between {np.min(weights)} and "
- f"{np.max(weights)}.")
+ f"weights between {weights.min()} and "
+ f"{weights.max()}.")
def _determine_weight_exp(weights: np.ndarray,
@@ -197,16 +201,17 @@ def _determine_num_weight_bits(weights: np.ndarray,
return num_weight_bits
-def truncate_weights(weights: np.ndarray,
+def truncate_weights(weights: ty.Union[np.ndarray, spmatrix],
sign_mode: SignMode,
num_weight_bits: int,
- max_num_weight_bits: ty.Optional[int] = 8) -> np.ndarray:
+ max_num_weight_bits: ty.Optional[int] = 8
+ ) -> ty.Union[np.ndarray, spmatrix]:
"""Truncate the least significant bits of the weight matrix given the
sign mode and number of weight bits.
Parameters
----------
- weights : numpy.ndarray
+ weights : numpy.ndarray, spmatrix
Weight matrix that is to be truncated.
sign_mode : SignMode
Sign mode to use for truncation. See SignMode class for the
@@ -222,7 +227,7 @@ def truncate_weights(weights: np.ndarray,
numpy.ndarray
Truncated weight matrix.
"""
- weights = np.copy(weights).astype(np.int32)
+ weights = weights.copy().astype(np.int32)
if sign_mode == SignMode.INHIBITORY:
weights = -weights
@@ -230,25 +235,27 @@ def truncate_weights(weights: np.ndarray,
mixed_flag = int(sign_mode == SignMode.MIXED)
num_truncate_bits = max_num_weight_bits - num_weight_bits + mixed_flag
- truncated_weights = np.left_shift(
- np.right_shift(weights, num_truncate_bits),
- num_truncate_bits).astype(np.int32)
+ if isinstance(weights, np.ndarray):
+ weights = (weights >> num_truncate_bits) << num_truncate_bits
+ elif isinstance(weights, spmatrix):
+ weights.data = (weights.data >> num_truncate_bits) << num_truncate_bits
+ weights.eliminate_zeros()
if sign_mode == SignMode.INHIBITORY:
- truncated_weights = -truncated_weights
+ weights = -weights
- return truncated_weights
+ return weights
-def clip_weights(weights: np.ndarray,
+def clip_weights(weights: ty.Union[np.ndarray, spmatrix],
sign_mode: SignMode,
- num_bits: int) -> np.ndarray:
+ num_bits: int) -> ty.Union[np.ndarray, spmatrix]:
"""Truncate the least significant bits of the weight matrix given the
sign mode and number of weight bits.
Parameters
----------
- weights : numpy.ndarray
+ weights : numpy.ndarray, spmatrix
Weight matrix that is to be truncated.
sign_mode : SignMode
Sign mode to use for truncation.
@@ -260,7 +267,7 @@ def clip_weights(weights: np.ndarray,
numpy.ndarray
Truncated weight matrix.
"""
- weights = np.copy(weights).astype(np.int32)
+ weights = weights.copy().astype(np.int32)
mixed_flag = int(sign_mode == SignMode.MIXED)
inhibitory_flag = int(sign_mode == SignMode.INHIBITORY)
@@ -271,9 +278,13 @@ def clip_weights(weights: np.ndarray,
min_wgt = (-2 ** num_bits) * mixed_flag
max_wgt = 2 ** num_bits - 1
- clipped_weights = np.clip(weights, min_wgt, max_wgt)
+ if isinstance(weights, np.ndarray):
+ weights = np.clip(weights, min_wgt, max_wgt)
+ elif isinstance(weights, spmatrix):
+ weights[weights > max_wgt] = max_wgt
+ weights[weights < min_wgt] = min_wgt
if inhibitory_flag:
- clipped_weights = -clipped_weights
+ weights = -weights
- return clipped_weights
+ return weights
diff --git a/tests/lava/magma/compiler/subcompilers/py/test_pyproc_compiler.py b/tests/lava/magma/compiler/subcompilers/py/test_pyproc_compiler.py
index 18b968c9c..e0f9c7c03 100644
--- a/tests/lava/magma/compiler/subcompilers/py/test_pyproc_compiler.py
+++ b/tests/lava/magma/compiler/subcompilers/py/test_pyproc_compiler.py
@@ -54,7 +54,6 @@ def __init__(self, **kwargs):
class MockRuntimeService:
__name__ = "MockRuntimeService"
- pass
# Define minimal Protocol to be implemented.
@@ -124,7 +123,7 @@ def test_compile_py_proc_models(self):
# There should be three PyProcessBuilders...
self.assertEqual(len(builders), 3)
- for proc, builder in builders.items():
+ for builder in builders.values():
self.assertIsInstance(builder, PyProcessBuilder)
# ... one for each Process.
b1 = ty.cast(PyProcessBuilder, builders[p1])
diff --git a/tests/lava/magma/compiler/subcompilers/test_channel_builders_factory.py b/tests/lava/magma/compiler/subcompilers/test_channel_builders_factory.py
index 5029096c6..5781ff14f 100644
--- a/tests/lava/magma/compiler/subcompilers/test_channel_builders_factory.py
+++ b/tests/lava/magma/compiler/subcompilers/test_channel_builders_factory.py
@@ -2,13 +2,11 @@
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
-from enum import Enum
import logging
import typing as ty
import unittest
from unittest.mock import Mock
-import numpy as np
from lava.magma.compiler.builders.channel_builder import ChannelBuilderMp
from lava.magma.compiler.channel_map import ChannelMap, Payload, PortPair
from lava.magma.runtime.message_infrastructure.interfaces import ChannelType
@@ -16,9 +14,9 @@
from lava.magma.compiler.subcompilers.channel_builders_factory import \
ChannelBuildersFactory
from lava.magma.compiler.utils import LoihiPortInitializer, PortInitializer
-from lava.magma.compiler.var_model import LoihiAddress, LoihiVarModel
from lava.magma.core.decorator import implements, requires
from lava.magma.core.model.model import AbstractProcessModel
+from lava.magma.core.model.interfaces import AbstractPortImplementation
from lava.magma.core.model.py.model import AbstractPyProcessModel
from lava.magma.core.model.py.ports import (PyInPort, PyOutPort, PyRefPort,
PyVarPort,
@@ -30,7 +28,7 @@
from lava.magma.core.process.ports.reduce_ops import ReduceSum
from lava.magma.core.process.process import AbstractProcess
from lava.magma.core.process.variable import Var
-from lava.magma.core.resources import CPU, LMT, NeuroCore
+from lava.magma.core.resources import CPU
from lava.magma.core.run_configs import RunConfig
from lava.magma.core.sync.protocol import AbstractSyncProtocol
@@ -67,7 +65,6 @@ def __init__(self, **kwargs):
class MockRuntimeService:
__name__ = "MockRuntimeService"
- pass
# Define minimal Protocol to be implemented
@@ -153,7 +150,7 @@ def __init__(
def select(self, proc, proc_models):
py_proc_model = None
sub_proc_model = None
- c_proc_model = None
+
# Find PyProcModel or SubProcModel
for pm in proc_models:
if issubclass(pm, AbstractSubProcessModel):
@@ -161,7 +158,6 @@ def select(self, proc, proc_models):
if issubclass(pm, AbstractPyProcessModel):
py_proc_model = pm
# Make selection
-
if self.select_sub_proc_model and sub_proc_model:
return sub_proc_model
if py_proc_model and not self.select_lmt:
@@ -357,9 +353,6 @@ def test_create_channel_builders(self):
channel_builders = self.factory.from_channel_map(channel_map, self.cfg)
# This should result in 5 channel builders (one for each arrow above)
- from lava.magma.compiler.builders.channel_builder import \
- ChannelBuilderMp
-
self.assertEqual(len(channel_builders), 5)
for cb in channel_builders:
self.assertIsInstance(cb, ChannelBuilderMp)
diff --git a/tests/lava/magma/compiler/test_channel_map.py b/tests/lava/magma/compiler/test_channel_map.py
index abce36844..43b2262c5 100644
--- a/tests/lava/magma/compiler/test_channel_map.py
+++ b/tests/lava/magma/compiler/test_channel_map.py
@@ -33,7 +33,6 @@ def __init__(self, **kwargs):
class MockRuntimeService:
__name__ = "MockRuntimeService"
- pass
# Define minimal Protocol to be implemented
diff --git a/tests/lava/magma/compiler/test_compiler.py b/tests/lava/magma/compiler/test_compiler.py
index 8d750218b..1046253c3 100644
--- a/tests/lava/magma/compiler/test_compiler.py
+++ b/tests/lava/magma/compiler/test_compiler.py
@@ -66,7 +66,6 @@ def __init__(self, **kwargs):
class MockRuntimeService:
__name__ = "MockRuntimeService"
- pass
# Define minimal Protocol to be implemented
@@ -436,9 +435,6 @@ def test_extract_proc_builders(self) -> None:
# Create some mock Processes.
proc1 = Mock(spec_set=AbstractProcess)
proc2 = Mock(spec_set=AbstractProcess)
- proc3 = Mock(spec_set=AbstractProcess)
- proc4 = Mock(spec_set=AbstractProcess)
- proc5 = Mock(spec_set=AbstractProcess)
# Create some Builders.
py_builder1 = PyProcessBuilder(AbstractPyProcessModel, 0)
diff --git a/tests/lava/magma/compiler/test_node.py b/tests/lava/magma/compiler/test_node.py
index ea2bcfece..c23b84a07 100644
--- a/tests/lava/magma/compiler/test_node.py
+++ b/tests/lava/magma/compiler/test_node.py
@@ -12,8 +12,6 @@
class MockProcess(AbstractProcess):
"""A mock process"""
- pass
-
class TestNode(unittest.TestCase):
def test_node_creation(self):
diff --git a/tests/lava/magma/core/learning/test_learning_rule.py b/tests/lava/magma/core/learning/test_learning_rule.py
index 7b1384f00..4c2956553 100644
--- a/tests/lava/magma/core/learning/test_learning_rule.py
+++ b/tests/lava/magma/core/learning/test_learning_rule.py
@@ -7,30 +7,15 @@
from lava.magma.core.learning.learning_rule import (
LoihiLearningRule,
- Loihi2FLearningRule,
- Loihi3FLearningRule,
+ Loihi2FLearningRule
)
from lava.magma.core.learning.product_series import ProductSeries
from lava.magma.core.run_conditions import RunSteps
from lava.magma.core.run_configs import Loihi2SimCfg
-from lava.proc.lif.process import LIF, LearningLIF
+from lava.proc.lif.process import LIF
from lava.proc.dense.process import LearningDense, Dense
from lava.proc.monitor.process import Monitor
from lava.proc.io.source import RingBuffer as SpikeIn
-from lava.magma.core.model.py.neuron import (
- LearningNeuronModelFloat,
- LearningNeuronModelFixed,
-)
-from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
-from lava.magma.core.model.py.ports import PyInPort, PyOutPort
-from lava.magma.core.model.py.type import LavaPyType
-from lava.magma.core.resources import CPU
-from lava.magma.core.decorator import implements, requires, tag
-from lava.proc.lif.models import (
- AbstractPyLifModelFloat,
- AbstractPyLifModelFixed,
-)
-from lava.proc.io.source import RingBuffer as SpikeIn
def create_network(
diff --git a/tests/lava/magma/core/learning/test_random.py b/tests/lava/magma/core/learning/test_random.py
index ecbc18cdd..21e6ad52b 100644
--- a/tests/lava/magma/core/learning/test_random.py
+++ b/tests/lava/magma/core/learning/test_random.py
@@ -3,7 +3,6 @@
# See: https://spdx.org/licenses/
import unittest
-import numpy as np
from lava.magma.core.learning.random import TraceRandom, ConnVarRandom
diff --git a/tests/lava/magma/core/model/py/test_model.py b/tests/lava/magma/core/model/py/test_model.py
index 34bab40d8..2af801fe6 100644
--- a/tests/lava/magma/core/model/py/test_model.py
+++ b/tests/lava/magma/core/model/py/test_model.py
@@ -13,7 +13,6 @@
PyLoihiProcessModel, PyLoihiModelToPyAsyncModel
)
-from lava.proc import io
from lava.proc.lif.process import LIF
from lava.proc.sdn.process import SigmaDelta
from lava.proc.dense.process import Dense
@@ -127,10 +126,10 @@ def test_sdn_dense_sdn(self):
'state_exp': 6}
dense_params = {'weights': weights, 'num_message_bits': 16}
- input = SigmaDelta(**input_params)
+ input_ = SigmaDelta(**input_params)
output = SigmaDelta(**output_params)
dense = Dense(**dense_params)
- input.s_out.connect(dense.s_in)
+ input_.s_out.connect(dense.s_in)
dense.a_out.connect(output.a_in)
run_cnd = RunSteps(num_steps=2)
@@ -141,12 +140,12 @@ def test_sdn_dense_sdn(self):
output.stop()
# Run the same network in async mode.
- # Currently we don't allow the same process to run twice
+ # Currently, we don't allow the same process to run twice
# Copy the model used for pyproc model
- input = SigmaDelta(**input_params)
+ input_ = SigmaDelta(**input_params)
output = SigmaDelta(**output_params)
dense = Dense(**dense_params)
- input.s_out.connect(dense.s_in)
+ input_.s_out.connect(dense.s_in)
dense.a_out.connect(output.a_in)
output.run(condition=run_cnd,
diff --git a/tests/lava/magma/core/model/test_decorators.py b/tests/lava/magma/core/model/test_decorators.py
index 1c92e1665..a40cd74df 100644
--- a/tests/lava/magma/core/model/test_decorators.py
+++ b/tests/lava/magma/core/model/test_decorators.py
@@ -48,21 +48,21 @@ class TestProtocol(AbstractSyncProtocol):
# We must pass a class, not an instance or anything else
with self.assertRaises(TypeError):
@implements(proc=TestProc(), protocol=TestProtocol) # type: ignore
- class TestModel(AbstractProcessModel): # type: ignore
+ class TestModel(AbstractProcessModel): # pylint: disable=W0612
def run(self):
pass
# Same for 'protocol'
with self.assertRaises(TypeError):
@implements(proc=TestProc, protocol=TestProtocol()) # type: ignore
- class TestModel2(AbstractProcessModel):
+ class TestModel2(AbstractProcessModel): # pylint: disable=W0612
def run(self):
pass
# And we can only decorate a subclass of 'AbstractProcessModel'
with self.assertRaises(AssertionError):
@implements(proc=TestProc, protocol=TestProtocol)
- class TestProcess2(AbstractProcess):
+ class TestProcess2(AbstractProcess): # pylint: disable=W0612
pass
def test_implements_subclassing(self):
@@ -125,7 +125,7 @@ def run(self):
# attributes must fail
with self.assertRaises(AssertionError):
@implements(protocol=TestProtocol2)
- class SubTestModel(TestModel):
+ class SubTestModel(TestModel): # pylint: disable=W0612
pass
def test_requires(self):
@@ -190,7 +190,7 @@ def test_requires_failing(self):
# We must decorate a ProcessModel and nothing else:
with self.assertRaises(AssertionError):
@requires(CPU)
- class Something(AbstractProcess):
+ class Something(AbstractProcess): # pylint: disable=W0612
pass
# We must decorate a ProcessModel with an 'AbstractResource' class
@@ -198,7 +198,7 @@ class Something(AbstractProcess):
with self.assertRaises(TypeError):
@requires(CPU()) # type: ignore
- class TestModel(AbstractProcessModel):
+ class TestModel(AbstractProcessModel): # pylint: disable=W0612
def run(self):
pass
@@ -241,20 +241,20 @@ def test_tags_failing(self):
# Only decorating ProcessModels is allowed
with self.assertRaises(AssertionError):
@tag('some-tag')
- class SomeClass(AbstractProcess):
+ class SomeClass(AbstractProcess): # pylint: disable=W0612
pass
# Tags should be just comma-separated keywords
with self.assertRaises(AssertionError):
@tag('keyword1', ['keyword2', 'keyword3'])
- class TestModel2(AbstractProcessModel):
+ class TestModel2(AbstractProcessModel): # pylint: disable=W0612
def run(self):
pass
# Tags should be just comma-separated keywords
with self.assertRaises(AssertionError):
@tag('tag1', [['tag2'], 'tag4'])
- class SomeOtherClass(AbstractProcess):
+ class SomeOtherClass(AbstractProcess): # pylint: disable=W0612
pass
diff --git a/tests/lava/magma/core/process/ports/test_ports.py b/tests/lava/magma/core/process/ports/test_ports.py
index 33f155814..594dcaab2 100644
--- a/tests/lava/magma/core/process/ports/test_ports.py
+++ b/tests/lava/magma/core/process/ports/test_ports.py
@@ -290,7 +290,8 @@ class VarProcess(AbstractProcess):
def test_connect_RefPort_to_Var_process_conflict(self):
"""Checks connecting RefPort implicitly to Var, with registered
- processes and conflicting names. -> AssertionError"""
+ processes and conflicting names. -> adding _k with k=1,2,3... to
+ the name."""
# Create a mock parent process
class VarProcess(AbstractProcess):
@@ -307,9 +308,21 @@ class VarProcess(AbstractProcess):
v.name = "existing_attr"
# ... and connect it directly via connect_var(..)
- # The naming conflict should raise an AssertionError
- with self.assertRaises(AssertionError):
- rp.connect_var(v)
+ rp.connect_var(v)
+
+ # This has the same effect as connecting a RefPort explicitly via a
+ # VarPort to a Var...
+ self.assertEqual(rp.get_dst_vars(), [v])
+ # ... but still creates a VarPort implicitly
+ vp = rp.get_dst_ports()[0]
+ self.assertIsInstance(vp, VarPort)
+ # ... which wraps the original Var
+ self.assertEqual(vp.var, v)
+
+ # In this case, the VarPort inherits its name and parent process from
+ # the Var it wraps + _implicit_port + _k with k=1,2,3...
+ self.assertEqual(vp.name, "_" + v.name + "_implicit_port" + "_1")
+ self.assertEqual(vp.process, v.process)
@unittest.skip("Currently not supported")
def test_connect_RefPort_to_many_Vars(self):
diff --git a/tests/lava/magma/core/process/test_lif_dense_lif.py b/tests/lava/magma/core/process/test_lif_dense_lif.py
index 591214967..798c47fb9 100644
--- a/tests/lava/magma/core/process/test_lif_dense_lif.py
+++ b/tests/lava/magma/core/process/test_lif_dense_lif.py
@@ -29,11 +29,11 @@ def select(self, process, proc_models):
class TestLifDenseLif(unittest.TestCase):
def test_lif_dense_lif(self):
- self.lif1 = LIF(shape=(1,))
- self.dense = Dense(weights=np.eye(1))
- self.lif2 = LIF(shape=(1,))
- self.lif1.out_ports.s_out.connect(self.dense.in_ports.s_in)
- self.dense.out_ports.a_out.connect(self.lif2.in_ports.a_in)
- self.lif1.run(condition=RunSteps(num_steps=10),
- run_cfg=SimpleRunConfig(sync_domains=[]))
- self.lif1.stop()
+ lif1 = LIF(shape=(1,))
+ dense = Dense(weights=np.eye(1))
+ lif2 = LIF(shape=(1,))
+ lif1.out_ports.s_out.connect(dense.in_ports.s_in)
+ dense.out_ports.a_out.connect(lif2.in_ports.a_in)
+ lif1.run(condition=RunSteps(num_steps=10),
+ run_cfg=SimpleRunConfig(sync_domains=[]))
+ lif1.stop()
diff --git a/tests/lava/magma/core/process/test_process.py b/tests/lava/magma/core/process/test_process.py
index 8a33ad8fb..e2938874b 100644
--- a/tests/lava/magma/core/process/test_process.py
+++ b/tests/lava/magma/core/process/test_process.py
@@ -6,6 +6,9 @@
import unittest
from unittest.mock import Mock, seal
import typing as ty
+from lava.magma.compiler.executable import Executable
+from lava.magma.core.decorator import implements, requires
+from lava.magma.core.model.py.model import AbstractPyProcessModel
from lava.magma.core.process.ports.ports import (
InPort,
@@ -20,7 +23,11 @@
)
from lava.magma.core.model.model import AbstractProcessModel
from lava.magma.core.process.variable import Var
+from lava.magma.core.resources import CPU
from lava.magma.core.run_conditions import RunSteps
+from lava.magma.core.run_configs import RunConfig
+from lava.magma.core.sync.protocol import AbstractSyncProtocol
+from lava.magma.runtime.runtime import Runtime
class MinimalProcess(AbstractProcess):
@@ -30,6 +37,34 @@ def __init__(self, name: ty.Optional[str] = None):
super().__init__(name=name)
+class MinimalRuntimeService:
+ __name__ = 'MinimalRuntimeService'
+
+ def __init__(self):
+ pass
+
+
+class MinimalProtocol(AbstractSyncProtocol):
+ @property
+ def runtime_service(self):
+ return {CPU: MinimalRuntimeService()}
+
+
+@implements(proc=MinimalProcess, protocol=MinimalProtocol)
+@requires(CPU)
+class MinimalPyProcessModel(AbstractPyProcessModel):
+ def run(self):
+ raise NotImplementedError('This model doesnt run')
+
+
+class MinimalRunConfig(RunConfig):
+ def __init__(self):
+ super().__init__(custom_sync_domains=None, loglevel=logging.WARNING)
+
+ def select(self, proc, proc_models):
+ return proc_models[0]
+
+
class TestCollection(unittest.TestCase):
def setUp(self):
"""Reset ProcessServer before each test."""
@@ -259,13 +294,33 @@ class TestProcess(unittest.TestCase):
def test_model_property(self) -> None:
"""Tests whether the ProcessModel of a Process can be obtained
through a property method."""
-
p = MinimalProcess()
p._model_class = Mock(spec_set=AbstractProcessModel)
seal(p._model_class)
-
self.assertIsInstance(p.model_class, AbstractProcessModel)
+ def test_compile(self) -> None:
+ """Test whether compile creates an executable which is ready
+ to build the process model for a simple process."""
+ p = MinimalProcess()
+ run_cfg = MinimalRunConfig()
+ e = p.compile(run_cfg)
+ self.assertIsInstance(e, Executable)
+ self.assertEqual(len(e.proc_builders), 1)
+
+ @unittest.skip("This case cannot run becase the MinimalPyProcessModel")
+ def test_create_runtime(self) -> None:
+ """Tests the create_runtime method."""
+ p = MinimalProcess()
+ self.assertIsNone(p.runtime)
+ run_cfg = MinimalRunConfig()
+ p.create_runtime(run_cfg)
+ r = p.runtime
+ self.assertIsInstance(r, Runtime)
+ self.assertTrue(r._is_initialized)
+ self.assertFalse(r._is_started)
+ self.assertFalse(r._is_running)
+
def test_run_without_run_config_raises_error(self) -> None:
"""Tests whether an error is raised when run() is called on
uncompiled Processes without specifying a RunConfig."""
diff --git a/tests/lava/magma/runtime/test_async_protocol.py b/tests/lava/magma/runtime/test_async_protocol.py
index 0cf3152ee..98e02c857 100644
--- a/tests/lava/magma/runtime/test_async_protocol.py
+++ b/tests/lava/magma/runtime/test_async_protocol.py
@@ -68,7 +68,7 @@ def test_async_process_model(self):
Verifies the working of Asynchronous Process
"""
process = AsyncProcess1(shape=(2, 2))
- simple_sync_domain = SyncDomain("simple", AsyncProtocol(), [process])
+ _ = SyncDomain("simple", AsyncProtocol(), [process])
process.run(condition=RunContinuous(), run_cfg=Loihi2SimCfg())
process.stop()
@@ -78,7 +78,7 @@ def test_async_process_model_pause(self):
effect
"""
process = AsyncProcess1(shape=(2, 2))
- simple_sync_domain = SyncDomain("simple", AsyncProtocol(), [process])
+ _ = SyncDomain("simple", AsyncProtocol(), [process])
process.run(condition=RunContinuous(), run_cfg=Loihi2SimCfg())
process.pause()
process.stop()
@@ -89,7 +89,7 @@ def test_async_process_num_steps(self):
implicitly passed as num_steps for the process.
"""
process = AsyncProcess2(shape=(2, 2))
- simple_sync_domain = SyncDomain("simple", AsyncProtocol(), [process])
+ _ = SyncDomain("simple", AsyncProtocol(), [process])
process.run(condition=RunSteps(num_steps=10), run_cfg=Loihi2SimCfg())
process.stop()
@@ -99,7 +99,7 @@ def test_async_process_get(self):
of the variable after run finishes.
"""
process = AsyncProcess2(shape=(2, 2))
- simple_sync_domain = SyncDomain("simple", AsyncProtocol(), [process])
+ _ = SyncDomain("simple", AsyncProtocol(), [process])
process.run(condition=RunSteps(num_steps=10), run_cfg=Loihi2SimCfg())
print(process.u.get())
process.stop()
diff --git a/tests/lava/magma/runtime/test_get_set_non_determinism.py b/tests/lava/magma/runtime/test_get_set_non_determinism.py
index d9c6fc295..b5fce8f56 100644
--- a/tests/lava/magma/runtime/test_get_set_non_determinism.py
+++ b/tests/lava/magma/runtime/test_get_set_non_determinism.py
@@ -42,7 +42,7 @@ class TestNonDeterminismUpdate(unittest.TestCase):
def test_non_determinism_update(self):
nb_runs = 10000
demo_process = DemoProcess(nb_runs=nb_runs)
- for i in range(nb_runs):
+ for _ in range(nb_runs):
demo_process.run(condition=RunSteps(num_steps=1),
run_cfg=Loihi1SimCfg())
diff --git a/tests/lava/magma/runtime/test_loihi_with_async_protocol.py b/tests/lava/magma/runtime/test_loihi_with_async_protocol.py
index 634b0be84..8c6865b18 100644
--- a/tests/lava/magma/runtime/test_loihi_with_async_protocol.py
+++ b/tests/lava/magma/runtime/test_loihi_with_async_protocol.py
@@ -18,11 +18,6 @@
from lava.magma.core.sync.protocols.async_protocol import AsyncProtocol
from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
-"""
-This test checks if Process with Loihi Protocol works properly with
-process with Async Protocol.
-"""
-
class AsyncProcessDest(AbstractProcess):
def __init__(self, **kwargs):
@@ -92,6 +87,10 @@ def run_spk(self):
class TestProcess(unittest.TestCase):
+ """This test checks if Process with Loihi Protocol works properly with
+ process with Async Protocol.
+ """
+
def test_async_with_loihi_protocol(self):
"""
Test is to send the data to AsyncProcessSrc from AsyncProcessSrc via
diff --git a/tests/lava/proc/conv/test_utils.py b/tests/lava/proc/conv/test_utils.py
index 4542973b5..ac1e8b2f5 100644
--- a/tests/lava/proc/conv/test_utils.py
+++ b/tests/lava/proc/conv/test_utils.py
@@ -36,7 +36,7 @@ def test_conv(self) -> None:
kernel_size[0], kernel_size[1],
in_channels // groups]
weights = np.random.randint(256, size=weight_dims) - 128
- input = np.random.random(
+ input_ = np.random.random(
(
# input needs to be a certain size
# to make sure the output dimension is never negative
@@ -45,13 +45,13 @@ def test_conv(self) -> None:
+ [in_channels]
)
- out = utils.conv_scipy(input, weights, kernel_size,
+ out = utils.conv_scipy(input_, weights, kernel_size,
stride, padding, dilation, groups)
if compare: # if torch is available, compare against it.
out_gt = F.conv2d(
torch.unsqueeze( # torch expects a batch dimension NCHW
- torch.FloatTensor(input.transpose([2, 1, 0])),
+ torch.FloatTensor(input_.transpose([2, 1, 0])),
dim=0,
),
torch.FloatTensor(
@@ -70,7 +70,7 @@ def test_conv(self) -> None:
error = np.abs(out - out_gt).mean()
if error >= 1e-3: # small eps to account for float/double calc
# Setting failed! Print out the dimensions for debugging.
- print(f'{input.shape=}')
+ print(f'{input_.shape=}')
print(f'{weights.shape=}')
print(f'{kernel_size=}')
print(f'{stride=}')
diff --git a/tests/lava/proc/dense/test_learning.py b/tests/lava/proc/dense/test_learning.py
index b3d8de32d..77886771e 100644
--- a/tests/lava/proc/dense/test_learning.py
+++ b/tests/lava/proc/dense/test_learning.py
@@ -697,8 +697,9 @@ def test_learning_graded_spike_reg_imp_bit_approx_y0_condition(self):
learning_rule_cnd = "y0"
graded_spike_cfg = GradedSpikeCfg.USE_REGULAR_IMPULSE
- pre_ring_buffer, learning_dense, _ = \
- self.create_network(num_steps, learning_rule_cnd, graded_spike_cfg)
+ pre_ring_buffer, dense, _ = self.create_network(num_steps,
+ learning_rule_cnd,
+ graded_spike_cfg)
# x1 updates with decayed regular impulse, at the end of the epoch
expected_x1_data = [0.0, 0.0, 0.0, 14.0, 14.0]
@@ -714,9 +715,9 @@ def test_learning_graded_spike_reg_imp_bit_approx_y0_condition(self):
pre_ring_buffer.run(condition=self._run_cnd,
run_cfg=self._run_cfg)
- x1_data.append(learning_dense.x1.get()[0])
- x2_data.append(learning_dense.x2.get()[0])
- wgt_data.append(learning_dense.weights.get()[0, 0])
+ x1_data.append(dense.x1.get()[0])
+ x2_data.append(dense.x2.get()[0])
+ wgt_data.append(dense.weights.get()[0, 0])
pre_ring_buffer.stop()
diff --git a/tests/lava/proc/dense/test_models.py b/tests/lava/proc/dense/test_models.py
index ed2baafab..467e3de1c 100644
--- a/tests/lava/proc/dense/test_models.py
+++ b/tests/lava/proc/dense/test_models.py
@@ -568,7 +568,7 @@ def test_matrix_weight_delay_expansion(self):
delays = np.zeros(shape, dtype=int)
delays[2, 2] = 2
max_delay = np.max(delays)
- wgt_dly = AbstractPyDelayDenseModel.get_del_wgts(weights, delays)
+ wgt_dly = AbstractPyDelayDenseModel.get_delay_wgts_mat(weights, delays)
# Expected shape is maximum delay=2 + 1 = 3 times first dimension of
# original shape (3, 4) => (9, 4)
expected_shape = ((max_delay + 1) * 3, 4)
diff --git a/tests/lava/proc/io/test_dataloader.py b/tests/lava/proc/io/test_dataloader.py
index e12514244..6e72fae47 100644
--- a/tests/lava/proc/io/test_dataloader.py
+++ b/tests/lava/proc/io/test_dataloader.py
@@ -50,20 +50,20 @@ def __init__(self, shape: tuple, dtype: np.dtype) -> None:
def __len__(self) -> int:
return 10
- def __getitem__(self, id: int) -> Tuple[np.ndarray, int]:
- data = np.arange(np.prod(self.shape)).reshape(self.shape) + id
+ def __getitem__(self, id_: int) -> Tuple[np.ndarray, int]:
+ data = np.arange(np.prod(self.shape)).reshape(self.shape) + id_
data = data % np.prod(self.shape)
data = data.astype(self.dtype)
- label = id
+ label = id_
return data, label
class SpikeDataset(DummyDataset):
- def __getitem__(self, id: int) -> Tuple[np.ndarray, int]:
- data = np.arange(np.prod(self.shape)).reshape(self.shape[::-1]) + id
+ def __getitem__(self, id_: int) -> Tuple[np.ndarray, int]:
+ data = np.arange(np.prod(self.shape)).reshape(self.shape[::-1]) + id_
data = data.transpose(np.arange(len(self.shape))[::-1]) % 13
data = data >= 10
- label = id
+ label = id_
return data, label
diff --git a/tests/lava/proc/io/test_source_sink.py b/tests/lava/proc/io/test_source_sink.py
index b800601d6..134706572 100644
--- a/tests/lava/proc/io/test_source_sink.py
+++ b/tests/lava/proc/io/test_source_sink.py
@@ -38,11 +38,11 @@ def test_source_sink(self) -> None:
"""Test whatever is being sent form source is received at sink."""
num_steps = 10
shape = (64, 64, 16)
- input = np.random.randint(256, size=shape + (num_steps,))
- input -= 128
+ input_ = np.random.randint(256, size=shape + (num_steps,))
+ input_ -= 128
# input = 0.5 * input
- source = SendProcess(data=input)
+ source = SendProcess(data=input_)
sink = ReceiveProcess(shape=shape, buffer=num_steps)
source.out_ports.s_out.connect(sink.in_ports.a_in)
@@ -53,8 +53,8 @@ def test_source_sink(self) -> None:
sink.stop()
self.assertTrue(
- np.all(output == input),
+ np.all(output == input_),
f'Input and Ouptut do not match.\n'
- f'{output[output!=input]=}\n'
- f'{input[output!=input] =}\n'
+ f'{output[output!=input_]=}\n'
+ f'{input_[output!=input_] =}\n'
)
diff --git a/tests/lava/proc/lif/test_models.py b/tests/lava/proc/lif/test_models.py
index e5d03126a..d9ec66528 100644
--- a/tests/lava/proc/lif/test_models.py
+++ b/tests/lava/proc/lif/test_models.py
@@ -1,9 +1,10 @@
-# Copyright (C) 2021-22 Intel Corporation
+# Copyright (C) 2021-23 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
# See: https://spdx.org/licenses/
import unittest
import numpy as np
+from numpy.testing import assert_almost_equal
from lava.magma.core.decorator import implements, requires, tag
from lava.magma.core.model.py.model import PyLoihiProcessModel
@@ -13,10 +14,10 @@
from lava.magma.core.process.process import AbstractProcess
from lava.magma.core.process.variable import Var
from lava.magma.core.resources import CPU
-from lava.magma.core.run_configs import Loihi1SimCfg, Loihi2SimCfg, RunConfig
+from lava.magma.core.run_configs import Loihi2SimCfg, RunConfig
from lava.magma.core.run_conditions import RunSteps
from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
-from lava.proc.lif.process import LIF, LIFReset, TernaryLIF
+from lava.proc.lif.process import LIF, LIFReset, TernaryLIF, LIFRefractory
from lava.proc import io
@@ -244,7 +245,7 @@ def test_float_pm_impulse_dv(self):
rcfg = LifRunConfig(select_tag='floating_pt')
lif_v = []
# Run 1 timestep at a time and collect state variable u
- for j in range(num_steps):
+ for _ in range(num_steps):
lif.run(condition=rcnd, run_cfg=rcfg)
lif_v.append(lif.v.get()[0])
lif.stop()
@@ -393,7 +394,6 @@ def test_bitacc_pm_scaling_of_bias(self):
"""
Tests fixed point LIF ProcessModel's scaling of threshold.
"""
- num_steps = 1
bias_mant = 2 ** 12 - 1
bias_exp = 5
# Set up high threshold and high bias current to check for potential
@@ -825,3 +825,37 @@ def test_fixed_model(self):
self.assertTrue(np.array_equal(u[:, reset_offset - 1:], u_gt_post))
self.assertTrue(np.array_equal(v[:, :reset_offset - 1], v_gt_pre))
self.assertTrue(np.array_equal(v[:, reset_offset - 1:], v_gt_post))
+
+
+class TestLIFRefractory(unittest.TestCase):
+ """Test LIF Refractory process model"""
+
+ def test_float_model(self):
+ """Test float model"""
+ num_neurons = 2
+ num_steps = 8
+ refractory_period = 1
+
+ # Two neurons with different biases
+ lif_refractory = LIFRefractory(shape=(num_neurons,),
+ u=np.arange(num_neurons),
+ bias_mant=np.arange(num_neurons) + 1,
+ bias_exp=np.ones(
+ (num_neurons,), dtype=float),
+ vth=4.,
+ refractory_period=refractory_period)
+
+ v_logger = io.sink.Read(buffer=num_steps)
+ v_logger.connect_var(lif_refractory.v)
+
+ lif_refractory.run(condition=RunSteps(num_steps),
+ run_cfg=Loihi2SimCfg(select_tag="floating_pt"))
+
+ v = v_logger.data.get()
+ lif_refractory.stop()
+
+ # Voltage is expected to remain at reset level for two time steps
+ v_expected = np.array([[1, 2, 3, 4, 0, 0, 1, 2],
+ [2, 0, 0, 2, 0, 0, 2, 0]], dtype=float)
+
+ assert_almost_equal(v, v_expected)
diff --git a/tests/lava/proc/rf/test_models.py b/tests/lava/proc/rf/test_models.py
index 50906f419..a89a66a67 100644
--- a/tests/lava/proc/rf/test_models.py
+++ b/tests/lava/proc/rf/test_models.py
@@ -67,15 +67,15 @@ def run_test(
self,
period: float,
alpha: float,
- input: np.ndarray,
+ input_: np.ndarray,
state_exp: int = 0,
decay_bits: int = 0,
vth: float = 1,
tag: str = 'floating_pt',
) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
- input = np.int32(input.reshape(1, -1))
- num_steps = input.size
- source = io.source.RingBuffer(data=input)
+ input_ = np.int32(input_.reshape(1, -1))
+ num_steps = input_.size
+ source = io.source.RingBuffer(data=input_)
rf = RF(shape=(1,),
period=period,
alpha=alpha,
@@ -102,7 +102,7 @@ def run_test(
imag = imag_monitor.get_data()[rf.name]["imag"]
rf.stop()
- return input, real, imag, s_out
+ return input_, real, imag, s_out
def test_float_no_decay(self):
"""Verify that a neuron with no voltage decay spikes
@@ -112,9 +112,9 @@ def test_float_no_decay(self):
alpha = 0
num_steps = 100
- input = np.zeros(num_steps)
- input[0] = 1.1 # spike at first timestep
- _, _, _, s_out = self.run_test(period, alpha, input)
+ input_ = np.zeros(num_steps)
+ input_[0] = 1.1 # spike at first timestep
+ _, _, _, s_out = self.run_test(period, alpha, input_)
# observe differences in spike times
spike_idx = np.argwhere(s_out[0, :])
@@ -134,9 +134,9 @@ def test_float_decay(self):
vth = 1.1
num_steps = 100
- input = np.zeros(num_steps)
- input[0] = 1 # spike at first timestep
- _, real, _, _ = self.run_test(period, alpha, input, vth=vth)
+ input_ = np.zeros(num_steps)
+ input_[0] = 1 # spike at first timestep
+ _, real, _, _ = self.run_test(period, alpha, input_, vth=vth)
ideal_real = np.round((1 - alpha)**np.arange(num_steps), 6)
round_real = np.round(real.flatten(), 6)
@@ -155,10 +155,10 @@ def test_fixed_pm_no_decay(self):
period = 10
num_steps = 100
- input = np.zeros(num_steps)
- input[0] = 1 # spike at first timestep
+ input_ = np.zeros(num_steps)
+ input_[0] = 1 # spike at first timestep
- _, _, _, s_out = self.run_test(period, alpha, input, vth=vth,
+ _, _, _, s_out = self.run_test(period, alpha, input_, vth=vth,
state_exp=state_exp,
decay_bits=decay_bits,
tag="fixed_pt")
@@ -173,7 +173,7 @@ def test_fixed_pm_no_decay(self):
# Run Test RF Dynamics
real, imag = rf_dynamics(0, 0, sin_decay, cos_decay,
- input * (1 << state_exp),
+ input_ * (1 << state_exp),
np.zeros(num_steps),
decay_bits)
@@ -197,10 +197,10 @@ def test_fixed_pm_decay1(self):
period = 10
num_steps = 100
- input = np.zeros(num_steps)
- input[0] = 2 # spike at first timestep
+ input_ = np.zeros(num_steps)
+ input_[0] = 2 # spike at first timestep
- _, _, _, s_out = self.run_test(period, alpha, input, vth=vth,
+ _, _, _, s_out = self.run_test(period, alpha, input_, vth=vth,
state_exp=state_exp,
decay_bits=decay_bits,
tag="fixed_pt")
@@ -215,7 +215,7 @@ def test_fixed_pm_decay1(self):
# Run Test RF Dynamics
real, imag = rf_dynamics(0, 0, sin_decay, cos_decay,
- input * (1 << state_exp),
+ input_ * (1 << state_exp),
np.zeros(num_steps),
decay_bits)
@@ -248,12 +248,12 @@ def test_fixed_pm_decay2(self):
cos_decay = int(cos_decay * (1 << decay_bits))
num_steps = 100
- input = np.zeros(num_steps)
- input[0] = 1 # spike at first timestep
+ input_ = np.zeros(num_steps)
+ input_[0] = 1 # spike at first timestep
decay_bits = 12
state_exp = 6
- _, real, _, _ = self.run_test(period, alpha, input, vth=vth,
+ _, real, _, _ = self.run_test(period, alpha, input_, vth=vth,
state_exp=state_exp,
decay_bits=decay_bits,
tag="fixed_pt")
diff --git a/tests/lava/proc/rf_iz/test_models.py b/tests/lava/proc/rf_iz/test_models.py
index c1c8a56e4..12e5621db 100644
--- a/tests/lava/proc/rf_iz/test_models.py
+++ b/tests/lava/proc/rf_iz/test_models.py
@@ -20,15 +20,15 @@ def run_test(
self,
period: float,
alpha: float,
- input: np.ndarray,
+ input_: np.ndarray,
state_exp: int = 0,
decay_bits: int = 0,
vth: float = 1,
tag: str = 'floating_pt',
) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
- input = input.reshape(1, -1)
- num_steps = input.size
- source = io.source.RingBuffer(data=input)
+ input_ = input_.reshape(1, -1)
+ num_steps = input_.size
+ source = io.source.RingBuffer(data=input_)
rf = RF_IZ(shape=(1,),
period=period,
alpha=alpha,
@@ -55,7 +55,7 @@ def run_test(
imag = imag_monitor.get_data()[rf.name]["imag"]
rf.stop()
- return input, real, imag, s_out
+ return input_, real, imag, s_out
def test_float_reset(self):
"""Ensure that spikes events are followed by proper rf_iz reset
@@ -65,9 +65,9 @@ def test_float_reset(self):
eps = 1e-5
num_steps = 100
- input = np.zeros(num_steps)
- input[[0, 10, 20]] = 1 # Will ensure 3 spikes
- _, real, imag, s_out = self.run_test(period, alpha, input)
+ input_ = np.zeros(num_steps)
+ input_[[0, 10, 20]] = 1 # Will ensure 3 spikes
+ _, real, imag, s_out = self.run_test(period, alpha, input_)
s_out = s_out.flatten() == 1 # change to bool
self.assertGreaterEqual(s_out.sum(), 1) # ensure network is spiking
self.assertListEqual(real.flatten()[s_out].tolist(),
@@ -84,9 +84,9 @@ def test_fixed_pm_reset(self):
eps = 1 # in fixed point 1 is the smallest value we can have
state_exp = 6
num_steps = 100
- input = np.zeros(num_steps)
- input[[0, 10, 20]] = 1 # Will ensure 3 spikes
- _, real, imag, s_out = self.run_test(period, alpha, input,
+ input_ = np.zeros(num_steps)
+ input_[[0, 10, 20]] = 1 # Will ensure 3 spikes
+ _, real, imag, s_out = self.run_test(period, alpha, input_,
tag="fixed_pt",
state_exp=state_exp,
decay_bits=12)
diff --git a/tests/lava/proc/sdn/test_models.py b/tests/lava/proc/sdn/test_models.py
index 3c59f839b..be86f1ea1 100644
--- a/tests/lava/proc/sdn/test_models.py
+++ b/tests/lava/proc/sdn/test_models.py
@@ -24,13 +24,13 @@ def run_test(
num_steps: int,
tag: str = 'fixed_pt'
) -> Tuple[np.ndarray, np.ndarray]:
- input = np.sin(0.1 * np.arange(num_steps).reshape(1, -1))
+ input_ = np.sin(0.1 * np.arange(num_steps).reshape(1, -1))
if tag == 'fixed_pt':
- input *= (1 << 12)
- input = input.astype(int)
- input[:, 1:] -= input[:, :-1]
+ input_ *= (1 << 12)
+ input_ = input_.astype(int)
+ input_[:, 1:] -= input_[:, :-1]
- source = io.source.RingBuffer(data=input)
+ source = io.source.RingBuffer(data=input_)
sigma = Sigma(shape=(1,))
sink = io.sink.RingBuffer(shape=sigma.shape, buffer=num_steps)
@@ -44,18 +44,18 @@ def run_test(
output = sink.data.get()
sigma.stop()
- return input, output
+ return input_, output
def test_sigma_decoding_fixed(self) -> None:
"""Test sigma decoding with cumulative sum."""
num_steps = 100
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
tag='fixed_pt'
)
- error = np.abs(np.cumsum(input, axis=1) - output).max()
+ error = np.abs(np.cumsum(input_, axis=1) - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -65,12 +65,12 @@ def test_sigma_decoding_float(self) -> None:
"""Test sigma decoding with cumulative sum."""
num_steps = 100
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
tag='floating_pt'
)
- error = np.abs(np.cumsum(input, axis=1) - output).max()
+ error = np.abs(np.cumsum(input_, axis=1) - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -90,11 +90,11 @@ def run_test(
cum_error: bool,
tag: str = 'fixed_pt',
) -> Tuple[np.ndarray, np.ndarray]:
- input = np.sin(0.1 * np.arange(num_steps).reshape(1, -1))
- input *= (1 << spike_exp + state_exp)
- input[:, 1:] -= input[:, :-1]
+ input_ = np.sin(0.1 * np.arange(num_steps).reshape(1, -1))
+ input_ *= (1 << spike_exp + state_exp)
+ input_[:, 1:] -= input_[:, :-1]
- source = io.source.RingBuffer(data=input.astype(int) * (1 << 6))
+ source = io.source.RingBuffer(data=input_.astype(int) * (1 << 6))
sdn = SigmaDelta(
shape=(1,),
vth=vth,
@@ -115,10 +115,10 @@ def run_test(
output = sink.data.get()
sdn.stop()
- input = np.cumsum(input, axis=1)
+ input_ = np.cumsum(input_, axis=1)
output = np.cumsum(output, axis=1)
- return input, output
+ return input_, output
def test_reconstruction_fixed(self) -> None:
"""Tests fixed point sigma delta reconstruction. The max absolute
@@ -128,7 +128,7 @@ def test_reconstruction_fixed(self) -> None:
spike_exp = 6
state_exp = 6
vth = 10 << (spike_exp + state_exp)
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
vth=vth,
act_mode=ActivationMode.UNIT,
@@ -137,7 +137,7 @@ def test_reconstruction_fixed(self) -> None:
cum_error=False,
)
- error = np.abs(input - output).max()
+ error = np.abs(input_ - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -151,7 +151,7 @@ def test_reconstruction_float(self) -> None:
spike_exp = 0
state_exp = 0
vth = 10
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
vth=vth,
act_mode=ActivationMode.UNIT,
@@ -161,7 +161,7 @@ def test_reconstruction_float(self) -> None:
tag='floating_pt'
)
- error = np.abs(input - output).max()
+ error = np.abs(input_ - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -175,7 +175,7 @@ def test_reconstruction_cum_error_fixed(self) -> None:
spike_exp = 6
state_exp = 6
vth = 10 << (spike_exp + state_exp)
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
vth=vth,
act_mode=ActivationMode.UNIT,
@@ -184,7 +184,7 @@ def test_reconstruction_cum_error_fixed(self) -> None:
cum_error=True,
)
- error = np.abs(input - output).max()
+ error = np.abs(input_ - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -198,7 +198,7 @@ def test_reconstruction_cum_error_float(self) -> None:
spike_exp = 0
state_exp = 0
vth = 10
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
vth=vth,
act_mode=ActivationMode.UNIT,
@@ -208,7 +208,7 @@ def test_reconstruction_cum_error_float(self) -> None:
tag='floating_pt'
)
- error = np.abs(input - output).max()
+ error = np.abs(input_ - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -222,7 +222,7 @@ def test_reconstruction_relu_fixed(self) -> None:
spike_exp = 0
state_exp = 0
vth = 10 << (spike_exp + state_exp)
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
vth=vth,
act_mode=ActivationMode.RELU,
@@ -231,7 +231,7 @@ def test_reconstruction_relu_fixed(self) -> None:
cum_error=False,
)
- error = np.abs(np.maximum(input, 0) - output).max()
+ error = np.abs(np.maximum(input_, 0) - output).max()
if verbose:
print(f'Max abs error = {error}')
@@ -245,7 +245,7 @@ def test_reconstruction_relu_float(self) -> None:
vth = 10
spike_exp = 0
state_exp = 0
- input, output = self.run_test(
+ input_, output = self.run_test(
num_steps=num_steps,
vth=vth,
act_mode=ActivationMode.RELU,
@@ -255,7 +255,7 @@ def test_reconstruction_relu_float(self) -> None:
tag='floating_pt',
)
- error = np.abs(np.maximum(input, 0) - output).max()
+ error = np.abs(np.maximum(input_, 0) - output).max()
if verbose:
print(f'Max abs error = {error}')
diff --git a/tests/lava/proc/sparse/__init__.py b/tests/lava/proc/sparse/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/lava/proc/sparse/test_models.py b/tests/lava/proc/sparse/test_models.py
new file mode 100644
index 000000000..5f045df6b
--- /dev/null
+++ b/tests/lava/proc/sparse/test_models.py
@@ -0,0 +1,1449 @@
+# Copyright (C) 2023 Intel Corporation
+# SPDX-License-Identifier: BSD-3-Clause
+# See: https://spdx.org/licenses/
+
+import unittest
+import numpy as np
+from lava.magma.core.learning.learning_rule import Loihi2FLearningRule
+from scipy.sparse import csr_matrix
+
+from lava.proc.dense.process import LearningDense
+from lava.proc.sparse.process import Sparse, DelaySparse, LearningSparse
+from lava.proc.learning_rules.stdp_learning_rule import STDPLoihi
+from lava.proc.dense.process import Dense
+from lava.proc.sparse.models import AbstractPyDelaySparseModel as APDSM
+from lava.proc.io.source import RingBuffer as Source
+from lava.proc.io.sink import RingBuffer as Sink
+
+from lava.magma.core.run_configs import Loihi2SimCfg
+from lava.magma.core.decorator import implements, requires, tag
+from lava.magma.core.model.py.model import PyLoihiProcessModel
+from lava.magma.core.model.py.ports import PyOutPort, PyInPort
+from lava.magma.core.model.py.type import LavaPyType
+from lava.magma.core.process.ports.ports import OutPort, InPort
+from lava.magma.core.process.process import AbstractProcess
+from lava.magma.core.process.variable import Var
+from lava.magma.core.resources import CPU
+from lava.magma.core.run_conditions import RunSteps
+from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
+from lava.proc.dense.models import AbstractPyDelayDenseModel
+from lava.utils.weightutils import SignMode
+
+
+def create_network(input_data, conn, weights):
+ source = Source(data=input_data)
+ sink = Sink(shape=(weights.shape[0], ),
+ buffer=input_data.shape[1])
+
+ source.s_out.connect(conn.s_in)
+ conn.a_out.connect(sink.a_in)
+
+ return source, conn, sink
+
+
+def create_learning_network(data_pre, conn, data_post, weights=None):
+ pre = Source(data=data_pre)
+ post = Source(data=data_post)
+
+ if weights is not None:
+ sink = Sink(shape=(weights.shape[0], ),
+ buffer=data_post.shape[1])
+
+ conn.a_out.connect(sink.a_in)
+
+ pre.s_out.connect(conn.s_in)
+ post.s_out.connect(conn.s_in_bap)
+
+ if weights is not None:
+ return pre, conn, post, sink
+ else:
+ return pre, conn, post
+
+
+class TestSparseProcessModelFloat(unittest.TestCase):
+ """Tests for Sparse class in floating point precision. """
+
+ def test_consistency_with_dense_random_shape(self):
+ """Tests if the results of Sparse and Dense are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights[np.abs(weights) < 0.7] = 0
+
+ inp = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+
+ conn = Dense(weights=weights)
+ dense_net = create_network(inp, conn, weights)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ # Weights_got_dense = conn.weights.get()
+ result_dense = dense_net[2].data.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = Sparse(weights=weights_sparse)
+ sparse_net = create_network(inp, conn, weights_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ # Weights_got_sparse = conn.weights.get()
+ result_sparse = sparse_net[2].data.get()
+ conn.stop()
+
+ np.testing.assert_array_almost_equal(result_sparse, result_dense)
+
+ def test_consistency_with_dense_random_shape_graded(self):
+ """Tests if the results of Sparse and Dense are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights[np.abs(weights) < 0.7] = 0
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ conn = Dense(weights=weights, num_message_bits=8)
+ dense_net = create_network(inp, conn, weights)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ dense_net[0].run(condition=run_cond, run_cfg=run_cfg)
+ result_dense = dense_net[2].data.get()
+ dense_net[0].stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = Sparse(weights=weights_sparse, num_message_bits=8)
+ sparse_net = create_network(inp, conn, weights_sparse)
+ sparse_net[0].run(condition=run_cond, run_cfg=run_cfg)
+
+ result_sparse = sparse_net[2].data.get()
+ sparse_net[0].stop()
+
+ np.testing.assert_array_almost_equal(result_sparse, result_dense)
+
+ def test_weights_get(self):
+ """Tests the get method on weights."""
+
+ simtime = 10
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights[np.abs(weights) < 0.7] = 0
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn = Sparse(weights=weights_sparse)
+ create_network(inp, conn, weights_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got = conn.weights.get()
+ conn.stop()
+
+ self.assertIsInstance(weights_got, csr_matrix)
+ np.testing.assert_array_equal(weights_got.toarray(), weights)
+
+ def test_weights_set(self):
+ """Tests the set method on weights."""
+ simtime = 2
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights_init = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights_init[np.abs(weights_init) < 0.7] = 0
+ weights_init_sparse = csr_matrix(weights_init)
+
+ new_weights_sparse = weights_init_sparse.copy()
+ new_weights_sparse.data = (np.random.random(
+ new_weights_sparse.data.shape) - 0.5) * 2
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ run_cond = RunSteps(num_steps=1)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn = Sparse(weights=weights_init_sparse)
+ create_network(inp, conn, weights_init_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ new_weights_sparse = conn.weights.init.copy()
+ new_weights_sparse.data = np.random.permutation(new_weights_sparse.data)
+
+ conn.weights.set(new_weights_sparse)
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got_ts_2 = conn.weights.get()
+
+ conn.stop()
+
+ self.assertIsInstance(weights_got_ts_2, csr_matrix)
+ np.testing.assert_array_equal(weights_got_ts_2.toarray(),
+ new_weights_sparse.toarray())
+
+
+class TestSparseProcessModelFixed(unittest.TestCase):
+ """Tests for Sparse class in fixed point precision. """
+
+ def test_consitency_with_dense_random_shape(self):
+ """Tests if the results of Sparse and Dense are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights[np.abs(weights) < 0.7] = 0
+ weights *= 20
+ weights = weights.astype(int)
+
+ inp = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+
+ conn = Dense(weights=weights)
+ dense_net = create_network(inp, conn, weights)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='fixed_pt')
+
+ dense_net[0].run(condition=run_cond, run_cfg=run_cfg)
+ result_dense = dense_net[2].data.get()
+ dense_net[0].stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = Sparse(weights=weights_sparse)
+ sparse_net = create_network(inp, conn, weights_sparse)
+ sparse_net[0].run(condition=run_cond, run_cfg=run_cfg)
+
+ result_sparse = sparse_net[2].data.get()
+ sparse_net[0].stop()
+
+ np.testing.assert_array_almost_equal(result_sparse, result_dense)
+
+ def test_consitency_with_dense_random_shape_graded(self):
+ """Tests if the results of Sparse and Dense are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights[np.abs(weights) < 0.7] = 0
+ weights *= 20
+ weights = weights.astype(int)
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ conn = Dense(weights=weights, num_message_bits=8)
+ dense_net = create_network(inp, conn, weights)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='fixed_pt')
+
+ dense_net[0].run(condition=run_cond, run_cfg=run_cfg)
+ result_dense = dense_net[2].data.get()
+ dense_net[0].stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = Sparse(weights=weights_sparse, num_message_bits=8)
+ sparse_net = create_network(inp, conn, weights_sparse)
+ sparse_net[0].run(condition=run_cond, run_cfg=run_cfg)
+
+ result_sparse = sparse_net[2].data.get()
+ sparse_net[0].stop()
+
+ np.testing.assert_array_almost_equal(result_sparse, result_dense)
+
+ def test_weights_get(self):
+ """Tests the get method on weights."""
+
+ simtime = 10
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights_init = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights_init[np.abs(weights_init) < 0.7] = 0
+ weights_init *= 20
+ weights_init = weights_init.astype(int)
+ weights_sparse = csr_matrix(weights_init)
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn = Sparse(weights=weights_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got = conn.weights.get()
+ conn.stop()
+
+ self.assertIsInstance(weights_got, csr_matrix)
+ np.testing.assert_array_equal(weights_got.toarray(), weights_init)
+
+ def test_weights_set(self):
+ """tests the set method on weights."""
+ simtime = 2
+ shape = np.random.randint(1, 300, 2).tolist()
+ weights_init = (np.random.random(shape) - 0.5) * 2
+
+ # Sparsify
+ weights_init[np.abs(weights_init) < 0.7] = 0
+ weights_init *= 20
+ weights_init = weights_init.astype(int)
+ weights_init_sparse = csr_matrix(weights_init)
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ run_cond = RunSteps(num_steps=1)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn = Sparse(weights=weights_init_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ new_weights_sparse = conn.weights.init.copy()
+ new_weights_sparse.data = np.random.permutation(new_weights_sparse.data)
+
+ conn.weights.set(new_weights_sparse)
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got_ts_2 = conn.weights.get()
+
+ conn.stop()
+
+ self.assertIsInstance(weights_got_ts_2, csr_matrix)
+ np.testing.assert_array_equal(weights_got_ts_2.toarray(),
+ new_weights_sparse.toarray())
+
+ def test_weights_set_failure(self):
+ """This tests tries to use set() to change weights but fails as
+ the number of non-zero weights and their indices change"""
+ simtime = 2
+ shape = (2, 2)
+ weights_init = np.array([[0, 32], [13, 0]])
+ new_weights = np.array([[0, 0], [13, 0]])
+ new_weights_2 = np.array([[32, 0], [13, 0]])
+
+ weights_init_sparse = csr_matrix(weights_init)
+ new_weights_sparse = csr_matrix(new_weights)
+ new_weights_sparse_2 = csr_matrix(new_weights_2)
+
+ inp = (np.random.rand(shape[1], simtime) * 10).astype(int)
+
+ run_cond = RunSteps(num_steps=1)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn = Sparse(weights=weights_init_sparse)
+ sparse_net = create_network(inp, conn, weights_init_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ self.assertRaises(ValueError, conn.weights.set, new_weights_sparse)
+ self.assertRaises(ValueError, conn.weights.set, new_weights_sparse_2)
+ conn.stop()
+
+
+class TestLearningSparseProcessModelFloat(unittest.TestCase):
+ """Tests for LearningSparse class in floating point precision. """
+
+ def test_consistency_with_learning_dense_random_shape(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+ weights[weights == 0] = 0.1
+
+ learning_rule = STDPLoihi(
+ learning_rate=1,
+ A_plus=1,
+ A_minus=-1,
+ tau_plus=10,
+ tau_minus=10,
+ t_epoch=2,
+ )
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+ post = (np.random.rand(shape[0], simtime) > 0.7).astype(int)
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule)
+ create_learning_network(pre, conn, post)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ weights_got_dense = conn.weights.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule)
+ create_learning_network(pre, conn, post)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got_sparse = conn.weights.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(weights_got_dense,
+ weights_got_sparse.toarray())
+
+ def test_consistency_with_learning_dense_random_shape_dt(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+ weights[weights == 0] = 0.1
+
+ learning_rule = Loihi2FLearningRule(dt="x0 * y1 - y0 * x1",
+ x1_tau=10,
+ y1_tau=16,
+ x1_impulse=16,
+ y1_impulse=15,
+ t_epoch=2)
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+ post = (np.random.rand(shape[0], simtime) > 0.7).astype(int)
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ tags_got_dense = conn.tag_1.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ tags_got_sparse = conn.tag_1.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(tags_got_dense,
+ tags_got_sparse.toarray())
+
+ def test_consistency_with_learning_dense_random_shape_dd(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+ weights[weights == 0] = 0.1
+
+ learning_rule = Loihi2FLearningRule(dd="x0 * y1 - y0 * x1",
+ x1_tau=10,
+ y1_tau=16,
+ x1_impulse=16,
+ y1_impulse=15,
+ t_epoch=2)
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+ post = (np.random.rand(shape[0], simtime) > 0.7).astype(int)
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule)
+ dense_net = create_learning_network(pre, conn, post)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ tags_got_dense = conn.tag_2.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule)
+ sparse_net = create_learning_network(pre, conn, post)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ tags_got_sparse = conn.tag_2.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(tags_got_dense,
+ tags_got_sparse.toarray())
+
+ def test_consistency_with_learning_dense_random_shape_graded(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = (np.random.random(shape) - 0.5) * 2
+ weights[weights == 0] = 0.1
+
+ learning_rule = STDPLoihi(
+ learning_rate=1,
+ A_plus=1,
+ A_minus=-1,
+ tau_plus=10,
+ tau_minus=10,
+ t_epoch=2,
+ )
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7) * 3
+ post = (np.random.rand(shape[0], simtime) > 0.7) * 2
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule,
+ num_message_bits=8)
+
+ dense_net = create_learning_network(pre, conn, post, weights=weights)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='floating_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ weights_got_dense = conn.weights.get()
+ result_dense = dense_net[-1].data.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule,
+ num_message_bits=8)
+
+ sparse_net = create_learning_network(pre,
+ conn,
+ post,
+ weights=weights_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got_sparse = conn.weights.get()
+ result_sparse = sparse_net[-1].data.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(weights_got_dense,
+ weights_got_sparse.toarray())
+
+ np.testing.assert_array_almost_equal(result_sparse, result_dense)
+
+
+class TestLearningSparseProcessModelFixed(unittest.TestCase):
+ """Tests for LearningSparse class in fixed point precision. """
+
+ def test_consistency_with_learning_dense_random_shape(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent. """
+
+ simtime = 100
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = ((np.random.random(shape) - 0.5) * 20).astype(int)
+ weights[abs(weights) < 2] = 2
+
+ learning_rule = STDPLoihi(
+ learning_rate=1,
+ A_plus=1,
+ A_minus=-1,
+ tau_plus=10,
+ tau_minus=10,
+ t_epoch=2,
+ )
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+ post = (np.random.rand(shape[0], simtime) > 0.7).astype(int)
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule)
+ dense_net = create_learning_network(pre, conn, post)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='fixed_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ weights_got_dense = conn.weights.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule)
+ sparse_net = create_learning_network(pre, conn, post)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got_sparse = conn.weights.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(weights_got_dense,
+ weights_got_sparse.toarray())
+
+ def test_consistency_with_learning_dense_random_shape_dt(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent using dt in the learning rule. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = ((np.random.random(shape) - 0.5) * 20).astype(int)
+ weights[abs(weights) < 2] = 2
+
+ learning_rule = Loihi2FLearningRule(dt="x0 * y1 - y0 * x1",
+ x1_tau=10,
+ y1_tau=16,
+ x1_impulse=16,
+ y1_impulse=15,
+ t_epoch=2)
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+ post = (np.random.rand(shape[0], simtime) > 0.7).astype(int)
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule)
+ dense_net = create_learning_network(pre, conn, post)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='fixed_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ tags_got_dense = conn.tag_1.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule)
+ sparse_net = create_learning_network(pre, conn, post)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ tags_got_sparse = conn.tag_1.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(tags_got_dense,
+ tags_got_sparse.toarray())
+
+ def test_consistency_with_learning_dense_random_shape_dd(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent using dd in the learning rule. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = ((np.random.random(shape) - 0.5) * 20).astype(int)
+ weights[abs(weights) < 2] = 2
+
+ learning_rule = Loihi2FLearningRule(dd="x0 * y1 - y0 * x1",
+ x1_tau=10,
+ y1_tau=16,
+ x1_impulse=16,
+ y1_impulse=15,
+ t_epoch=2)
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7).astype(int)
+ post = (np.random.rand(shape[0], simtime) > 0.7).astype(int)
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule)
+ dense_net = create_learning_network(pre, conn, post)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='fixed_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ tags_got_dense = conn.tag_2.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule)
+ sparse_net = create_learning_network(pre, conn, post)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ tags_got_sparse = conn.tag_2.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(tags_got_dense,
+ tags_got_sparse.toarray())
+
+ def test_consistency_with_learning_dense_random_shape_graded(self):
+ """Tests if the results of LearningSparse and LearningDense
+ are consistent. """
+
+ simtime = 10
+ shape = np.random.randint(1, 100, 2).tolist()
+ weights = ((np.random.random(shape) - 0.5) * 20).astype(int)
+ weights[abs(weights) < 2] = 2
+
+ learning_rule = STDPLoihi(
+ learning_rate=1,
+ A_plus=1,
+ A_minus=-1,
+ tau_plus=10,
+ tau_minus=10,
+ t_epoch=2,
+ )
+
+ pre = (np.random.rand(shape[1], simtime) > 0.7) * 3
+ post = (np.random.rand(shape[0], simtime) > 0.7) * 2
+
+ conn = LearningDense(weights=weights,
+ tag_1=weights.copy(),
+ tag_2=weights.copy(),
+ learning_rule=learning_rule,
+ num_message_bits=8)
+
+ dense_net = create_learning_network(pre, conn, post, weights=weights)
+
+ run_cond = RunSteps(num_steps=simtime)
+ run_cfg = Loihi2SimCfg(select_tag='fixed_pt')
+
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+ weights_got_dense = conn.weights.get()
+ result_dense = dense_net[-1].data.get()
+ conn.stop()
+
+ # Run the same network with Sparse
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ tag_1=weights_sparse.copy(),
+ tag_2=weights_sparse.copy(),
+ learning_rule=learning_rule,
+ num_message_bits=8)
+
+ sparse_net = create_learning_network(pre,
+ conn,
+ post,
+ weights=weights_sparse)
+ conn.run(condition=run_cond, run_cfg=run_cfg)
+
+ weights_got_sparse = conn.weights.get()
+ result_sparse = sparse_net[-1].data.get()
+ conn.stop()
+
+ np.testing.assert_array_equal(weights_got_dense,
+ weights_got_sparse.toarray())
+
+ np.testing.assert_array_almost_equal(result_sparse, result_dense)
+
+
+class VecSendandRecvProcess(AbstractProcess):
+ """
+ Process of a user-defined shape that sends an arbitrary vector
+
+ Process also listens for incoming connections via InPort a_in. This
+ allows the test Process to validate that network behavior won't deadlock
+ in the presence of recurrent connections.
+
+ Parameters
+ ----------
+ shape: tuple, shape of the process
+ vec_to_send: np.ndarray, vector of spike values to send
+ send_at_times: np.ndarray, vector bools. Send the `vec_to_send` at times
+ when there is a True
+ """
+
+ def __init__(self, **kwargs):
+ super().__init__()
+ shape = kwargs.pop("shape", (1,))
+ vec_to_send = kwargs.pop("vec_to_send")
+ send_at_times = kwargs.pop("send_at_times")
+ num_steps = kwargs.pop("num_steps", 1)
+ self.shape = shape
+ self.num_steps = num_steps
+ self.vec_to_send = Var(shape=shape, init=vec_to_send)
+ self.send_at_times = Var(shape=(num_steps,), init=send_at_times)
+ self.s_out = OutPort(shape=shape)
+ self.a_in = InPort(shape=shape)
+
+
+class VecRecvProcess(AbstractProcess):
+ """
+ Process that receives arbitrary vectors
+
+ Parameters
+ ----------
+ shape: tuple, shape of the process
+ """
+
+ def __init__(self, **kwargs):
+ super().__init__()
+ shape = kwargs.get("shape", (1,))
+ self.shape = shape
+ self.s_in = InPort(shape=(shape[1],))
+ self.spk_data = Var(shape=shape, init=0)
+
+
+@implements(proc=VecSendandRecvProcess, protocol=LoihiProtocol)
+@requires(CPU)
+@tag('floating_pt')
+class PyVecSendModelFloat(PyLoihiProcessModel):
+ s_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, bool, precision=1)
+ a_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, float)
+ vec_to_send: np.ndarray = LavaPyType(np.ndarray, bool, precision=1)
+ send_at_times: np.ndarray = LavaPyType(np.ndarray, bool, precision=1)
+
+ def run_spk(self):
+ """
+ Send `spikes_to_send` if current time-step requires it
+ """
+ self.a_in.recv()
+
+ if self.send_at_times[self.time_step - 1]:
+ self.s_out.send(self.vec_to_send)
+ else:
+ self.s_out.send(np.zeros_like(self.vec_to_send))
+
+
+@implements(proc=VecSendandRecvProcess, protocol=LoihiProtocol)
+@requires(CPU)
+@tag('fixed_pt')
+class PyVecSendModelFixed(PyLoihiProcessModel):
+ s_out: PyOutPort = LavaPyType(PyOutPort.VEC_DENSE, bool, precision=1)
+ a_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, np.int32, precision=16)
+ vec_to_send: np.ndarray = LavaPyType(np.ndarray, bool, precision=1)
+ send_at_times: np.ndarray = LavaPyType(np.ndarray, bool, precision=1)
+
+ def run_spk(self):
+ """
+ Send `spikes_to_send` if current time-step requires it
+ """
+ self.a_in.recv()
+
+ if self.send_at_times[self.time_step - 1]:
+ self.s_out.send(self.vec_to_send)
+ else:
+ self.s_out.send(np.zeros_like(self.vec_to_send))
+
+
+@implements(proc=VecRecvProcess, protocol=LoihiProtocol)
+@requires(CPU)
+@tag('floating_pt')
+class PySpkRecvModelFloat(PyLoihiProcessModel):
+ s_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, bool, precision=1)
+ spk_data: np.ndarray = LavaPyType(np.ndarray, float)
+
+ def run_spk(self):
+ """Receive spikes and store in an internal variable"""
+ spk_in = self.s_in.recv()
+ self.spk_data[self.time_step - 1, :] = spk_in
+
+
+@implements(proc=VecRecvProcess, protocol=LoihiProtocol)
+@tag('fixed_pt')
+class PySpkRecvModelFixed(PyLoihiProcessModel):
+ s_in: PyInPort = LavaPyType(PyInPort.VEC_DENSE, bool, precision=1)
+ spk_data: np.ndarray = LavaPyType(np.ndarray, int, precision=1)
+
+ def run_spk(self):
+ """Receive spikes and store in an internal variable"""
+ spk_in = self.s_in.recv()
+ self.spk_data[self.time_step - 1, :] = spk_in
+
+
+class TestDelaySparseProcessModel(unittest.TestCase):
+ """Tests for ProcessModels of Sparse with synaptic delay."""
+
+ def test_matrix_weight_delay_expansion(self):
+ """Tests if the weight-delay matrix is consistent between Dense
+ and Sparse"""
+ shape = (5, 4)
+ weights = np.zeros(shape, dtype=float)
+ weights[3, 3] = 1
+ weights[1, 2] = 3
+ weights[3, 1] = 1
+ delays = np.zeros(shape, dtype=int)
+ delays[3, 3] = 1
+ delays[1, 2] = 3
+ delays[3, 1] = 2
+
+ weights_sparse = csr_matrix(weights)
+ delays_sparse = csr_matrix(delays)
+ wgt_dly_dense = AbstractPyDelayDenseModel.get_delay_wgts_mat(weights,
+ delays)
+ wgt_dly_sparse = APDSM.get_delay_wgts_mat(weights_sparse,
+ delays_sparse)
+ self.assertTrue(np.all(wgt_dly_sparse == wgt_dly_dense))
+
+ def test_float_pm_buffer_delay(self):
+ """Tests floating point Sparse ProcessModel connectivity and temporal
+ dynamics. All input 'neurons' from the VecSendandRcv fire
+ once at time t=4, and only 1 connection weight
+ in the Sparse Process is non-zero. The value of the delay matrix for
+ this weight is 2. The non-zero connection should have an activation
+ of 1 at timestep t=7.
+ """
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],),
+ num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process with a single non-zero connection weight at
+ # entry [2, 2] of the connectivity matrix and a delay of 2 at entry
+ # [2, 2] in the delay matrix.
+ weights = np.zeros(shape, dtype=float)
+ weights[2, 2] = 1
+ delays = np.zeros(shape, dtype=int)
+ delays[2, 2] = 2
+ weights = csr_matrix(weights)
+ delays = csr_matrix(delays)
+ sparse = DelaySparse(weights=weights, delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='floating_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # a_out will be equal to 1 at timestep 7, because the dendritic
+ # accumulators work on inputs from the previous timestep + 2.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[6, 2] = 1.
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_float_pm_fan_in_delay(self):
+ """
+ Tests floating point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-in to a receiving neuron is greater than 1
+ and synaptic delays are configured.
+ """
+ shape = (3, 4)
+ num_steps = 10
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up a Sparse Process where all input layer neurons project to a
+ # single output layer neuron with varying delays.
+ weights = np.zeros(shape, dtype=float)
+ weights[2, :] = [2, -3, 4, -5]
+ delays = np.zeros(shape, dtype=int)
+ delays[2, :] = [1, 2, 2, 4]
+ weights = csr_matrix(weights)
+ delays = csr_matrix(delays)
+ sparse = DelaySparse(weights=weights, delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='floating_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neuron 3 will be equal to 2 at timestep 6, 1=-3+4 at timestep 7
+ # and -5 at timestep 9
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[5, 2] = 2
+ expected_spk_data[6, 2] = 1
+ expected_spk_data[8, 2] = -5
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_float_pm_fan_out_delay(self):
+ """
+ Tests floating point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-out of a projecting neuron is greater than 1
+ and synaptic delays are configured.
+ """
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep t=4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up a Sparse Process where a single input layer neuron
+ # projects to all output layer neurons with a delay of 2 for
+ # all synapses.
+ weights = np.zeros(shape, dtype=float)
+ weights[:, 2] = [3, 4, 5]
+ delays = np.zeros(shape, dtype=int)
+ delays = 2
+ weights = csr_matrix(weights)
+ sparse = DelaySparse(weights=weights, delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='floating_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neurons 1-3 will be equal to 3, 4, and 5, respectively, at
+ # timestep 7.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[6, :] = [3, 4, 5]
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_float_pm_fan_out_delay_2(self):
+ """
+ Tests floating point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-out of a projecting neuron is greater than 1
+ and synaptic delays are configured.
+ """
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep t=4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up a Sparse Process where a single input layer neuron projects
+ # to all output layer neurons with varying delays.
+ weights = np.zeros(shape, dtype=float)
+ weights[:, 2] = [3, 4, 5]
+ delays = np.zeros(shape, dtype=int)
+ delays[:, 2] = [0, 1, 2]
+ weights = csr_matrix(weights)
+ delays = csr_matrix(delays)
+ sparse = DelaySparse(weights=weights, delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='floating_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neurons 1-3 will be equal to 3, 4, and 5, respectively, at
+ # timestep 5, 6 and 7, respectively.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[4, 0] = 3
+ expected_spk_data[5, 1] = 4
+ expected_spk_data[6, 2] = 5
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_float_pm_recurrence_delays(self):
+ """
+ Tests that floating Sparse ProcessModel has non-blocking dynamics
+ for recurrent connectivity architectures and synaptic delays are
+ configured.
+ """
+ shape = (3, 3)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(True, (num_steps,))
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process with fully connected recurrent connectivity
+ # architecture
+ weights = np.ones(shape, dtype=float)
+ delays = 2
+ weights = csr_matrix(weights)
+ sparse = DelaySparse(weights=weights, delays=delays)
+ # Receive neuron spikes
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(sps.a_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='floating_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ sparse.stop()
+
+ def test_bitacc_pm_fan_out_excitatory_delay(self):
+ """
+ Tests fixed-point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-out of a projecting neuron is greater than 1
+ and all connections are excitatory (sign_mode = 2) and synaptic
+ delays are configured.
+ """
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process in which a single input neuron projects
+ # to all output neurons.
+ weights = np.zeros(shape, dtype=float)
+ weights[:, 2] = [0.5, 300, 40]
+ delays = np.zeros(shape, dtype=int)
+ delays[:, 2] = [0, 1, 2]
+ weights = csr_matrix(weights)
+ delays = csr_matrix(delays)
+ sparse = DelaySparse(weights=weights,
+ delays=delays,
+ sign_mode=SignMode.EXCITATORY)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='fixed_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neurons 1-3 will be equal to 0, 255, and 40, respectively,
+ # at timestep 5, 6 and 7, because a_out can only have integer values
+ # between 0 and 255 and we have a delay of 0, 1, 2 on the synapses,
+ # respectively.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[4, 0] = 0
+ expected_spk_data[5, 1] = 255
+ expected_spk_data[6, 2] = 40
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_bitacc_pm_fan_out_mixed_sign_delay(self):
+ """
+ Tests fixed-point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-out of a projecting neuron is greater than 1
+ and connections are both excitatory and inhibitory (sign_mode = 1).
+ When using mixed sign weights and full 8 bit weight precision,
+ a_out can take even values from -256 to 254. A delay of 2 for all
+ synapses is configured.
+ """
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process in which a single input neuron projects to
+ # all output neurons with both excitatory and inhibitory weights.
+ weights = np.zeros(shape, dtype=float)
+ weights[:, 2] = [300, -300, 39]
+ delays = np.zeros(shape, dtype=int)
+ delays = 2
+ weights = csr_matrix(weights)
+ sparse = DelaySparse(weights=weights,
+ delays=delays,
+ sign_mode=SignMode.MIXED)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='fixed_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neurons 1-3 will be equal to 254, -256, and 38, respectively,
+ # at timestep 7, because a_out can only have even values between
+ # -256 and 254 and a delay of 2 is configured.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[6, :] = [254, -256, 38]
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_bitacc_pm_fan_out_weight_exp_delay(self):
+ """
+ Tests fixed-point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-out of a projecting neuron is greater than 1
+ , connections are both excitatory and inhibitory (sign_mode = 1),
+ and weight_exp = 1.
+ When using mixed sign weights, full 8 bit weight precision,
+ and weight_exp = 1, a_out can take even values from -512 to 508.
+ As a result of setting weight_exp = 1, the expected a_out result
+ is 2x that of the previous unit test. A delay of 0, 1, 2 is
+ configured for respective synapses.
+ """
+
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process in which all input neurons project to a
+ # single output neuron with mixed sign connection weights.
+ weights = np.zeros(shape, dtype=float)
+ weights[:, 2] = [300, -300, 39]
+ delays = np.zeros(shape, dtype=int)
+ delays[:, 2] = [0, 1, 2]
+ weights = csr_matrix(weights)
+ delays = csr_matrix(delays)
+ # Set weight_exp = 1. This affects weight scaling.
+ sparse = DelaySparse(weights=weights, weight_exp=1, delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='fixed_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neurons 1-3 will be equal to 508, -512, and 76, respectively,
+ # at timestep 5, 6, and 7, respectively, because a_out can only
+ # have values between -512 and 508 such that a_out % 4 = 0.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[4, 0] = 508
+ expected_spk_data[5, 1] = -512
+ expected_spk_data[6, 2] = 76
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_bitacc_pm_fan_out_weight_precision_delay(self):
+ """
+ Tests fixed-point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-out of a projecting neuron is greater than 1
+ , connections are both excitatory and inhibitory (sign_mode = 1),
+ and num_weight_bits = 7.
+ When using mixed sign weights and 7 bit weight precision,
+ a_out can take values from -256 to 252 such that a_out % 4 = 0.
+ All synapses have a delay of 2 configured.
+ """
+
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process in which all input neurons project to a
+ # single output neuron with mixed sign connection weights.
+ weights = np.zeros(shape, dtype=float)
+ weights[:, 2] = [300, -300, 39]
+ delays = np.zeros(shape, dtype=int)
+ delays = 2
+ weights = csr_matrix(weights)
+ # Set num_weight_bits = 7. This affects weight scaling.
+ sparse = DelaySparse(weights=weights,
+ num_weight_bits=7,
+ delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='fixed_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neurons 1-3 will be equal to 252, -256, and 36, respectively,
+ # at timestep 7, because a_out can only have values between -256
+ # and 252 such that a_out % 4 = 0.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[6, :] = [252, -256, 36]
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_bitacc_pm_fan_in_mixed_sign_delay(self):
+ """
+ Tests fixed-point Sparse ProcessModel dendritic accumulation
+ behavior when the fan-in of a receiving neuron is greater than 1
+ and connections are both excitatory and inhibitory (sign_mode = 1).
+ When using mixed sign weights and full 8 bit weight precision,
+ a_out can take even values from -256 to 254. All synapses have a
+ delay of 2 configured.
+ """
+ shape = (3, 4)
+ num_steps = 8
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(False, (num_steps,))
+ send_at_times[3] = True
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process in which all input layer neurons project to
+ # a single output layer neuron with both excitatory and inhibitory
+ # weights.
+ weights = np.zeros(shape, dtype=float)
+ weights[2, :] = [300, -300, 39, -0.4]
+ delays = np.zeros(shape, dtype=int)
+ delays = 2
+ weights = csr_matrix(weights)
+ sparse = DelaySparse(weights=weights,
+ sign_mode=SignMode.MIXED,
+ delays=delays)
+ # Receive neuron spikes
+ spr = VecRecvProcess(shape=(num_steps, shape[0]))
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(spr.s_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='fixed_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ # Gather spike data and stop
+ spk_data_through_run = spr.spk_data.get()
+ sparse.stop()
+ # Gold standard for the test
+ # Expected behavior is that a_out corresponding to output
+ # neuron 3 will be equal to 36=254-256+38-0 at timestep 7, because
+ # weights can only have even values between -256 and 254.
+ expected_spk_data = np.zeros((num_steps, shape[0]))
+ expected_spk_data[6, 2] = 36
+ self.assertTrue(np.all(expected_spk_data == spk_data_through_run))
+
+ def test_bitacc_pm_recurrence_delay(self):
+ """
+ Tests that bit accurate Sparse ProcessModel has non-blocking
+ dynamics for recurrent connectivity architectures. All
+ synapses have a delay of 2 configured.
+ """
+ shape = (3, 3)
+ num_steps = 6
+ # Set up external input to emulate every neuron spiking once on
+ # timestep 4.
+ vec_to_send = np.ones((shape[1],), dtype=float)
+ send_at_times = np.repeat(True, (num_steps,))
+ sps = VecSendandRecvProcess(shape=(shape[1],), num_steps=num_steps,
+ vec_to_send=vec_to_send,
+ send_at_times=send_at_times)
+ # Set up Sparse Process with fully connected recurrent connectivity
+ # architecture.
+ weights = np.ones(shape, dtype=float)
+ delays = 2
+ weights = csr_matrix(weights)
+ sparse = DelaySparse(weights=weights, delays=delays)
+ # Receive neuron spikes
+ sps.s_out.connect(sparse.s_in)
+ sparse.a_out.connect(sps.a_in)
+ # Configure execution and run
+ rcnd = RunSteps(num_steps=num_steps)
+ rcfg = Loihi2SimCfg(select_tag='floating_pt')
+ sparse.run(condition=rcnd, run_cfg=rcfg)
+ sparse.stop()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/lava/proc/sparse/test_process.py b/tests/lava/proc/sparse/test_process.py
new file mode 100644
index 000000000..e26c22ae8
--- /dev/null
+++ b/tests/lava/proc/sparse/test_process.py
@@ -0,0 +1,134 @@
+# Copyright (C) 2023 Intel Corporation
+# SPDX-License-Identifier: BSD-3-Clause
+# See: https://spdx.org/licenses/
+
+import unittest
+import numpy as np
+from scipy.sparse import csr_matrix, spmatrix
+
+from lava.utils.sparse import find
+from lava.proc.sparse.process import Sparse, LearningSparse, DelaySparse
+from lava.proc.learning_rules.stdp_learning_rule import STDPLoihi
+
+
+class TestFunctions(unittest.TestCase):
+ """Test helper function for Sparse"""
+
+ def test_find_with_explicit_zeros(self):
+
+ mat = np.random.randint(-10, 10, (3, 5))
+ spmat = csr_matrix(mat)
+ spmat.data[0] = 0
+
+ _, _, vals = find(spmat, explicit_zeros=True)
+
+ self.assertTrue(np.all(spmat.data in vals))
+
+
+class TestSparseProcess(unittest.TestCase):
+ """Tests for Sparse class"""
+
+ def test_init(self):
+ """Tests instantiation of Sparse"""
+ shape = (100, 200)
+ weights = np.random.random(shape)
+
+ # Sparsify
+ weights[weights < 0.7] = 0
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = Sparse(weights=weights_sparse)
+
+ self.assertIsInstance(conn.weights.init, spmatrix)
+ np.testing.assert_array_equal(conn.weights.init.toarray(), weights)
+
+
+class TestLearningSparseProcess(unittest.TestCase):
+ """Tests for LearningSparse class"""
+
+ def test_init(self):
+ """Tests instantiation of LearningSparse"""
+
+ learning_rule = STDPLoihi(
+ learning_rate=1,
+ A_plus=1,
+ A_minus=-2,
+ tau_plus=10,
+ tau_minus=10,
+ t_epoch=2,
+ )
+
+ shape = (100, 200)
+ weights = np.random.random(shape)
+
+ # Sparsify
+ weights[weights < 0.7] = 0
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+
+ conn = LearningSparse(weights=weights_sparse,
+ learning_rule=learning_rule)
+
+ self.assertIsInstance(conn.weights.init, spmatrix)
+ np.testing.assert_array_equal(conn.weights.init.toarray(), weights)
+
+
+class TestDelaySparseProcess(unittest.TestCase):
+ """Tests for Sparse class"""
+
+ def test_init(self):
+ """Tests instantiation of Sparse"""
+ shape = (100, 200)
+ weights = np.random.random(shape)
+ delays = np.random.randint(0, 3, shape)
+
+ # Sparsify
+ weights[weights < 0.7] = 0
+ delays[weights < 0.7] = 0
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+ delays_sparse = csr_matrix(delays)
+
+ conn = DelaySparse(weights=weights_sparse, delays=delays_sparse)
+
+ self.assertIsInstance(conn.weights.init, spmatrix)
+ np.testing.assert_array_equal(conn.weights.init.toarray(), weights)
+
+ def test_validate_shapes(self):
+ """Tests if the weights and delay have correct shape"""
+
+ shape = (3, 2)
+ weights = np.random.random(shape)
+
+ shape = (2, 3)
+ delays = np.random.randint(0, 3, shape)
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+ delays_sparse = csr_matrix(delays)
+
+ np.testing.assert_raises(ValueError,
+ DelaySparse,
+ weights=weights_sparse,
+ delays=delays_sparse)
+
+ def test_validate_nonzero_delays(self):
+ """Tests if the weights and delay have correct shape"""
+
+ shape = (3, 2)
+ weights = np.random.random(shape)
+ delays = np.random.randint(0, 3, shape)
+ delays[0] = -1
+
+ # Convert to spmatrix
+ weights_sparse = csr_matrix(weights)
+ delays_sparse = csr_matrix(delays)
+
+ np.testing.assert_raises(ValueError,
+ DelaySparse,
+ weights=weights_sparse,
+ delays=delays_sparse)
diff --git a/tests/lava/proc/spiker/test_models.py b/tests/lava/proc/spiker/test_models.py
index 147dbf269..9d92bc328 100644
--- a/tests/lava/proc/spiker/test_models.py
+++ b/tests/lava/proc/spiker/test_models.py
@@ -17,7 +17,7 @@ def test_single_spiker_counter(self):
"Tests a single spiker for multiple time steps."
spiker = Spiker(shape=(1,), period=5)
counter = []
- for timestep in range(20):
+ for _ in range(20):
spiker.run(condition=RunSteps(num_steps=1),
run_cfg=Loihi2SimCfg())
counter.append(spiker.counter.get()[0])
@@ -31,7 +31,7 @@ def test_multiple_spikers_counter(self):
spiker = Spiker(shape=(2,), period=5)
counter1 = []
counter2 = []
- for timestep in range(20):
+ for _ in range(20):
spiker.run(condition=RunSteps(num_steps=1),
run_cfg=Loihi2SimCfg())
counter1.append(spiker.counter.get()[0])
diff --git a/tests/lava/test_utils/utils.py b/tests/lava/test_utils/utils.py
index e1ec81397..27eb9f11d 100644
--- a/tests/lava/test_utils/utils.py
+++ b/tests/lava/test_utils/utils.py
@@ -3,13 +3,13 @@
# See: https://spdx.org/licenses/
import os
-import subprocess
+import subprocess # noqa S404
import importlib
class Utils:
- """Utility Class containing testing helper
- code that can be reused between tests
+ """Utility Class containing testing helper code that can be reused
+ between tests.
"""
@staticmethod
@@ -26,7 +26,7 @@ def get_bool_env_setting(env_var: str):
@staticmethod
def is_loihi2_available() -> bool:
- """"Checks if Loihi2 is available and can be accessed."""
+ """Checks if Loihi 2 is available and can be accessed."""
is_loihi2 = False
is_slurm = False
@@ -37,7 +37,7 @@ def is_loihi2_available() -> bool:
is_slurm = True
# Check if Loihi2 is available
- sinfo = subprocess.run("sinfo", # noqa: S603, S607
+ sinfo = subprocess.run("sinfo", # nosec # noqa: S603, S607
stdout=subprocess.PIPE).stdout.decode(
'utf-8')
for line in sinfo.split("\n"):
diff --git a/tests/lava/tutorials/test_tutorials.py b/tests/lava/tutorials/test_tutorials.py
index 1ca31679c..569585a8e 100644
--- a/tests/lava/tutorials/test_tutorials.py
+++ b/tests/lava/tutorials/test_tutorials.py
@@ -5,7 +5,7 @@
import glob
import os
import platform
-import subprocess # noqa: S404
+import subprocess # noqa S404
import sys
import tempfile
import typing as ty
@@ -115,7 +115,8 @@ def _convert_and_execute_notebook(
fout.name[0:-3],
notebook,
]
- subprocess.check_call(args, env=env) # noqa: S603
+ subprocess.check_call(args, env=env) # nosec # noqa: S603
+
fout.seek(0)
return subprocess.run(["ipython", "-c", fout.read()], # noqa # nosec
env=env) # noqa # nosec
diff --git a/tests/lava/utils/test_plots.py b/tests/lava/utils/test_plots.py
index 04765af1f..4219e5297 100644
--- a/tests/lava/utils/test_plots.py
+++ b/tests/lava/utils/test_plots.py
@@ -30,7 +30,7 @@ def test_bad_spikes_shape(self) -> None:
with self.assertRaises(ValueError) as cm:
raster_plot(spikes)
- self.assertEquals(
+ self.assertEqual(
str(cm.exception),
"Parameter must have exactly two dimensions and "
"they must be non-empty.",
@@ -43,19 +43,19 @@ def test_non_binary_values(self) -> None:
with self.assertRaises(ValueError) as cm:
raster_plot(spikes)
- self.assertEquals(str(cm.exception), error_msg)
+ self.assertEqual(str(cm.exception), error_msg)
spikes = np.array([[0, -1], [0, 0]])
with self.assertRaises(ValueError) as cm:
raster_plot(spikes)
- self.assertEquals(str(cm.exception), error_msg)
+ self.assertEqual(str(cm.exception), error_msg)
def test_bad_stride(self) -> None:
with self.assertRaises(ValueError) as cm:
raster_plot(self.spikes, stride=11)
- self.assertEquals(
+ self.assertEqual(
str(cm.exception),
"Stride must not be greater than the number of neurons.",
)
@@ -64,7 +64,7 @@ def test_both_fig_and_figsize_provided(self) -> None:
with self.assertRaises(ValueError) as cm:
raster_plot(self.spikes, fig=plt.figure(), figsize=(10, 10))
- self.assertEquals(
+ self.assertEqual(
str(cm.exception),
"Must use at most one of the following: fig, figsize.",
)
diff --git a/tutorials/in_depth/three_factor_learning/utils.py b/tutorials/in_depth/three_factor_learning/utils.py
index 230cadfc6..7320fe94d 100644
--- a/tutorials/in_depth/three_factor_learning/utils.py
+++ b/tutorials/in_depth/three_factor_learning/utils.py
@@ -3,21 +3,14 @@
# See: https://spdx.org/licenses/
import matplotlib.pyplot as plt
-import typing as ty
import numpy as np
-from lava.proc.lif.process import LIF, AbstractLIF, LogConfig, LearningLIF
-from lava.proc.io.source import RingBuffer
-from lava.proc.dense.process import LearningDense, Dense
-from lava.magma.core.process.neuron import LearningNeuronProcess
-from lava.proc.learning_rules.r_stdp_learning_rule import RewardModulatedSTDP
-from lava.magma.core.process.variable import Var
-from lava.magma.core.process.ports.ports import InPort, OutPort
+from lava.proc.lif.process import LearningLIF
from lava.magma.core.model.py.neuron import (
LearningNeuronModelFloat, LearningNeuronModelFixed
)
from lava.magma.core.sync.protocols.loihi_protocol import LoihiProtocol
-from lava.magma.core.model.py.ports import PyInPort, PyOutPort
+from lava.magma.core.model.py.ports import PyOutPort
from lava.magma.core.model.py.type import LavaPyType
from lava.magma.core.resources import CPU
from lava.magma.core.decorator import implements, requires, tag
@@ -188,8 +181,7 @@ def run_spk(self) -> None:
self.s_out_y3.send(self.y3)
-def generate_post_spikes(pre_spike_times,
- num_steps, spike_prob_post):
+def generate_post_spikes(pre_spike_times, num_steps, spike_prob_post):
"""generates specific post synaptic spikes to
demonstrate potentiation and depression.
"""
@@ -211,16 +203,17 @@ def generate_post_spikes(pre_spike_times,
return spike_raster_post
+
def plot_spikes(spikes, figsize, legend, colors, title, num_steps):
offsets = list(range(1, len(spikes) + 1))
num_x_ticks = np.arange(0, num_steps+1, 25)
plt.figure(figsize=figsize)
- spikes_plot = plt.eventplot(positions=spikes,
- lineoffsets=offsets,
- linelength=0.9,
- colors=colors)
+ plt.eventplot(positions=spikes,
+ lineoffsets=offsets,
+ linelength=0.9,
+ colors=colors)
plt.title(title)
plt.xlabel("Time steps")
@@ -233,9 +226,9 @@ def plot_spikes(spikes, figsize, legend, colors, title, num_steps):
plt.yticks(ticks=offsets, labels=legend)
-
plt.show()
+
def plot_time_series(time, time_series, ylabel, title, figsize, color):
plt.figure(figsize=figsize)
plt.step(time, time_series, color=color)
@@ -250,7 +243,10 @@ def plot_time_series(time, time_series, ylabel, title, figsize, color):
plt.show()
-def plot_time_series_subplots(time, time_series_y1, time_series_y2, ylabel, title, figsize, color, legend, leg_loc="upper left"):
+
+def plot_time_series_subplots(time, time_series_y1, time_series_y2, ylabel,
+ title, figsize, color, legend,
+ leg_loc="upper left"):
plt.figure(figsize=figsize)
plt.step(time, time_series_y1, label=legend[0], color=color[0])
@@ -268,7 +264,9 @@ def plot_time_series_subplots(time, time_series_y1, time_series_y2, ylabel, titl
plt.show()
-def plot_spikes_time_series(time, time_series, spikes, figsize, legend, colors, title, num_steps):
+
+def plot_spikes_time_series(time, time_series, spikes, figsize, legend,
+ colors, title, num_steps):
offsets = list(range(1, len(spikes) + 1))
num_x_ticks = np.arange(0, num_steps+1, 25)