From 19105e7033a79e272f70ab4884035b5bdec71ce0 Mon Sep 17 00:00:00 2001 From: Mathis Richter Date: Tue, 22 Mar 2022 23:29:56 +0100 Subject: [PATCH 1/2] Virtual ports inherit capabilities of their parent ports (#234) Signed-off-by: Mathis Richter --- pyproject.toml | 1 + src/lava/magma/core/process/ports/ports.py | 383 +++++++++++------- .../magma/core/process/ports/test_ports.py | 47 +++ .../ports/test_virtual_ports_in_process.py | 184 ++++++++- 4 files changed, 459 insertions(+), 156 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b2431b466..f453c738d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ numpy = "^1.22.2" pytest = "^7.0.1" scipy = "^1.8.0" unittest2 = "^1.1.0" +wrapt = "^1.14.0" [tool.poetry.dev-dependencies] bandit = "1.7.2" diff --git a/src/lava/magma/core/process/ports/ports.py b/src/lava/magma/core/process/ports/ports.py index 7dc0f8b82..e3a43be68 100644 --- a/src/lava/magma/core/process/ports/ports.py +++ b/src/lava/magma/core/process/ports/ports.py @@ -2,11 +2,14 @@ # 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 import numpy as np import functools as ft +import wrapt from lava.magma.core.process.interfaces import AbstractProcessMember import lava.magma.core.process.ports.exceptions as pe @@ -70,8 +73,8 @@ def __init__(self, shape: ty.Tuple): def _validate_ports( self, - ports: ty.List["AbstractPort"], - port_type: ty.Type["AbstractPort"], + ports: ty.List[AbstractPort], + port_type: ty.Type[AbstractPort], assert_same_shape: bool = True, assert_same_type: bool = False, ): @@ -95,14 +98,14 @@ def _validate_ports( "are incompatible." .format(self.shape, p.shape)) - def _add_inputs(self, inputs: ty.List["AbstractPort"]): + def _add_inputs(self, inputs: ty.List[AbstractPort]): """Adds new input connections to port. Does not allow that same inputs get connected more than once to port.""" if not is_disjoint(self.in_connections, inputs): raise pe.DuplicateConnectionError() self.in_connections += inputs - def _add_outputs(self, outputs: ty.List["AbstractPort"]): + def _add_outputs(self, outputs: ty.List[AbstractPort]): """Adds new output connections to port. Does not allow that same outputs get connected more than once to port.""" if not is_disjoint(self.out_connections, outputs): @@ -111,8 +114,8 @@ def _add_outputs(self, outputs: ty.List["AbstractPort"]): def _connect_forward( self, - ports: ty.List["AbstractPort"], - port_type: ty.Type["AbstractPort"], + ports: ty.List[AbstractPort], + port_type: ty.Type[AbstractPort], assert_same_shape: bool = True, assert_same_type: bool = True, ): @@ -131,8 +134,8 @@ def _connect_forward( def _connect_backward( self, - ports: ty.List["AbstractPort"], - port_type: ty.Type["AbstractPort"], + ports: ty.List[AbstractPort], + port_type: ty.Type[AbstractPort], assert_same_shape: bool = True, assert_same_type: bool = True, ): @@ -150,7 +153,7 @@ def _connect_backward( for p in ports: p._add_outputs([self]) - def get_src_ports(self, _include_self=False) -> ty.List["AbstractPort"]: + def get_src_ports(self, _include_self=False) -> ty.List[AbstractPort]: """Returns the list of all source ports that connect either directly or indirectly (through other ports) to this port.""" if len(self.in_connections) == 0: @@ -182,7 +185,7 @@ def get_incoming_transform_funcs(self) -> ty.Dict[str, ty.List[ft.partial]]: return transform_funcs def get_incoming_virtual_ports(self) \ - -> ty.Tuple[str, ty.List["AbstractVirtualPort"]]: + -> ty.Tuple[str, ty.List[AbstractVirtualPort]]: """Returns the list of all incoming virtual ports in order from source to the current port. @@ -232,7 +235,7 @@ def get_outgoing_transform_funcs(self) -> ty.Dict[str, ty.List[ft.partial]]: return transform_funcs def get_outgoing_virtual_ports(self) \ - -> ty.Tuple[str, ty.List["AbstractVirtualPort"]]: + -> ty.Tuple[str, ty.List[AbstractVirtualPort]]: """Returns the list of all outgoing virtual ports in order from the current port to the destination port. @@ -264,7 +267,7 @@ def get_outgoing_virtual_ports(self) \ return dst_port_id, virtual_ports - def get_dst_ports(self, _include_self=False) -> ty.List["AbstractPort"]: + def get_dst_ports(self, _include_self=False) -> ty.List[AbstractPort]: """Returns the list of all destination ports that this port connects to either directly or indirectly (through other ports).""" if len(self.out_connections) == 0: @@ -278,7 +281,11 @@ def get_dst_ports(self, _include_self=False) -> ty.List["AbstractPort"]: ports += p.get_dst_ports(True) return ports - def reshape(self, new_shape: ty.Tuple[int, ...]) -> "ReshapePort": + def reshape( + self, + new_shape: ty.Tuple[int, ...] + ) -> ty.Union[RefPortInterface, OutPortInterface, InPortInterface, + VarPortInterface, ReshapePort]: """Reshapes this port by deriving and returning a new virtual ReshapePort with the new shape. This implies that the resulting ReshapePort can only be forward connected to another port. @@ -291,23 +298,31 @@ def reshape(self, new_shape: ty.Tuple[int, ...]) -> "ReshapePort": if self.size != math.prod(new_shape): raise pe.ReshapeError(self.shape, new_shape) - reshape_port = ReshapePort(new_shape, old_shape=self.shape) + # create a virtual ReshapePort and decorate it with the interface of + # the current (parent) port + reshape_port = self._decorate_virtual_port( + ReshapePort(new_shape, old_shape=self.shape)) + self._connect_forward( [reshape_port], AbstractPort, assert_same_shape=False ) return reshape_port - def flatten(self) -> "ReshapePort": + def flatten( + self + ) -> ty.Union[RefPortInterface, OutPortInterface, InPortInterface, + VarPortInterface, ReshapePort]: """Flattens this port to a (N,)-shaped port by deriving and returning a new virtual ReshapePort with a N equal to the total number of elements of this port.""" return self.reshape((self.size,)) def concat_with( - self, - ports: ty.Union["AbstractPort", ty.List["AbstractPort"]], - axis: int, - ) -> "ConcatPort": + self, + ports: ty.Union[AbstractPort, ty.List[AbstractPort]], + axis: int, + ) -> ty.Union[RefPortInterface, OutPortInterface, InPortInterface, + VarPortInterface, ConcatPort]: """Concatenates this port with other ports in given order along given axis by deriving and returning a new virtual ConcatPort. This implies resulting ConcatPort can only be forward connected to another port. @@ -325,13 +340,17 @@ def concat_with( else: port_type = AbstractRVPort self._validate_ports(ports, port_type, assert_same_shape=False) - return ConcatPort(ports, axis) + + # create a virtual ConcatPort and decorate it with the interface of + # the current (parent) port + return self._decorate_virtual_port(ConcatPort(ports, axis)) def transpose( self, axes: ty.Optional[ty.Union[ty.Tuple[int, ...], ty.List]] = None - ) -> "TransposePort": + ) -> ty.Union[RefPortInterface, OutPortInterface, InPortInterface, + VarPortInterface, TransposePort]: """Permutes the tensor dimension of this port by deriving and returning a new virtual TransposePort the new permuted dimension. This implies that the resulting TransposePort can only be forward connected to @@ -358,12 +377,54 @@ def transpose( raise pe.TransposeIndexError(self.shape, axes, idx) new_shape = tuple([self.shape[i] for i in axes]) - transpose_port = TransposePort(new_shape, axes) + + # create a virtual TransposePort and decorate it with the interface of + # the current (parent) port + transpose_port = self._decorate_virtual_port( + TransposePort(new_shape, axes)) + self._connect_forward( [transpose_port], AbstractPort, assert_same_shape=False ) return transpose_port + def _decorate_virtual_port( + self, + virtual_port: AbstractVirtualPort + ) -> ty.Union[RefPortInterface, OutPortInterface, InPortInterface, + VarPortInterface, AbstractVirtualPort]: + """Wraps the given virtual port into a decorator class that has the + same interface as the current port. This is used in the creation of + virtual ports, which need to 'inherit' the same kind of interface and + capabilities as their parent port. If a virtual port is, + for instance, created based on a RefPort, maybe by calling + >>> rp = RefPort(shape=(1, 2, 3) + >>> virtual_port = rp.reshape(new_shape=(6,)) + then the user must be able to call any method on the virtual port + that is also available on a RefPort (and makes sense in that + context). + + Parameters + ---------- + virtual_port : AbstractVirtualPort + the virtual port that should be decorated + + Returns + ------- + virtual_port : AbstractVirtualPort + the decorated virtual port + """ + if isinstance(self, RefPortInterface): + return RefPortDecorator(virtual_port) + elif isinstance(self, OutPortInterface): + return OutPortDecorator(virtual_port) + elif isinstance(self, InPortInterface): + return InPortDecorator(virtual_port) + elif isinstance(self, VarPortInterface): + return VarPortDecorator(virtual_port) + else: + return virtual_port + class AbstractIOPort(AbstractPort): """Abstract base class for InPorts and OutPorts. @@ -403,18 +464,11 @@ class AbstractDstPort(ABC): pass -class OutPort(AbstractIOPort, AbstractSrcPort): - """Output ports are members of a Lava Process and can be connected to - other ports to facilitate sending of messages via channels. - - OutPorts connect to other InPorts of peer processes or to other OutPorts of - processes that contain this OutPort's parent process as a sub process. - Similarly, OutPorts can receive connections from other OutPorts of nested - sub processes. - """ - +class OutPortInterface(AbstractPort): + """Interface of the OutPort that can be decorated on a virtual port using + the OutPortDecorator class.""" def connect( - self, ports: ty.Union["AbstractIOPort", ty.List["AbstractIOPort"]] + self, ports: ty.Union[AbstractIOPort, ty.List[AbstractIOPort]] ): """Connects this OutPort to other InPort(s) of another process or to OutPort(s) of its parent process. @@ -425,7 +479,18 @@ def connect( """ self._connect_forward(to_list(ports), AbstractIOPort) - def connect_from(self, ports: ty.Union["OutPort", ty.List["OutPort"]]): + +class OutPort(OutPortInterface, AbstractIOPort, AbstractSrcPort): + """Output ports are members of a Lava Process and can be connected to + other ports to facilitate sending of messages via channels. + + OutPorts connect to other InPorts of peer processes or to other OutPorts of + processes that contain this OutPort's parent process as a sub process. + Similarly, OutPorts can receive connections from other OutPorts of nested + sub processes. + """ + + def connect_from(self, ports: ty.Union[OutPort, ty.List[OutPort]]): """Connects other OutPort(s) of a nested process to this OutPort. OutPorts cannot receive connections from other InPorts. @@ -436,7 +501,27 @@ def connect_from(self, ports: ty.Union["OutPort", ty.List["OutPort"]]): self._connect_backward(to_list(ports), OutPort) -class InPort(AbstractIOPort, AbstractDstPort): +class OutPortDecorator(wrapt.ObjectProxy, OutPortInterface): + """Enables decorating a virtual port with the interface of an OutPort.""" + def __init__(self, wrapped: AbstractVirtualPort): + super().__init__(wrapped) + + +class InPortInterface(AbstractPort): + """Interface of the InPort that can be decorated on a virtual port using + the InPortDecorator class.""" + def connect(self, ports: ty.Union[InPort, ty.List[InPort]]): + """Connects this InPort to other InPort(s) of a nested process. InPorts + cannot connect to other OutPorts. + + Parameters + ---------- + :param ports: The InPort(s) to connect to. + """ + self._connect_forward(to_list(ports), InPort) + + +class InPort(InPortInterface, AbstractIOPort, AbstractDstPort): """Input ports are members of a Lava Process and can be connected to other ports to facilitate receiving of messages via channels. @@ -454,18 +539,8 @@ def __init__( super().__init__(shape) self._reduce_op = reduce_op - def connect(self, ports: ty.Union["InPort", ty.List["InPort"]]): - """Connects this InPort to other InPort(s) of a nested process. InPorts - cannot connect to other OutPorts. - - Parameters - ---------- - :param ports: The InPort(s) to connect to. - """ - self._connect_forward(to_list(ports), InPort) - def connect_from( - self, ports: ty.Union["AbstractIOPort", ty.List["AbstractIOPort"]] + self, ports: ty.Union[AbstractIOPort, ty.List[AbstractIOPort]] ): """Connects other OutPort(s) to this InPort or connects other InPort(s) of parent process to this InPort. @@ -477,29 +552,18 @@ def connect_from( self._connect_backward(to_list(ports), AbstractIOPort) -# TODO: (PP) enable connecting multiple Vars/VarPorts/RefPort to a RefPort -class RefPort(AbstractRVPort, AbstractSrcPort): - """RefPorts are members of a Lava Process and can be connected to - internal Lava Vars of other processes to facilitate direct shared memory - access to those processes. +class InPortDecorator(wrapt.ObjectProxy, InPortInterface): + """Enables decorating a virtual port with the interface of an InPort.""" + def __init__(self, wrapped: AbstractVirtualPort): + super().__init__(wrapped) - Shared-memory-based communication can have side-effects and should - therefore be used with caution. - - RefPorts connect to other VarPorts of peer processes or to other RefPorts - of processes that contain this RefPort's parent process as a sub process - via the connect(..) method.. - Similarly, RefPorts can receive connections from other RefPorts of nested - sub processes via the connect_from(..) method. - - Here, VarPorts only serve as a wrapper for Vars. VarPorts can be created - statically during process definition to explicitly expose a Var for - remote memory access (which might be safer). - Alternatively, VarPorts can be created dynamically by connecting a - RefPort to a Var via the connect_var(..) method.""" +# TODO: (PP) enable connecting multiple Vars/VarPorts/RefPort to a RefPort +class RefPortInterface(AbstractPort): + """Interface of the RefPort that can be decorated on a virtual port using + the RefPortDecorator class.""" def connect( - self, ports: ty.Union["AbstractRVPort", ty.List["AbstractRVPort"]] + self, ports: ty.Union[AbstractRVPort, ty.List[AbstractRVPort]] ): """Connects this RefPort to other VarPort(s) of another process or to RefPort(s) of its parent process. @@ -509,12 +573,13 @@ def connect( :param ports: The AbstractRVPort(s) to connect to. """ + if isinstance(ports, list) and len(ports) == 1: + ports = ports[0] + # Check if multiple ports should be connected (currently not supported) if len(to_list(ports)) > 1 \ - or (len(self.get_dst_ports()) > 0 - and not isinstance(ports, AbstractSrcPort)) \ - or (len(self.get_src_ports()) > 0 - and not isinstance(ports, AbstractDstPort)): + or len(self.get_dst_ports()) > 0 \ + or len(ports.get_src_ports()) > 0: raise AssertionError( "Currently only 1:1 connections are supported for RefPorts:" " {!r}: {!r}".format( @@ -530,35 +595,6 @@ def connect( p.process.__class__.__name__, p.name)) self._connect_forward(to_list(ports), AbstractRVPort) - def connect_from(self, ports: ty.Union["RefPort", ty.List["RefPort"]]): - """Connects other RefPort(s) of a nested process to this RefPort. - RefPorts cannot receive connections from other VarPorts. - - Parameters - ---------- - :param ports: The RefPort(s) that connect to this RefPort. - """ - - # Check if multiple ports should be connected (currently not supported) - if len(to_list(ports)) > 1 \ - or (len(self.get_dst_ports()) > 0 - and not isinstance(ports, AbstractSrcPort)) \ - or (len(self.get_src_ports()) > 0 - and not isinstance(ports, AbstractDstPort)): - raise AssertionError( - "Currently only 1:1 connections are supported for RefPorts:" - " {!r}: {!r}".format( - self.process.__class__.__name__, self.name)) - - for p in to_list(ports): - if not isinstance(p, RefPort): - raise TypeError( - "RefPorts can only receive connections from RefPorts: " - "{!r}: {!r} -> {!r}: {!r}".format( - self.process.__class__.__name__, self.name, - p.process.__class__.__name__, p.name)) - self._connect_backward(to_list(ports), RefPort) - def connect_var(self, variables: ty.Union[Var, ty.List[Var]]): """Connects this RefPort to Lava Process Var(s) to facilitate shared memory access. @@ -569,11 +605,7 @@ def connect_var(self, variables: ty.Union[Var, ty.List[Var]]): """ # Check if multiple ports should be connected (currently not supported) - if len(to_list(variables)) > 1 \ - or (len(self.get_dst_ports()) > 0 - and not isinstance(variables, AbstractSrcPort)) \ - or (len(self.get_src_ports()) > 0 - and not isinstance(variables, AbstractDstPort)): + if len(to_list(variables)) > 1: raise AssertionError( "Currently only 1:1 connections are supported for RefPorts:" " {!r}: {!r}".format( @@ -610,7 +642,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) @@ -630,36 +662,69 @@ def create_implicit_var_port(var: Var) -> "ImplicitVarPort": return vp -# TODO: (PP) enable connecting multiple VarPorts/RefPorts to a VarPort -class VarPort(AbstractRVPort, AbstractDstPort): - """VarPorts are members of a Lava Process and act as a wrapper for - internal Lava Vars to facilitate connections between RefPorts and Vars - for shared memory access from the parent process of the RefPort to - the parent process of the Var. +# TODO: (PP) enable connecting multiple Vars/VarPorts/RefPort to a RefPort +class RefPort(RefPortInterface, AbstractRVPort, AbstractSrcPort): + """RefPorts are members of a Lava Process and can be connected to + internal Lava Vars of other processes to facilitate direct shared memory + access to those processes. Shared-memory-based communication can have side-effects and should therefore be used with caution. - VarPorts can receive connections from other RefPorts of peer processes - or from other VarPorts of processes that contain this VarPort's parent - process as a sub process via the connect(..) method. Similarly, VarPorts - can connect to other VarPorts of nested sub processes via the - connect_from(..) method. + RefPorts connect to other VarPorts of peer processes or to other RefPorts + of processes that contain this RefPort's parent process as a sub process + via the connect(..) method.. + Similarly, RefPorts can receive connections from other RefPorts of nested + sub processes via the connect_from(..) method. - VarPorts can either be created in the constructor of a Process to - explicitly expose a Var for shared memory access (which might be safer). + Here, VarPorts only serve as a wrapper for Vars. VarPorts can be created + statically during process definition to explicitly expose a Var for + remote memory access (which might be safer). Alternatively, VarPorts can be created dynamically by connecting a - RefPort to a Var via the RefPort.connect_var(..) method.""" + RefPort to a Var via the connect_var(..) method.""" + + def connect_from(self, ports: ty.Union[RefPort, ty.List[RefPort]]): + """Connects other RefPort(s) of a nested process to this RefPort. + RefPorts cannot receive connections from other VarPorts. + + Parameters + ---------- + :param ports: The RefPort(s) that connect to this RefPort. + """ + + # Check if multiple ports should be connected (currently not supported) + if len(to_list(ports)) > 1 \ + or (len(self.get_dst_ports()) > 0 + and not isinstance(ports, AbstractSrcPort)) \ + or (len(self.get_src_ports()) > 0 + and not isinstance(ports, AbstractDstPort)): + raise AssertionError( + "Currently only 1:1 connections are supported for RefPorts:" + " {!r}: {!r}".format( + self.process.__class__.__name__, self.name)) + + for p in to_list(ports): + if not isinstance(p, RefPort): + raise TypeError( + "RefPorts can only receive connections from RefPorts: " + "{!r}: {!r} -> {!r}: {!r}".format( + self.process.__class__.__name__, self.name, + p.process.__class__.__name__, p.name)) + self._connect_backward(to_list(ports), RefPort) - def __init__(self, var: Var): - if not isinstance(var, Var): - raise AssertionError("'var' must be of type Var.") - if not var.shareable: - raise pe.VarNotSharableError(var.name) - AbstractRVPort.__init__(self, var.shape) - self.var = var - def connect(self, ports: ty.Union["VarPort", ty.List["VarPort"]]): +class RefPortDecorator(wrapt.ObjectProxy, RefPortInterface): + """Enables decorating a virtual port with the interface of a RefPort.""" + def __init__(self, wrapped: AbstractVirtualPort): + super().__init__(wrapped) + + +# TODO: (PP) enable connecting multiple VarPorts/RefPorts to a VarPort +class VarPortInterface(AbstractPort): + """Interface of the VarPort that can be decorated on a virtual port using + the VarPortDecorator class.""" + + def connect(self, ports: ty.Union[VarPort, ty.List[VarPort]]): """Connects this VarPort to other VarPort(s) of a nested process. VarPorts cannot connect to other RefPorts. @@ -688,8 +753,38 @@ def connect(self, ports: ty.Union["VarPort", ty.List["VarPort"]]): p.process.__class__.__name__, p.name)) self._connect_forward(to_list(ports), VarPort) + +# TODO: (PP) enable connecting multiple VarPorts/RefPorts to a VarPort +class VarPort(VarPortInterface, AbstractRVPort, AbstractDstPort): + """VarPorts are members of a Lava Process and act as a wrapper for + internal Lava Vars to facilitate connections between RefPorts and Vars + for shared memory access from the parent process of the RefPort to + the parent process of the Var. + + Shared-memory-based communication can have side-effects and should + therefore be used with caution. + + VarPorts can receive connections from other RefPorts of peer processes + or from other VarPorts of processes that contain this VarPort's parent + process as a sub process via the connect(..) method. Similarly, VarPorts + can connect to other VarPorts of nested sub processes via the + connect_from(..) method. + + VarPorts can either be created in the constructor of a Process to + explicitly expose a Var for shared memory access (which might be safer). + Alternatively, VarPorts can be created dynamically by connecting a + RefPort to a Var via the RefPort.connect_var(..) method.""" + + def __init__(self, var: Var): + if not isinstance(var, Var): + raise AssertionError("'var' must be of type Var.") + if not var.shareable: + raise pe.VarNotSharableError(var.name) + AbstractRVPort.__init__(self, var.shape) + self.var = var + def connect_from( - self, ports: ty.Union["AbstractRVPort", ty.List["AbstractRVPort"]] + self, ports: ty.Union[AbstractRVPort, ty.List[AbstractRVPort]] ): """Connects other RefPort(s) to this VarPort or connects other VarPort(s) of parent process to this VarPort. @@ -720,6 +815,12 @@ def connect_from( self._connect_backward(to_list(ports), AbstractRVPort) +class VarPortDecorator(wrapt.ObjectProxy, VarPortInterface): + """Enables decorating a virtual port with the interface of a VarPort.""" + def __init__(self, wrapped: AbstractVirtualPort): + super().__init__(wrapped) + + class ImplicitVarPort(VarPort): """Sub class for VarPort to identify implicitly created VarPorts when a RefPort connects directly to a Var.""" @@ -741,32 +842,6 @@ def process(self): derived from.""" return self._parent_port.process - def connect(self, ports: ty.Union["AbstractPort", ty.List["AbstractPort"]]): - """Connects this virtual port to other port(s). - - Parameters - ---------- - :param ports: The port(s) to connect to. Connections from an IOPort - to a RVPort and vice versa are not allowed. - """ - # Determine allows port_type - if isinstance(self._parent_port, OutPort): - # If OutPort, only allow other IO ports - port_type = AbstractIOPort - elif isinstance(self._parent_port, InPort): - # If InPort, only allow other InPorts - port_type = InPort - elif isinstance(self._parent_port, RefPort): - # If RefPort, only allow other Ref- or VarPorts - port_type = AbstractRVPort - elif isinstance(self._parent_port, VarPort): - # If VarPort, only allow other VarPorts - port_type = VarPort - else: - raise TypeError("Illegal parent port.") - # Connect to ports - self._connect_forward(to_list(ports), port_type) - @abstractmethod def get_transform_func_fwd(self) -> ft.partial: """Returns a function pointer that implements the forward (fwd) diff --git a/tests/lava/magma/core/process/ports/test_ports.py b/tests/lava/magma/core/process/ports/test_ports.py index 0e6fe26c4..cbb275253 100644 --- a/tests/lava/magma/core/process/ports/test_ports.py +++ b/tests/lava/magma/core/process/ports/test_ports.py @@ -330,6 +330,53 @@ def test_connect_RefPort_to_many_Vars(self): self.assertIsInstance(vps[1], VarPort) self.assertNotEqual(vps[0], vps[1]) + # TODO (MR): Remove this unit test as soon as 1:many connections are + # implemented. + def test_connect_RefPort_to_many_Vars_raises_exception(self): + """Checks that a RefPort cannot be connected to many Vars.""" + + # We can have multiple Vars... + v1 = Var((1, 2, 3)) + v2 = Var((1, 2, 3)) + # ...and connect a RefPort to them + rp = RefPort((1, 2, 3)) + with self.assertRaises(AssertionError): + rp.connect_var([v1, v2]) + + # TODO (MR): Remove this unit test as soon as 1:many connections are + # implemented. + def test_connect_RefPort_to_connected_RefPort_raises_exception(self): + """Checks that a RefPort cannot be connected to another RefPort that + alread has an incoming connection.""" + + rp1 = RefPort((1, 2, 3)) + rp2 = RefPort((1, 2, 3)) + rp3 = RefPort((1, 2, 3)) + + # We can connect two RefPorts... + rp1.connect(rp3) + + # ...but we cannot connect another RefPort to one that has already + # been connected. + with self.assertRaises(AssertionError): + rp2.connect(rp3) + + # TODO (MR): Remove this unit test as soon as 1:many connections are + # implemented. + def test_connect_RefPort_to_multiple_RefPorts_raises_exception(self): + """Checks that a RefPort cannot be connected multiple RefPorts.""" + + rp1 = RefPort((1, 2, 3)) + rp2 = RefPort((1, 2, 3)) + rp3 = RefPort((1, 2, 3)) + + # We can connect two RefPorts... + rp1.connect(rp3) + + # ...but we cannot connect the first RefPort to another RefPort. + with self.assertRaises(AssertionError): + rp1.connect(rp2) + def test_connect_RefPort_to_Var_with_incompatible_shape(self): """Checks that shapes must be compatible when connecting ports.""" diff --git a/tests/lava/magma/core/process/ports/test_virtual_ports_in_process.py b/tests/lava/magma/core/process/ports/test_virtual_ports_in_process.py index d19c294e9..cfc73f072 100644 --- a/tests/lava/magma/core/process/ports/test_virtual_ports_in_process.py +++ b/tests/lava/magma/core/process/ports/test_virtual_ports_in_process.py @@ -7,7 +7,6 @@ import numpy as np import functools as ft -from lava.magma.compiler.compiler import Compiler from lava.magma.core.decorator import requires, tag, implements from lava.magma.core.model.py.model import PyLoihiProcessModel from lava.magma.core.model.sub.model import AbstractSubProcessModel @@ -30,7 +29,11 @@ InPort, OutPort, RefPort, - VarPort + VarPort, + RefPortDecorator, + OutPortDecorator, + InPortDecorator, + VarPortDecorator ) @@ -72,6 +75,7 @@ def test_outport_to_inport_in_hierarchical_processes(self) -> None: virtual_port = MockVirtualPort(new_shape=self.new_shape, axes=self.axes) + virtual_port = OutPortDecorator(virtual_port) source.out_port._connect_forward( [virtual_port], AbstractPort, assert_same_shape=False @@ -308,8 +312,10 @@ def test_chaining_multiple_virtual_ports(self) -> None: virtual_port1 = MockVirtualPort(new_shape=self.new_shape, axes=self.axes) + virtual_port1 = OutPortDecorator(virtual_port1) virtual_port2 = MockVirtualPort(new_shape=self.shape, axes=tuple(np.argsort(self.axes))) + virtual_port2 = OutPortDecorator(virtual_port2) source.out_port._connect_forward( [virtual_port1], AbstractPort, assert_same_shape=False @@ -344,8 +350,10 @@ def test_multiple_virtual_ports_connected_to_an_inport(self) -> None: virtual_port1 = MockVirtualPort(new_shape=self.new_shape, axes=self.axes) + virtual_port1 = OutPortDecorator(virtual_port1) virtual_port2 = MockVirtualPort(new_shape=self.new_shape, axes=(0, 2, 1)) + virtual_port2 = OutPortDecorator(virtual_port2) source1.out_port._connect_forward( [virtual_port1], AbstractPort, assert_same_shape=False @@ -373,6 +381,101 @@ def test_multiple_virtual_ports_connected_to_an_inport(self) -> None: f'{expected[output!=expected] =}\n' ) + def test_refport_writing_to_var(self) -> None: + """Tests connecting a (writing) RefPort to a Var via a virtual port.""" + source = RefPortWriteProcess(data=self.input_data) + sink = VarPortProcess(data=np.zeros(self.new_shape)) + + virtual_port = MockVirtualPort(new_shape=self.new_shape, + axes=self.axes) + virtual_port = RefPortDecorator(virtual_port) + + source.ref_port._connect_forward( + [virtual_port], AbstractPort, assert_same_shape=False + ) + virtual_port.connect_var(sink.data) + + try: + sink.run(condition=RunSteps(num_steps=self.num_steps), + run_cfg=Loihi1SimCfg(select_tag='floating_pt')) + output = sink.data.get() + finally: + sink.stop() + + expected = self.input_data.transpose(self.axes) + self.assertTrue( + np.all(output == expected), + f'Input and output do not match.\n' + f'{output[output!=expected]=}\n' + f'{expected[output!=expected] =}\n' + ) + + def test_chaining_virtual_ports_from_refport_writing_to_var(self) -> None: + """Tests connecting a (writing) RefPort to a Var via a virtual port.""" + source = RefPortWriteProcess(data=self.input_data) + sink = VarPortProcess(data=np.zeros(self.shape)) + + virtual_port1 = MockVirtualPort(new_shape=self.new_shape, + axes=self.axes) + virtual_port2 = MockVirtualPort(new_shape=self.shape, + axes=tuple(np.argsort(self.axes))) + + virtual_port1 = RefPortDecorator(virtual_port1) + virtual_port2 = RefPortDecorator(virtual_port2) + + source.ref_port._connect_forward( + [virtual_port1], AbstractPort, assert_same_shape=False + ) + virtual_port1._connect_forward( + [virtual_port2], AbstractPort, assert_same_shape=False + ) + + virtual_port2.connect_var(sink.data) + try: + sink.run(condition=RunSteps(num_steps=self.num_steps), + run_cfg=Loihi1SimCfg(select_tag='floating_pt')) + output = sink.data.get() + finally: + sink.stop() + + expected = self.input_data + self.assertTrue( + np.all(output == expected), + f'Input and output do not match.\n' + f'{output[output!=expected]=}\n' + f'{expected[output!=expected] =}\n' + ) + + def test_refport_reading_from_var(self) -> None: + """Tests connecting a (reading) RefPort to a Var via a virtual port.""" + source = RefPortReadProcess(data=np.zeros(self.shape)) + sink = VarPortProcess(data=self.input_data.transpose(self.axes)) + + virtual_port = MockVirtualPort(new_shape=self.new_shape, + axes=self.axes) + + virtual_port = RefPortDecorator(virtual_port) + + source.ref_port._connect_forward( + [virtual_port], AbstractPort, assert_same_shape=False + ) + virtual_port.connect_var(sink.data) + + try: + sink.run(condition=RunSteps(num_steps=self.num_steps), + run_cfg=Loihi1SimCfg(select_tag='floating_pt')) + output = source.data.get() + finally: + sink.stop() + + expected = self.input_data + self.assertTrue( + np.all(output == expected), + f'Input and output do not match.\n' + f'{output[output!=expected]=}\n' + f'{expected[output!=expected] =}\n' + ) + class TestTransposePort(unittest.TestCase): """Tests virtual TransposePorts on Processes that are executed.""" @@ -458,6 +561,30 @@ def test_transpose_refport_read_from_varport(self) -> None: f'{expected[output!=expected] =}\n' ) + def test_transpose_refport_write_to_var(self) -> None: + """Tests a virtual TransposePort between a RefPort and a Var (via an + ImplicitVarPort), where the RefPort writes to the Var.""" + + source = RefPortWriteProcess(data=self.input_data) + sink = VarPortProcess(data=np.zeros(self.shape_transposed)) + + source.ref_port.transpose(axes=self.axes).connect_var(sink.data) + + try: + sink.run(condition=RunSteps(num_steps=self.num_steps), + run_cfg=Loihi1SimCfg(select_tag='floating_pt')) + output = sink.data.get() + finally: + sink.stop() + + expected = self.input_data.transpose(self.axes) + self.assertTrue( + np.all(output == expected), + f'Input and output do not match.\n' + f'{output[output!=expected]=}\n' + f'{expected[output!=expected] =}\n' + ) + class TestReshapePort(unittest.TestCase): """Tests virtual ReshapePorts on Processes that are executed.""" @@ -540,6 +667,30 @@ def test_reshape_refport_read_from_varport(self) -> None: f'{expected[output!=expected] =}\n' ) + def test_reshape_refport_write_to_var(self) -> None: + """Tests a virtual ReshapePort between a RefPort and a Var, + where the RefPort writes to the Var.""" + + source = RefPortWriteProcess(data=self.input_data) + sink = VarPortProcess(data=np.zeros(self.shape_reshaped)) + + source.ref_port.reshape(self.shape_reshaped).connect_var(sink.data) + + try: + sink.run(condition=RunSteps(num_steps=self.num_steps), + run_cfg=Loihi1SimCfg(select_tag='floating_pt')) + output = sink.data.get() + finally: + sink.stop() + + expected = self.input_data.reshape(self.shape_reshaped) + self.assertTrue( + np.all(output == expected), + f'Input and output do not match.\n' + f'{output[output!=expected]=}\n' + f'{expected[output!=expected] =}\n' + ) + class TestFlattenPort(unittest.TestCase): """Tests virtual ReshapePorts, created by the flatten() method, @@ -623,6 +774,30 @@ def test_flatten_refport_read_from_varport(self) -> None: f'{expected[output!=expected] =}\n' ) + def test_flatten_refport_write_to_var(self) -> None: + """Tests a virtual ReshapePort with flatten() between a RefPort and a + Var, where the RefPort writes to the Var.""" + + source = RefPortWriteProcess(data=self.input_data) + sink = VarPortProcess(data=np.zeros(self.shape_reshaped)) + + source.ref_port.flatten().connect_var(sink.data) + + try: + sink.run(condition=RunSteps(num_steps=self.num_steps), + run_cfg=Loihi1SimCfg(select_tag='floating_pt')) + output = sink.data.get() + finally: + sink.stop() + + expected = self.input_data.ravel() + self.assertTrue( + np.all(output == expected), + f'Input and output do not match.\n' + f'{output[output!=expected]=}\n' + f'{expected[output!=expected] =}\n' + ) + # A minimal Process with an OutPort class OutPortProcess(AbstractProcess): @@ -726,6 +901,7 @@ def __init__(self, proc): virtual_port = MockVirtualPort(new_shape=proc.proc_params['s_shape'], axes=proc.proc_params['axes']) + virtual_port = InPortDecorator(virtual_port) proc.in_port._connect_forward( [virtual_port], AbstractPort, assert_same_shape=False ) @@ -757,6 +933,7 @@ def __init__(self, proc): virtual_port = MockVirtualPort(new_shape=proc.proc_params['h_shape'], axes=proc.proc_params['axes']) + virtual_port = OutPortDecorator(virtual_port) self.out_proc.out_port._connect_forward( [virtual_port], AbstractPort, assert_same_shape=False ) @@ -853,6 +1030,7 @@ def __init__(self, proc): virtual_port = MockVirtualPort(new_shape=proc.proc_params['h_shape'], axes=proc.proc_params['axes']) + virtual_port = RefPortDecorator(virtual_port) self.ref_write_proc.ref_port._connect_forward( [virtual_port], AbstractPort, assert_same_shape=False ) @@ -884,6 +1062,7 @@ def __init__(self, proc): virtual_port = MockVirtualPort(new_shape=proc.proc_params['h_shape'], axes=proc.proc_params['axes']) + virtual_port = RefPortDecorator(virtual_port) self.ref_read_proc.ref_port._connect_forward( [virtual_port], AbstractPort, assert_same_shape=False ) @@ -920,6 +1099,7 @@ def __init__(self, proc): virtual_port = MockVirtualPort(new_shape=s_data.shape, axes=proc.proc_params['axes']) + virtual_port = VarPortDecorator(virtual_port) proc.var_port._connect_forward( [virtual_port], AbstractPort, assert_same_shape=False ) From e1909904673cb8bd76e6598711e2152bae6c3843 Mon Sep 17 00:00:00 2001 From: Mathis Richter Date: Wed, 23 Mar 2022 00:13:44 +0100 Subject: [PATCH 2/2] Updated poetry lock file Signed-off-by: Mathis Richter --- poetry.lock | 350 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 212 insertions(+), 138 deletions(-) diff --git a/poetry.lock b/poetry.lock index 70ddbb45b..ae8cbf15e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -182,7 +182,7 @@ python-versions = ">=3.6,<4.0" [[package]] name = "cryptography" -version = "36.0.1" +version = "36.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "dev" optional = false @@ -225,7 +225,7 @@ python-versions = "*" [[package]] name = "docutils" -version = "0.16" +version = "0.17.1" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false @@ -288,7 +288,7 @@ pycodestyle = "*" [[package]] name = "flake8-bugbear" -version = "22.1.11" +version = "22.3.20" 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 @@ -440,7 +440,7 @@ docs = ["alabaster", "pygments-github-lexers", "recommonmark", "sphinx"] [[package]] name = "fonttools" -version = "4.29.1" +version = "4.31.2" description = "Tools to manipulate font files" category = "main" optional = false @@ -517,7 +517,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.11.2" +version = "4.11.3" description = "Read metadata from Python packages" category = "dev" optional = false @@ -599,7 +599,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [[package]] name = "kiwisolver" -version = "1.3.2" +version = "1.4.0" description = "A fast implementation of the Cassowary constraint solver" category = "main" optional = false @@ -623,7 +623,7 @@ python-versions = "*" [[package]] name = "markupsafe" -version = "2.1.0" +version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" optional = false @@ -882,11 +882,11 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.0.1" +version = "7.1.1" description = "pytest: simple powerful testing with Python" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} @@ -929,7 +929,7 @@ six = ">=1.5" [[package]] name = "pytz" -version = "2021.3" +version = "2022.1" description = "World timezone definitions, modern and historical" category = "dev" optional = false @@ -1100,14 +1100,14 @@ dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] [[package]] name = "sphinx-tabs" -version = "3.2.0" +version = "3.3.1" description = "Tabbed views for Sphinx" category = "dev" optional = false python-versions = "~=3.6" [package.dependencies] -docutils = ">=0.16.0,<0.17.0" +docutils = ">=0.17.0,<0.18.0" pygments = "*" sphinx = ">=2,<5" @@ -1260,20 +1260,20 @@ traceback2 = "*" [[package]] name = "urllib3" -version = "1.26.8" +version = "1.26.9" 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.*, <4" [package.extras] -brotli = ["brotlipy (>=0.6.0)"] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.13.3" +version = "20.13.4" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -1297,6 +1297,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "wrapt" +version = "1.14.0" +description = "Module for decorators, wrappers and monkey patching." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + [[package]] name = "zipp" version = "3.7.0" @@ -1312,7 +1320,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [metadata] lock-version = "1.1" python-versions = ">=3.8, <3.11" -content-hash = "71c6447f13faba04f761a8eaf7c1eb0632c18799c412d3118f8f70c8bf563610" +content-hash = "d3301bfbb0964fa57a808b34a8d77c4b6d24e569a87291c25a0a10d9ed1a010c" [metadata.files] alabaster = [ @@ -1467,26 +1475,26 @@ crashtest = [ {file = "crashtest-0.3.1.tar.gz", hash = "sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd"}, ] cryptography = [ - {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, - {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"}, - {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"}, - {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"}, - {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"}, - {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"}, - {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"}, + {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:4e2dddd38a5ba733be6a025a1475a9f45e4e41139d1321f412c6b360b19070b6"}, + {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:4881d09298cd0b669bb15b9cfe6166f16fc1277b4ed0d04a22f3d6430cb30f1d"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea634401ca02367c1567f012317502ef3437522e2fc44a3ea1844de028fa4b84"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7be666cc4599b415f320839e36367b273db8501127b38316f3b9f22f17a0b815"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8241cac0aae90b82d6b5c443b853723bcc66963970c67e56e71a2609dc4b5eaf"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2d54e787a884ffc6e187262823b6feb06c338084bbe80d45166a1cb1c6c5bf"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:c2c5250ff0d36fd58550252f54915776940e4e866f38f3a7866d92b32a654b86"}, + {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ec6597aa85ce03f3e507566b8bcdf9da2227ec86c4266bd5e6ab4d9e0cc8dab2"}, + {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ca9f686517ec2c4a4ce930207f75c00bf03d94e5063cbc00a1dc42531511b7eb"}, + {file = "cryptography-36.0.2-cp36-abi3-win32.whl", hash = "sha256:f64b232348ee82f13aac22856515ce0195837f6968aeaa94a3d0353ea2ec06a6"}, + {file = "cryptography-36.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:53e0285b49fd0ab6e604f4c5d9c5ddd98de77018542e88366923f152dbeb3c29"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:32db5cc49c73f39aac27574522cecd0a4bb7384e71198bc65a0d23f901e89bb7"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b3d199647468d410994dbeb8cec5816fb74feb9368aedf300af709ef507e3e"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:da73d095f8590ad437cd5e9faf6628a218aa7c387e1fdf67b888b47ba56a17f0"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0a3bf09bb0b7a2c93ce7b98cb107e9170a90c51a0162a20af1c61c765b90e60b"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8897b7b7ec077c819187a123174b645eb680c13df68354ed99f9b40a50898f77"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82740818f2f240a5da8dfb8943b360e4f24022b093207160c77cadade47d7c85"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1f64a62b3b75e4005df19d3b5235abd43fa6358d5516cfc43d87aeba8d08dd51"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e167b6b710c7f7bc54e67ef593f8731e1f45aa35f8a8a7b72d6e42ec76afd4b3"}, + {file = "cryptography-36.0.2.tar.gz", hash = "sha256:70f8f4f7bb2ac9f340655cbac89d68c527af5bb4387522a8413e841e3e6628c9"}, ] cycler = [ {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, @@ -1501,8 +1509,8 @@ distlib = [ {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, ] docutils = [ - {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, - {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, + {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, + {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, ] entrypoints = [ {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, @@ -1523,8 +1531,8 @@ flake8-bandit = [ {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, ] flake8-bugbear = [ - {file = "flake8-bugbear-22.1.11.tar.gz", hash = "sha256:4c2a4136bd4ecb8bf02d5159af302ffc067642784c9d0488b33ce4610da825ee"}, - {file = "flake8_bugbear-22.1.11-py3-none-any.whl", hash = "sha256:ce7ae44aaaf67ef192b8a6de94a5ac617144e1675ad0654fdea556f48dc18d9b"}, + {file = "flake8-bugbear-22.3.20.tar.gz", hash = "sha256:152e64a86f6bff6e295d630ccc993f62434c1fd2b20d2fae47547cb1c1b868e0"}, + {file = "flake8_bugbear-22.3.20-py3-none-any.whl", hash = "sha256:19fe179ee3286e16198603c438788e2949e79f31d653f0bdb56d53fb69217bd0"}, ] flake8-builtins = [ {file = "flake8-builtins-1.5.3.tar.gz", hash = "sha256:09998853b2405e98e61d2ff3027c47033adbdc17f9fe44ca58443d876eb00f3b"}, @@ -1571,8 +1579,8 @@ flakeheaven = [ {file = "flakeheaven-0.11.1.tar.gz", hash = "sha256:20f5a573b8e85be5a73fed2e3967f7ab8b5e77714a5898d8b634dd31a0b75f9b"}, ] fonttools = [ - {file = "fonttools-4.29.1-py3-none-any.whl", hash = "sha256:1933415e0fbdf068815cb1baaa1f159e17830215f7e8624e5731122761627557"}, - {file = "fonttools-4.29.1.zip", hash = "sha256:2b18a172120e32128a80efee04cff487d5d140fe7d817deb648b2eee023a40e4"}, + {file = "fonttools-4.31.2-py3-none-any.whl", hash = "sha256:2df636a3f402ef14593c6811dac0609563b8c374bd7850e76919eb51ea205426"}, + {file = "fonttools-4.31.2.zip", hash = "sha256:236b29aee6b113e8f7bee28779c1230a86ad2aac9a74a31b0aedf57e7dfb62a4"}, ] gitdb = [ {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, @@ -1595,8 +1603,8 @@ imagesize = [ {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.11.2-py3-none-any.whl", hash = "sha256:d16e8c1deb60de41b8e8ed21c1a7b947b0bc62fab7e1d470bcdf331cea2e6735"}, - {file = "importlib_metadata-4.11.2.tar.gz", hash = "sha256:b36ffa925fe3139b2f6ff11d6925ffd4fa7bc47870165e3ac260ac7b4f91e6ac"}, + {file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"}, + {file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, @@ -1619,50 +1627,49 @@ keyring = [ {file = "keyring-23.5.0.tar.gz", hash = "sha256:9012508e141a80bd1c0b6778d5c610dd9f8c464d75ac6774248500503f972fb9"}, ] kiwisolver = [ - {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6"}, - {file = "kiwisolver-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470"}, - {file = "kiwisolver-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298"}, - {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84"}, - {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb"}, - {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0"}, - {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402"}, - {file = "kiwisolver-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0"}, - {file = "kiwisolver-1.3.2-cp310-cp310-win32.whl", hash = "sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977"}, - {file = "kiwisolver-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-win32.whl", hash = "sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589"}, - {file = "kiwisolver-1.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8"}, - {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f"}, - {file = "kiwisolver-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84"}, - {file = "kiwisolver-1.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829"}, - {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af"}, - {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536"}, - {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76"}, - {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b"}, - {file = "kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28"}, - {file = "kiwisolver-1.3.2-cp38-cp38-win32.whl", hash = "sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c"}, - {file = "kiwisolver-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031"}, - {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507"}, - {file = "kiwisolver-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f"}, - {file = "kiwisolver-1.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9"}, - {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009"}, - {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6"}, - {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8"}, - {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b"}, - {file = "kiwisolver-1.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439"}, - {file = "kiwisolver-1.3.2-cp39-cp39-win32.whl", hash = "sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9"}, - {file = "kiwisolver-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386"}, - {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc"}, - {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f"}, - {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf"}, - {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223"}, - {file = "kiwisolver-1.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560"}, - {file = "kiwisolver-1.3.2.tar.gz", hash = "sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"}, + {file = "kiwisolver-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:70e7b7a4ebeddef423115ea31857732fc04e0f38dd1e6385e1af05b6164a3d0f"}, + {file = "kiwisolver-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:384b5076b2c0172003abca9ba8b8c5efcaaffd31616f3f5e0a09dcc34772d012"}, + {file = "kiwisolver-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:334a7e3d498a0a791245f0964c746d0414e9b13aef73237f0d798a2101fdbae9"}, + {file = "kiwisolver-1.4.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:734e943ae519cdb8534d9053f478417c525ec921c06896ec7119e65d9ea4a687"}, + {file = "kiwisolver-1.4.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:65cbdbe14dc5988e362eb15e02dd24c6724238cb235132f812f1e3a29a61a3de"}, + {file = "kiwisolver-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf0080449d6ea39b817d85abd2c20d2d42fd9b1587544d64371d28d93c379cf"}, + {file = "kiwisolver-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd0223a3a4ddcc0d0e06c6cfeb0adde2bc19c08b4c7fc79d48dac2486a4b115b"}, + {file = "kiwisolver-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed30c5e58e578a2981c67346b2569e04120d1b80fa6906c207fe824d24603313"}, + {file = "kiwisolver-1.4.0-cp310-cp310-win32.whl", hash = "sha256:ed937691f522cc2362c280c903837a4e35195659b9935b598e3cd448db863605"}, + {file = "kiwisolver-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:576ba51b9f4e4d0d583c1cd257f53397bdc5e66a5e49fe68712f658426115777"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2467fe5fff6ed2a728e10dca9b1f37e9b911ca5b228a7d8990c8e3abf80c1724"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff7ae6fb6dce2f520b2d46efc801605fa1378fb19bb4580aebc6174eab05a0"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:313724e85fd14d581a939fa02424f4dc772fd914bc04499a8a6377d47313b966"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb997d1631b20745b18674d68dd6f1d9d45db512efd5fe0f162a5d4a6bbdd211"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97372c837add54e3e64a811464b14bb01428c4e9256072b6296f04157ea23246"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4471a48f53d20d49f263ca888aab77b754525ef35e6767657e1a44a724a8b0af"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:1cf8c81e8a5fb4f5dcbd473fdb619b895313d29b7c60e4545827dcc6efbd8efc"}, + {file = "kiwisolver-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:87367ba1ad3819f7189fe8faff5f75a7603f526576033e7b86e10b598f8790b2"}, + {file = "kiwisolver-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:139c75216e5875ee5f8f4f7adcc3cd339f46f0d66bda2e10d8d21386d635476f"}, + {file = "kiwisolver-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:895b2df026006ff7434b03ca495983d0d26da96f6d58414c77d616747ee77e34"}, + {file = "kiwisolver-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbf9aa926de224af15c974750fecdc7d2c0043428372acaaf61216e202abbf21"}, + {file = "kiwisolver-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8cd1f81bc35ec24cb82a7d0b805521e3d71b25b8a493d5810d18dc29644c6ef8"}, + {file = "kiwisolver-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:199f32bf6f3d3e2246024326497513c5c49c62aecee86f0ac019f5991978d505"}, + {file = "kiwisolver-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af6a7c956a45ee721e4263f5823e1a3b2e6b21a7e2b3646b3794e000620609d0"}, + {file = "kiwisolver-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3891527ec51b0365bb50de9bf826ce3d5b1adc276685b2779889762437bbd359"}, + {file = "kiwisolver-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14f43edc25daa0646d4b4e86c2ebdd32d785ab73a65a570130a3d234a4554b07"}, + {file = "kiwisolver-1.4.0-cp38-cp38-win32.whl", hash = "sha256:5ecf82bb25cec7df4bfcf37afe49f6f6202b4fa4029be7cb0848ed319c72d356"}, + {file = "kiwisolver-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:34e2e39a219b203fa3a82af5b9f8d386a8718677de7a9b82a9634e292a8f4e0a"}, + {file = "kiwisolver-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c19457f58941da61681efaabd5b1c37893108a2f922b9b19538f6921911186d"}, + {file = "kiwisolver-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0a6f3d5063e7fd6662e4773778ad2cb36e598abc6eb171af4a072ca86b441d0"}, + {file = "kiwisolver-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:676f9fac93f97f529dc80b5d6731099fad337549408e8bdd929343b7cb679797"}, + {file = "kiwisolver-1.4.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4b70f0729947d6327cd659e1b3477ced44a317a4ba441238b2a3642990f0ebd7"}, + {file = "kiwisolver-1.4.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:925a32900fc16430ba0dec2c0fca2e776eaf2fdc0930d5552be0a59e23304001"}, + {file = "kiwisolver-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ec8bd4e162fd0a8723467395c5bb16fd665a528b78e9339886c82965ed8efb"}, + {file = "kiwisolver-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b4d1db32a4f1682df1480fd68eb1400235ac8f9ad8932e1624fdb23eb891904"}, + {file = "kiwisolver-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:38ebc0cb30ed2f59bd15e23591a53698005123e90e880f1af4600fcdbe4912e1"}, + {file = "kiwisolver-1.4.0-cp39-cp39-win32.whl", hash = "sha256:8f63b981678ca894bb665bcd5043bde2c9ba600e69df730c1ceeadd73ddbcb8c"}, + {file = "kiwisolver-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:b1ff5582bf55e85728119c5a23f695b8e408e15eee7d0f5effe0ee8ad1f8b523"}, + {file = "kiwisolver-1.4.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c29496625c61e18d97a6f6c2f2a55759ca8290fc21a751bc57824599c431c0d2"}, + {file = "kiwisolver-1.4.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:71d44a6a59ea53d41e5950a42ec496fa821bd86f292fb3e10aa1b3932ecfc65e"}, + {file = "kiwisolver-1.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf2030bf18c21bf91fa9cf6a403a765519c9168bd7a91ba1d66d5c7f70ded1e"}, + {file = "kiwisolver-1.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:5ca92de8e48678a2cbbd90adb10773e3553bb9fd1c090bf0dfe5fc3337a181ea"}, + {file = "kiwisolver-1.4.0.tar.gz", hash = "sha256:7508b01e211178a85d21f1f87029846b77b2404a4c68cbd14748d4d4142fa3b8"}, ] linecache2 = [ {file = "linecache2-1.0.0-py2.py3-none-any.whl", hash = "sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef"}, @@ -1673,46 +1680,46 @@ lockfile = [ {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, ] markupsafe = [ - {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-win32.whl", hash = "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454"}, - {file = "MarkupSafe-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a"}, - {file = "MarkupSafe-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-win32.whl", hash = "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8"}, - {file = "MarkupSafe-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-win32.whl", hash = "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05"}, - {file = "MarkupSafe-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7"}, - {file = "MarkupSafe-2.1.0.tar.gz", hash = "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, ] matplotlib = [ {file = "matplotlib-3.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:456cc8334f6d1124e8ff856b42d2cc1c84335375a16448189999496549f7182b"}, @@ -1796,6 +1803,7 @@ numpy = [ {file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"}, {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e"}, {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4"}, + {file = "numpy-1.22.3-cp310-cp310-win32.whl", hash = "sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430"}, {file = "numpy-1.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4"}, {file = "numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce"}, {file = "numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe"}, @@ -1926,8 +1934,8 @@ pyparsing = [ {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, ] pytest = [ - {file = "pytest-7.0.1-py3-none-any.whl", hash = "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db"}, - {file = "pytest-7.0.1.tar.gz", hash = "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"}, + {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"}, + {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"}, ] pytest-cov = [ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, @@ -1938,8 +1946,8 @@ python-dateutil = [ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, ] pytz = [ - {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, - {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, + {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, + {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, ] pywin32-ctypes = [ {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, @@ -2046,8 +2054,8 @@ sphinx-rtd-theme = [ {file = "sphinx_rtd_theme-1.0.0.tar.gz", hash = "sha256:eec6d497e4c2195fa0e8b2016b337532b8a699a68bcb22a512870e16925c6a5c"}, ] sphinx-tabs = [ - {file = "sphinx-tabs-3.2.0.tar.gz", hash = "sha256:33137914ed9b276e6a686d7a337310ee77b1dae316fdcbce60476913a152e0a4"}, - {file = "sphinx_tabs-3.2.0-py3-none-any.whl", hash = "sha256:1e1b1846c80137bd81a78e4a69b02664b98b1e1da361beb30600b939dfc75065"}, + {file = "sphinx-tabs-3.3.1.tar.gz", hash = "sha256:d10dd7fb2700329b8e5948ab9f8e3ef54fff30f79d2e42cfd1b0089ae26e8c5e"}, + {file = "sphinx_tabs-3.3.1-py3-none-any.whl", hash = "sha256:73209aa769246501f6de9e33051cfd2d54f5900e0cc28a63367d8e4af4c0db5d"}, ] sphinxcontrib-applehelp = [ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, @@ -2102,17 +2110,83 @@ unittest2 = [ {file = "unittest2-1.1.0.tar.gz", hash = "sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579"}, ] urllib3 = [ - {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, - {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, + {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, + {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, ] virtualenv = [ - {file = "virtualenv-20.13.3-py2.py3-none-any.whl", hash = "sha256:dd448d1ded9f14d1a4bfa6bfc0c5b96ae3be3f2d6c6c159b23ddcfd701baa021"}, - {file = "virtualenv-20.13.3.tar.gz", hash = "sha256:e9dd1a1359d70137559034c0f5433b34caf504af2dc756367be86a5a32967134"}, + {file = "virtualenv-20.13.4-py2.py3-none-any.whl", hash = "sha256:c3e01300fb8495bc00ed70741f5271fc95fed067eb7106297be73d30879af60c"}, + {file = "virtualenv-20.13.4.tar.gz", hash = "sha256:ce8901d3bbf3b90393498187f2d56797a8a452fb2d0d7efc6fd837554d6f679c"}, ] webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] +wrapt = [ + {file = "wrapt-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:5a9a1889cc01ed2ed5f34574c90745fab1dd06ec2eee663e8ebeefe363e8efd7"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9a3ff5fb015f6feb78340143584d9f8a0b91b6293d6b5cf4295b3e95d179b88c"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4b847029e2d5e11fd536c9ac3136ddc3f54bc9488a75ef7d040a3900406a91eb"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9a5a544861b21e0e7575b6023adebe7a8c6321127bb1d238eb40d99803a0e8bd"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:88236b90dda77f0394f878324cfbae05ae6fde8a84d548cfe73a75278d760291"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f0408e2dbad9e82b4c960274214af533f856a199c9274bd4aff55d4634dedc33"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9d8c68c4145041b4eeae96239802cfdfd9ef927754a5be3f50505f09f309d8c6"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:22626dca56fd7f55a0733e604f1027277eb0f4f3d95ff28f15d27ac25a45f71b"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:65bf3eb34721bf18b5a021a1ad7aa05947a1767d1aa272b725728014475ea7d5"}, + {file = "wrapt-1.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09d16ae7a13cff43660155383a2372b4aa09109c7127aa3f24c3cf99b891c330"}, + {file = "wrapt-1.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:debaf04f813ada978d7d16c7dfa16f3c9c2ec9adf4656efdc4defdf841fc2f0c"}, + {file = "wrapt-1.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748df39ed634851350efa87690c2237a678ed794fe9ede3f0d79f071ee042561"}, + {file = "wrapt-1.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1807054aa7b61ad8d8103b3b30c9764de2e9d0c0978e9d3fc337e4e74bf25faa"}, + {file = "wrapt-1.14.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763a73ab377390e2af26042f685a26787c402390f682443727b847e9496e4a2a"}, + {file = "wrapt-1.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8529b07b49b2d89d6917cfa157d3ea1dfb4d319d51e23030664a827fe5fd2131"}, + {file = "wrapt-1.14.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:68aeefac31c1f73949662ba8affaf9950b9938b712fb9d428fa2a07e40ee57f8"}, + {file = "wrapt-1.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59d7d92cee84a547d91267f0fea381c363121d70fe90b12cd88241bd9b0e1763"}, + {file = "wrapt-1.14.0-cp310-cp310-win32.whl", hash = "sha256:3a88254881e8a8c4784ecc9cb2249ff757fd94b911d5df9a5984961b96113fff"}, + {file = "wrapt-1.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:9a242871b3d8eecc56d350e5e03ea1854de47b17f040446da0e47dc3e0b9ad4d"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a65bffd24409454b889af33b6c49d0d9bcd1a219b972fba975ac935f17bdf627"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9d9fcd06c952efa4b6b95f3d788a819b7f33d11bea377be6b8980c95e7d10775"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:db6a0ddc1282ceb9032e41853e659c9b638789be38e5b8ad7498caac00231c23"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:14e7e2c5f5fca67e9a6d5f753d21f138398cad2b1159913ec9e9a67745f09ba3"}, + {file = "wrapt-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:6d9810d4f697d58fd66039ab959e6d37e63ab377008ef1d63904df25956c7db0"}, + {file = "wrapt-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:d808a5a5411982a09fef6b49aac62986274ab050e9d3e9817ad65b2791ed1425"}, + {file = "wrapt-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b77159d9862374da213f741af0c361720200ab7ad21b9f12556e0eb95912cd48"}, + {file = "wrapt-1.14.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36a76a7527df8583112b24adc01748cd51a2d14e905b337a6fefa8b96fc708fb"}, + {file = "wrapt-1.14.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0057b5435a65b933cbf5d859cd4956624df37b8bf0917c71756e4b3d9958b9e"}, + {file = "wrapt-1.14.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0a4ca02752ced5f37498827e49c414d694ad7cf451ee850e3ff160f2bee9d3"}, + {file = "wrapt-1.14.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8c6be72eac3c14baa473620e04f74186c5d8f45d80f8f2b4eda6e1d18af808e8"}, + {file = "wrapt-1.14.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:21b1106bff6ece8cb203ef45b4f5778d7226c941c83aaaa1e1f0f4f32cc148cd"}, + {file = "wrapt-1.14.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:493da1f8b1bb8a623c16552fb4a1e164c0200447eb83d3f68b44315ead3f9036"}, + {file = "wrapt-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:89ba3d548ee1e6291a20f3c7380c92f71e358ce8b9e48161401e087e0bc740f8"}, + {file = "wrapt-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:729d5e96566f44fccac6c4447ec2332636b4fe273f03da128fff8d5559782b06"}, + {file = "wrapt-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:891c353e95bb11abb548ca95c8b98050f3620a7378332eb90d6acdef35b401d4"}, + {file = "wrapt-1.14.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23f96134a3aa24cc50614920cc087e22f87439053d886e474638c68c8d15dc80"}, + {file = "wrapt-1.14.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6807bcee549a8cb2f38f73f469703a1d8d5d990815c3004f21ddb68a567385ce"}, + {file = "wrapt-1.14.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6915682f9a9bc4cf2908e83caf5895a685da1fbd20b6d485dafb8e218a338279"}, + {file = "wrapt-1.14.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f2f3bc7cd9c9fcd39143f11342eb5963317bd54ecc98e3650ca22704b69d9653"}, + {file = "wrapt-1.14.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3a71dbd792cc7a3d772ef8cd08d3048593f13d6f40a11f3427c000cf0a5b36a0"}, + {file = "wrapt-1.14.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5a0898a640559dec00f3614ffb11d97a2666ee9a2a6bad1259c9facd01a1d4d9"}, + {file = "wrapt-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:167e4793dc987f77fd476862d32fa404d42b71f6a85d3b38cbce711dba5e6b68"}, + {file = "wrapt-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d066ffc5ed0be00cd0352c95800a519cf9e4b5dd34a028d301bdc7177c72daf3"}, + {file = "wrapt-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d9bdfa74d369256e4218000a629978590fd7cb6cf6893251dad13d051090436d"}, + {file = "wrapt-1.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2498762814dd7dd2a1d0248eda2afbc3dd9c11537bc8200a4b21789b6df6cd38"}, + {file = "wrapt-1.14.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f24ca7953f2643d59a9c87d6e272d8adddd4a53bb62b9208f36db408d7aafc7"}, + {file = "wrapt-1.14.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b835b86bd5a1bdbe257d610eecab07bf685b1af2a7563093e0e69180c1d4af1"}, + {file = "wrapt-1.14.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b21650fa6907e523869e0396c5bd591cc326e5c1dd594dcdccac089561cacfb8"}, + {file = "wrapt-1.14.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:354d9fc6b1e44750e2a67b4b108841f5f5ea08853453ecbf44c81fdc2e0d50bd"}, + {file = "wrapt-1.14.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1f83e9c21cd5275991076b2ba1cd35418af3504667affb4745b48937e214bafe"}, + {file = "wrapt-1.14.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:61e1a064906ccba038aa3c4a5a82f6199749efbbb3cef0804ae5c37f550eded0"}, + {file = "wrapt-1.14.0-cp38-cp38-win32.whl", hash = "sha256:28c659878f684365d53cf59dc9a1929ea2eecd7ac65da762be8b1ba193f7e84f"}, + {file = "wrapt-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:b0ed6ad6c9640671689c2dbe6244680fe8b897c08fd1fab2228429b66c518e5e"}, + {file = "wrapt-1.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3f7e671fb19734c872566e57ce7fc235fa953d7c181bb4ef138e17d607dc8a1"}, + {file = "wrapt-1.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87fa943e8bbe40c8c1ba4086971a6fefbf75e9991217c55ed1bcb2f1985bd3d4"}, + {file = "wrapt-1.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4775a574e9d84e0212f5b18886cace049a42e13e12009bb0491562a48bb2b758"}, + {file = "wrapt-1.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d57677238a0c5411c76097b8b93bdebb02eb845814c90f0b01727527a179e4d"}, + {file = "wrapt-1.14.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00108411e0f34c52ce16f81f1d308a571df7784932cc7491d1e94be2ee93374b"}, + {file = "wrapt-1.14.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d332eecf307fca852d02b63f35a7872de32d5ba8b4ec32da82f45df986b39ff6"}, + {file = "wrapt-1.14.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:01f799def9b96a8ec1ef6b9c1bbaf2bbc859b87545efbecc4a78faea13d0e3a0"}, + {file = "wrapt-1.14.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47045ed35481e857918ae78b54891fac0c1d197f22c95778e66302668309336c"}, + {file = "wrapt-1.14.0-cp39-cp39-win32.whl", hash = "sha256:2eca15d6b947cfff51ed76b2d60fd172c6ecd418ddab1c5126032d27f74bc350"}, + {file = "wrapt-1.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb36fbb48b22985d13a6b496ea5fb9bb2a076fea943831643836c9f6febbcfdc"}, + {file = "wrapt-1.14.0.tar.gz", hash = "sha256:8323a43bd9c91f62bb7d4be74cc9ff10090e7ef820e27bfe8815c57e68261311"}, +] zipp = [ {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"},