From ff34bbd7c14d873976d02652c4fd90d56c232533 Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Mon, 4 Dec 2023 17:22:58 +0000 Subject: [PATCH 01/10] Add updated scripts under aizynthfinder --- aizynthfinder/aizynthfinder.py | 41 +- aizynthfinder/analysis/tree_analysis.py | 5 +- aizynthfinder/analysis/utils.py | 11 +- aizynthfinder/chem/__init__.py | 1 - aizynthfinder/chem/mol.py | 82 ++-- aizynthfinder/chem/reaction.py | 182 +++------ aizynthfinder/chem/serialization.py | 6 - aizynthfinder/context/collection.py | 4 +- aizynthfinder/context/config.py | 165 ++++---- aizynthfinder/context/cost/__init__.py | 4 - aizynthfinder/context/cost/collection.py | 73 ---- aizynthfinder/context/cost/costs.py | 52 --- aizynthfinder/context/policy/__init__.py | 1 + .../context/policy/expansion_strategies.py | 194 +++++++-- .../context/policy/filter_strategies.py | 17 +- aizynthfinder/context/policy/policies.py | 143 ++++--- aizynthfinder/context/policy/utils.py | 4 +- aizynthfinder/context/scoring/__init__.py | 5 + aizynthfinder/context/scoring/collection.py | 67 +++- aizynthfinder/context/scoring/scorers.py | 375 +++++++++++++++--- aizynthfinder/context/stock/__init__.py | 6 +- aizynthfinder/context/stock/queries.py | 107 ++++- aizynthfinder/context/stock/stock.py | 97 +++-- aizynthfinder/interfaces/aizynthapp.py | 94 ++--- aizynthfinder/interfaces/aizynthcli.py | 10 +- aizynthfinder/reactiontree.py | 4 +- aizynthfinder/search/andor_trees.py | 6 +- aizynthfinder/search/breadth_first/nodes.py | 11 +- .../search/breadth_first/search_tree.py | 4 +- aizynthfinder/search/dfpn/nodes.py | 4 +- aizynthfinder/search/dfpn/search_tree.py | 4 +- aizynthfinder/search/mcts/node.py | 143 +++++-- aizynthfinder/search/mcts/search.py | 14 +- aizynthfinder/search/mcts/state.py | 54 +-- aizynthfinder/search/retrostar/cost.py | 94 ++++- aizynthfinder/search/retrostar/nodes.py | 47 ++- aizynthfinder/search/retrostar/search_tree.py | 12 +- aizynthfinder/tools/download_public_data.py | 22 +- aizynthfinder/tools/make_stock.py | 83 +++- aizynthfinder/training/__init__.py | 0 aizynthfinder/training/keras_models.py | 267 ------------- aizynthfinder/training/make_false_products.py | 277 ------------- .../training/preprocess_expansion.py | 145 ------- aizynthfinder/training/preprocess_filter.py | 85 ---- .../training/preprocess_recommender.py | 78 ---- aizynthfinder/training/training.py | 35 -- aizynthfinder/training/utils.py | 288 -------------- aizynthfinder/utils/files.py | 13 +- aizynthfinder/utils/image.py | 65 --- aizynthfinder/utils/loading.py | 6 +- aizynthfinder/utils/logging.py | 5 +- aizynthfinder/utils/math.py | 7 + aizynthfinder/utils/mongo.py | 4 +- aizynthfinder/utils/type_utils.py | 1 + 54 files changed, 1456 insertions(+), 2068 deletions(-) delete mode 100644 aizynthfinder/context/cost/__init__.py delete mode 100644 aizynthfinder/context/cost/collection.py delete mode 100644 aizynthfinder/context/cost/costs.py delete mode 100644 aizynthfinder/training/__init__.py delete mode 100644 aizynthfinder/training/keras_models.py delete mode 100644 aizynthfinder/training/make_false_products.py delete mode 100644 aizynthfinder/training/preprocess_expansion.py delete mode 100644 aizynthfinder/training/preprocess_filter.py delete mode 100644 aizynthfinder/training/preprocess_recommender.py delete mode 100644 aizynthfinder/training/training.py delete mode 100644 aizynthfinder/training/utils.py create mode 100644 aizynthfinder/utils/math.py diff --git a/aizynthfinder/aizynthfinder.py b/aizynthfinder/aizynthfinder.py index 09e2c2a..958af9c 100644 --- a/aizynthfinder/aizynthfinder.py +++ b/aizynthfinder/aizynthfinder.py @@ -15,6 +15,7 @@ ) from aizynthfinder.chem import FixedRetroReaction, Molecule, TreeMolecule from aizynthfinder.context.config import Configuration +from aizynthfinder.context.scoring import CombinedScorer from aizynthfinder.reactiontree import ReactionTreeFromExpansion from aizynthfinder.search.andor_trees import AndOrSearchTreeBase from aizynthfinder.search.mcts import MctsSearchTree @@ -60,7 +61,9 @@ class AiZynthFinder: :param configdict: the config as a dictionary source, defaults to None """ - def __init__(self, configfile: str = None, configdict: StrDict = None) -> None: + def __init__( + self, configfile: Optional[str] = None, configdict: Optional[StrDict] = None + ) -> None: self._logger = logger() if configfile: @@ -102,7 +105,9 @@ def target_mol(self, mol: Molecule) -> None: self._target_mol = mol def build_routes( - self, selection: RouteSelectionArguments = None, scorer: str = "state score" + self, + selection: Optional[RouteSelectionArguments] = None, + scorer: Optional[str] = None, ) -> None: """ Build reaction routes @@ -114,10 +119,15 @@ def build_routes( :param scorer: a reference to the object used to score the nodes :raises ValueError: if the search tree not initialized """ + + scorer = scorer or self.config.post_processing.route_scorer + if not self.tree: raise ValueError("Search tree not initialized") - self.analysis = TreeAnalysis(self.tree, scorer=self.scorers[scorer]) + _scorer = self.scorers[scorer] + + self.analysis = TreeAnalysis(self.tree, scorer=_scorer) config_selection = RouteSelectionArguments( nmin=self.config.post_processing.min_routes, nmax=self.config.post_processing.max_routes, @@ -157,13 +167,17 @@ def prepare_tree(self) -> None: raise ValueError("Target molecule unsanitizable") self.stock.reset_exclusion_list() - if self.config.exclude_target_from_stock and self.target_mol in self.stock: + if ( + self.config.search.exclude_target_from_stock + and self.target_mol in self.stock + ): self.stock.exclude(self.target_mol) self._logger.debug("Excluding the target compound from the stock") self._setup_search_tree() self.analysis = None self.routes = RouteCollection([]) + self.expansion_policy.reset_cache() def stock_info(self) -> StrDict: """ @@ -202,9 +216,12 @@ def tree_search(self, show_progress: bool = False) -> float: time_past = time.time() - time0 if show_progress: - pbar = tqdm(total=self.config.iteration_limit, leave=False) + pbar = tqdm(total=self.config.search.iteration_limit, leave=False) - while time_past < self.config.time_limit and i <= self.config.iteration_limit: + while ( + time_past < self.config.search.time_limit + and i <= self.config.search.iteration_limit + ): if show_progress: pbar.update(1) self.search_stats["iterations"] += 1 @@ -218,7 +235,7 @@ def tree_search(self, show_progress: bool = False) -> float: self.search_stats["first_solution_time"] = time.time() - time0 self.search_stats["first_solution_iteration"] = i - if self.config.return_first and is_solved: + if self.config.search.return_first and is_solved: self._logger.debug("Found first solved route") self.search_stats["returned_first"] = True break @@ -234,12 +251,12 @@ def tree_search(self, show_progress: bool = False) -> float: def _setup_search_tree(self) -> None: self._logger.debug("Defining tree root: %s" % self.target_smiles) - if self.config.search_algorithm.lower() == "mcts": + if self.config.search.algorithm.lower() == "mcts": self.tree = MctsSearchTree( root_smiles=self.target_smiles, config=self.config ) else: - cls = load_dynamic_class(self.config.search_algorithm) + cls = load_dynamic_class(self.config.search.algorithm) self.tree = cls(root_smiles=self.target_smiles, config=self.config) @@ -260,7 +277,9 @@ class AiZynthExpander: :param configdict: the config as a dictionary source, defaults to None """ - def __init__(self, configfile: str = None, configdict: StrDict = None) -> None: + def __init__( + self, configfile: Optional[str] = None, configdict: Optional[StrDict] = None + ) -> None: self._logger = logger() if configfile: @@ -278,7 +297,7 @@ def do_expansion( self, smiles: str, return_n: int = 5, - filter_func: Callable[[RetroReaction], bool] = None, + filter_func: Optional[Callable[[RetroReaction], bool]] = None, ) -> List[Tuple[FixedRetroReaction, ...]]: """ Do the expansion of the given molecule returning a list of diff --git a/aizynthfinder/analysis/tree_analysis.py b/aizynthfinder/analysis/tree_analysis.py index 071353a..95282b9 100644 --- a/aizynthfinder/analysis/tree_analysis.py +++ b/aizynthfinder/analysis/tree_analysis.py @@ -19,6 +19,7 @@ Any, Iterable, List, + Optional, Sequence, StrDict, Tuple, @@ -41,7 +42,7 @@ class TreeAnalysis: def __init__( self, search_tree: Union[MctsSearchTree, AndOrSearchTreeBase], - scorer: Scorer = None, + scorer: Optional[Scorer] = None, ) -> None: self.search_tree = search_tree if scorer is None: @@ -65,7 +66,7 @@ def best(self) -> Union[MctsNode, ReactionTree]: return sorted_routes[0] def sort( - self, selection: RouteSelectionArguments = None + self, selection: Optional[RouteSelectionArguments] = None ) -> Tuple[Union[Sequence[MctsNode], Sequence[ReactionTree]], Sequence[float]]: """ Sort and select the nodes or routes in the search tree. diff --git a/aizynthfinder/analysis/utils.py b/aizynthfinder/analysis/utils.py index 3a05262..5888f4b 100644 --- a/aizynthfinder/analysis/utils.py +++ b/aizynthfinder/analysis/utils.py @@ -15,7 +15,13 @@ from aizynthfinder.utils.image import make_visjs_page if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import FrameColors, Sequence, StrDict, Tuple + from aizynthfinder.utils.type_utils import ( + FrameColors, + Optional, + Sequence, + StrDict, + Tuple, + ) @dataclass @@ -69,7 +75,7 @@ def to_dict(self) -> StrDict: def to_visjs_page( self, filename: str, - in_stock_colors: FrameColors = None, + in_stock_colors: Optional[FrameColors] = None, ) -> None: """ Create a visualization of the combined reaction tree using the vis.js network library. @@ -93,7 +99,6 @@ def _add_reaction_trees_to_node( base_node: UniqueMolecule, rt_node_spec: Sequence[Tuple[UniqueMolecule, nx.DiGraph]], ) -> None: - reaction_groups = defaultdict(list) # Group the reactions from the nodes at this level based on the reaction smiles for node, graph in rt_node_spec: diff --git a/aizynthfinder/chem/__init__.py b/aizynthfinder/chem/__init__.py index 225f4f9..a792bbb 100644 --- a/aizynthfinder/chem/__init__.py +++ b/aizynthfinder/chem/__init__.py @@ -9,7 +9,6 @@ ) from aizynthfinder.chem.reaction import ( FixedRetroReaction, - Reaction, RetroReaction, SmilesBasedRetroReaction, TemplatedRetroReaction, diff --git a/aizynthfinder/chem/mol.py b/aizynthfinder/chem/mol.py index a349bce..8864151 100644 --- a/aizynthfinder/chem/mol.py +++ b/aizynthfinder/chem/mol.py @@ -41,7 +41,10 @@ class Molecule: """ def __init__( - self, rd_mol: RdMol = None, smiles: str = None, sanitize: bool = False + self, + rd_mol: Optional[RdMol] = None, + smiles: Optional[str] = None, + sanitize: bool = False, ) -> None: if not rd_mol and not smiles: raise MoleculeException( @@ -148,19 +151,24 @@ def basic_compare(self, other: "Molecule") -> bool: """ return self.inchi_key[:14] == other.inchi_key[:14] - def fingerprint(self, radius: int, nbits: int = 2048) -> np.ndarray: + def fingerprint( + self, radius: int, nbits: int = 2048, chiral: bool = False + ) -> np.ndarray: """ Returns the Morgan fingerprint of the molecule :param radius: the radius of the fingerprint :param nbits: the length of the fingerprint + :param chiral: if True, include chirality information :return: the fingerprint """ key = radius, nbits if key not in self._fingerprints: self.sanitize() - bitvect = AllChem.GetMorganFingerprintAsBitVect(self.rd_mol, *key) + bitvect = AllChem.GetMorganFingerprintAsBitVect( + self.rd_mol, *key, useChirality=chiral + ) array = np.zeros((1,)) DataStructs.ConvertToNumpyArray(bitvect, array) self._fingerprints[key] = array @@ -187,7 +195,7 @@ def make_unique(self) -> "UniqueMolecule": """ return UniqueMolecule(rd_mol=self.rd_mol) - def remove_atom_mapping(self, exceptions: Sequence[int] = None) -> None: + def remove_atom_mapping(self, exceptions: Optional[Sequence[int]] = None) -> None: """ Remove all mappings of the atoms and update the smiles @@ -247,7 +255,6 @@ class TreeMolecule(Molecule): :ivar original_smiles: the SMILES as passed when instantiating the class :ivar parent: parent molecule :ivar transform: a numerical number corresponding to the depth in the tree - :ivar tracked_atom_indices: tracked atom indices and what indices they correspond to in this molecule :param parent: a TreeMolecule object that is the parent :param transform: the transform value, defaults to None @@ -262,11 +269,11 @@ class TreeMolecule(Molecule): def __init__( self, parent: Optional["TreeMolecule"], - transform: int = None, - rd_mol: RdMol = None, - smiles: str = None, + transform: Optional[int] = None, + rd_mol: Optional[RdMol] = None, + smiles: Optional[str] = None, sanitize: bool = False, - mapping_update_callback: Callable[["TreeMolecule"], None] = None, + mapping_update_callback: Optional[Callable[["TreeMolecule"], None]] = None, ) -> None: super().__init__(rd_mol=rd_mol, smiles=smiles, sanitize=sanitize) self.parent = parent @@ -276,10 +283,10 @@ def __init__( self.transform = transform or 0 self.original_smiles = smiles - self.tracked_atom_indices: Dict[int, Optional[int]] = {} self.mapped_mol = Chem.Mol(self.rd_mol) + self._atom_bonds: List[Tuple[int, int]] = [] if not self.parent: - self._init_tracking() + self._set_atom_mappings() elif mapping_update_callback is not None: mapping_update_callback(self) @@ -288,7 +295,6 @@ def __init__( if self.parent: self.remove_atom_mapping() - self._update_tracked_atoms() @property def mapping_to_index(self) -> Dict[int, int]: @@ -301,28 +307,33 @@ def mapping_to_index(self) -> Dict[int, int]: } return self._atom_mappings - def _init_tracking(self): - self.tracked_atom_indices = dict(self.mapping_to_index) - for idx, atom in enumerate(self.mapped_mol.GetAtoms()): - atom.SetAtomMapNum(idx + 1) + @property + def mapped_atom_bonds(self) -> List[Tuple[int, int]]: + """Return a list of atom bonds as tuples on the mapped atom indices""" + bonds = [] + for bond in self.mapped_mol.GetBonds(): + bonds.append((bond.GetBeginAtom().GetIdx(), bond.GetEndAtom().GetIdx())) + + self._atom_bonds = [ + (self.index_to_mapping[atom_index1], self.index_to_mapping[atom_index2]) + for atom_index1, atom_index2 in bonds + ] + return self._atom_bonds + + def _set_atom_mappings(self) -> None: + atom_mappings = [ + atom.GetAtomMapNum() + for atom in self.mapped_mol.GetAtoms() + if atom.GetAtomMapNum() != 0 + ] + + mapper = max(atom_mappings) + 1 if atom_mappings else 1 self._atom_mappings = {} - - def _update_tracked_atoms(self) -> None: - if self.parent is None: - return - - if not self.parent.tracked_atom_indices: - return - - parent2child_map = { - atom_index: self.mapping_to_index.get(mapping_index) - for mapping_index, atom_index in self.parent.mapping_to_index.items() - } - - self.tracked_atom_indices = { - tracked_index: parent2child_map[parent_index] # type: ignore - for tracked_index, parent_index in self.parent.tracked_atom_indices.items() - } + for atom_index, atom in enumerate(self.mapped_mol.GetAtoms()): + if atom.GetAtomMapNum() == 0: + atom.SetAtomMapNum(mapper) + mapper += 1 + self._atom_mappings[atom.GetAtomMapNum()] = atom_index class UniqueMolecule(Molecule): @@ -337,7 +348,10 @@ class UniqueMolecule(Molecule): """ def __init__( - self, rd_mol: RdMol = None, smiles: str = None, sanitize: bool = False + self, + rd_mol: Optional[RdMol] = None, + smiles: Optional[str] = None, + sanitize: bool = False, ) -> None: super().__init__(rd_mol=rd_mol, smiles=smiles, sanitize=sanitize) diff --git a/aizynthfinder/chem/reaction.py b/aizynthfinder/chem/reaction.py index 042ea89..56db3e3 100644 --- a/aizynthfinder/chem/reaction.py +++ b/aizynthfinder/chem/reaction.py @@ -15,7 +15,11 @@ from rdkit.Chem import AllChem from rdkit.Chem.rdchem import BondDir, BondStereo, ChiralType -from aizynthfinder.chem.mol import Molecule, MoleculeException, TreeMolecule +from aizynthfinder.chem.mol import ( + Molecule, + MoleculeException, + TreeMolecule, +) from aizynthfinder.utils.logging import logger if TYPE_CHECKING: @@ -40,19 +44,22 @@ class _ReactionInterfaceMixin: The methods `_products_getter` and `_reactants_getter` needs to be implemented by subclasses """ - def fingerprint(self, radius: int, nbits: int = None) -> np.ndarray: + def fingerprint( + self, radius: int, nbits: Optional[int] = None, chiral: bool = False + ) -> np.ndarray: """ Returns a difference fingerprint :param radius: the radius of the fingerprint :param nbits: the length of the fingerprint. If not given it will use RDKit default, defaults to None + :param chiral: if True, include chirality information :return: the fingerprint """ product_fp = sum( - mol.fingerprint(radius, nbits) for mol in self._products_getter() # type: ignore + mol.fingerprint(radius, nbits, chiral) for mol in self._products_getter() # type: ignore ) reactants_fp = sum( - mol.fingerprint(radius, nbits) for mol in self._reactants_getter() # type: ignore + mol.fingerprint(radius, nbits, chiral) for mol in self._reactants_getter() # type: ignore ) return reactants_fp - product_fp # type: ignore @@ -98,107 +105,6 @@ def reaction_smiles(self) -> str: return "%s>>%s" % (reactants, products) -class Reaction(_ReactionInterfaceMixin): - """ - An abstraction of a reaction. Encapsulate an RDKit reaction object and - functions that can be applied to such a reaction. - - :ivar mols: the Molecule objects that this reaction are applied to - :ivar smarts: the SMARTS representation of the reaction - :ivar index: a unique index of this reaction, - to count for the fact that a reaction can produce more than one outcome - :ivar metadata: meta data associated with the reaction - - :param mols: the molecules - :param smarts: the SMARTS fragment - :param index: the index, defaults to 0 - :param metadata: some meta data - """ - - def __init__( - self, - mols: List[Molecule], - smarts: str, - index: int = 0, - metadata: StrDict = None, - ) -> None: - self.mols = mols - self.smarts = smarts - self.index = index - self.metadata: StrDict = metadata or {} - self._products: Optional[Tuple[Tuple[Molecule, ...], ...]] = None - self._rd_reaction: Optional[RdReaction] = None - self._smiles: Optional[str] = None - - @property - def products(self) -> Tuple[Tuple[Molecule, ...], ...]: - """ - Returns the product molecules. - Apply the reaction if necessary. - - :return: the products of the reaction - """ - if not self._products: - self.apply() - assert self._products is not None - return self._products - - @property - def rd_reaction(self) -> RdReaction: - """ - The reaction as a RDkit reaction object - - :return: the reaction object - """ - if not self._rd_reaction: - self._rd_reaction = AllChem.ReactionFromSmarts(self.smarts) - return self._rd_reaction - - @property - def smiles(self) -> str: - """ - The reaction as a SMILES - - :return: the SMILES - """ - if self._smiles is None: - try: - self._smiles = AllChem.ReactionToSmiles(self.rd_reaction) - except ValueError: - self._smiles = "" # noqa - return self._smiles - - def apply(self) -> Tuple[Tuple[Molecule, ...], ...]: - """ - Apply a reactions smarts to list of reactant and return the products - - Will try to sanitize the reactants, and if that fails it will not return that molecule - - :return: the products of the reaction - """ - num_rectantant_templates = self.rd_reaction.GetNumReactantTemplates() - reactants = tuple(mol.rd_mol for mol in self.mols[:num_rectantant_templates]) - products_list = self.rd_reaction.RunReactants(reactants) - - outcomes = [] - for products in products_list: - try: - mols = tuple(Molecule(rd_mol=mol, sanitize=True) for mol in products) - except MoleculeException: - pass - else: - outcomes.append(mols) - self._products = tuple(outcomes) - - return self._products - - def _products_getter(self) -> Tuple[Molecule, ...]: - return self.products[self.index] - - def _reactants_getter(self) -> List[Molecule]: - return self.mols - - class RetroReaction(abc.ABC, _ReactionInterfaceMixin): """ A retrosynthesis reaction. Only a single molecule is the reactant. @@ -220,7 +126,11 @@ class RetroReaction(abc.ABC, _ReactionInterfaceMixin): _required_kwargs: List[str] = [] def __init__( - self, mol: TreeMolecule, index: int = 0, metadata: StrDict = None, **kwargs: Any + self, + mol: TreeMolecule, + index: int = 0, + metadata: Optional[StrDict] = None, + **kwargs: Any, ) -> None: if any(name not in kwargs for name in self._required_kwargs): raise KeyError( @@ -287,7 +197,7 @@ def unqueried(self) -> bool: """ return self._reactants is None - def copy(self, index: int = None) -> "RetroReaction": + def copy(self, index: Optional[int] = None) -> "RetroReaction": """ Shallow copy of this instance. @@ -296,7 +206,9 @@ def copy(self, index: int = None) -> "RetroReaction": """ # pylint: disable=protected-access index = index if index is not None else self.index - new_reaction = self.__class__(self.mol, index, self.metadata, **self._kwargs) + new_reaction = self.__class__( + self.mol, index, dict(self.metadata), **self._kwargs + ) new_reaction._reactants = tuple(mol_list for mol_list in self._reactants or []) new_reaction._smiles = self._smiles return new_reaction @@ -363,7 +275,11 @@ class TemplatedRetroReaction(RetroReaction): _required_kwargs = ["smarts"] def __init__( - self, mol: TreeMolecule, index: int = 0, metadata: StrDict = None, **kwargs: Any + self, + mol: TreeMolecule, + index: int = 0, + metadata: Optional[StrDict] = None, + **kwargs: Any, ): super().__init__(mol, index, metadata, **kwargs) self.smarts: str = kwargs["smarts"] @@ -382,16 +298,6 @@ def rd_reaction(self) -> RdReaction: self._rd_reaction = AllChem.ReactionFromSmarts(self.smarts) return self._rd_reaction - def forward_reaction(self) -> Reaction: - """ - Create the forward reaction corresponding to the SMARTS and reactants of this reaction - - :return: the forward reaction - """ - fwd_smarts = ">>".join(self.smarts.split(">>")[::-1]) - mols = [Molecule(rd_mol=mol.rd_mol) for mol in self.reactants[self.index]] - return Reaction(mols=mols, smarts=fwd_smarts) - def to_dict(self) -> StrDict: dict_ = super().to_dict() dict_["smarts"] = self.smarts @@ -517,7 +423,11 @@ class SmilesBasedRetroReaction(RetroReaction): _required_kwargs = ["reactants_str"] def __init__( - self, mol: TreeMolecule, index: int = 0, metadata: StrDict = None, **kwargs: Any + self, + mol: TreeMolecule, + index: int = 0, + metadata: Optional[StrDict] = None, + **kwargs: Any, ): super().__init__(mol, index, metadata, **kwargs) self.reactants_str: str = kwargs["reactants_str"] @@ -605,7 +515,10 @@ class FixedRetroReaction(_ReactionInterfaceMixin): """ def __init__( - self, mol: UniqueMolecule, smiles: str = "", metadata: StrDict = None + self, + mol: UniqueMolecule, + smiles: str = "", + metadata: Optional[StrDict] = None, ) -> None: self.mol = mol self.smiles = smiles @@ -622,6 +535,27 @@ def copy(self) -> "FixedRetroReaction": new_reaction.reactants = tuple(mol_list for mol_list in self.reactants) return new_reaction + def to_smiles_based_retroreaction(self) -> SmilesBasedRetroReaction: + """ + Convert a FixedRetroReaction to a SmilesBasedRetroReaction. + + :return: the SmilesBasedRetroReaction. + """ + if self.metadata and "mapped_reaction_smiles" in self.metadata.keys(): + mapped_reaction_smiles = self.metadata["mapped_reaction_smiles"] + else: + mapped_reaction_smiles = self.reaction_smiles() + + mapped_reaction_smiles = mapped_reaction_smiles.split(">>") + product = mapped_reaction_smiles[0] + reactants = mapped_reaction_smiles[1] + + return SmilesBasedRetroReaction( + mol=TreeMolecule(smiles=product, parent=None), + mapped_prod_smiles=product, + reactants_str=reactants, + ) + def _products_getter(self) -> Tuple[UniqueMolecule, ...]: return self.reactants[0] @@ -630,9 +564,7 @@ def _reactants_getter(self) -> List[UniqueMolecule]: def hash_reactions( - reactions: Union[ - Iterable[Reaction], Iterable[RetroReaction], Iterable[FixedRetroReaction] - ], + reactions: Union[Iterable[RetroReaction], Iterable[FixedRetroReaction]], sort: bool = True, ) -> str: """ @@ -692,7 +624,7 @@ def __init__(self, product: TreeMolecule) -> None: # Pre-list chiral double bonds (for copying back into outcomes/matching) self.bond_dirs_by_mapnum = {} - for (i, j, b) in self.bonds_by_mapnum: + for i, j, b in self.bonds_by_mapnum: if b.GetBondDir() != BondDir.NONE: self.bond_dirs_by_mapnum[(i, j)] = b.GetBondDir() self.bond_dirs_by_mapnum[(j, i)] = BondDirOpposite[b.GetBondDir()] diff --git a/aizynthfinder/chem/serialization.py b/aizynthfinder/chem/serialization.py index 99bd9ba..8c30b0c 100644 --- a/aizynthfinder/chem/serialization.py +++ b/aizynthfinder/chem/serialization.py @@ -50,7 +50,6 @@ def _add_mol(self, mol: aizynthfinder.chem.Molecule) -> None: if isinstance(mol, aizynthfinder.chem.TreeMolecule): dict_["parent"] = self[mol.parent] dict_["transform"] = mol.transform - dict_["tracked_atom_indices"] = mol.tracked_atom_indices if not mol.parent: dict_["smiles"] = mol.original_smiles else: @@ -106,15 +105,10 @@ def _create_molecules(self, store: dict) -> None: cls = spec["class"] if "parent" in spec: spec["parent"] = self[spec["parent"]] - tracked_atom_indices = None - if "tracked_atom_indices" in spec: - tracked_atom_indices = spec.pop("tracked_atom_indices") kwargs = dict(spec) del kwargs["class"] self._objects[id_] = getattr(aizynthfinder.chem, cls)(**kwargs) - if tracked_atom_indices is not None: - self._objects[id_].tracked_atom_indices = tracked_atom_indices def serialize_action( diff --git a/aizynthfinder/context/collection.py b/aizynthfinder/context/collection.py index f38178a..c7ac97d 100644 --- a/aizynthfinder/context/collection.py +++ b/aizynthfinder/context/collection.py @@ -8,7 +8,7 @@ from aizynthfinder.utils.logging import logger if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import Any, List, StrDict, Union + from aizynthfinder.utils.type_utils import Any, List, Optional, StrDict, Union class ContextCollection(abc.ABC): @@ -72,7 +72,7 @@ def selection(self) -> Union[List[str], str, None]: def selection(self, value: str) -> None: self.select(value) - def deselect(self, key: str = None) -> None: + def deselect(self, key: Optional[str] = None) -> None: """ Deselect one or all items diff --git a/aizynthfinder/context/config.py b/aizynthfinder/context/config.py index 0efbe14..8b8e39a 100644 --- a/aizynthfinder/context/config.py +++ b/aizynthfinder/context/config.py @@ -4,19 +4,17 @@ import os import re -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import TYPE_CHECKING import yaml - -from aizynthfinder.context.cost import MoleculeCost from aizynthfinder.context.policy import ExpansionPolicy, FilterPolicy from aizynthfinder.context.scoring import ScorerCollection from aizynthfinder.context.stock import Stock from aizynthfinder.utils.logging import logger if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import Any, Dict, Optional, StrDict, Union + from aizynthfinder.utils.type_utils import Any, Dict, List, Optional, StrDict, Union @dataclass @@ -25,60 +23,68 @@ class _PostprocessingConfiguration: max_routes: int = 25 all_routes: bool = False route_distance_model: Optional[str] = None + route_scorer: str = "state score" @dataclass -class Configuration: # pylint: disable=R0902 +class _SearchConfiguration: + algorithm: str = "mcts" + algorithm_config: Dict[str, Any] = field( + default_factory=lambda: { + "C": 1.4, + "default_prior": 0.5, + "use_prior": True, + "prune_cycles_in_search": True, + "search_reward": "state score", + "immediate_instantiation": (), + "mcts_grouping": None, + } + ) + max_transforms: int = 6 + iteration_limit: int = 100 + time_limit: int = 120 + return_first: bool = False + exclude_target_from_stock: bool = True + break_bonds: List[List[int]] = field(default_factory=list) + freeze_bonds: List[List[int]] = field(default_factory=list) + break_bonds_operator: str = "and" + + +@dataclass +class Configuration: """ Encapsulating the settings of the tree search, including the policy, the stock, the loaded scorers and various parameters. - - All the parameters can be retrieved as attributes of the Configuration - object, e.g. - - .. code-block:: - - config.max_transforms # The maximum of transform - config.iteration_limit # The maximum number of iterations """ - C: float = 1.4 # pylint: disable=invalid-name - cutoff_cumulative: float = 0.995 - cutoff_number: int = 50 - additive_expansion: bool = False - use_rdchiral: bool = True - max_transforms: int = 6 - default_prior: float = 0.5 - use_prior: bool = True - iteration_limit: int = 100 - return_first: bool = False - time_limit: int = 120 - filter_cutoff: float = 0.05 - exclude_target_from_stock: bool = True - template_column: str = "retro_template" - prune_cycles_in_search: bool = True - use_remote_models: bool = False - search_algorithm: str = "mcts" - post_processing: _PostprocessingConfiguration = _PostprocessingConfiguration() - stock: Stock = None # type: ignore - expansion_policy: ExpansionPolicy = None # type: ignore - filter_policy: FilterPolicy = None # type: ignore - scorers: ScorerCollection = None # type: ignore - molecule_cost: MoleculeCost = None # type: ignore + search: _SearchConfiguration = field(default_factory=_SearchConfiguration) + post_processing: _PostprocessingConfiguration = field( + default_factory=_PostprocessingConfiguration + ) + stock: Stock = field(init=False) + expansion_policy: ExpansionPolicy = field(init=False) + filter_policy: FilterPolicy = field(init=False) + scorers: ScorerCollection = field(init=False) def __post_init__(self) -> None: - self._properties: StrDict = {} self.stock = Stock() self.expansion_policy = ExpansionPolicy(self) self.filter_policy = FilterPolicy(self) self.scorers = ScorerCollection(self) - self.molecule_cost = MoleculeCost() self._logger = logger() def __eq__(self, other: Any) -> bool: if not isinstance(other, Configuration): return False - return self.properties == other.properties + for key, setting in vars(self).items(): + if isinstance(setting, (int, float, str, bool, list)): + if ( + vars(self)[key] != vars(other)[key] + or self.search != other.search + or self.post_processing != other.post_processing + ): + return False + return True @classmethod def from_dict(cls, source: StrDict) -> "Configuration": @@ -90,16 +96,19 @@ def from_dict(cls, source: StrDict) -> "Configuration": :param source: the dictionary source :return: a Configuration object with settings from the source """ - # pylint: disable=protected-access + expansion_config = source.pop("expansion", {}) + filter_config = source.pop("filter", {}) + stock_config = source.pop("stock", {}) + scorer_config = source.pop("scorer", {}) + config_obj = Configuration() - src_copy = dict(source) # Make a copy so we can pop items - config_obj._update_from_config(src_copy) + config_obj._update_from_config(dict(source)) - config_obj.expansion_policy.load_from_config(**src_copy.get("policy", {})) - config_obj.filter_policy.load_from_config(**src_copy.get("filter", {})) - config_obj.stock.load_from_config(**src_copy.get("stock", {})) - config_obj.scorers.load_from_config(**src_copy.get("scorer", {})) - config_obj.molecule_cost.load_from_config(**src_copy.get("molecule_cost", {})) + config_obj.expansion_policy.load_from_config(**expansion_config) + config_obj.filter_policy.load_from_config(**filter_config) + config_obj.stock.load_from_config(**stock_config) + config_obj.scorers.create_default_scorers() + config_obj.scorers.load_from_config(**scorer_config) return config_obj @@ -128,46 +137,30 @@ def from_file(cls, filename: str) -> "Configuration": _config = yaml.load(txt, Loader=yaml.SafeLoader) return Configuration.from_dict(_config) - @property - def properties(self) -> Dict[str, Union[int, float, str, bool]]: - """Return the basic properties of the config as a dictionary""" - dict_ = {} - for item in dir(self): - if item == "properties" or item.startswith("_"): - continue - attr = getattr(self, item) - if isinstance(attr, (int, float, str, bool)): - dict_[item] = attr - return dict_ - - @properties.setter - def properties(self, dict_: Dict[str, Union[int, float, str, bool]]) -> None: - """ - Update the configuration using dictionary of parameters - - If a value is None that setting is ignored. + def _update_from_config(self, config: StrDict) -> None: + self.post_processing = _PostprocessingConfiguration( + **config.pop("post_processing", {}) + ) - :param dict_: the dictionary of properties - """ - for setting, value in dict_.items(): + search_config = config.pop("search", {}) + for setting, value in search_config.items(): if value is None: continue - if not hasattr(self, setting): + if not hasattr(self.search, setting): raise AttributeError(f"Could not find attribute to set: {setting}") - if not isinstance(value, (int, float, str, bool)): - raise ValueError( - f"Trying to set property with invalid value {setting}={value}" - ) - setattr(self, setting, value) - self._logger.info(f"Setting {setting.replace('_', ' ')} to {value}") - - def _update_from_config(self, config: StrDict) -> None: - # The first 3 places for properties are kept for historical reasons, but they are not recommended usage - dict_ = config.get("finder", {}).pop("properties", {}) - dict_.update(config.get("policy", {}).pop("properties", {})) - dict_.update(config.get("filter", {}).pop("properties", {})) - dict_.update(config.pop("properties", {})) - self.post_processing = _PostprocessingConfiguration( - **dict_.pop("post_processing", {}) - ) - self.properties = dict_ + if setting.endswith("_bonds"): + if not isinstance(value, list): + raise ValueError("Bond settings need to be lists") + value = _handle_bond_pair_tuples(value) if value else [] + if setting == "algorithm_config": + if not isinstance(value, dict): + raise ValueError("algorithm_config settings need to be dictionary") + self.search.algorithm_config.update(value) + else: + setattr(self.search, setting, value) + + +def _handle_bond_pair_tuples(bonds: List[List[int]]) -> List[List[int]]: + if not all(len(bond_pair) == 2 for bond_pair in bonds): + raise ValueError("Lists of bond pairs to break/freeze should be of length 2") + return [bond_pair[:2] for bond_pair in bonds] diff --git a/aizynthfinder/context/cost/__init__.py b/aizynthfinder/context/cost/__init__.py deleted file mode 100644 index 36c5fd3..0000000 --- a/aizynthfinder/context/cost/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -""" Sub-package that defines various cost algorithms -""" -from aizynthfinder.context.cost.collection import MoleculeCost -from aizynthfinder.context.cost.costs import MoleculeCostCalculator, ZeroMoleculeCost diff --git a/aizynthfinder/context/cost/collection.py b/aizynthfinder/context/cost/collection.py deleted file mode 100644 index a9851c6..0000000 --- a/aizynthfinder/context/cost/collection.py +++ /dev/null @@ -1,73 +0,0 @@ -""" Module containing classes to compute the molecule cost in some search algorithms -""" -from __future__ import annotations - -from typing import TYPE_CHECKING - -from aizynthfinder.context.collection import ContextCollection -from aizynthfinder.context.cost.costs import MoleculeCostCalculator, ZeroMoleculeCost -from aizynthfinder.context.cost.costs import __name__ as costs_module -from aizynthfinder.utils.exceptions import CostException -from aizynthfinder.utils.loading import load_dynamic_class - -if TYPE_CHECKING: - from aizynthfinder.chem import Molecule - from aizynthfinder.utils.type_utils import Any, Dict - - -class MoleculeCost(ContextCollection): - """Collection of molecular cost objects""" - - _single_selection: bool = True - _collection_name: str = "molecule cost" - - _aliases: Dict[str, Any] = { - "zero": ZeroMoleculeCost, - } - - def __init__(self) -> None: - super().__init__() - self._cache: Dict[str, float] = {} - self._items["zero"] = ZeroMoleculeCost() - self._selection = ["zero"] - - def __call__(self, mol: Molecule) -> float: - if not isinstance(self.selection, str): - raise CostException("No cost selected cannot compute it!") - if mol.inchi_key not in self._cache: - self._cache[mol.inchi_key] = self[self.selection](mol) - return self._cache[mol.inchi_key] - - def load(self, cost: MoleculeCost) -> None: # type: ignore - """ - Add a pre-initialized cost calculator object to the collection - - :param cost: the item to add - """ - if not isinstance(cost, MoleculeCostCalculator): - raise CostException( - "Only objects of classes inherited from MoleculeCostCalculator can be added" - ) - self._items[repr(cost)] = cost - - def load_from_config(self, **costs_config: Any) -> None: - """ - Load one or more cost models from a configuration - - The format should be: - key: config_for_model - - :param costs_config: the configuration - """ - for name_spec, scorer_config in costs_config.items(): - if name_spec in self._aliases: - cls = self._aliases[name_spec] - else: - cls = load_dynamic_class(name_spec, costs_module, CostException) - obj = cls(**(scorer_config or {})) - config_str = ( - f" from configuration '{scorer_config}'" if scorer_config else "" - ) - self._logger.info(f"Loaded cost: '{repr(obj)}'{config_str}") - self._items[repr(obj)] = obj - self.select_last() diff --git a/aizynthfinder/context/cost/costs.py b/aizynthfinder/context/cost/costs.py deleted file mode 100644 index 915a706..0000000 --- a/aizynthfinder/context/cost/costs.py +++ /dev/null @@ -1,52 +0,0 @@ -""" Module containing classes that implements different cost calculators -""" -from __future__ import annotations - -import abc -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from aizynthfinder.chem import Molecule - from aizynthfinder.context.config import Configuration - - -class MoleculeCostCalculator(abc.ABC): - """ - A base class for all molecule cost calculators. - - The cost can be computed by either calling the `calculate` method - of by calling the instantiated class with a molecule. - - .. code-block:: - - calculator = MyCost() - cost = calculator.calculate(molecule) - cost = calculator(molecule) - - :param config: the configuration of the tree search - """ - - def __init__(self, config: Configuration = None) -> None: - self._config = config - - def __call__(self, mol: Molecule) -> float: - return self.calculate(mol) - - @abc.abstractmethod - def calculate(self, mol: Molecule) -> float: - """ - Calculate the cost of a molecule - - :param mol: the query molecule - :return: the estimated cost - """ - - -class ZeroMoleculeCost(MoleculeCostCalculator): - """Encapsulation of a Zero cost model""" - - def __repr__(self) -> str: - return "zero" - - def calculate(self, mol: Molecule) -> float: - return 0.0 diff --git a/aizynthfinder/context/policy/__init__.py b/aizynthfinder/context/policy/__init__.py index 1435471..2951826 100644 --- a/aizynthfinder/context/policy/__init__.py +++ b/aizynthfinder/context/policy/__init__.py @@ -2,6 +2,7 @@ """ from aizynthfinder.context.policy.expansion_strategies import ( ExpansionStrategy, + MultiExpansionStrategy, TemplateBasedExpansionStrategy, ) from aizynthfinder.context.policy.filter_strategies import ( diff --git a/aizynthfinder/context/policy/expansion_strategies.py b/aizynthfinder/context/policy/expansion_strategies.py index 07d1287..21c3a79 100644 --- a/aizynthfinder/context/policy/expansion_strategies.py +++ b/aizynthfinder/context/policy/expansion_strategies.py @@ -13,12 +13,13 @@ from aizynthfinder.utils.exceptions import PolicyException from aizynthfinder.utils.logging import logger from aizynthfinder.utils.models import load_model +from aizynthfinder.utils.math import softmax if TYPE_CHECKING: from aizynthfinder.chem import TreeMolecule from aizynthfinder.chem.reaction import RetroReaction from aizynthfinder.context.config import Configuration - from aizynthfinder.utils.type_utils import Any, List, Sequence, Tuple + from aizynthfinder.utils.type_utils import Any, Dict, List, Sequence, Tuple class ExpansionStrategy(abc.ABC): @@ -51,45 +52,150 @@ def __init__(self, key: str, config: Configuration, **kwargs: str) -> None: self.key = key def __call__( - self, molecules: Sequence[TreeMolecule] + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, ) -> Tuple[List[RetroReaction], List[float]]: - return self.get_actions(molecules) + return self.get_actions(molecules, cache_molecules) @abc.abstractmethod def get_actions( - self, molecules: Sequence[TreeMolecule] + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, ) -> Tuple[List[RetroReaction], List[float]]: """ Get all the probable actions of a set of molecules :param molecules: the molecules to consider + :param cache_molecules: additional molecules to submit to the expansion + policy but that only will be cached for later use :return: the actions and the priors of those actions """ + def reset_cache(self) -> None: + """Reset the prediction cache""" + + +class MultiExpansionStrategy(ExpansionStrategy): + """ + A base class for combining multiple expansion strategies. + + The strategy can be used by either calling the `get_actions` method + or by calling the instantiated class with a list of molecules. + + :ivar expansion_strategy_keys: the keys of the selected expansion strategies + :ivar additive_expansion: a conditional setting to specify whether all the actions + and priors of the selected expansion strategies should be combined or not. + Defaults to False. + + :param key: the key or label + :param config: the configuration of the tree search + :param expansion_strategies: the keys of the selected expansion strategies. All keys + of the selected expansion strategies must exist in the expansion policies listed + in config + """ + + _required_kwargs = ["expansion_strategies"] + + def __init__( + self, + key: str, + config: Configuration, + **kwargs: str, + ) -> None: + super().__init__(key, config, **kwargs) + self._config = config + self.expansion_strategy_keys = kwargs["expansion_strategies"] + self.additive_expansion: bool = bool(kwargs.get("additive_expansion", False)) + + def get_actions( + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, + ) -> Tuple[List[RetroReaction], List[float]]: + """ + Get all the probable actions of a set of molecules, using the selected policies. + + The default implementation combines all the actions and priors of the + selected expansion strategies into two lists respectively if the + 'additive_expansion' setting is set to True. This function can be overridden by + a sub class to combine different expansion strategies in different ways. + + :param molecules: the molecules to consider + :return: the actions and the priors of those actions + :raises: PolicyException: if the policy isn't selected + """ + expansion_strategies = self._get_expansion_strategies_from_config() + + all_possible_actions = [] + all_priors = [] + for expansion_strategy in expansion_strategies: + possible_actions, priors = expansion_strategy.get_actions( + molecules, cache_molecules + ) + all_possible_actions.extend(possible_actions) + all_priors.extend(priors) + if not self.additive_expansion and all_possible_actions: + break + return all_possible_actions, all_priors + + def _get_expansion_strategies_from_config(self) -> List[ExpansionStrategy]: + if not all( + key in self._config.expansion_policy.items + for key in self.expansion_strategy_keys + ): + raise ValueError( + "The input expansion strategy keys must exist in the " + "expansion policies listed in config" + ) + return [ + self._config.expansion_policy[key] for key in self.expansion_strategy_keys + ] + class TemplateBasedExpansionStrategy(ExpansionStrategy): """ A template-based expansion strategy that will return `TemplatedRetroReaction` objects upon expansion. + :ivar template_column: the column in the template file that contains the templates + :ivar cutoff_cumulative: the accumulative probability of the suggested templates + :ivar cutoff_number: the maximum number of templates to returned + :ivar use_rdchiral: a boolean to apply templates with RDChiral + :ivar use_remote_models: a boolean to connect to remote TensorFlow servers + :ivar rescale_prior: a boolean to apply softmax to the priors + :ivar chiral_fingerprints: if True will base expansion on chiral fingerprint + :param key: the key or label :param config: the configuration of the tree search - :param source: the source of the policy model - :param templatefile: the path to a HDF5 file with the templates - :raises PolicyException: if the length of the model output vector is not same as the number of templates + :param model: the source of the policy model + :param template: the path to a HDF5 file with the templates + :raises PolicyException: if the length of the model output vector is not same as the + number of templates """ - _required_kwargs = ["source", "templatefile"] + _required_kwargs = [ + "model", + "template", + ] def __init__(self, key: str, config: Configuration, **kwargs: str) -> None: super().__init__(key, config, **kwargs) - source = kwargs["source"] - templatefile = kwargs["templatefile"] + source = kwargs["model"] + templatefile = kwargs["template"] + self.template_column: str = kwargs.get("template_column", "retro_template") + self.cutoff_cumulative: float = float(kwargs.get("cutoff_cumulative", 0.995)) + self.cutoff_number: int = int(kwargs.get("cutoff_number", 50)) + self.use_rdchiral: bool = bool(kwargs.get("use_rdchiral", True)) + self.use_remote_models: bool = bool(kwargs.get("use_remote_models", False)) + self.rescale_prior: bool = bool(kwargs.get("rescale_prior", False)) + self.chiral_fingerprints = bool(kwargs.get("chiral_fingerprints", False)) self._logger.info( f"Loading template-based expansion policy model from {source} to {self.key}" ) - self.model = load_model(source, self.key, self._config.use_remote_models) + self.model = load_model(source, self.key, self.use_remote_models) self._logger.info(f"Loading templates from {templatefile} to {self.key}") if templatefile.endswith(".csv.gz") or templatefile.endswith(".csv"): @@ -104,49 +210,56 @@ def __init__(self, key: str, config: Configuration, **kwargs: str) -> None: f"The number of templates ({len(self.templates)}) does not agree with the " # type: ignore f"output dimensions of the model ({self.model.output_size})" ) + self._cache: Dict[str, Tuple[np.ndarray, np.ndarray]] = {} # pylint: disable=R0914 def get_actions( - self, molecules: Sequence[TreeMolecule] + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, ) -> Tuple[List[RetroReaction], List[float]]: """ Get all the probable actions of a set of molecules, using the selected policies and given cutoffs :param molecules: the molecules to consider + :param cache_molecules: additional molecules to submit to the expansion + policy but that only will be cached for later use :return: the actions and the priors of those actions """ possible_actions = [] - priors = [] + priors: List[float] = [] + cache_molecules = cache_molecules or [] + self._update_cache(list(molecules) + list(cache_molecules)) for mol in molecules: - model = self.model - templates = self.templates - - all_transforms_prop = self._predict(mol, model) - probable_transforms_idx = self._cutoff_predictions(all_transforms_prop) - possible_moves = templates.iloc[probable_transforms_idx] - probs = all_transforms_prop[probable_transforms_idx] - + probable_transforms_idx, probs = self._cache[mol.inchi_key] + possible_moves = self.templates.iloc[probable_transforms_idx] + if self.rescale_prior: + probs = softmax(probs) priors.extend(probs) for idx, (move_index, move) in enumerate(possible_moves.iterrows()): metadata = dict(move) - del metadata[self._config.template_column] + del metadata[self.template_column] metadata["policy_probability"] = float(probs[idx].round(4)) metadata["policy_probability_rank"] = idx metadata["policy_name"] = self.key metadata["template_code"] = move_index - metadata["template"] = move[self._config.template_column] + metadata["template"] = move[self.template_column] possible_actions.append( TemplatedRetroReaction( mol, - smarts=move[self._config.template_column], + smarts=move[self.template_column], metadata=metadata, - use_rdchiral=self._config.use_rdchiral, + use_rdchiral=self.use_rdchiral, ) ) return possible_actions, priors # type: ignore + def reset_cache(self) -> None: + """Reset the prediction cache""" + self._cache = {} + def _cutoff_predictions(self, predictions: np.ndarray) -> np.ndarray: """ Get the top transformations, by selecting those that have: @@ -155,14 +268,31 @@ def _cutoff_predictions(self, predictions: np.ndarray) -> np.ndarray: """ sortidx = np.argsort(predictions)[::-1] cumsum: np.ndarray = np.cumsum(predictions[sortidx]) - if any(cumsum >= self._config.cutoff_cumulative): - maxidx = int(np.argmin(cumsum < self._config.cutoff_cumulative)) + if any(cumsum >= self.cutoff_cumulative): + maxidx = int(np.argmin(cumsum < self.cutoff_cumulative)) else: maxidx = len(cumsum) - maxidx = min(maxidx, self._config.cutoff_number) or 1 + maxidx = min(maxidx, self.cutoff_number) or 1 return sortidx[:maxidx] - @staticmethod - def _predict(mol: TreeMolecule, model: Any) -> np.ndarray: - fp_arr = _make_fingerprint(mol, model) - return np.array(model.predict(fp_arr)).flatten() + def _update_cache(self, molecules: Sequence[TreeMolecule]) -> None: + pred_inchis = [] + fp_list = [] + for molecule in molecules: + if molecule.inchi_key in self._cache or molecule.inchi_key in pred_inchis: + continue + fp_list.append( + _make_fingerprint(molecule, self.model, self.chiral_fingerprints) + ) + pred_inchis.append(molecule.inchi_key) + + if not pred_inchis: + return + + pred_list = np.asarray(self.model.predict(np.vstack(fp_list))) + for pred, inchi in zip(pred_list, pred_inchis): + probable_transforms_idx = self._cutoff_predictions(pred) + self._cache[inchi] = ( + probable_transforms_idx, + pred[probable_transforms_idx], + ) diff --git a/aizynthfinder/context/policy/filter_strategies.py b/aizynthfinder/context/policy/filter_strategies.py index 786f94b..f76ef8c 100644 --- a/aizynthfinder/context/policy/filter_strategies.py +++ b/aizynthfinder/context/policy/filter_strategies.py @@ -66,21 +66,28 @@ class QuickKerasFilter(FilterStrategy): """ Filter quick-filter trained on artificial negative data + :ivar use_remote_models: a boolean to connect to remote TensorFlow servers. Defaults + to False. + :ivar filter_cutoff: the cut-off value + :param key: the key or label :param config: the configuration of the tree search - :param source: the source of the policy model + :param model: the source of the policy model """ - _required_kwargs: List[str] = ["source"] + _required_kwargs: List[str] = ["model"] def __init__(self, key: str, config: Configuration, **kwargs: Any) -> None: super().__init__(key, config, **kwargs) - source = kwargs["source"] + source = kwargs["model"] + # self.settings = self._config.filter_settings self._logger.info(f"Loading filter policy model from {source} to {key}") - self.model = load_model(source, key, self._config.use_remote_models) + self.use_remote_models: bool = bool(kwargs.get("use_remote_models", False)) + self.model = load_model(source, key, self.use_remote_models) self._prod_fp_name = kwargs.get("prod_fp_name", "input_1") self._rxn_fp_name = kwargs.get("rxn_fp_name", "input_2") self._exclude_from_policy: List[str] = kwargs.get("exclude_from_policy", []) + self.filter_cutoff: float = float(kwargs.get("filter_cutoff", 0.05)) def apply(self, reaction: RetroReaction) -> None: if reaction.metadata.get("policy_name", "") in self._exclude_from_policy: @@ -102,7 +109,7 @@ def feasibility(self, reaction: RetroReaction) -> Tuple[bool, float]: return False, 0.0 prob = self._predict(reaction) - feasible = prob >= self._config.filter_cutoff + feasible = prob >= self.filter_cutoff return feasible, prob def _predict(self, reaction: RetroReaction) -> float: diff --git a/aizynthfinder/context/policy/policies.py b/aizynthfinder/context/policy/policies.py index 38018df..cb13152 100644 --- a/aizynthfinder/context/policy/policies.py +++ b/aizynthfinder/context/policy/policies.py @@ -27,7 +27,7 @@ from aizynthfinder.chem import TreeMolecule from aizynthfinder.chem.reaction import RetroReaction from aizynthfinder.context.config import Configuration - from aizynthfinder.utils.type_utils import Any, List, Sequence, Tuple + from aizynthfinder.utils.type_utils import Any, Dict, List, Sequence, Tuple class ExpansionPolicy(ContextCollection): @@ -46,17 +46,23 @@ def __init__(self, config: Configuration) -> None: self._config = config def __call__( - self, molecules: Sequence[TreeMolecule] + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, ) -> Tuple[List[RetroReaction], List[float]]: - return self.get_actions(molecules) + return self.get_actions(molecules, cache_molecules) def get_actions( - self, molecules: Sequence[TreeMolecule] + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, ) -> Tuple[List[RetroReaction], List[float]]: """ Get all the probable actions of a set of molecules, using the selected policies :param molecules: the molecules to consider + :param cache_molecules: additional molecules that potentially are sent to + the expansion model but for which predictions are not returned :return: the actions and the priors of those actions :raises: PolicyException: if the policy isn't selected """ @@ -66,11 +72,11 @@ def get_actions( all_possible_actions = [] all_priors = [] for name in self.selection: - possible_actions, priors = self[name].get_actions(molecules) + possible_actions, priors = self[name].get_actions( + molecules, cache_molecules + ) all_possible_actions.extend(possible_actions) all_priors.extend(priors) - if not self._config.additive_expansion and all_possible_actions: - break return all_possible_actions, all_priors def load(self, source: ExpansionStrategy) -> None: # type: ignore @@ -90,41 +96,48 @@ def load_from_config(self, **config: Any) -> None: Load one or more expansion policy from a configuration The format should be - files: - key: - - path_to_model - - path_to_templates - or - template-based: - key: - - path_to_model - - path_to_templates + key: + type: name of the expansion class or custom_package.custom_model.CustomClass + model: path_to_model + template: path_to_templates + other settings or params or - custom_package.custom_model.CustomClass: - key: - param1: value1 - param2: value2 + key: + - path_to_model + - path_to_templates :param config: the configuration """ - files_spec = config.get("files", config.get("template-based", {})) - for key, policy_spec in files_spec.items(): - modelfile, templatefile = policy_spec - strategy = TemplateBasedExpansionStrategy( - key, self._config, source=modelfile, templatefile=templatefile - ) - self.load(strategy) - - # Load policies specifying a module and class, e.g. package.module.MyStrategyClass - for strategy_spec, strategy_config in config.items(): - if strategy_spec in ["files", "template-based"]: - continue - cls = load_dynamic_class( - strategy_spec, expansion_strategy_module, PolicyException - ) - for key, policy_spec in strategy_config.items(): - obj = cls(key, self._config, **(policy_spec or {})) - self.load(obj) + for key, strategy_config in config.items(): + if not isinstance(strategy_config, dict): + model, template = strategy_config + kwargs = {"model": model, "template": template} + cls = TemplateBasedExpansionStrategy + else: + if ( + "type" not in strategy_config + or strategy_config["type"] == "template-based" + ): + cls = TemplateBasedExpansionStrategy + else: + cls = load_dynamic_class( + strategy_config["type"], + expansion_strategy_module, + PolicyException, + ) + kwargs = dict(strategy_config) + + if "type" in kwargs: + del kwargs["type"] + obj = cls(key, self._config, **kwargs) + self.load(obj) + + def reset_cache(self) -> None: + """ + Reset the cache on all loaded policies + """ + for policy in self._items.values(): + policy.reset_cache() class FilterPolicy(ContextCollection): @@ -176,32 +189,36 @@ def load_from_config(self, **config: Any) -> None: Load one or more filter policy from a configuration The format should be - files: - key: path_to_model + key: + type: name of the filter class or custom_package.custom_model.CustomClass + model: path_to_model + other settings or params or - quick-filter: - key: path_to_model - or - custom_package.custom_model.CustomClass: - key: - param1: value1 - param2: value2 + key: path_to_model :param config: the configuration """ - files_spec = config.get("files", config.get("quick-filter", {})) - for key, modelfile in files_spec.items(): - strategy = QuickKerasFilter(key, self._config, source=modelfile) - self.load(strategy) - - # Load policies specifying a module and class, e.g. package.module.MyStrategyClass - for strategy_spec, strategy_config in config.items(): - if strategy_spec in ["files", "quick-filter"]: - continue - strategy_spec2 = FILTER_STRATEGY_ALIAS.get(strategy_spec, strategy_spec) - cls = load_dynamic_class( - strategy_spec2, filter_strategy_module, PolicyException - ) - for key, policy_spec in strategy_config.items(): - obj = cls(key, self._config, **(policy_spec or {})) - self.load(obj) + for key, strategy_config in config.items(): + if not isinstance(strategy_config, dict): + model = strategy_config + kwargs = {"model": model} + cls = QuickKerasFilter + else: + if ( + "type" not in strategy_config + or strategy_config["type"] == "quick-filter" + ): + cls = QuickKerasFilter + else: + strategy_spec = FILTER_STRATEGY_ALIAS.get( + strategy_config["type"], strategy_config["type"] + ) + cls = load_dynamic_class( + strategy_spec, filter_strategy_module, PolicyException + ) + kwargs = dict(strategy_config) + + if "type" in kwargs: + del kwargs["type"] + obj = cls(key, self._config, **kwargs) + self.load(obj) diff --git a/aizynthfinder/context/policy/utils.py b/aizynthfinder/context/policy/utils.py index 7cd4595..ffc5d5f 100644 --- a/aizynthfinder/context/policy/utils.py +++ b/aizynthfinder/context/policy/utils.py @@ -13,7 +13,7 @@ def _make_fingerprint( - obj: Union[TreeMolecule, RetroReaction], model: Any + obj: Union[TreeMolecule, RetroReaction], model: Any, chiral: bool = False ) -> np.ndarray: - fingerprint = obj.fingerprint(radius=2, nbits=len(model)) + fingerprint = obj.fingerprint(radius=2, nbits=len(model), chiral=chiral) return fingerprint.reshape([1, len(model)]) diff --git a/aizynthfinder/context/scoring/__init__.py b/aizynthfinder/context/scoring/__init__.py index 0722f73..92b9e17 100644 --- a/aizynthfinder/context/scoring/__init__.py +++ b/aizynthfinder/context/scoring/__init__.py @@ -3,12 +3,17 @@ from aizynthfinder.context.scoring.collection import ScorerCollection from aizynthfinder.context.scoring.scorers import ( AverageTemplateOccurrenceScorer, + CombinedScorer, + FractionInStockScorer, + MaxTransformScorerer, NumberOfPrecursorsInStockScorer, NumberOfPrecursorsScorer, NumberOfReactionsScorer, PriceSumScorer, + ReactionClassMembershipScorer, RouteCostScorer, Scorer, StateScorer, + StockAvailabilityScorer, ) from aizynthfinder.utils.exceptions import ScorerException diff --git a/aizynthfinder/context/scoring/collection.py b/aizynthfinder/context/scoring/collection.py index 20d8456..3fc84fe 100644 --- a/aizynthfinder/context/scoring/collection.py +++ b/aizynthfinder/context/scoring/collection.py @@ -59,8 +59,14 @@ class ScorerCollection(ContextCollection): def __init__(self, config: Configuration) -> None: super().__init__() self._config = config + self.create_default_scorers() + + def create_default_scorers(self) -> None: + """ + Setup the scores that only need the config as their input. + """ for cls in _SIMPLE_SCORERS: - self.load(cls(config)) + self.load(cls(self._config)) def load(self, scorer: Scorer) -> None: # type: ignore """ @@ -96,6 +102,26 @@ class along with the ``config`` parameter. self._logger.info(f"Loaded scorer: '{repr(obj)}'{config_str}") self._items[repr(obj)] = obj + def make_subset(self, subset_names: List[str]) -> "ScorerCollection": + """ + Make a new scorer collection by taking a subset of this + collection. The scorer instances will be shared between + the collections + + :param subset_names: the scorers to copy over + :returns: the newly formed collection + """ + new_collection = ScorerCollection(self._config) + for name in new_collection.names(): + del new_collection[name] + for name in subset_names: + try: + scorer = self._items[name] + except KeyError: + raise ScorerException(f"Unable to find '{name}' in parent collection") + new_collection.load(scorer) + return new_collection + def names(self) -> List[str]: """Return a list of the names of all the loaded scorers""" return self.items @@ -103,3 +129,42 @@ def names(self) -> List[str]: def objects(self) -> List[Scorer]: """Return a list of all the loaded scorer objects""" return list(self._items.values()) + + def score_vector(self, item: _Scoreable) -> Sequence[float]: + """ + For the given item, score it with all selected scorers + and return a vector + + :param item: the item to be scored + :returns: the vector with the scores + """ + if not self.selection: + return [] + return [self[scorer](item) for scorer in self.selection] + + def weighted_score(self, item: _Scoreable, weights: Sequence[float]) -> float: + """ + For the given item, score it with all selected scorers + and return a weighted sum of all the scores. + + If weights is not the same length as the number of scorers + an exception is raised. + + If no scorers are selected this will raise an exception + + :param item: the item to be scored + :param weights: the weights of the scorers + :returns: the weighted sum + """ + if not self.selection: + raise ScorerException( + "No scorers are selected so cannot compute weighted sum" + ) + + if len(weights) != len(self.selection): + raise ScorerException( + "The number of weights given does not agree with the number of scorers" + ) + return sum( + weight * score for weight, score in zip(weights, self.score_vector(item)) + ) diff --git a/aizynthfinder/context/scoring/scorers.py b/aizynthfinder/context/scoring/scorers.py index 34939b4..b9ac45d 100644 --- a/aizynthfinder/context/scoring/scorers.py +++ b/aizynthfinder/context/scoring/scorers.py @@ -5,24 +5,85 @@ import abc from collections import defaultdict from collections.abc import Sequence as SequenceAbc +from dataclasses import dataclass from typing import TYPE_CHECKING +import numpy as np + from aizynthfinder.chem import TreeMolecule from aizynthfinder.context.stock import StockException from aizynthfinder.reactiontree import ReactionTree -from aizynthfinder.search.mcts import MctsNode, MctsState +from aizynthfinder.search.mcts import MctsNode from aizynthfinder.utils.exceptions import ScorerException if TYPE_CHECKING: from aizynthfinder.chem import FixedRetroReaction, Molecule, RetroReaction from aizynthfinder.context.config import Configuration - from aizynthfinder.utils.type_utils import Iterable, Sequence, Tuple, TypeVar, Union + from aizynthfinder.utils.type_utils import ( + Iterable, + Optional, + Sequence, + StrDict, + Tuple, + TypeVar, + Union, + ) _Scoreable = TypeVar("_Scoreable", MctsNode, ReactionTree) _Scoreables = Sequence[_Scoreable] _ScorerItemType = Union[_Scoreables, _Scoreable] +@dataclass +class SquashScaler: + """ + Squash function loosely adapted from a sigmoid function with parameters + to modify and offset the shape + + :param slope: the slope of the midpoint + :param xoffset: the offset of the midpoint along the x-axis + :param yoffset: the offset of the curve along the y-axis + """ + + slope: float + xoffset: float + yoffset: float + + def __call__(self, val: float) -> float: + return 1 / (1 + np.exp(self.slope * -(val - self.xoffset))) - self.yoffset + + +@dataclass +class MinMaxScaler: + """ + Scaling function that normalises the value between 0 - 1, + the reverse variable controls the direction of scaling, + reverse should set to be true for rewards that need to be minimised + the scale_factor could be used to adjust the scores when they are too small or too big + + :param val: the value that is being scaled + :param min_val: minimum val param val could take + :param max_val: maximum val param val could take + :param scale_factor: scaling factor applied to the minmax scaled output + """ + + min_val: float + max_val: float + reverse: bool + scale_factor: float = 1 + + def __call__(self, val: float) -> float: + val = np.clip(val, self.min_val, self.max_val) + if self.reverse: + numerator = self.max_val - val + else: + numerator = val - self.min_val + return (numerator / (self.max_val - self.min_val)) * self.scale_factor + + +_SCALERS = {"squash": SquashScaler, "min_max": MinMaxScaler} + + class Scorer(abc.ABC): """ Abstract base class for classes that do scoring on MCTS-like nodes or reaction trees. @@ -43,11 +104,28 @@ class Scorer(abc.ABC): scores = scorer([node1, node2]) :param config: the configuration the tree search + :param scaler_params: the parameter settings of the scaler """ - def __init__(self, config: Configuration = None) -> None: + scorer_name = "base" + + def __init__( + self, + config: Optional[Configuration] = None, + scaler_params: Optional[StrDict] = None, + ) -> None: self._config = config self._reverse_order: bool = True + self._scaler = None + self._scaler_name = "" + if scaler_params: + self._scaler_name = scaler_params["name"] + del scaler_params["name"] + if scaler_params: + self._scaler = _SCALERS[self._scaler_name](**scaler_params) + else: + # for paramterless function + self._scaler = _SCALERS[self._scaler_name] def __call__(self, item: _ScorerItemType) -> Union[float, Sequence[float]]: if isinstance(item, SequenceAbc): @@ -58,6 +136,12 @@ def __call__(self, item: _ScorerItemType) -> Union[float, Sequence[float]]: f"Unable to score item from class {item.__class__.__name__}" ) + def __repr__(self) -> str: + repr_name = self.scorer_name + if self._scaler_name: + repr_name += f"-{self._scaler_name}" + return repr_name + def sort( self, items: _Scoreables ) -> Tuple[_Scoreables, Sequence[float], Sequence[int]]: @@ -78,45 +162,70 @@ def sort( def _score_just_one(self, item: _Scoreable) -> float: if isinstance(item, MctsNode): - return self._score_node(item) - return self._score_reaction_tree(item) - - def _score_many(self, items: _Scoreables) -> Sequence[float]: - if isinstance(items[0], MctsNode): - return self._score_nodes(items) - if isinstance(items[0], ReactionTree): - return self._score_reaction_trees(items) + node_score = self._score_node(item) + if self._scaler: + node_score = self._scaler(node_score) + return node_score + if isinstance(item, ReactionTree): + tree_score = self._score_reaction_tree(item) + if self._scaler: + tree_score = self._scaler(tree_score) + return tree_score raise ScorerException( - f"Unable to score item from class {items[0].__class__.__name__}" + f"Unable to score item from class {item.__class__.__name__}" ) + def _score_many(self, items: _Scoreables) -> Sequence[float]: + return [self._score_just_one(item) for item in items] + @abc.abstractmethod def _score_node(self, node: MctsNode) -> float: pass - def _score_nodes(self, nodes: _Scoreables) -> Sequence[float]: - return [self._score_node(node) for node in nodes] - @abc.abstractmethod def _score_reaction_tree(self, tree: ReactionTree) -> float: pass - def _score_reaction_trees(self, trees: _Scoreables) -> Sequence[float]: - return [self._score_reaction_tree(tree) for tree in trees] - class StateScorer(Scorer): """Class for scoring nodes based on the state score""" - def __init__(self, config: Configuration) -> None: - super().__init__(config) + scorer_name = "state score" + + def __init__( + self, config: Configuration, scaler_params: Optional[StrDict] = None + ) -> None: + super().__init__(config, scaler_params) + # This is necessary because config should not be optional for this scorer self._config: Configuration = config + self._transform_scorer = MaxTransformScorerer( + config, + scaler_params={"name": "squash", "slope": -1, "yoffset": 0, "xoffset": 4}, + ) + self._in_stock_scorer = FractionInStockScorer(config) - def __repr__(self) -> str: - return "state score" + def _score(self, item: _Scoreable) -> float: + in_stock_fraction = self._in_stock_scorer(item) + max_transform = self._transform_scorer(item) + # A scorer can return a list of float if the item is a list of trees/nodes, + # but that is not the case here. However this is needed because of mypy + assert isinstance(in_stock_fraction, float) and isinstance(max_transform, float) + return 0.95 * in_stock_fraction + 0.05 * max_transform def _score_node(self, node: MctsNode) -> float: - return node.state.score + return self._score(node) + + def _score_reaction_tree(self, tree: ReactionTree) -> float: + return self._score(tree) + + +class MaxTransformScorerer(Scorer): + """Class for scoring nodes based on the maximum transform""" + + scorer_name = "max transform" + + def _score_node(self, node: MctsNode) -> float: + return node.state.max_transforms def _score_reaction_tree(self, tree: ReactionTree) -> float: mols = [ @@ -125,19 +234,45 @@ def _score_reaction_tree(self, tree: ReactionTree) -> float: ) for leaf in tree.leafs() ] - state = MctsState(mols, self._config) - return state.score + return max(mol.transform for mol in mols) + + +class FractionInStockScorer(Scorer): + """Class for scoring nodes based on the fraction in stock""" + + scorer_name = "fraction in stock" + + def __init__( + self, config: Configuration, scaler_params: Optional[StrDict] = None + ) -> None: + super().__init__(config, scaler_params) + # This is necessary because config should not be optional for this scorer + self._config: Configuration = config + + def _score_node(self, node: MctsNode) -> float: + num_in_stock = np.sum(node.state.in_stock_list) + num_molecules = len(node.state.mols) + return float(num_in_stock) / float(num_molecules) + + def _score_reaction_tree(self, tree: ReactionTree) -> float: + leaves = list(tree.leafs()) + num_in_stock = sum(mol in self._config.stock for mol in leaves) + num_molecules = len(leaves) + return float(num_in_stock) / float(num_molecules) class NumberOfReactionsScorer(Scorer): """Class for scoring nodes based on the number of reaction it took to get to a node""" - def __init__(self, config: Configuration = None) -> None: - super().__init__(config) - self._reverse_order = False + scorer_name = "number of reactions" - def __repr__(self) -> str: - return "number of reactions" + def __init__( + self, + config: Optional[Configuration] = None, + scaler_params: Optional[StrDict] = None, + ) -> None: + super().__init__(config, scaler_params) + self._reverse_order = False def _score_node(self, node: MctsNode) -> float: reactions = node.actions_to() @@ -150,12 +285,15 @@ def _score_reaction_tree(self, tree: ReactionTree) -> float: class NumberOfPrecursorsScorer(Scorer): """Class for scoring nodes based on the number of pre-cursors in a node or route""" - def __init__(self, config: Configuration = None) -> None: - super().__init__(config) - self._reverse_order = False + scorer_name = "number of pre-cursors" - def __repr__(self) -> str: - return "number of pre-cursors" + def __init__( + self, + config: Optional[Configuration] = None, + scaler_params: Optional[StrDict] = None, + ) -> None: + super().__init__(config, scaler_params) + self._reverse_order = False def _score_node(self, node: MctsNode) -> float: return len(node.state.mols) @@ -165,14 +303,16 @@ def _score_reaction_tree(self, tree: ReactionTree) -> float: class NumberOfPrecursorsInStockScorer(Scorer): - """Class for scoring nodes based on the number of pre-cursors in stock a node or route""" + """Class for scoring nodes based on the number of pre-cursors in stock a + node or route""" - def __init__(self, config: Configuration) -> None: - super().__init__(config) - self._stock = config.stock + scorer_name = "number of pre-cursors in stock" - def __repr__(self) -> str: - return "number of pre-cursors in stock" + def __init__( + self, config: Configuration, scaler_params: Optional[StrDict] = None + ) -> None: + super().__init__(config, scaler_params) + self._stock = config.stock def _score_node(self, node: MctsNode) -> float: return len([mol for mol in node.state.mols if mol in self._stock]) @@ -182,10 +322,10 @@ def _score_reaction_tree(self, tree: ReactionTree) -> float: class AverageTemplateOccurrenceScorer(Scorer): - """Class for scoring the nodes based on the average occurrence of the templates used to get to a node""" + """Class for scoring the nodes based on the average occurrence of the + templates used to get to a node""" - def __repr__(self) -> str: - return "average template occurrence" + scorer_name = "average template occurrence" def _calc_average( self, reactions: Sequence[Union[FixedRetroReaction, RetroReaction]] @@ -211,22 +351,21 @@ def _get_occurrence(reaction: Union[FixedRetroReaction, RetroReaction]) -> int: class PriceSumScorer(Scorer): """Scorer that sums the prices of all pre-cursors""" + scorer_name = "sum of prices" + def __init__( self, config: Configuration, + scaler_params: Optional[StrDict] = None, default_cost: float = 1.0, not_in_stock_multiplier: int = 10, ) -> None: - super().__init__(config) + super().__init__(config, scaler_params) self._config: Configuration = config - self.default_cost = default_cost self.not_in_stock_multiplier = not_in_stock_multiplier self._reverse_order = False - def __repr__(self) -> str: - return "sum of prices" - def _calculate_leaf_costs( self, leafs: Union[Sequence[Molecule], Iterable[Molecule]] ) -> dict: @@ -259,9 +398,12 @@ class RouteCostScorer(PriceSumScorer): From Badowski et al. Chem Sci. 2019, 10, 4640 """ + scorer_name = "route cost" + def __init__( self, config: Configuration, + scaler_params: Optional[StrDict] = None, reaction_cost: int = 1, average_yield: float = 0.8, default_cost: int = 1, @@ -269,6 +411,7 @@ def __init__( ) -> None: super().__init__( config, + scaler_params, default_cost=default_cost, not_in_stock_multiplier=not_in_stock_multiplier, ) @@ -276,9 +419,6 @@ def __init__( self.average_yield = average_yield self._reverse_order = False - def __repr__(self) -> str: - return "route cost" - def _score_node(self, node: MctsNode) -> float: leaf_costs = self._calculate_leaf_costs(node.state.mols) @@ -318,3 +458,134 @@ def _recursive_score(node): leaf_costs = self._calculate_leaf_costs(tree.leafs()) return _recursive_score(tree.root) + + +class ReactionClassMembershipScorer(Scorer): + """ + Scorer that checks if the reaction classes are in a specified set + + The score is calculated as product over each reaction. For each reaction + the reaction classification is checked if it is in a given list of classes. + """ + + def __init__( + self, + config: Configuration, + reaction_class_set: Sequence[str], + in_set_score: float = 1.0, + not_in_set_score: float = 0.1, + ) -> None: + super().__init__(config) + self.reaction_class_set = set(item.split(" ")[0] for item in reaction_class_set) + self.in_set_score = in_set_score + self.not_in_set_score = not_in_set_score + + def __repr__(self) -> str: + return "reaction class membership" + + def _calc_product( + self, reactions: Sequence[Union[FixedRetroReaction, RetroReaction]] + ) -> float: + if not reactions: + return 1.0 + prod = 1.0 + for reaction in reactions: + membership = self._get_membership(reaction) + prod *= self.in_set_score if membership else self.not_in_set_score + return prod + + def _get_membership( + self, reaction: Union[FixedRetroReaction, RetroReaction] + ) -> bool: + classification = reaction.metadata.get("classification") + if not classification: + return 0.0 in self.reaction_class_set + return classification.split(" ")[0] in self.reaction_class_set + + def _score_node(self, node: MctsNode) -> float: + return self._calc_product(node.actions_to()) + + def _score_reaction_tree(self, tree: ReactionTree) -> float: + return self._calc_product(list(tree.reactions())) + + +class StockAvailabilityScorer(Scorer): + """ + Scorer that computes score based on the stock availability of the starting material + + The score is calculated as a product of a stock score per starting material. The stock + score for each molecule is based on the source of the stock, or a default value if the + molecule is not in stock. + """ + + def __init__( + self, + config: Configuration, + source_score: StrDict, + default_score: float = 0.1, + ) -> None: + super().__init__(config) + assert self._config is not None + self.source_score = source_score + self.default_score = default_score + + def __repr__(self) -> str: + return "stock availability" + + def _calculate_leaf_costs( + self, leafs: Union[Sequence[Molecule], Iterable[Molecule]] + ) -> float: + assert self._config is not None + prod = 1.0 + for mol in leafs: + availability = self._config.stock.availability_list(mol) + scores = [ + self.source_score[source] + for source in availability + if source in self.source_score + ] + prod *= max(scores) if scores else self.default_score + return prod + + def _score_node(self, node: MctsNode) -> float: + return self._calculate_leaf_costs(node.state.mols) + + def _score_reaction_tree(self, tree: ReactionTree) -> float: + return self._calculate_leaf_costs(tree.leafs()) + + +class CombinedScorer(Scorer): + """Class for scoring nodes and reaction trees by combining weighted scores from a list of scorers + + If no weights are provided as input, the scorer provides default weights that are + equal for all input scorers. + + The CombinedScorer cannot be instantiated from the config file as it requires the + names of the scorers to combine as input. + """ + + def __init__( + self, + config: Configuration, + scorers: Sequence[str], + weights: Optional[Sequence[float]] = None, + ) -> None: + super().__init__(config) + self._scorers = [config.scorers[scorer] for scorer in scorers] + self._weights = weights if weights else [1 / len(scorers)] * len(scorers) + + def __repr__(self) -> str: + return " + ".join([repr(scorer) for scorer in self._scorers]) + + def _combine_score(self, scores: Sequence[float]) -> float: + return sum( + score * weight for score, weight in zip(scores, self._weights) + ) / sum(self._weights) + + def _score_node(self, node: MctsNode) -> float: + scores = [scorer(node) for scorer in self._scorers] + return self._combine_score(scores) + + def _score_reaction_tree(self, tree: ReactionTree) -> float: + scores = [scorer(tree) for scorer in self._scorers] + return self._combine_score(scores) diff --git a/aizynthfinder/context/stock/__init__.py b/aizynthfinder/context/stock/__init__.py index d201e53..0202ee6 100644 --- a/aizynthfinder/context/stock/__init__.py +++ b/aizynthfinder/context/stock/__init__.py @@ -1,5 +1,9 @@ """ Sub-package containing stock routines """ -from aizynthfinder.context.stock.queries import MongoDbInchiKeyQuery, StockQueryMixin +from aizynthfinder.context.stock.queries import ( + InMemoryInchiKeyQuery, + MongoDbInchiKeyQuery, + StockQueryMixin, +) from aizynthfinder.context.stock.stock import Stock from aizynthfinder.utils.exceptions import StockException diff --git a/aizynthfinder/context/stock/queries.py b/aizynthfinder/context/stock/queries.py index 3947ae7..9938ed5 100644 --- a/aizynthfinder/context/stock/queries.py +++ b/aizynthfinder/context/stock/queries.py @@ -7,6 +7,13 @@ import pandas as pd +try: + import molbloom +except ImportError: + HAS_MOLBLOOM = False +else: + HAS_MOLBLOOM = True + from aizynthfinder.chem import Molecule from aizynthfinder.utils.exceptions import StockException from aizynthfinder.utils.mongo import get_mongo_client @@ -16,7 +23,7 @@ from pymongo.database import Database as MongoDatabase # pylint: disable=ungrouped-imports - from aizynthfinder.utils.type_utils import Optional, Set + from aizynthfinder.utils.type_utils import Optional, Set, StrDict # pylint: disable=no-self-use @@ -86,25 +93,59 @@ class InMemoryInchiKeyQuery(StockQueryMixin): * A Pandas dataframe in HDF5 or CSV format * A text file with an inchi key on each row - The pandas dataframe must have a column "inchi_key" with InChIkeys. + The dataframe must have a column with InChIkeys that by default is "inchi_key". The HDF5 file must have a dataset called "table". - :parameter filename: the path to the file with inchi-keys + If the source is a dataframe, then optionally it can contain prices and this + columns can be specified with the "price_column" argument. + + :parameter path: the path to the file with inchi-keys + :parameter inchi_key_col: the name of the column of the InChI keys + :paramater price_col: the name of the column with the optional prices """ - def __init__(self, filename: str) -> None: - ext = os.path.splitext(filename)[1] + def __init__( + self, + path: str, + inchi_key_col: str = "inchi_key", + price_col: Optional[str] = None, + ) -> None: + ext = os.path.splitext(path)[1] + if ext not in [".h5", ".hdf5", ".csv"]: + with open(path, "r") as fileobj: + inchis = fileobj.read().splitlines() + self._stock_inchikeys = set(inchis) + self._price_dict: StrDict = {} + return + if ext in [".h5", ".hdf5"]: - stock = pd.read_hdf(filename, key="table") # type: ignore - inchis = stock.inchi_key.values # type: ignore + stock_df: pd.DataFrame = pd.read_hdf(path, key="table") elif ext == ".csv": - stock = pd.read_csv(filename) - inchis = stock.inchi_key.values - else: - with open(filename, "r") as fileobj: - inchis = fileobj.read().splitlines() + stock_df = pd.read_csv( + path, + usecols=[inchi_key_col, price_col] if price_col else [inchi_key_col], + ) + inchis = stock_df[inchi_key_col].values self._stock_inchikeys = set(inchis) + if price_col is None: + self._price_dict = {} + return + + if len(stock_df) != len(self._stock_inchikeys): + raise StockException( + "InChI keys in stock df are expected to be unique, currently they are not" + ) + if stock_df[price_col].isnull().sum() != 0: + raise StockException( + "null values found in the price column, please drop/impute them first" + ) + if stock_df[price_col].min() < 0: + raise StockException( + f"expected non-negative prices, the min in the current file {path} is {stock_df[price_col].min()} " + ) + self._price_dict = dict(zip(stock_df[inchi_key_col], stock_df[price_col])) + def __contains__(self, mol: Molecule) -> bool: return mol.inchi_key in self._stock_inchikeys @@ -116,6 +157,15 @@ def stock_inchikeys(self) -> Set[str]: """Return the InChiKeys in this stock""" return self._stock_inchikeys + def price(self, mol: Molecule) -> float: + if not self._price_dict: + raise StockException( + "no prices created, check the path type and if price column is supplied" + ) + if mol in self: + return self._price_dict[mol.inchi_key] + raise StockException(f"no price info available for {mol.smiles}") + class MongoDbInchiKeyQuery(StockQueryMixin): """ @@ -136,7 +186,7 @@ class MongoDbInchiKeyQuery(StockQueryMixin): def __init__( self, - host: str = None, + host: Optional[str] = None, database: str = "stock_db", collection: str = "molecules", ) -> None: @@ -168,3 +218,34 @@ def availability_string(self, mol: Molecule) -> str: item["source"] for item in self.molecules.find({"inchi_key": mol.inchi_key}) ] return ",".join(sources) + + +class MolbloomFilterQuery(StockQueryMixin): + """ + A stock query class that is based on an a molbloom filter + for SMILES strings or InChI keys + + :parameter path: the path to the saved bloom filter + :parameter smiles_based: if True will use SMILES for lookup instead of InChI keys + """ + + def __init__(self, path: str, smiles_based: bool = False) -> None: + if not HAS_MOLBLOOM: + raise ImportError( + "Cannot use this stock query class because it seems like molbloom is not installed. " + "Please install aizynthfinder with extras dependencies." + ) + self._filter = molbloom.BloomFilter(path) + self._smiles_based = smiles_based + + def __contains__(self, mol: Molecule) -> bool: + if self._smiles_based: + return mol.smiles in self._filter + return mol.inchi_key in self._filter + + +STOCK_QUERY_ALIAS = { + "inchiset": "InMemoryInchiKeyQuery", + "mongodb": "MongoDbInchiKeyQuery", + "bloom": "MolbloomFilterQuery", +} diff --git a/aizynthfinder/context/stock/stock.py b/aizynthfinder/context/stock/stock.py index 5b6b658..fc322c2 100644 --- a/aizynthfinder/context/stock/stock.py +++ b/aizynthfinder/context/stock/stock.py @@ -10,13 +10,24 @@ from aizynthfinder.context.collection import ContextCollection from aizynthfinder.context.stock.queries import ( InMemoryInchiKeyQuery, - MongoDbInchiKeyQuery, + MolbloomFilterQuery, + STOCK_QUERY_ALIAS, + StockQueryMixin, ) +from aizynthfinder.context.stock.queries import __name__ as queries_module from aizynthfinder.utils.exceptions import StockException from aizynthfinder.utils.loading import load_dynamic_class if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import Any, List, Set, StrDict, Union + from aizynthfinder.utils.type_utils import ( + Any, + Dict, + List, + Optional, + Set, + StrDict, + Union, + ) class Stock(ContextCollection): @@ -128,63 +139,67 @@ def exclude(self, mol: Molecule) -> None: """ self._exclude.add(mol.inchi_key) - def load(self, source: Union[str, Any], key: str) -> None: # type: ignore + def load(self, source: StockQueryMixin, key: str) -> None: # type: ignore """ - Load a stock. + Add a pre-initialized stock query object to the stock - If `source` is a string, it is taken as a path to a filename and the - stock is loaded as an `InMemoryInchiKeyQuery` object. - - If `source` is not a string, it is taken as a custom object that - implements the `__contains__` and `__len__` methods for querying. - - :param source: the source of the sock + :param source: the item to add :param key: The key that will be used to select the stock """ - src_str = str(source) - if "object at 0x" in src_str: - src_str = source.__class__.__name__ - self._logger.info(f"Loading stock from {src_str} to {key}") + if not isinstance(source, StockQueryMixin): + raise StockException( + "Only objects of classes inherited from StockQueryMixin can be added" + ) - if isinstance(source, str): - source = InMemoryInchiKeyQuery(source) + self._logger.info(f"Loading stock from {source.__class__.__name__} to {key}") self._items[key] = source def load_from_config(self, **config: Any) -> None: """ - Load stocks from a configuration + Load one or more stock queries from a configuration + + The key can be "stop_criteria" in case the config is given to the + `set_stop_criteria` method - The key can be "files" in case stocks are loaded from a file - The key can be "mongodb" in case a ``MongoDbInchiKeyQuery`` object is instantiated - The key can be "stop_criteria" in case the config is given to the `set_stop_criteria` method - The key can point to a custom stock class, e.g. ``mypackage.mymodule.MyStock`` - in case this stock object is instantiated + The format should be + key: + type: name of the stock class or custom_package.custom_model.CustomClass + path: path to the stock file + other settings or params + or + key: path_to_model :param config: the configuration """ - known_keys = ["files", "mongodb", "stop_criteria"] if "stop_criteria" in config: self.set_stop_criteria(config["stop_criteria"]) - for key, stockfile in config.get("files", {}).items(): - self.load(stockfile, key) - - if "mongodb" in config: - query_obj = MongoDbInchiKeyQuery(**(config["mongodb"] or {})) - self.load(query_obj, "mongodb_stock") - - # Load stocks specifying a module and class, e.g. package.module.MyQueryClass - for name, stock_config in config.items(): - if name in known_keys or name.find(".") == -1: + for key, stock_config in config.items(): + if key == "stop_criteria": continue - try: - query_cls = load_dynamic_class(name) - except ValueError as err: - self._logger.warning(str(err)) + if not isinstance(stock_config, dict): + kwargs = {"path": stock_config} + if stock_config.endswith(".bloom"): + cls: Any = MolbloomFilterQuery + else: + cls = InMemoryInchiKeyQuery else: - query_obj = query_cls(**(stock_config or {})) - self.load(query_obj, query_cls.__name__) + if "type" not in stock_config or stock_config["type"] == "inchiset": + cls = InMemoryInchiKeyQuery + else: + stock_query = STOCK_QUERY_ALIAS.get( + stock_config["type"], stock_config["type"] + ) + cls = load_dynamic_class( + stock_query, queries_module, StockException + ) + kwargs = dict(stock_config) + + if "type" in kwargs: + del kwargs["type"] + obj = cls(**kwargs) + self.load(obj, key) def price(self, mol: Molecule) -> float: """ @@ -216,7 +231,7 @@ def select(self, value: Union[str, List[str]], append: bool = False) -> None: except (TypeError, ValueError): # In case len is not possible to compute pass - def set_stop_criteria(self, criteria: dict = None) -> None: + def set_stop_criteria(self, criteria: Optional[Dict] = None) -> None: """ Set criteria that stop the search diff --git a/aizynthfinder/interfaces/aizynthapp.py b/aizynthfinder/interfaces/aizynthapp.py index 04a070c..5baca55 100644 --- a/aizynthfinder/interfaces/aizynthapp.py +++ b/aizynthfinder/interfaces/aizynthapp.py @@ -12,12 +12,10 @@ import jupytext from IPython.display import HTML, display from ipywidgets import ( - BoundedFloatText, BoundedIntText, Button, Checkbox, Dropdown, - FloatText, HBox, IntText, Label, @@ -68,7 +66,7 @@ def setup(self) -> None: """ Create the widgets and display the GUI. This is typically done on instantiation, but this method - if for more advanced uses. + is for more advanced uses. """ self._create_input_widgets() self._create_search_widgets() @@ -138,76 +136,39 @@ def _create_input_widgets(self) -> None: ) max_time_box = self._make_slider_input("time_limit", "Time (min)", 1, 120) - self._input["time_limit"].value = self.finder.config.time_limit / 60 + self._input["time_limit"].value = self.finder.config.search.time_limit / 60 max_iter_box = self._make_slider_input( "iteration_limit", "Max Iterations", 100, 2000 ) - self._input["iteration_limit"].value = self.finder.config.iteration_limit + self._input["iteration_limit"].value = self.finder.config.search.iteration_limit self._input["return_first"] = widgets.Checkbox( - value=self.finder.config.return_first, + value=self.finder.config.search.return_first, description="Return first solved route", ) - vbox = VBox( - [ - self._input["policy"], - self._input["filter"], - max_time_box, - max_iter_box, - self._input["return_first"], - ] - ) - box_options = HBox([box_stocks, vbox]) - - self._input["C"] = FloatText(description="C", value=self.finder.config.C) self._input["max_transforms"] = BoundedIntText( - description="Max steps for substrates", + description="Max tree depth", min=1, max=20, - value=self.finder.config.max_transforms, - style={"description_width": "initial"}, - ) - self._input["cutoff_cumulative"] = BoundedFloatText( - description="Policy cutoff cumulative", - min=0, - max=1, - value=self.finder.config.cutoff_cumulative, - style={"description_width": "initial"}, - ) - self._input["cutoff_number"] = BoundedIntText( - description="Policy cutoff number", - min=1, - max=1000, - value=self.finder.config.cutoff_number, - style={"description_width": "initial"}, - ) - self._input["filter_cutoff"] = BoundedFloatText( - description="Filter cutoff", - min=0, - max=1, - value=self.finder.config.filter_cutoff, + value=self.finder.config.search.max_transforms, style={"description_width": "initial"}, ) self._input["exclude_target_from_stock"] = widgets.Checkbox( - value=self.finder.config.exclude_target_from_stock, + value=self.finder.config.search.exclude_target_from_stock, description="Exclude target from stock", ) - box_advanced = VBox( + vbox = VBox( [ - self._input["C"], + self._input["policy"], + self._input["filter"], + max_time_box, + max_iter_box, + self._input["return_first"], self._input["max_transforms"], - self._input["cutoff_cumulative"], - self._input["cutoff_number"], - self._input["filter_cutoff"], self._input["exclude_target_from_stock"], ] ) - - children = [box_options, box_advanced] - tab = widgets.Tab() - tab.children = children - tab.set_title(0, "Options") - tab.set_title(1, "Advanced") - display(tab) + box_options = HBox([box_stocks, vbox]) + display(box_options) def _create_route_widgets(self) -> None: self._input["scorer"] = widgets.Dropdown( @@ -318,19 +279,18 @@ def _prepare_search(self) -> None: self.finder.filter_policy.deselect() else: self.finder.filter_policy.select(self._input["filter"].value) - self.finder.config.properties = { - "C": self._input["C"].value, - "max_transforms": self._input["max_transforms"].value, - "cutoff_cumulative": self._input["cutoff_cumulative"].value, - "cutoff_number": int(self._input["cutoff_number"].value), - "return_first": self._input["return_first"].value, - "time_limit": self._input["time_limit"].value * 60, - "iteration_limit": self._input["iteration_limit"].value, - "filter_cutoff": self._input["filter_cutoff"].value, - "exclude_target_from_stock": self._input[ - "exclude_target_from_stock" - ].value, - } + + self.finder.config.search.max_transforms = self._input[ + "max_transforms" + ].value + self.finder.config.search.return_first = self._input["return_first"].value + self.finder.config.search.time_limit = self._input["time_limit"].value * 60 + self.finder.config.search.iteration_limit = self._input[ + "iteration_limit" + ].value + self.finder.config.search.exclude_target_from_stock = self._input[ + "exclude_target_from_stock" + ].value smiles = self._input["smiles"].value print("Setting target molecule with smiles: %s" % smiles) diff --git a/aizynthfinder/interfaces/aizynthcli.py b/aizynthfinder/interfaces/aizynthcli.py index d8c608e..221414e 100644 --- a/aizynthfinder/interfaces/aizynthcli.py +++ b/aizynthfinder/interfaces/aizynthcli.py @@ -42,7 +42,7 @@ def _do_clustering( finder: AiZynthFinder, results: StrDict, detailed_results: bool, - model_path: str = None, + model_path: Optional[str] = None, ) -> None: time0 = time.perf_counter_ns() if model_path: @@ -186,9 +186,14 @@ def _process_single_smiles( return finder.tree_search(show_progress=True) finder.build_routes() + finder.routes.compute_scores(*finder.scorers.objects()) with open(output_name, "w") as fileobj: - json.dump(finder.routes.dicts, fileobj, indent=2) + json.dump( + finder.routes.dict_with_extra(include_metadata=True, include_scores=True), + fileobj, + indent=2, + ) logger().info(f"Trees saved to {output_name}") scores = ", ".join("%.4f" % score for score in finder.routes.scores) @@ -242,6 +247,7 @@ def _process_multi_smiles( continue search_time = finder.tree_search() finder.build_routes() + finder.routes.compute_scores(*finder.scorers.objects()) stats = finder.extract_statistics() solved_str = "is solved" if stats["is_solved"] else "is not solved" diff --git a/aizynthfinder/reactiontree.py b/aizynthfinder/reactiontree.py index eeb650b..9f461c5 100644 --- a/aizynthfinder/reactiontree.py +++ b/aizynthfinder/reactiontree.py @@ -209,7 +209,7 @@ def to_dict(self, include_metadata=False) -> StrDict: def to_image( self, - in_stock_colors: FrameColors = None, + in_stock_colors: Optional[FrameColors] = None, show_all: bool = True, ) -> PilImage: """ @@ -237,7 +237,7 @@ def to_json(self, include_metadata=False) -> str: def _build_dict( self, node: Union[UniqueMolecule, FixedRetroReaction], - dict_: StrDict = None, + dict_: Optional[StrDict] = None, include_metadata=False, ) -> StrDict: if dict_ is None: diff --git a/aizynthfinder/search/andor_trees.py b/aizynthfinder/search/andor_trees.py index ce54639..a7006c6 100644 --- a/aizynthfinder/search/andor_trees.py +++ b/aizynthfinder/search/andor_trees.py @@ -34,7 +34,9 @@ def children(self) -> List["TreeNodeMixin"]: class AndOrSearchTreeBase(abc.ABC): """A base class for a search tree based on an AND/OR structure""" - def __init__(self, config: Configuration, root_smiles: str = None) -> None: + def __init__( + self, config: Configuration, root_smiles: Optional[str] = None + ) -> None: self.config = config self._root_smiles = root_smiles @@ -141,7 +143,7 @@ def _select_child_node(self, children: List[TreeNodeMixin]) -> TreeNodeMixin: class _AndOrTrace(nx.DiGraph): """Helper class for the SplitAndOrTree class.""" - def __init__(self, root: TreeNodeMixin = None) -> None: + def __init__(self, root: Optional[TreeNodeMixin] = None) -> None: super().__init__() self.root = root self._first_reaction: Optional[TreeNodeMixin] = None diff --git a/aizynthfinder/search/breadth_first/nodes.py b/aizynthfinder/search/breadth_first/nodes.py index 37f5f1e..37b044a 100644 --- a/aizynthfinder/search/breadth_first/nodes.py +++ b/aizynthfinder/search/breadth_first/nodes.py @@ -15,7 +15,7 @@ MoleculeSerializer, ) from aizynthfinder.context.config import Configuration - from aizynthfinder.utils.type_utils import List, Sequence, Set, StrDict + from aizynthfinder.utils.type_utils import List, Optional, Sequence, Set, StrDict class MoleculeNode(TreeNodeMixin): @@ -33,7 +33,10 @@ class MoleculeNode(TreeNodeMixin): """ def __init__( - self, mol: TreeMolecule, config: Configuration, parent: ReactionNode = None + self, + mol: TreeMolecule, + config: Configuration, + parent: Optional[ReactionNode] = None, ) -> None: self.mol = mol self._config = config @@ -42,7 +45,7 @@ def __init__( self._children: List[ReactionNode] = [] # Makes it unexpandable if we have reached maximum depth - self.expandable = self.mol.transform <= self._config.max_transforms + self.expandable = self.mol.transform < self._config.search.max_transforms if self.in_stock: self.expandable = False @@ -65,7 +68,7 @@ def from_dict( dict_: StrDict, config: Configuration, molecules: MoleculeDeserializer, - parent: ReactionNode = None, + parent: Optional[ReactionNode] = None, ) -> "MoleculeNode": """ Create a new node from a dictionary, i.e. deserialization diff --git a/aizynthfinder/search/breadth_first/search_tree.py b/aizynthfinder/search/breadth_first/search_tree.py index d1524bd..2acf6e5 100644 --- a/aizynthfinder/search/breadth_first/search_tree.py +++ b/aizynthfinder/search/breadth_first/search_tree.py @@ -28,7 +28,9 @@ class SearchTree(AndOrSearchTreeBase): :param root_smiles: the root will be set to a node representing this molecule, defaults to None """ - def __init__(self, config: Configuration, root_smiles: str = None) -> None: + def __init__( + self, config: Configuration, root_smiles: Optional[str] = None + ) -> None: super().__init__(config, root_smiles) self._mol_nodes: List[MoleculeNode] = [] self._added_mol_nodes: List[MoleculeNode] = [] diff --git a/aizynthfinder/search/dfpn/nodes.py b/aizynthfinder/search/dfpn/nodes.py index 5c11653..ebc7845 100644 --- a/aizynthfinder/search/dfpn/nodes.py +++ b/aizynthfinder/search/dfpn/nodes.py @@ -100,7 +100,7 @@ def __init__( mol: TreeMolecule, config: Configuration, owner: SearchTree, - parent: ReactionNode = None, + parent: Optional[ReactionNode] = None, ) -> None: super().__init__() @@ -112,7 +112,7 @@ def __init__( self.tree = owner # Makes it unexpandable if we have reached maximum depth - self.expandable = self.mol.transform <= self._config.max_transforms + self.expandable = self.mol.transform < self._config.search.max_transforms if self.in_stock: self.expandable = False diff --git a/aizynthfinder/search/dfpn/search_tree.py b/aizynthfinder/search/dfpn/search_tree.py index aeeba81..f71687c 100644 --- a/aizynthfinder/search/dfpn/search_tree.py +++ b/aizynthfinder/search/dfpn/search_tree.py @@ -31,7 +31,9 @@ class SearchTree(AndOrSearchTreeBase): :param root_smiles: the root will be set to a node representing this molecule, defaults to None """ - def __init__(self, config: Configuration, root_smiles: str = None) -> None: + def __init__( + self, config: Configuration, root_smiles: Optional[str] = None + ) -> None: super().__init__(config, root_smiles) self._mol_nodes: List[MoleculeNode] = [] self._logger = logger() diff --git a/aizynthfinder/search/mcts/node.py b/aizynthfinder/search/mcts/node.py index d8081e0..6c25645 100644 --- a/aizynthfinder/search/mcts/node.py +++ b/aizynthfinder/search/mcts/node.py @@ -59,7 +59,7 @@ def __init__( state: MctsState, owner: MctsSearchTree, config: Configuration, - parent: MctsNode = None, + parent: Optional[MctsNode] = None, ): self._state = state self._config = config @@ -85,6 +85,10 @@ def __init__( if parent: self.blacklist = self.blacklist.union(parent.blacklist) + if self._algo_config["mcts_grouping"]: + self._degeneracy_check = self._algo_config["mcts_grouping"].lower() + else: + self._degeneracy_check = "none" self._logger = logger() def __getitem__(self, node: "MctsNode") -> StrDict: @@ -119,7 +123,7 @@ def from_dict( tree: MctsSearchTree, config: Configuration, molecules: MoleculeDeserializer, - parent: "MctsNode" = None, + parent: Optional["MctsNode"] = None, ) -> "MctsNode": """ Create a new node from a dictionary, i.e. deserialization @@ -175,6 +179,11 @@ def state(self) -> MctsState: """Return the underlying state of the node""" return self._state + @property + def _algo_config(self) -> StrDict: + """Just a convinient, shorter name of this""" + return self._config.search.algorithm_config + def actions_to(self) -> List[RetroReaction]: """ Returns the actions leading to this node @@ -220,6 +229,9 @@ def expand(self) -> None: Expansion is the process of creating the children of the node, without instantiating a child object. The actions and priors are taken from the policy network. + + If immediate instantiation is marked for some policies, however, the + children nodes will be instantiated. """ if self.is_expanded: msg = f"Oh no! This node is already expanded. id={id(self)}" @@ -231,19 +243,25 @@ def expand(self) -> None: self.is_expanded = True + cache_molecules = [] + if self.parent: + for child in self.parent.children: + if child is not self: + cache_molecules.extend(child.state.expandable_mols) + # Calculate the possible actions, fill the child_info lists # Actions by default only assumes 1 set of reactants ( self._children_actions, self._children_priors, - ) = self._expansion_policy(self.state.expandable_mols) + ) = self._expansion_policy(self.state.expandable_mols, cache_molecules) nactions = len(self._children_actions) self._children_visitations = [1] * nactions self._children = [None] * nactions - if self._config.use_prior: + if self._algo_config["use_prior"]: self._children_values = list(self._children_priors) else: - self._children_values = [self._config.default_prior] * nactions + self._children_values = [self._algo_config["default_prior"]] * nactions if nactions == 0: # Reverse the expansion if it did not produce any children self.is_expandable = False @@ -252,6 +270,19 @@ def expand(self) -> None: if self.tree: self.tree.profiling["expansion_calls"] += 1 + if not self._algo_config["immediate_instantiation"]: + return + # Instantiate all children actions created by the marked policy, + # a new list of actions will be iterated over, because it can grow due + # to instantiation + for child_idx, action in enumerate(self._children_actions[:nactions]): + policy_name = action.metadata.get("policy_name") + if ( + policy_name + and policy_name in self._algo_config["immediate_instantiation"] + ): + self._instantiate_child(child_idx) + def is_terminal(self) -> bool: """ Node is terminal if its unexpandable, or the internal state is terminal (solved) @@ -351,14 +382,22 @@ def _children_q(self) -> np.ndarray: def _children_u(self) -> np.ndarray: total_visits = np.log(np.sum(self._children_visitations)) child_visits = np.array(self._children_visitations) - return self._config.C * np.sqrt(2 * total_visits / child_visits) + return self._algo_config["C"] * np.sqrt(2 * total_visits / child_visits) def _create_children_nodes( self, states: List[MctsState], child_idx: int - ) -> List[Optional["MctsNode"]]: + ) -> List["MctsNode"]: new_nodes = [] first_child_idx = child_idx for state_index, state in enumerate(states): + if self._generated_degeneracy(state, first_child_idx): + # Only need to disable first new child, + # if the action generated more states, we will just not generate + # a child for that state + if state_index == 0: + self._children_values[child_idx] = -1e6 + continue + # If there's more than one outcome, the lists need be expanded if state_index > 0: child_idx = self._expand_children_lists(first_child_idx, state_index) @@ -366,10 +405,11 @@ def _create_children_nodes( if self._filter_child_reaction(self._children_actions[child_idx]): self._children_values[child_idx] = -1e6 else: - self._children[child_idx] = MctsNode( + new_node = MctsNode( state=state, owner=self.tree, config=self._config, parent=self ) - new_nodes.append(self._children[child_idx]) + self._children[child_idx] = new_node + new_nodes.append(new_node) return new_nodes def _expand_children_lists(self, old_index: int, action_index: int) -> int: @@ -398,31 +438,66 @@ def _filter_child_reaction(self, reaction: RetroReaction) -> bool: return True return False - def _regenerated_blacklisted(self, reaction: RetroReaction) -> bool: - if not self._config.prune_cycles_in_search: + def _generated_degeneracy(self, new_state: MctsState, child_idx: int) -> bool: + """ + Check if a new MCTS state is equal to another MCTS state of a children + node. + + The check can be "partial" in which the equality is based only on the expandable molecules, + or "full" in which the equality is based on all molecules in the state. + + The comparison will not be made on unexpanded children nodes + or terminal children nodes. + + The metadata of the degenerate action will be added to the metadata + of the previously created equal state. + """ + + def equal_states(query_state): + if self._degeneracy_check == "partial": + return query_state.expandables_hash == new_state.expandables_hash + return query_state == new_state + + if self._degeneracy_check not in ["partial", "full"]: + return False + previous_action = None + for child, action in zip(self._children, self._children_actions): + if ( + child is not None + and not child.is_terminal() + and equal_states(child.state) + ): + previous_action = action + break + + if previous_action is None: return False - for reactants in reaction.reactants: - for mol in reactants: - if mol.inchi_key in self.blacklist: - return True - return False - def _select_child(self, child_idx: int) -> Optional["MctsNode"]: + # No need to copy the metadata because it will be the same + if previous_action is self._children_actions[child_idx]: + return True + + metadata_copy = dict(self._children_actions[child_idx].metadata) + if "additional_actions" not in previous_action.metadata: + previous_action.metadata["additional_actions"] = [] + previous_action.metadata["additional_actions"].append(metadata_copy) + return True + + def _instantiate_child(self, child_idx: int) -> List["MctsNode"]: """ - Selecting a child node implies instantiating the children nodes + Instantiate the children node The algorithm is: - * If the child has already been instantiated, return immediately * Apply the reaction associated with the child * If the application of the action failed, set value to -1e6 and return None * Create a new state array, one new state for each of the reaction outcomes * Create new child nodes - If a filter policy is available and the reaction outcome is unlikely set value of child to -1e6 - * Select a random node of the feasible ones to return + * Return all new nodes """ - if self._children[child_idx]: - return self._children[child_idx] + if self._children[child_idx] is not None: + raise NodeUnexpectedBehaviourException("Node already instantiated") reaction = self._children_actions[child_idx] if reaction.unqueried: @@ -432,15 +507,35 @@ def _select_child(self, child_idx: int) -> Optional["MctsNode"]: if not self._check_child_reaction(reaction): self._children_values[child_idx] = -1e6 - return None + return [] keep_mols = [mol for mol in self.state.mols if mol is not reaction.mol] new_states = [ MctsState(keep_mols + list(reactants), self._config) for reactants in reaction.reactants ] - new_nodes = self._create_children_nodes(new_states, child_idx) + return self._create_children_nodes(new_states, child_idx) + + def _regenerated_blacklisted(self, reaction: RetroReaction) -> bool: + if not self._algo_config["prune_cycles_in_search"]: + return False + for reactants in reaction.reactants: + for mol in reactants: + if mol.inchi_key in self.blacklist: + return True + return False + + def _select_child(self, child_idx: int) -> Optional["MctsNode"]: + """ + Selecting a child node implies instantiating the children nodes + + If the child has already been instantiated, return immediately + Otherwise, select a random node of the feasible ones to return + """ + if self._children[child_idx]: + return self._children[child_idx] + new_nodes = self._instantiate_child(child_idx) if new_nodes: return random.choice(new_nodes) return None diff --git a/aizynthfinder/search/mcts/search.py b/aizynthfinder/search/mcts/search.py index c3f9a06..f3ea9b1 100644 --- a/aizynthfinder/search/mcts/search.py +++ b/aizynthfinder/search/mcts/search.py @@ -26,8 +26,9 @@ class MctsSearchTree: :param root_smiles: the root will be set to a node representing this molecule, defaults to None """ - def __init__(self, config: Configuration, root_smiles: str = None) -> None: - + def __init__( + self, config: Configuration, root_smiles: Optional[str] = None + ) -> None: self.profiling = { "expansion_calls": 0, "reactants_generations": 0, @@ -42,6 +43,8 @@ def __init__(self, config: Configuration, root_smiles: str = None) -> None: self.root = None self.config = config self._graph: Optional[nx.DiGraph] = None + self.reward_scorer_name = config.search.algorithm_config["search_reward"] + self.reward_scorer = config.scorers[self.reward_scorer_name] @classmethod def from_json(cls, filename: str, config: Configuration) -> "MctsSearchTree": @@ -119,15 +122,14 @@ def one_iteration(self) -> bool: self.profiling["iterations"] += 1 leaf = self.select_leaf() leaf.expand() - rollout_child = None while not leaf.is_terminal(): child = leaf.promising_child() - if not rollout_child: - rollout_child = child if child: child.expand() leaf = child - self.backpropagate(leaf, leaf.state.score) + + state_score = self.reward_scorer(leaf) + self.backpropagate(leaf, state_score) return leaf.state.is_solved def select_leaf(self) -> MctsNode: diff --git a/aizynthfinder/search/mcts/state.py b/aizynthfinder/search/mcts/state.py index 3e381b6..162ec7e 100644 --- a/aizynthfinder/search/mcts/state.py +++ b/aizynthfinder/search/mcts/state.py @@ -5,7 +5,6 @@ import os from typing import TYPE_CHECKING -import numpy as np from rdkit.Chem import Draw from aizynthfinder.chem import TreeMolecule @@ -35,6 +34,7 @@ class MctsState: :ivar is_solved: is true if all molecules are in stock: :ivar max_transforms: the maximum of the transforms of the molecule :ivar is_terminal: is true if the all molecules are in stock or if the maximum transforms has been reached + :ivar expandables_hash: an hash string computed on the expandable molecules :param mols: the molecules of the state :param config: settings of the tree search algorithm @@ -51,13 +51,14 @@ def __init__(self, mols: Sequence[TreeMolecule], config: Configuration) -> None: self.is_solved = all(self.in_stock_list) self.max_transforms = max(mol.transform for mol in self.mols) self.is_terminal = ( - self.max_transforms > config.max_transforms + self.max_transforms > config.search.max_transforms ) or self.is_solved - self._score: Optional[float] = None inchis = [mol.inchi_key for mol in self.mols] - inchis.sort() - self._hash = hash(tuple(inchis)) + self._hash = hash(tuple(sorted(inchis))) + + inchis = [mol.inchi_key for mol in self.expandable_mols] + self.expandables_hash = hash(tuple(sorted(inchis))) def __hash__(self) -> int: return self._hash @@ -69,12 +70,11 @@ def __eq__(self, other: object) -> bool: def __str__(self) -> str: """A string representation of the state (for print(state))""" - string = "%s\n%s\n%s\n%s\nScore: %0.3F Solved: %s" % ( + string = "%s\n%s\n%s\n%s\n Solved: %s" % ( str([mol.smiles for mol in self.mols]), str([mol.transform for mol in self.mols]), str([mol.parent.smiles if mol.parent else "-" for mol in self.mols]), str(self.in_stock_list), - self.score, self.is_solved, ) return string @@ -98,18 +98,6 @@ def from_dict( mols = molecules.get_tree_molecules(dict_["mols"]) return MctsState(mols, config) - @property - def score(self) -> float: - """ - Returns the score of the state - - :return: the score - :rtype: float - """ - if not self._score: - self._score = self._calc_score() - return self._score - @property def stock_availability(self) -> List[str]: """ @@ -149,31 +137,3 @@ def to_image(self, ncolumns: int = 6) -> Any: legends = self.stock_availability mols = [mol.rd_mol for mol in self.mols] return Draw.MolsToGridImage(mols, molsPerRow=ncolumns, legends=legends) - - def _calc_score(self) -> float: - # How many is in stock (number between 0 and 1) - num_in_stock = np.sum(self.in_stock_list) - # This fraction in stock, makes the algorithm artificially add stock compounds by cyclic addition/removal - fraction_in_stock = num_in_stock / len(self.mols) - - # Max_transforms should be low - max_transforms = self.max_transforms - # Squash function, 1 to 0, 0.5 around 4. - max_transforms_score = self._squash_function(max_transforms, -1, 0, 4) - - # NB weights should sum to 1, to ensure that all - score4 = 0.95 * fraction_in_stock + 0.05 * max_transforms_score - return float(score4) - - @staticmethod - def _squash_function( - val: float, slope: float, yoffset: float, xoffset: float - ) -> float: - """Squash function loosely adapted from a sigmoid function with parameters - to modify and offset the shape - - :param val: the sign of the function, if the function goes from 1 to 0 or from 0 to 1 - :param slope: the slope of the midpoint - :param xoffset: the offset of the midpoint along the x-axis - :param yoffset: the offset of the curve along the y-axis""" - return 1 / (1 + np.exp(slope * -(val - xoffset))) - yoffset diff --git a/aizynthfinder/search/retrostar/cost.py b/aizynthfinder/search/retrostar/cost.py index ecd5da2..4418e66 100644 --- a/aizynthfinder/search/retrostar/cost.py +++ b/aizynthfinder/search/retrostar/cost.py @@ -1,4 +1,4 @@ -""" Module containing Retro* cost model """ +""" Module containing Retro* cost models """ from __future__ import annotations import pickle @@ -6,14 +6,60 @@ import numpy as np +from aizynthfinder.search.retrostar.cost import __name__ as retrostar_cost_module +from aizynthfinder.utils.loading import load_dynamic_class + if TYPE_CHECKING: from aizynthfinder.chem import Molecule - from aizynthfinder.utils.type_utils import List, Tuple + from aizynthfinder.context.config import Configuration + from aizynthfinder.utils.type_utils import Any, List, Tuple + + +class MoleculeCost: + """ + A class to compute the molecule cost. + + The cost to be computed is taken from the input config. If no `molecule_cost` is + set, assigns ZeroMoleculeCost as the `cost` by default. The `molecule_cost` can be + set as a dictionary in config under `search` in the following format: + 'algorithm': 'retrostar' + 'algorithm_config': { + 'molecule_cost': { + 'cost': name of the search cost class or custom_package.custom_model.CustomClass, + other settings or params + } + } + + The cost can be computed by calling the instantiated class with a molecule. + + .. code-block:: + + calculator = MyCost(config) + cost = calculator.calculate(molecule) + + :param config: the configuration of the tree search + """ + + def __init__(self, config: Configuration) -> None: + self._config = config + if "molecule_cost" not in self._config.search.algorithm_config: + self._config.search.algorithm_config["molecule_cost"] = { + "cost": "ZeroMoleculeCost" + } + kwargs = self._config.search.algorithm_config["molecule_cost"].copy() + + cls = load_dynamic_class(kwargs["cost"], retrostar_cost_module) + del kwargs["cost"] + + self.molecule_cost = cls(**kwargs) if kwargs else cls() + + def __call__(self, mol: Molecule) -> float: + return self.molecule_cost.calculate(mol) class RetroStarCost: """ - Encapsulation of a the original Retro* molecular cost model + Encapsulation of the original Retro* molecular cost model Numpy implementation of original pytorch model @@ -23,7 +69,7 @@ class RetroStarCost: mol = Molecule(smiles="CCC") scorer = RetroStarCost() - score = scorer(mol) + score = scorer.calculate(mol) The model provided when creating the scorer object should be a pickled tuple. @@ -36,23 +82,25 @@ class RetroStarCost: :param dropout_rate: the dropout_rate """ - def __init__( - self, - model_path: str, - fingerprint_length: int = 2048, - fingerprint_radius: int = 2, - dropout_rate: float = 0.1, - ): - self._dropout_prob = 1.0 - dropout_rate - self._fingerprint_length = fingerprint_length - self._fingerprint_radius = fingerprint_radius + _required_kwargs = ["model_path"] + + def __init__(self, **kwargs: Any) -> None: + model_path = kwargs["model_path"] + self.fingerprint_length: int = int(kwargs.get("fingerprint_length", 2048)) + self.fingerprint_radius: int = int(kwargs.get("fingerprint_radius", 2)) + self.dropout_rate: float = float(kwargs.get("dropout_rate", 0.1)) + + self._dropout_prob = 1.0 - self.dropout_rate self._weights, self._biases = self._load_model(model_path) - def __call__(self, mol: Molecule) -> float: + def __repr__(self) -> str: + return "retrostar" + + def calculate(self, mol: Molecule) -> float: # pylint: disable=invalid-name mol.sanitize() vec = mol.fingerprint( - radius=self._fingerprint_radius, nbits=self._fingerprint_length + radius=self.fingerprint_radius, nbits=self.fingerprint_length ) for W, b in zip(self._weights[:-1], self._biases[:-1]): vec = np.matmul(vec, W) + b @@ -64,12 +112,8 @@ def __call__(self, mol: Molecule) -> float: vec = np.matmul(vec, self._weights[-1]) + self._biases[-1] return float(np.log(1 + np.exp(vec))) - def __repr__(self) -> str: - return "retrostar" - @staticmethod def _load_model(model_path: str) -> Tuple[List[np.ndarray], List[np.ndarray]]: - with open(model_path, "rb") as fileobj: weights, biases = pickle.load(fileobj) @@ -77,3 +121,13 @@ def _load_model(model_path: str) -> Tuple[List[np.ndarray], List[np.ndarray]]: [np.asarray(item) for item in weights], [np.asarray(item) for item in biases], ) + + +class ZeroMoleculeCost: + """Encapsulation of a Zero cost model""" + + def __repr__(self) -> str: + return "zero" + + def calculate(self, mol: Molecule) -> float: + return 0.0 diff --git a/aizynthfinder/search/retrostar/nodes.py b/aizynthfinder/search/retrostar/nodes.py index ed23a76..fb58e54 100644 --- a/aizynthfinder/search/retrostar/nodes.py +++ b/aizynthfinder/search/retrostar/nodes.py @@ -9,6 +9,7 @@ from aizynthfinder.chem import TreeMolecule from aizynthfinder.chem.serialization import deserialize_action, serialize_action from aizynthfinder.search.andor_trees import TreeNodeMixin +from aizynthfinder.search.retrostar.cost import MoleculeCost if TYPE_CHECKING: from aizynthfinder.chem import RetroReaction @@ -17,7 +18,7 @@ MoleculeSerializer, ) from aizynthfinder.context.config import Configuration - from aizynthfinder.utils.type_utils import List, Sequence, Set, StrDict + from aizynthfinder.utils.type_utils import List, Optional, Sequence, Set, StrDict class MoleculeNode(TreeNodeMixin): @@ -38,11 +39,16 @@ class MoleculeNode(TreeNodeMixin): """ def __init__( - self, mol: TreeMolecule, config: Configuration, parent: ReactionNode = None + self, + mol: TreeMolecule, + config: Configuration, + molecule_cost: MoleculeCost, + parent: Optional[ReactionNode] = None, ) -> None: self.mol = mol self._config = config - self.cost = config.molecule_cost(mol) + self.molecule_cost = molecule_cost + self.cost = self.molecule_cost(mol) self.value = self.cost self.in_stock = mol in config.stock self.parent = parent @@ -50,14 +56,16 @@ def __init__( self._children: List[ReactionNode] = [] self.solved = self.in_stock # Makes it unexpandable if we have reached maximum depth - self.expandable = self.mol.transform <= self._config.max_transforms + self.expandable = self.mol.transform < self._config.search.max_transforms if self.in_stock: self.expandable = False self.value = 0 @classmethod - def create_root(cls, smiles: str, config: Configuration) -> "MoleculeNode": + def create_root( + cls, smiles: str, config: Configuration, molecule_cost: MoleculeCost + ) -> "MoleculeNode": """ Create a root node for a tree using a SMILES. @@ -66,7 +74,7 @@ def create_root(cls, smiles: str, config: Configuration) -> "MoleculeNode": :return: the created node """ mol = TreeMolecule(parent=None, transform=0, smiles=smiles) - return MoleculeNode(mol=mol, config=config) + return MoleculeNode(mol=mol, config=config, molecule_cost=molecule_cost) @classmethod def from_dict( @@ -74,7 +82,8 @@ def from_dict( dict_: StrDict, config: Configuration, molecules: MoleculeDeserializer, - parent: ReactionNode = None, + molecule_cost: MoleculeCost, + parent: Optional[ReactionNode] = None, ) -> "MoleculeNode": """ Create a new node from a dictionary, i.e. deserialization @@ -86,11 +95,14 @@ def from_dict( :return: a deserialized node """ mol = molecules.get_tree_molecules([dict_["mol"]])[0] - node = MoleculeNode(mol, config, parent) + node = MoleculeNode(mol, config, molecule_cost, parent) + node.molecule_cost = molecule_cost for attr in ["cost", "expandable", "value"]: setattr(node, attr, dict_[attr]) node.children = [ - ReactionNode.from_dict(child, config, molecules, parent=node) + ReactionNode.from_dict( + child, config, molecules, node.molecule_cost, parent=node + ) for child in dict_["children"] ] return node @@ -138,7 +150,10 @@ def add_stub(self, cost: float, reaction: RetroReaction) -> Sequence[MoleculeNod return [] rxn_node = ReactionNode.create_stub( - cost=cost, reaction=reaction, parent=self, config=self._config + cost=cost, + reaction=reaction, + parent=self, + config=self._config, ) self._children.append(rxn_node) @@ -258,7 +273,10 @@ def create_stub( node = cls(cost, reaction, parent) reactants = reaction.reactants[reaction.index] node.children = [ - MoleculeNode(mol=mol, config=config, parent=node) for mol in reactants + MoleculeNode( + mol=mol, config=config, molecule_cost=parent.molecule_cost, parent=node + ) + for mol in reactants ] node.solved = all(child.solved for child in node.children) # rn(R|T) @@ -273,6 +291,7 @@ def from_dict( dict_: StrDict, config: Configuration, molecules: MoleculeDeserializer, + molecule_cost: MoleculeCost, parent: MoleculeNode, ) -> ReactionNode: """ @@ -289,7 +308,7 @@ def from_dict( for attr in ["cost", "value", "target_value"]: setattr(node, attr, dict_[attr]) node.children = [ - MoleculeNode.from_dict(child, config, molecules, parent=node) + MoleculeNode.from_dict(child, config, molecules, molecule_cost, parent=node) for child in dict_["children"] ] node.solved = all(child.solved for child in node.children) @@ -322,7 +341,7 @@ def serialize(self, molecule_store: MoleculeSerializer) -> StrDict: dict_["children"] = [child.serialize(molecule_store) for child in self.children] return dict_ - def update(self, value: float, from_mol: TreeMolecule = None) -> None: + def update(self, value: float, from_mol: Optional[TreeMolecule] = None) -> None: """ Update the node as part of the update algorithm, calling the `update()` method of its parent @@ -339,7 +358,7 @@ def update(self, value: float, from_mol: TreeMolecule = None) -> None: self.parent.update(self.solved) - def _propagate(self, value: float, exclude: TreeMolecule = None) -> None: + def _propagate(self, value: float, exclude: Optional[TreeMolecule] = None) -> None: if not exclude: self.target_value += value diff --git a/aizynthfinder/search/retrostar/search_tree.py b/aizynthfinder/search/retrostar/search_tree.py index 7a75675..d4d4286 100644 --- a/aizynthfinder/search/retrostar/search_tree.py +++ b/aizynthfinder/search/retrostar/search_tree.py @@ -9,6 +9,7 @@ from aizynthfinder.chem.serialization import MoleculeDeserializer, MoleculeSerializer from aizynthfinder.search.andor_trees import AndOrSearchTreeBase, SplitAndOrTree +from aizynthfinder.search.retrostar.cost import MoleculeCost from aizynthfinder.search.retrostar.nodes import MoleculeNode from aizynthfinder.utils.exceptions import RejectionException from aizynthfinder.utils.logging import logger @@ -31,14 +32,17 @@ class SearchTree(AndOrSearchTreeBase): :param root_smiles: the root will be set to a node representing this molecule, defaults to None """ - def __init__(self, config: Configuration, root_smiles: str = None) -> None: + def __init__( + self, config: Configuration, root_smiles: Optional[str] = None + ) -> None: super().__init__(config, root_smiles) self._mol_nodes: List[MoleculeNode] = [] self._logger = logger() + self.molecule_cost = MoleculeCost(config) if root_smiles: self.root: Optional[MoleculeNode] = MoleculeNode.create_root( - root_smiles, config + root_smiles, config, self.molecule_cost ) self._mol_nodes.append(self.root) else: @@ -71,7 +75,9 @@ def _find_mol_nodes(node): with open(filename, "r") as fileobj: dict_ = json.load(fileobj) mol_deser = MoleculeDeserializer(dict_["molecules"]) - tree.root = MoleculeNode.from_dict(dict_["tree"], config, mol_deser) + tree.root = MoleculeNode.from_dict( + dict_["tree"], config, mol_deser, tree.molecule_cost + ) tree._mol_nodes.append(tree.root) # pylint: disable=protected-access for child in tree.root.children: _find_mol_nodes(child) diff --git a/aizynthfinder/tools/download_public_data.py b/aizynthfinder/tools/download_public_data.py index 28ceab7..e198012 100644 --- a/aizynthfinder/tools/download_public_data.py +++ b/aizynthfinder/tools/download_public_data.py @@ -7,7 +7,6 @@ import requests import tqdm - FILES_TO_DOWNLOAD = { "policy_model": { "filename": "uspto_model.hdf5", @@ -47,20 +46,17 @@ }, } -YAML_TEMPLATE = """policy: - files: - uspto: - - {} - - {} - ringbreaker: - - {} - - {} +YAML_TEMPLATE = """expansion: + uspto: + - {} + - {} + ringbreaker: + - {} + - {} filter: - files: - uspto: {} + uspto: {} stock: - files: - zinc: {} + zinc: {} """ diff --git a/aizynthfinder/tools/make_stock.py b/aizynthfinder/tools/make_stock.py index 65c265a..c6262f4 100644 --- a/aizynthfinder/tools/make_stock.py +++ b/aizynthfinder/tools/make_stock.py @@ -6,13 +6,21 @@ import importlib from typing import TYPE_CHECKING +try: + import molbloom +except ImportError: + HAS_MOLBLOOM = False +else: + HAS_MOLBLOOM = True + import pandas as pd +from rdkit import Chem from aizynthfinder.chem import Molecule, MoleculeException from aizynthfinder.context.stock import MongoDbInchiKeyQuery if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import Iterable, List + from aizynthfinder.utils.type_utils import Iterable, List, Optional _StrIterator = Iterable[str] @@ -41,9 +49,15 @@ def _get_arguments() -> argparse.Namespace: help="the name of the output file or source tag", ) parser.add_argument( - "--target", choices=["hdf5", "mongo"], help="type of output", default="hdf5" + "--target", + choices=["hdf5", "mongo", "molbloom", "molbloom-inchi"], + help="type of output", + default="hdf5", ) parser.add_argument("--host", help="the host of the Mongo database") + parser.add_argument( + "--bloom_params", nargs=2, type=int, help="the parameters to the Bloom filter" + ) return parser.parse_args() @@ -104,8 +118,59 @@ def make_hdf5_stock(inchi_keys: _StrIterator, filename: str) -> None: print(f"Created HDF5 stock with {len(data)} unique compounds") +def make_molbloom( + smiles_list: _StrIterator, filename: str, filter_size: int, approx_mols: int +) -> None: + """ + Put all the unique SMILES in a new bloom filter. + + :params smiles_list: the SMILES + :params filename: the path to the saved filter + :params filter_size: the size of the filter in bits + :params approx_mols: approximately the number of compounds + """ + filter_ = molbloom.CustomFilter(filter_size, approx_mols, "myfilter") + processed_smiles = set() + for smiles in smiles_list: + try: + smiles_can = Chem.CanonSmiles(smiles) + # pylint: disable=broad-except + except Exception: + print( + f"Failed to convert {smiles} to canonical SMILES.", + flush=True, + ) + continue + if smiles_can in processed_smiles: + continue + filter_.add(smiles_can) + processed_smiles.add(smiles_can) + filter_.save(filename) + print(f"Created bloom stock with {len(processed_smiles)} unique compounds") + + +def make_molbloom_inchi( + inchi_keys: _StrIterator, filename: str, filter_size: int, approx_mols: int +) -> None: + """ + Put all the unique InChI keys in a new bloom filter. + + :params inchi_keys: the Inchi Keys + :params filename: the path to the saved filter + :params filter_size: the size of the filter in bits + :params approx_mols: approximately the number of compounds + """ + filter_ = molbloom.CustomFilter(filter_size, approx_mols, "myfilter") + nadded = 0 + for inchi_key in inchi_keys: + filter_.add(inchi_key) + nadded += 1 + filter_.save(filename) + print(f"Created bloom stock with {nadded} unique compounds") + + def make_mongo_stock( - inchi_keys: _StrIterator, source_tag: str, host: str = None + inchi_keys: _StrIterator, source_tag: str, host: Optional[str] = None ) -> None: """ Put all the inchi keys from the given iterable in Mongo database as @@ -129,10 +194,22 @@ def main() -> None: else: smiles_gen = (smiles for smiles in extract_smiles_from_module(args.files)) + if not HAS_MOLBLOOM and args.target.startswith("molbloom"): + raise ImportError( + "Cannot create this stock format because it seems like molbloom is not installed. " + "Please install aizynthfinder with extras dependencies." + ) + + if args.target == "molbloom": + make_molbloom(smiles_gen, args.output, *args.bloom_params) + return + inchi_keys_gen = (inchi_key for inchi_key in _convert_smiles(smiles_gen)) if args.target == "hdf5": make_hdf5_stock(inchi_keys_gen, args.output) + elif args.target == "molbloom-inchi": + make_molbloom_inchi(inchi_keys_gen, args.output, *args.bloom_params) else: make_mongo_stock(inchi_keys_gen, args.output, args.host) diff --git a/aizynthfinder/training/__init__.py b/aizynthfinder/training/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aizynthfinder/training/keras_models.py b/aizynthfinder/training/keras_models.py deleted file mode 100644 index 8db6e49..0000000 --- a/aizynthfinder/training/keras_models.py +++ /dev/null @@ -1,267 +0,0 @@ -""" Module containing classes and routines used in training of policies. -""" -from __future__ import annotations - -import functools -import os -from typing import TYPE_CHECKING - -import numpy as np -from tensorflow.keras import regularizers -from tensorflow.keras.callbacks import ( - CSVLogger, - EarlyStopping, - ModelCheckpoint, - ReduceLROnPlateau, -) - -# pylint: disable=all -from tensorflow.keras.layers import Dense, Dot, Dropout, Input -from tensorflow.keras.metrics import top_k_categorical_accuracy -from tensorflow.keras.models import Model, Sequential -from tensorflow.keras.optimizers import Adam -from tensorflow.keras.utils import Sequence - -# pylint: enable=all -try: - from scipy import sparse - from sklearn.utils import shuffle -except ImportError: - raise ImportError( - "Training is not supported by this installation." - " Please install aizynthfinder with extras dependencies." - ) - -if TYPE_CHECKING: - from aizynthfinder.training.utils import Config - from aizynthfinder.utils.type_utils import Any, List, Tuple - - -top10_acc = functools.partial(top_k_categorical_accuracy, k=10) -top10_acc.__name__ = "top10_acc" # type: ignore - -top50_acc = functools.partial(top_k_categorical_accuracy, k=50) -top50_acc.__name__ = "top50_acc" # type: ignore - - -class _InMemorySequence(Sequence): # pylint: disable=W0223 - def __init__(self, config: Config, dataset_label: str) -> None: - self.batch_size = config["batch_size"] - input_filename = config.filename(dataset_label + "_inputs") - label_filename = config.filename(dataset_label + "_labels") - self.input_matrix = self._load_data(input_filename) - self.label_matrix = self._load_data(label_filename) - self.input_dim = self.input_matrix.shape[1] - - def __len__(self) -> int: - return int(np.ceil(self.label_matrix.shape[0] / float(self.batch_size))) - - def _make_slice(self, idx: int) -> slice: - if idx < 0 or idx >= len(self): - raise IndexError("index out of range") - - start = idx * self.batch_size - end = (idx + 1) * self.batch_size - return slice(start, end) - - @staticmethod - def _load_data(filename: str) -> Any: - try: - return sparse.load_npz(filename) - except ValueError: - return np.load(filename)["arr_0"] - - -class ExpansionModelSequence(_InMemorySequence): - """ - Custom sequence class to keep sparse, pre-computed matrices in memory. - Batches are created dynamically by slicing the in-memory arrays - The data will be shuffled on each epoch end - - :ivar output_dim: the output size (number of templates) - - :param config: the settings - :param dataset_label: the label of set, e.g. training, testing or validation - """ - - def __init__(self, config: Config, dataset_label: str) -> None: - super().__init__(config, dataset_label) - self.output_dim = self.label_matrix.shape[1] - - def __getitem__(self, idx: int) -> Tuple[np.ndarray, np.ndarray]: - idx_ = self._make_slice(idx) - return self.input_matrix[idx_].toarray(), self.label_matrix[idx_].toarray() - - def on_epoch_end(self) -> None: - self.input_matrix, self.label_matrix = shuffle( - self.input_matrix, self.label_matrix, random_state=0 - ) - - -class FilterModelSequence(_InMemorySequence): - """ - Custom sequence class to keep sparse, pre-computed matrices in memory. - Batches are created dynamically by slicing the in-memory arrays - The data will be shuffled on each epoch end - - :param config: the settings - :param dataset_label: the label of set, e.g. training, testing or validation - """ - - def __init__(self, config: Config, dataset_label: str) -> None: - super().__init__(config, dataset_label) - filename = config.filename(dataset_label + "_inputs2") - self.input_matrix2 = self._load_data(filename) - - def __getitem__(self, idx: int) -> Tuple[List[np.ndarray], np.ndarray]: - idx_ = self._make_slice(idx) - return ( - [self.input_matrix[idx_].toarray(), self.input_matrix2[idx_].toarray()], - self.label_matrix[idx_], - ) - - def on_epoch_end(self) -> None: - self.input_matrix, self.input_matrix2, self.label_matrix = shuffle( - self.input_matrix, self.input_matrix2, self.label_matrix, random_state=0 - ) - - -def _setup_callbacks(config: Config) -> List[Any]: - early_stopping = EarlyStopping(monitor="val_loss", patience=10) - csv_logger = CSVLogger(config.filename("_keras_training.log"), append=True) - - checkpoint_path = os.path.join(config["output_path"], "checkpoints") - if not os.path.exists(checkpoint_path): - os.mkdir(checkpoint_path) - checkpoint = ModelCheckpoint( - os.path.join(checkpoint_path, "keras_model.hdf5"), - monitor="loss", - save_best_only=True, - ) - - reduce_lr = ReduceLROnPlateau( - monitor="val_loss", - factor=0.5, - patience=5, - verbose=0, - mode="auto", - min_delta=0.000001, - cooldown=0, - min_lr=0, - ) - return [early_stopping, csv_logger, checkpoint, reduce_lr] - - -def _train_keras_model( - model: Model, - train_seq: _InMemorySequence, - valid_seq: _InMemorySequence, - loss: str, - metrics: List[Any], - config: Config, -) -> None: - adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0) - - model.compile( - optimizer=adam, - loss=loss, - metrics=metrics, - ) - - model.fit_generator( - train_seq, - steps_per_epoch=None, - epochs=config["epochs"], - verbose=1, - callbacks=_setup_callbacks(config), - validation_data=valid_seq, - validation_steps=None, - class_weight=None, - max_queue_size=20, - workers=20, - use_multiprocessing=False, - shuffle=True, - initial_epoch=0, - ) - - -def train_expansion_keras_model(config: Config) -> None: - """ - Train a expansion policy - - :param config: the settings - """ - train_seq = ExpansionModelSequence(config, "training") - valid_seq = ExpansionModelSequence(config, "validation") - - model = Sequential() - model.add( - Dense( - config["model"]["hidden_nodes"], - input_shape=(train_seq.input_dim,), - activation="elu", - kernel_regularizer=regularizers.l2(0.001), - ) - ) - model.add(Dropout(config["model"]["drop_out"])) - model.add(Dense(train_seq.output_dim, activation="softmax")) - - _train_keras_model( - model, - train_seq, - valid_seq, - "categorical_crossentropy", - ["accuracy", "top_k_categorical_accuracy", top10_acc, top50_acc], - config, - ) - - -def train_filter_keras_model(config: Config) -> None: - """Train a Filter model""" - train_seq = FilterModelSequence(config, "training") - valid_seq = FilterModelSequence(config, "validation") - - product_input_layer = Input(shape=(config["fingerprint_len"],)) - product_dense_layer = Dense(config["model"]["hidden_nodes"], activation="elu")( - product_input_layer - ) - product_droput_layer = Dropout(config["model"]["drop_out"])(product_dense_layer) - reaction_input_layer = Input(shape=(config["fingerprint_len"],)) - reaction_dense_layer = Dense(config["model"]["hidden_nodes"], activation="elu")( - reaction_input_layer - ) - cosine_layer = Dot(-1, normalize=True)([product_droput_layer, reaction_dense_layer]) - output_layer = Dense(1, activation="sigmoid")(cosine_layer) - model = Model( - inputs=[product_input_layer, reaction_input_layer], outputs=output_layer - ) - - _train_keras_model( - model, train_seq, valid_seq, "binary_crossentropy", ["accuracy"], config - ) - - -def train_recommender_keras_model(config: Config) -> None: - """Train a recommender model to be used in filter development""" - train_seq = ExpansionModelSequence(config, "training") - valid_seq = ExpansionModelSequence(config, "validation") - - model = Sequential() - model.add( - Dense( - config["model"]["hidden_nodes"], - input_shape=(config["fingerprint_len"],), - activation="elu", - ) - ) - model.add(Dropout(config["model"]["drop_out"])) - model.add(Dense(train_seq.output_dim, activation="softmax")) - - _train_keras_model( - model, - train_seq, - valid_seq, - "categorical_crossentropy", - ["accuracy", "top_k_categorical_accuracy", top10_acc, top50_acc], - config, - ) diff --git a/aizynthfinder/training/make_false_products.py b/aizynthfinder/training/make_false_products.py deleted file mode 100644 index 0f4faaf..0000000 --- a/aizynthfinder/training/make_false_products.py +++ /dev/null @@ -1,277 +0,0 @@ -""" Module routines for creating negative data for the training for filter policies -""" -from __future__ import annotations - -import argparse -import random -from typing import TYPE_CHECKING - -import pandas as pd -import tqdm - -# pylint: disable=all -from tensorflow.keras.models import load_model as load_keras_model - -# pylint: enable=all -import aizynthfinder.utils.logging # pylint: disable=unused-import -from aizynthfinder.chem import Molecule, MoleculeException, Reaction -from aizynthfinder.training.utils import ( - Config, - create_reactants_molecules, - reactants_to_fingerprint, - reaction_hash, - reverse_template, - split_reaction_smiles, -) - -if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import ( - Any, - Callable, - Iterable, - List, - Optional, - Sequence, - Tuple, - ) - - _DfGenerator = Iterable[Optional[pd.DataFrame]] - - -class _ReactionException(Exception): - pass - - -def random_application(library: pd.DataFrame, config: Config, _) -> _DfGenerator: - """ - Apply a random template to each row of reactants in the library - to make new, false reactions. - - :param library: the reaction library - :param config: the configuration - :yield: a new DataFrame with a false reaction for each row if a match could be found, otherwise None - """ - random.seed(100) # To have reproducible results - - def random_sampler(_): - for _ in range(config["negative_data"]["random_trials"]): - template_index = random.randrange(len(library)) - yield library.iloc[template_index] - - yield from _sample_library(library, config, random_sampler) - - -def recommender_application(library: pd.DataFrame, config: Config, _) -> _DfGenerator: - """ - Apply a template recommended by a neural network - to each row of reactants in the library in order to make new, false reactions. - - :param library: the reaction library - :param config: the configuration - :yield: a new DataFrame with a false reaction for each row if a match could be found, otherwise None - """ - - model = load_keras_model(config["negative_data"]["recommender_model"]) - topn = config["negative_data"]["recommender_topn"] - - def prediction_sampler(row): - fingerprint = reactants_to_fingerprint( - [row[config["column_map"]["reactants"]]], config - ) - fingerprint = fingerprint.reshape([1, config["fingerprint_len"]]) - prediction = model.predict(fingerprint).flatten() - prediction_indices = prediction.argsort()[::-1][:topn] - for template_code in prediction_indices: - yield library[library.template_code == template_code].iloc[0] - - yield from _sample_library(library, config, prediction_sampler) - - -def strict_application( - library: pd.DataFrame, config: Config, errors: list -) -> _DfGenerator: - """ - Apply the recorded template to each row of reactants in the library - to make new, false reactions. - - :param library: the reaction library - :param config: the configuration - :param errors: a list to fill with strings of produced errors - :yield: a new DataFrame with a false reaction for each row if a match could be found, otherwise None - """ - for _, row in library.iterrows(): - try: - new_df = _apply_forward_reaction(row, config) - except _ReactionException as err: - errors.append(str(err)) - else: - yield new_df - - -def _apply_forward_reaction( - template_row: pd.Series, config: Config -) -> Optional[pd.DataFrame]: - smarts_fwd = reverse_template(template_row[config["column_map"]["retro_template"]]) - mols = create_reactants_molecules(template_row[config["column_map"]["reactants"]]) - - try: - ref_mol = Molecule( - smiles=template_row[config["column_map"]["products"]], sanitize=True - ) - except MoleculeException as err: - raise _ReactionException( - f"reaction {template_row[config['column_map']['reaction_hash']]} failed with msg {str(err)}" - ) - - try: - products = Reaction(mols=mols, smarts=smarts_fwd).apply() - except ValueError as err: - raise _ReactionException( - f"reaction {template_row[config['column_map']['reaction_hash']]} failed with msg {str(err)}" - ) - - new_products = {product[0] for product in products if product[0] != ref_mol} - if not new_products: - return None - - correct_products = { - product[0] for product in products if product[0].basic_compare(ref_mol) - } - if not correct_products: - raise _ReactionException( - f"reaction {template_row[config['column_map']['reaction_hash']]} failed to produce correct product" - ) - - return _new_dataframe( - template_row, - config, - nrows=len(new_products), - reaction_hash=[ - reaction_hash(template_row[config["column_map"]["reactants"]], product) - for product in new_products - ], - products=[product.smiles for product in new_products], - ) - - -def _get_config(optional_args: Optional[Sequence[str]] = None) -> Tuple[Config, str]: - parser = argparse.ArgumentParser("Tool to generate artificial negative reactions") - parser.add_argument("config", help="the filename to a configuration file") - parser.add_argument( - "method", - choices=["strict", "random", "recommender"], - help="the method to create random data", - ) - args = parser.parse_args(optional_args) - - return Config(args.config), args.method - - -def _new_dataframe( - original: pd.Series, config: Config, nrows: int = 1, **kwargs: Any -) -> pd.DataFrame: - dict_ = {} - if config["in_csv_headers"]: - columns = list(original.index) - print(columns) - else: - dict_["index"] = 0 - columns = config["library_headers"][1:] - for column in columns: - dict_[column] = kwargs.get(column, [original[column]] * nrows) - return pd.DataFrame(dict_) - - -def _sample_library( - library: pd.DataFrame, config: Config, sampler_func: Callable -) -> _DfGenerator: - for _, row in library.iterrows(): - mols = create_reactants_molecules(row[config["column_map"]["reactants"]]) - try: - ref_mol = Molecule( - smiles=row[config["column_map"]["products"]], sanitize=True - ) - except MoleculeException: - yield None - continue - - new_product = None - for template_row in sampler_func(row): - if ( - row[config["column_map"]["template_hash"]] - == template_row[config["column_map"]["template_hash"]] - ): - continue - smarts_fwd = reverse_template( - template_row[config["column_map"]["retro_template"]] - ) - try: - new_product = Reaction(mols=mols, smarts=smarts_fwd).apply()[0][0] - except (ValueError, IndexError): - continue - if new_product.basic_compare(ref_mol): - continue - break # If we have reached here, we have found a match that fits all criteria - - if not new_product: - yield None - continue - - # pylint: disable=undefined-loop-variable - yield _new_dataframe( - row, - config, - reaction_hash=[ - reaction_hash(row[config["column_map"]["reactants"]], new_product) - ], - products=[new_product.smiles], - classification=[""], - retro_template=[template_row[config["column_map"]["retro_template"]]], - template_hash=[template_row[config["column_map"]["template_hash"]]], - selectivity=[0], - outcomes=[1], - template_code=[template_row["template_code"]], - ) - - -def main(optional_args: Optional[Sequence[str]] = None) -> None: - """Entry-point for the make_false_products tool""" - methods = { - "strict": strict_application, - "random": random_application, - "recommender": recommender_application, - } - - config, selected_method = _get_config(optional_args) - filename = config.filename("library") - library = pd.read_csv( - filename, - index_col=False, - header=0 if config["in_csv_headers"] else None, - names=None if config["in_csv_headers"] else config["library_headers"], - sep=config["csv_sep"], - ) - if config["reaction_smiles_column"]: - library = split_reaction_smiles(library, config) - false_lib = pd.DataFrame({column: [] for column in library.columns}) - - progress_bar = tqdm.tqdm(total=len(library)) - errors: List[str] = [] - for new_df in methods[selected_method](library, config, errors): - if new_df is not None: - false_lib = pd.concat([false_lib, new_df]) - progress_bar.update(1) - progress_bar.close() - - false_lib.to_csv( - config.filename("false_library"), - header=config["in_csv_headers"], - index=False, - sep=config["csv_sep"], - ) - with open(config.filename("_errors.txt"), "w") as fileobj: - fileobj.write("\n".join(errors)) - - -if __name__ == "__main__": - main() diff --git a/aizynthfinder/training/preprocess_expansion.py b/aizynthfinder/training/preprocess_expansion.py deleted file mode 100644 index eec88d5..0000000 --- a/aizynthfinder/training/preprocess_expansion.py +++ /dev/null @@ -1,145 +0,0 @@ -""" Module routines for pre-processing data for expansion policy training -""" -import argparse -import os -from typing import Sequence, Optional - -import pandas as pd -import numpy as np - -try: - from sklearn.preprocessing import LabelBinarizer, LabelEncoder - from scipy import sparse -except ImportError: - raise ImportError( - "Training is not supported by this installation." - " Please install aizynthfinder with extras dependencies." - ) - -from aizynthfinder.training.utils import ( - Config, - split_and_save_data, - smiles_to_fingerprint, - is_sanitizable, - split_reaction_smiles, -) - - -def _filter_dataset(config: Config) -> pd.DataFrame: - - filename = config.filename("raw_library") - if not os.path.exists(filename): - raise FileNotFoundError( - f"The file {filename} is missing - cannot proceed without the full template library." - ) - - # Skipping the last header as it is not available in the raw data - full_data = pd.read_csv( - filename, - index_col=False, - header=0 if config["in_csv_headers"] else None, - names=None if config["in_csv_headers"] else config["library_headers"][:-1], - sep=config["csv_sep"], - ) - if config["reaction_smiles_column"]: - full_data = split_reaction_smiles(full_data, config) - - if config["remove_unsanitizable_products"]: - products = full_data[config["column_map"]["products"]].to_numpy() - idx = np.apply_along_axis(is_sanitizable, 0, [products]) - full_data = full_data[idx] - - template_hash_col = config["column_map"]["template_hash"] - full_data = full_data.drop_duplicates(subset=config["column_map"]["reaction_hash"]) - template_group = full_data.groupby(template_hash_col) - template_group = template_group.size().sort_values(ascending=False) - min_index = template_group[template_group >= config["template_occurrence"]].index - dataset = full_data[full_data[template_hash_col].isin(min_index)] - - template_labels = LabelEncoder() - dataset = dataset.assign( - template_code=template_labels.fit_transform(dataset[template_hash_col]) - ) - dataset.to_csv( - config.filename("library"), - mode="w", - header=config["in_csv_headers"], - index=False, - sep=config["csv_sep"], - ) - return dataset - - -def _get_config(optional_args: Optional[Sequence[str]] = None) -> Config: - parser = argparse.ArgumentParser( - "Tool to pre-process a template library to be used in training a expansion network policy" - ) - parser.add_argument("config", help="the filename to a configuration file") - args = parser.parse_args(optional_args) - - return Config(args.config) - - -def _save_unique_templates(dataset: pd.DataFrame, config: Config) -> None: - template_hash_col = config["column_map"]["template_hash"] - template_group = dataset.groupby(template_hash_col, sort=False).size() - dataset = dataset[ - [config["column_map"]["retro_template"], "template_code"] - + config["metadata_headers"] - ] - if "classification" in dataset.columns: - dataset["classification"].fillna("-", inplace=True) - dataset = dataset.drop_duplicates(subset="template_code", keep="first") - dataset["library_occurrence"] = template_group.values - dataset.set_index("template_code", inplace=True) - dataset = dataset.sort_index() - dataset.rename( - columns={ - template_hash_col: "template_hash", - config["column_map"]["retro_template"]: "retro_template", - }, - inplace=True, - ) - dataset.to_hdf(config.filename("unique_templates"), "table") - - -def main(optional_args: Optional[Sequence[str]] = None) -> None: - """Entry-point for the preprocess_expansion tool""" - config = _get_config(optional_args) - if config["library_headers"][-1] != "template_code": - config["library_headers"].append("template_code") - - filename = config.filename("library") - if not os.path.exists(filename): - dataset = _filter_dataset(config) - else: - dataset = pd.read_csv( - filename, - index_col=False, - header=0 if config["in_csv_headers"] else None, - names=None if config["in_csv_headers"] else config["library_headers"], - sep=config["csv_sep"], - ) - if config["reaction_smiles_column"]: - dataset = split_reaction_smiles(dataset, config) - - print("Dataset filtered/loaded, generating labels...", flush=True) - labelb = LabelBinarizer(neg_label=0, pos_label=1, sparse_output=True) - labels = labelb.fit_transform(dataset[config["column_map"]["template_hash"]]) - split_and_save_data(labels, "labels", config) - - print("Labels created and split, generating inputs...", flush=True) - products = dataset[config["column_map"]["products"]].to_numpy() - inputs = np.apply_along_axis(smiles_to_fingerprint, 0, [products], config) - inputs = sparse.lil_matrix(inputs.T).tocsr() - split_and_save_data(inputs, "inputs", config) - - print("Inputs created and split, splitting full Dataset...", flush=True) - split_and_save_data(dataset, "library", config) - - print("Full Dataset split, creating unique template set", flush=True) - _save_unique_templates(dataset, config) - - -if __name__ == "__main__": - main() diff --git a/aizynthfinder/training/preprocess_filter.py b/aizynthfinder/training/preprocess_filter.py deleted file mode 100644 index d36b4fc..0000000 --- a/aizynthfinder/training/preprocess_filter.py +++ /dev/null @@ -1,85 +0,0 @@ -""" Module routines for pre-processing data for filter policy training -""" -import argparse -from typing import Sequence, Optional - -import pandas as pd -import numpy as np - -try: - from scipy import sparse -except ImportError: - raise ImportError( - "Training is not supported by this installation." - " Please install aizynthfinder with extras dependencies." - ) - -from aizynthfinder.training.utils import ( - Config, - split_and_save_data, - smiles_to_fingerprint, - reaction_to_fingerprints, - split_reaction_smiles, -) - - -def _get_config(optional_args: Optional[Sequence[str]] = None) -> Config: - parser = argparse.ArgumentParser( - "Tool to pre-process a template library to be used to train a in-scope filter network policy" - ) - parser.add_argument("config", help="the filename to a configuration file") - args = parser.parse_args(optional_args) - - return Config(args.config) - - -def main(optional_args: Optional[Sequence[str]] = None) -> None: - """Entry-point for the preprocess_filter tool""" - config = _get_config(optional_args) - - true_dataset = pd.read_csv( - config.filename("library"), - index_col=False, - header=0 if config["in_csv_headers"] else None, - names=None if config["in_csv_headers"] else config["library_headers"][:-1], - sep=config["csv_sep"], - ) - true_dataset["true_product"] = 1 - false_dataset = pd.read_csv( - config.filename("false_library"), - index_col=False, - header=0 if config["in_csv_headers"] else None, - names=None if config["in_csv_headers"] else config["library_headers"][:-1], - sep=config["csv_sep"], - ) - false_dataset["true_product"] = 0 - dataset = pd.concat([true_dataset, false_dataset]) - - if config["reaction_smiles_column"]: - dataset = split_reaction_smiles(dataset, config) - - print("Dataset loaded, generating Labels...", flush=True) - labels = dataset["true_product"].to_numpy() - split_and_save_data(labels, "labels", config) - - print("Labels created and split, generating Inputs...", flush=True) - products = dataset[config["column_map"]["products"]].to_numpy() - reactants = dataset[config["column_map"]["reactants"]].to_numpy() - inputs = np.apply_along_axis( - reaction_to_fingerprints, 0, [products, reactants], config - ).astype(np.int8) - inputs = sparse.lil_matrix(inputs.T).tocsr() - split_and_save_data(inputs, "inputs2", config) - - inputs = np.apply_along_axis(smiles_to_fingerprint, 0, [products], config).astype( - np.int8 - ) - inputs = sparse.lil_matrix(inputs.T).tocsr() - split_and_save_data(inputs, "inputs", config) - - print("Inputs created and split, splitting Full Dataset...", flush=True) - split_and_save_data(dataset, "library", config) - - -if __name__ == "__main__": - main() diff --git a/aizynthfinder/training/preprocess_recommender.py b/aizynthfinder/training/preprocess_recommender.py deleted file mode 100644 index 124f5ba..0000000 --- a/aizynthfinder/training/preprocess_recommender.py +++ /dev/null @@ -1,78 +0,0 @@ -""" Module routines for pre-processing data for recommender training -""" -import argparse -from typing import Sequence, Optional - -import pandas as pd -import numpy as np - -try: - from sklearn.preprocessing import LabelBinarizer - from scipy import sparse -except ImportError: - raise ImportError( - "Training is not supported by this installation." - " Please install aizynthfinder with extras dependencies." - ) - -from aizynthfinder.training.utils import ( - Config, - split_and_save_data, - reactants_to_fingerprint, - split_reaction_smiles, -) - - -def _get_config(optional_args: Optional[Sequence[str]] = None) -> Config: - parser = argparse.ArgumentParser( - "Tool to pre-process a template library to be used to train a recommender network" - ) - parser.add_argument("config", help="the filename to a configuration file") - args = parser.parse_args(optional_args) - - return Config(args.config) - - -def _save_unique_templates(dataset: pd.DataFrame, config: Config) -> None: - dataset = dataset[[config["column_map"]["retro_template"], "template_code"]] - dataset = dataset.drop_duplicates(subset="template_code", keep="first") - dataset.set_index("template_code", inplace=True) - dataset = dataset.sort_index() - dataset.to_hdf(config.filename("unique_templates"), "table") - - -def main(optional_args: Optional[Sequence[str]] = None) -> None: - """Entry-point for the preprocess_recommender tool""" - config = _get_config(optional_args) - - filename = config.filename("library") - dataset = pd.read_csv( - filename, - index_col=False, - header=0 if config["in_csv_headers"] else None, - names=None if config["in_csv_headers"] else config["library_headers"], - sep=config["csv_sep"], - ) - if config["reaction_smiles_column"]: - dataset = split_reaction_smiles(dataset, config) - - print("Dataset loaded, generating Labels...", flush=True) - labelbin = LabelBinarizer(neg_label=0, pos_label=1, sparse_output=True) - labels = labelbin.fit_transform(dataset[config["column_map"]["template_hash"]]) - split_and_save_data(labels, "labels", config) - - print("Labels created and split, generating Inputs...", flush=True) - reactants = dataset[config["column_map"]["reactants"]].to_numpy() - inputs = np.apply_along_axis(reactants_to_fingerprint, 0, [reactants], config) - inputs = sparse.lil_matrix(inputs.T).tocsr() - split_and_save_data(inputs, "inputs", config) - - print("Inputs created and split, splitting Full Dataset...", flush=True) - split_and_save_data(dataset, "library", config) - - print("Full Dataset split, creating unique template set", flush=True) - _save_unique_templates(dataset, config) - - -if __name__ == "__main__": - main() diff --git a/aizynthfinder/training/training.py b/aizynthfinder/training/training.py deleted file mode 100644 index e08fcd5..0000000 --- a/aizynthfinder/training/training.py +++ /dev/null @@ -1,35 +0,0 @@ -""" Module containing routines to setup the training of policies. -""" -import argparse -from typing import Optional, Sequence - -from aizynthfinder.training.utils import Config -from aizynthfinder.training.keras_models import ( - train_expansion_keras_model, - train_filter_keras_model, - train_recommender_keras_model, -) - - -def main(optional_args: Optional[Sequence[str]] = None) -> None: - """Entry-point for the aizynth_training tool""" - parser = argparse.ArgumentParser("Tool to train a network policy") - parser.add_argument("config", help="the filename to a configuration file") - parser.add_argument( - "model", - choices=["expansion", "filter", "recommender"], - help="the model to train", - ) - args = parser.parse_args(optional_args) - - config = Config(args.config) - if args.model == "expansion": - train_expansion_keras_model(config) - elif args.model == "filter": - train_filter_keras_model(config) - elif args.model == "recommender": - train_recommender_keras_model(config) - - -if __name__ == "__main__": - main() diff --git a/aizynthfinder/training/utils.py b/aizynthfinder/training/utils.py deleted file mode 100644 index 93088dc..0000000 --- a/aizynthfinder/training/utils.py +++ /dev/null @@ -1,288 +0,0 @@ -""" Module containing various classes and routines used in training tools -""" -from __future__ import annotations -import os -import hashlib -from collections.abc import Mapping -from typing import TYPE_CHECKING - -import yaml -import numpy as np -import pandas as pd - -try: - from scipy import sparse - from sklearn.model_selection import train_test_split -except ImportError: - raise ImportError( - "Training is not supported by this installation." - " Please install aizynthfinder with extras dependencies." - ) - - -from aizynthfinder.utils.paths import data_path -from aizynthfinder.chem import Molecule, MoleculeException - -if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import ( - StrDict, - Any, - List, - Union, - Tuple, - Sequence, - ) - - -class Config: - """ - Class that holds the configuration of the training. - - The settings are read from a yaml file. Default values - for all settings are taken from the ``data`` directory of the repo. - - Settings can be read and set with - - .. code-block:: - - batch_size = config["batch_size"] - config["batch_size"] = 100 - - :param config_filename: the path to a yaml file with settings - """ - - def __init__(self, config_filename: str = None) -> None: - filename = os.path.join(data_path(), "default_training.yml") - with open(filename, "r") as fileobj: - default_config = yaml.load(fileobj.read(), Loader=yaml.SafeLoader) - - self._config = default_config - - if config_filename is None: - return - - with open(config_filename, "r") as fileobj: - user_config = yaml.load(fileobj.read(), Loader=yaml.SafeLoader) - self._update_dict(default_config, user_config) - - def __getitem__(self, item: str) -> Any: - return self._config[item] - - def __setitem__(self, item: str, value: Any) -> None: - self._config[item] = value - - def filename(self, label: str) -> str: - """ - Return the absolute path to a file specified partly - by settings. - - A filename is constructed from: - ``output_path + file_prefix + file_postfix`` - - where ``file_postfix`` is either taken from the settings - by look-up, e.g. ``config["file_postfix"][label]`` or - directly from the ``label`` argument. - - :param label: the file postfix - :return: the filepath - """ - return os.path.join( - self["output_path"], - self["file_prefix"] + self["file_postfix"].get(label, label), - ) - - @staticmethod - def _update_dict(original: StrDict, other: StrDict) -> StrDict: - # Used to complement the update method of the built-in dict type - # it works for recursive dicts (to 1 level) - for key, val in original.items(): - if key not in other or not isinstance(other[key], type(val)): - continue - if isinstance(val, Mapping): - original[key] = Config._update_dict(original[key], other[key]) - else: - original[key] = other[key] - for key, val in other.items(): - if key not in original: - original[key] = val - return original - - -def create_reactants_molecules(reactants_str: str) -> List[Molecule]: - """ - Create Molecule objects from a SMILE string of reactants. - - Only molecules with atom mapping is kept. - - :param reactants_str: the SMILES string of the reactants - :return: the Molecule objects - """ - mols = [] - for smiles in reactants_str.split("."): - try: - mol = Molecule(smiles=smiles, sanitize=True) - except MoleculeException: - pass - else: - if mol.has_atom_mapping(): - mols.append(mol) - return mols - - -def is_sanitizable(args: Tuple[str]) -> bool: - """ - Check whether a SMILES is sanitizable - :param args: the SMILES in the first element - :return: whether the SMILES is sanitizable - """ - smiles = args[0] - try: - Molecule(smiles=smiles, sanitize=True) - except MoleculeException: - return False - else: - return True - - -def reverse_template(retro_template: str) -> str: - """ - Reverse the reaction template to switch product and reactants - - :param retro_template: the reaction template - :return: the reverse template - """ - return ">>".join(retro_template.split(">>")[::-1]) - - -def reaction_hash(reactants_smiles: str, product: Molecule) -> str: - """ - Create a reaction hash - - :param reactants_smiles: the SMILES string of the reactants - :param product: the product molecule - :return: the hash - """ - reactant_inchi = Molecule(smiles=reactants_smiles).inchi - product_inchi = product.inchi - concat_inchi = reactant_inchi + "++" + product_inchi - return hashlib.sha224(concat_inchi.encode("utf8")).hexdigest() - - -def split_and_save_data( - data: Union[pd.DataFrame, np.ndarray, sparse.csr_matrix], - data_label: str, - config: Config, -) -> None: - """ - Split input data into training, testing and validation sets, - and then saves it to disc. - - The input data can be either a pandas DataFrame a numpy array - or a sparse matrix. - - :param data: the data to split - :param data_label: the label of the data, if its input or labels - :param config: the settings - """ - train_size = config["split_size"]["training"] - testing_frac = config["split_size"]["testing"] - validation_frac = config["split_size"]["validation"] - testing_size = testing_frac / (testing_frac + validation_frac) - - train_arr, test_arr = train_test_split( - data, train_size=train_size, random_state=42, shuffle=True - ) - val_arr, test_arr = train_test_split( - test_arr, test_size=testing_size, random_state=42, shuffle=True - ) - - array_dict = {"training_": train_arr, "validation_": val_arr, "testing_": test_arr} - for label_prefix, arr in array_dict.items(): - filename = config.filename(label_prefix + data_label) - if isinstance(data, pd.DataFrame): - arr.to_csv( - filename, - sep=config["csv_sep"], - header=config["in_csv_headers"], - index=False, - ) - elif isinstance(data, np.ndarray): - np.savez(filename, arr) - else: - sparse.save_npz(filename, arr, compressed=True) - - -def smiles_to_fingerprint(args: Sequence[str], config: Config) -> np.ndarray: - """ - Convert a SMILES to a fingerprint vector - - :param args: the SMILES in the first element - :param config: the settings - :return: the fingerprint - """ - smiles = args[0] - return ( - Molecule(smiles=smiles) - .fingerprint( - config["fingerprint_radius"], - config["fingerprint_len"], - ) - .astype(np.int8) - ) - - -def reactants_to_fingerprint(args: Sequence[str], config: Config) -> np.ndarray: - """ - Convert a SMILES string of reactants to a fingerprint - - :param args: the SMILES in the first element - :param config: the settings - :return: the fingerprint - """ - reactants_smiles = args[0] - fingerprints = [] - for smiles in reactants_smiles.split("."): - try: - mol = Molecule(smiles=smiles, sanitize=True) - except MoleculeException: - pass - else: - if mol.has_atom_mapping(): - fingerprints.append( - mol.fingerprint( - config["fingerprint_radius"], config["fingerprint_len"] - ) - ) - return sum(fingerprints) # type: ignore - - -def reaction_to_fingerprints(args: Sequence[str], config: Config) -> np.ndarray: - """ - Convert a reaction SMILEs string a fingerprint - - :param args: the product SMILES in the first element, and reactants SMILES in the second - :param config: the settings - :return: the fingerprint - """ - product_smiles, reactants_smiles = args - product_fp = smiles_to_fingerprint([product_smiles], config) - reactant_fp = reactants_to_fingerprint([reactants_smiles], config) - - return (product_fp - reactant_fp).astype(np.int8) - - -def split_reaction_smiles(data: pd.DataFrame, config: Config) -> pd.DataFrame: - """ - Split a column of reaction SMILES into reactant and product columns - - :param data: the dateframe to process - :param config: the training configuration - :return: the new dataframe - """ - smiles_split = data[config["reaction_smiles_column"]].str.split(">", expand=True) - return data.assign( - **{ - config["column_map"]["reactants"]: smiles_split[0], - config["column_map"]["products"]: smiles_split[2], - } - ) diff --git a/aizynthfinder/utils/files.py b/aizynthfinder/utils/files.py index 0382bd7..a7a83cd 100644 --- a/aizynthfinder/utils/files.py +++ b/aizynthfinder/utils/files.py @@ -16,7 +16,14 @@ from aizynthfinder.utils.logging import logger if TYPE_CHECKING: - from aizynthfinder.utils.type_utils import Any, Callable, List, Sequence, Union + from aizynthfinder.utils.type_utils import ( + Any, + Callable, + List, + Optional, + Sequence, + Union, + ) def read_datafile(filename: Union[str, Path]) -> pd.DataFrame: @@ -50,14 +57,14 @@ def save_datafile(data: pd.DataFrame, filename: Union[str, Path]) -> None: @deprecated(version="4.0.0", reason="replaced by 'cat_datafiles'") def cat_hdf_files( - input_files: List[str], output_name: str, trees_name: str = None + input_files: List[str], output_name: str, trees_name: Optional[str] = None ) -> None: """Concatenate hdf5 or json datafiles""" cat_datafiles(input_files, output_name, trees_name) def cat_datafiles( - input_files: List[str], output_name: str, trees_name: str = None + input_files: List[str], output_name: str, trees_name: Optional[str] = None ) -> None: """ Concatenate hdf5 or json datafiles diff --git a/aizynthfinder/utils/image.py b/aizynthfinder/utils/image.py index 020133f..9e9511c 100644 --- a/aizynthfinder/utils/image.py +++ b/aizynthfinder/utils/image.py @@ -6,8 +6,6 @@ import io import os import shutil -import subprocess -import sys import tempfile from typing import TYPE_CHECKING @@ -207,69 +205,6 @@ def save_molecule_images( return spec -def make_graphviz_image( - molecules: Union[Sequence[Molecule], Sequence[UniqueMolecule]], - reactions: Union[Sequence[RetroReaction], Sequence[FixedRetroReaction]], - edges: Sequence[Tuple[Any, Any]], - frame_colors: Sequence[PilColor], - reaction_shapes: Sequence[str] = None, - use_splines: bool = True, -) -> PilImage: - """ - Create an image of a bipartite graph of molecules and reactions - using the dot program of graphviz - - :param molecules: the molecules nodes - :param reactions: the reaction nodes - :param edges: the edges of the graph - :param frame_colors: the color of the frame around each image - :param reaction_shapes: optional specification of shapes for each reaction - :param use_splines: if True tries to use splines to connect nodes in image - :raises FileNotFoundError: if the image could not be produced - :return: the create image - """ - - def _create_image(use_splines): - txt = template.render( - molecules=mol_spec, - reactions=rxn_spec, - edges=edges, - use_splines=use_splines, - ) - _, input_name = tempfile.mkstemp(suffix=".dot") - with open(input_name, "w") as this_fileobj: - this_fileobj.write(txt) - - _, output_img2 = tempfile.mkstemp(suffix=".png") - ext = ".bat" if sys.platform.startswith("win") else "" - subprocess.call([f"dot{ext}", "-T", "png", f"-o{output_img2}", input_name]) - if not os.path.exists(output_img2) or os.path.getsize(output_img2) == 0: - raise FileNotFoundError( - "Could not produce graph with layout - check that 'dot' command is in path" - ) - return output_img2 - - mol_spec = save_molecule_images(molecules, frame_colors) - reaction_shapes = reaction_shapes or ["circle"] * len(reactions) - rxn_spec = zip(reactions, reaction_shapes) - - template_filepath = os.path.join(data_path(), "templates", "reaction_tree.dot") - with open(template_filepath, "r") as fileobj: - template = Template(fileobj.read()) - template.globals["id"] = id # type: ignore - - if not use_splines: - output_img = _create_image(use_splines=False) - return Image.open(output_img) - - try: - output_img = _create_image(use_splines=True) - except FileNotFoundError: - output_img = _create_image(use_splines=False) - - return Image.open(output_img) - - def make_visjs_page( filename: str, molecules: Sequence[Molecule], diff --git a/aizynthfinder/utils/loading.py b/aizynthfinder/utils/loading.py index 7ec2a14..3ebcb97 100644 --- a/aizynthfinder/utils/loading.py +++ b/aizynthfinder/utils/loading.py @@ -5,11 +5,13 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from typing import Any + from typing import Any, Optional def load_dynamic_class( - name_spec: str, default_module: str = None, exception_cls: Any = ValueError + name_spec: str, + default_module: Optional[str] = None, + exception_cls: Any = ValueError, ) -> Any: """ Load an object from a dynamic specification. diff --git a/aizynthfinder/utils/logging.py b/aizynthfinder/utils/logging.py index cd0c90b..1e4c8c4 100644 --- a/aizynthfinder/utils/logging.py +++ b/aizynthfinder/utils/logging.py @@ -14,6 +14,7 @@ from rdkit import RDLogger from aizynthfinder.utils.paths import data_path +from aizynthfinder.utils.type_utils import Optional # Suppress RDKit errors due to incomplete template (e.g. aromatic non-ring atoms) rd_logger = RDLogger.logger() @@ -29,7 +30,9 @@ def logger() -> logging.Logger: return logging.getLogger("aizynthfinder") -def setup_logger(console_level: int, file_level: int = None) -> logging.Logger: +def setup_logger( + console_level: int, file_level: Optional[int] = None +) -> logging.Logger: """ Setup the logger that should be used by all classes diff --git a/aizynthfinder/utils/math.py b/aizynthfinder/utils/math.py new file mode 100644 index 0000000..20e140d --- /dev/null +++ b/aizynthfinder/utils/math.py @@ -0,0 +1,7 @@ +""" Module containing diverse math functions, including neural network-related functions. """ +import numpy as np + +# pylint: disable=invalid-name +def softmax(x: np.ndarray) -> np.ndarray: + """Compute softmax values for each sets of scores in x.""" + return np.exp(x) / np.sum(np.exp(x), axis=0) diff --git a/aizynthfinder/utils/mongo.py b/aizynthfinder/utils/mongo.py index 3d241ea..2bcfeb0 100644 --- a/aizynthfinder/utils/mongo.py +++ b/aizynthfinder/utils/mongo.py @@ -19,8 +19,8 @@ def get_mongo_client( host: str = "localhost", port: int = 27017, - user: str = None, - password: str = None, + user: Optional[str] = None, + password: Optional[str] = None, tls_certs_path: str = "", ) -> Optional[MongoClient]: """ diff --git a/aizynthfinder/utils/type_utils.py b/aizynthfinder/utils/type_utils.py index 2538c71..df5bda2 100644 --- a/aizynthfinder/utils/type_utils.py +++ b/aizynthfinder/utils/type_utils.py @@ -11,6 +11,7 @@ from PIL.Image import Image from rdkit import Chem +from rdkit.Chem import rdChemReactions from rdkit.DataStructs.cDataStructs import ExplicitBitVect StrDict = Dict[str, Any] From 81eeb24863cb98ed47a2a73e6e2d54acccfd903c Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 05:22:41 +0000 Subject: [PATCH 02/10] Add all other updated files --- CHANGELOG.md | 206 +- README.md | 83 +- docs/conf.py | 2 +- docs/configuration.rst | 195 +- docs/gui_input.png | Bin 37146 -> 31756 bytes docs/gui_results.png | Bin 80139 -> 62244 bytes docs/howto.rst | 58 +- docs/index.rst | 1 - docs/stocks.rst | 10 +- docs/training.rst | 161 - env-dev.yml | 2 +- env-users.yml | 4 +- poetry.lock | 4512 +++++++++-------- pyproject.toml | 2 +- tests/chem/test_mol.py | 10 + tests/chem/test_reaction.py | 135 +- tests/chem/test_serialization.py | 2 - tests/conftest.py | 67 +- tests/context/conftest.py | 15 +- .../context/data/linear_route_w_metadata.json | 65 + tests/context/data/simple_filter.bloom | Bin 0 -> 10258 bytes .../context/data/test_reactions_template.csv | 4 + tests/context/test_expansion_strategies.py | 115 + tests/context/test_mcts_config.py | 299 +- tests/context/test_mol_cost.py | 41 - tests/context/test_policy.py | 171 +- tests/context/test_score.py | 198 +- tests/context/test_stock.py | 301 +- tests/data/and_or_tree.json | 372 +- tests/data/full_search_tree.json.gz | Bin 218545 -> 179671 bytes tests/data/make_false2_template_library.csv | 4 - tests/data/make_false_template_library.csv | 3 - tests/data/test_reactions_template.csv | 4 + tests/data/tree_for_clustering.json | 39 +- tests/mcts/conftest.py | 6 +- tests/mcts/test_node.py | 23 +- tests/mcts/test_reward.py | 106 + tests/mcts/test_serialization.py | 8 +- tests/retrostar/conftest.py | 17 +- .../data/andor_tree_for_clustering.json | 372 +- tests/retrostar/test_retrostar.py | 6 +- tests/retrostar/test_retrostar_cost.py | 42 +- tests/retrostar/test_retrostar_nodes.py | 6 +- tests/test_cli.py | 12 +- tests/test_finder.py | 156 +- tests/test_training.py | 411 -- tests/utils/test_image.py | 48 +- 47 files changed, 4381 insertions(+), 3913 deletions(-) delete mode 100644 docs/training.rst create mode 100644 tests/context/data/linear_route_w_metadata.json create mode 100644 tests/context/data/simple_filter.bloom create mode 100644 tests/context/data/test_reactions_template.csv create mode 100644 tests/context/test_expansion_strategies.py delete mode 100644 tests/context/test_mol_cost.py delete mode 100644 tests/data/make_false2_template_library.csv delete mode 100644 tests/data/make_false_template_library.csv create mode 100644 tests/data/test_reactions_template.csv create mode 100644 tests/mcts/test_reward.py delete mode 100644 tests/test_training.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e0564d..26675a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,41 @@ # CHANGELOG +## Version 4.0.0 2023-11-30 + +### Features + +- `Configuration` now supports a `rescale_prior` property which rescales the priors in `TemplateBasedExpansionStrategy`. +- Functionality of `ScorerCollection` has been extended. +- Pricing is now supported in `InMemoryInchiKeyQuery`. +- Reward scorer has been added to Configuration scorers as `search_reward` item. +- `MaxTransformScorerer` and `FractionInStockScorer` have been created to separate scores in `StateScorer`. +- Reaction routes are scored with all reward scorers after the search is complete. +- `StockAvailabilityScorer` and `ReactionClassMembershipScorer` have been added to the scorers. +- Atom mapping existing in target molecule can be inherited. +- A caching feature has been add to the expansion strategies. +- Degenerate states can now be grouped in the MCTS algorithm. +- `ChemformerBasedExpansionStrategy` and `ModelZooExpansionStrategy` can be found under plugins and used as additional expansion strategies. +- Support for the stereocenter model has been added with to support chiral fingerprints for molecules and reactions. +- The `Configuration` format has been entirely revamped to a more easy-to-use format. +- A `MolbloomFilterQuery` has been created as a stock query class. + +### Trivial changes + +- Python version requirements have been updated to versions 3.9 - 3.11. +- `MoleculeCost` has been moved from aizynthfinder.context.cost.collection to the Retro* package. + +### Deprecations + +- Graphviz has been removed from aizynthfinder.utils.image. +- `Reaction` class has been removed from aizynthfinder.chem.reaction. +- aizynthfinder.context.cost package has been removed. + +### Bug-fixes + +- Fixed an issue with `max_transforms` to ensure only the given number of maximum depth is considered. +- Pinned Jupyter notebook version to ^6.5.3 to avoid errors when displaying widgets. +- Rollout child has been removed from the MCTS search algorithm. + ## Version 3.7.0 2023-06-01 (2023-04-11) ### Features @@ -23,7 +59,7 @@ - Fixing an issue when concatenating JSON data files. -## Version 3.6.0 2022-11-28 (2022-11-25) +## Version 3.6.0 2022-11-25 ### Features @@ -36,20 +72,35 @@ - Graphviz dependency for route drawing is removed, pure python implementation is used instead - Dependencies reworked so that a minimal package can be installed - Extra dependencies are related to route distances, clustering, training, MongoDB and external models -- Downloaded files are now the latest USPTO and Ringbreaker models +- (AZ) support for template lookup is removed ### Trivial changes - RDKit and route-distances package now installed from pypi - Documentation updated and extended -## Version 3.5.0 2022-11-28 (2022-07-21) +## Version 3.5.2 2022-07-27 + +### Trivial changes + +- Fix dependency for route-distances +- Update Seldon environment + +## Version 3.5.1 2022-07-22 + +### Bug-fixes + +- Fix atom-mapping inheritence for atoms only in reactants + +## Version 3.5.0 2022-07-21 ### Features +- All Seldon models now uses version 0.5.0 of aizynthfinder_models (Reaction connect models july 2022) - Atom-mapping is tracked from product to reactant - Support loading of template library from (gzipped) CSV file - Support of saving aizynthcli output to (gzipped) JSON file +- DeepRetrosynthesis model now returns a field called "mapped_reaction_smiles" - AiZynthExpander now tracks non-applicable templates ### Bug-fixes @@ -58,10 +109,12 @@ ### Trival changes - Silent progress bar when utilizing local Keras model + ## Version 3.4.0 2022-04-28 ### Features +- Deep retrosynthesis Seldon model - Gracefully fail predictions with aizynthcli if target is unsanitizable (Github issue 66) ### Trivial changes @@ -69,26 +122,25 @@ - Remove usage of depracted Pandas function append (Github issue 63) - Correct documentation of aizynthcli (Github issue 67) -## Version 3.3.1 2022-03-09 - -### Trivial changes - -- Updated pinned versions of route_distances, jinja2 and tensorflow - -## Version 3.3.0 2022-02-24 +## Version 3.3.0 2022-02-14 ### Features -- Support for Retro* tree search - Support for breadth-first exhaustive tree search - Support for depth-first proof-number tree search - Possible to save concatenated reaction trees to separate file +### Trivial changes + +- Retro* search algorithm moved to public package + +## Version 3.2.1 2022-01-17 + ### Bugfixes - RouteCostScorer fix for rare routes -## Version 3.2.0 2022-02-24 +## Version 3.2.0 2022-01-11 ### Features @@ -98,10 +150,12 @@ - Introduce short aliases for filter policies - Reaction shape support in GraphViz visualisation of routes -## Version 3.1.0 2021-12-21 +## Version 3.1.0 2021-11-09 ### Features +- Reaction connect API is updated for version 2.0 +- Filter to remove unreasonable expansions (when the template remove most of the molecule) - ReactantsCountFiler (Github issue 42) to filter reactions with incompatible number of reactants - ForwardRegenerationFiler to filter reactions where the forward reaction is incompatible - Possible to skip quick Keras filter for specific policies @@ -118,13 +172,23 @@ ### Trivial changes - Update type hints to be compatible with latest numpy release -- Update route-distances dependency + +## Version 3.0.1 2021-08-31 + +### Trivial changes + +- REST and GRPC Tensorflow clients now using named input vectors when provided + +### Bugfixes + +- Correct input vectors provided to REST and GRPC tensorflow clients for filter policy ## Version 3.0.0 2021-07-26 ### Features - Generalized expansion and filter policies - policies no longer need to be Keras models +- ReactionConnect-based expansion policy and stock query - Updated image generation for synthesis routes - Improved code to prune "regeneration reactions" in MCTS (Github issue 38) - Reactants are sorted in output from ReactionTree class @@ -141,7 +205,6 @@ - Removed MCTS-specific routines in the TreeAnalysis class - Removed code for identifying cycles in ReactionTree -- Remove JSON interface to AiZynthFinder class ### Bugfixes @@ -152,7 +215,7 @@ - Documentation updates - Extensive re-factoring of test cases -## Version 2.6.0 - 2021-06-11 (2021-05-03) +## Version 2.6.0 - 2021-05-03 ### Features @@ -161,12 +224,17 @@ - Route distance calculations with ML model is now supported - Reaction tree objects now has property `is_branched` +### Trivial changes -## Version 2.5.0 - 2021-06-11 (2021-03-30) +- `scikit-learn` is now imported before `tensorflow`, according to Github issue 30 + +## Version 2.5.0 - 2021-03-30 ### Features - Introduce an interface for search algorithm working on AND/OR trees +- Add a reference implementation of the Retro* algorithm in the az sub-package +- Improved AiZynthExpander model to group predictions with the same precursors - The progress bar is now removed upon completion of the tree search - Move `ReactionTree` class to a new module (this will not brake backwards compatibility) @@ -176,10 +244,9 @@ ### Trivial changes -- `scikit-learn` is now imported before `tensorflow`, according to Github issue 30 - -## Version 2.4.0 - 2021-02-22 (2021-02-22) +- Use pylint as the code linter +## Version 2.4.0 - 2021-02-22 ### Features @@ -192,19 +259,29 @@ - Update of black version causing some re-formatting - Small changes to documentation -## Version 2.3.0 - 2021-02-22 (2021-01-20) +## Version 2.3.0 - 2021-01-20 ### Features - Add option to timeout distance calculation of route collections - -## Version 2.2.1 - 2020-12-18 +- Add option to perform clustering in Seldon AiZynthFinder model +- Add new Seldon model AiZynthExpander encapsulating expansion policies ### Bugfixes -- Include templates for producing routes in package +- Jinja templates are now packaged with the python package + +## Version 2.2.1 - 2020-12-01 -## Version 2.2.0 - 2020-12-14 (2020-11-23) +### Bug fixes + +- Fix price and amount function in AiZynth MongoDB stock query + +### Trivial changes + +- Introduce caching of fingerprints in template info class + +## Version 2.2.0 - 2020-11-23 ### Features @@ -212,25 +289,37 @@ - Add new scorers for total price and route score - Add support for adding stop criteria to all stocks - Add stop criteria UI for Jupyter notebook +- Enable the applicability filtered-expansion model in Seldon model +- Improved memory management for template look-up ### Trivial changes - Refactor handling of MongoDB instances - Refactor code to connect with REST and gRPC servers +- Refactor AiZynth buyables query class -## Version 2.1.0 - 2020-12-07 (2020-11-03) +## Version 2.1.1 - 2020-11-08 + +### Bugfixes + +- Matching names of policies and scorers in Seldon model + +## Version 2.1.0 - 2020-11-03 ### Features - Possibility to extract a combined tree for all predicted routes - New classes to use Tensorflow servers as policies +- Add an internal stock query class to use on the AiZynth platform +- Enable use of the tool as a Seldon server ### Trivial changes +- Reduced memory consumption for average product similarity scorer - Improved code for route visualizaition -## Version 2.0.0 - 2020-11-24 (2020-09-29) +## Version 2.0.0 - 2020-09-29 ### Breaking changes @@ -252,25 +341,27 @@ - Catch exceptions from RDChiral more gracefully -## Version 1.2.0 - 2020-11-24 (2020-09-04) +## Version 1.2.0 - 2020-09-04 ### Features - Add score "number of pre-cursors" - Add score "number of pre-cursors in stock" +- Add a stock query to use the AiZynth Buyable API - Enable the loading of MCTS configuration from dict ### Bugfixes - Fix bug in State score for branched reaction trees - Fix bug in "Number of reaction" score for branched MCTS trees +- Fix bug in "Average template occurence" score for trees with no reactions - Fix bug in Jupyter GUI when selecting policies of several available ### Trivial changes - Update python requirement specifications -## Version 1.1.0 - 2020-11-24 (2020-06-30) +## Version 1.1.0 - 2020-06-30 ### Features @@ -278,6 +369,7 @@ - Flag repetetive patterns in routes so they can be hidden - Enable possibility to use more than one rollout policy - Add --nproc argument to aizynthcli to enable trivial multiprocessing +- Add tool to download publicly released data ### Bugfixes @@ -287,6 +379,58 @@ - Add consistency check between rollout neural network and template list -## Version 1.0.0 - 2020-06-11 +## Version 1.0.0 - 2020-06-01 + +### Breaking changes + +- The tree search algorithm now breaks down any target molecule in stock by default + +### Features + +- Add option to break down target molecules that are in stock +- Add a GUI extension and API to lookup reactions in Reaxys and Pistachio +- Metadata is added to reactions and to the output + +### Bugfixes + +- Fix issue with tree search when all children are rejected + +### Trivial changes + +- Improved documentation +- Improved test coverage +- Interface to graphviz is entirely within the package, not with third-party library + +## Version 0.3.0 - 2020-04-14 + +### Features + +- Add tools to train rollout policy model +- Add tools to create stock from SMILES +- Introduced the RouteCollection class for easy analysis of routes +- Introduced possibility to use external Keras model + +### Bugfixes + +- Fix recreation of reaction tree from dict for certain types of routes + + +## Version 0.2.0 - 2020-03-16 + +### Features + +- Moved internal tree search classes to aizynthfinder.mcts package +- Removed concept of runaway nodes, now exhaustively look through all actions +- Add auto-selecting of stocks and policy in aizynthcli tool +- Add support for custom stock class in aizynthcli tool +- Add support for MongoDB stock lookup + +### Bugfixes + +- Fix cut-off of predictions in Policy class based on threshold and minimum number + +## Version 0.1.0 - 2020-02-18 -- First public version +- Re-factored codebase +- Provide route visualization in Jupyter Notebooks +- Provide command to run predictions in batch \ No newline at end of file diff --git a/README.md b/README.md index c9a82f9..22e3b0f 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,7 @@ -# AiZynthFinder +# aizynthfinder -[![License](https://img.shields.io/github/license/MolecularAI/aizynthfinder)](https://github.com/MolecularAI/aizynthfinder/blob/master/LICENSE) -[![Tests](https://github.com/MolecularAI/aizynthfinder/workflows/tests/badge.svg)](https://github.com/MolecularAI/aizynthfinder/actions?workflow=tests) -[![codecov](https://codecov.io/gh/MolecularAI/aizynthfinder/branch/master/graph/badge.svg)](https://codecov.io/gh/MolecularAI/aizynthfinder) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black) -[![version](https://img.shields.io/github/v/release/MolecularAI/aizynthfinder)](https://github.com/MolecularAI/aizynthfinder/releases) -[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MolecularAI/aizynthfinder/blob/master/contrib/notebook.ipynb) - - -AiZynthFinder is a tool for retrosynthetic planning. The algorithm is based on a Monte Carlo tree search that recursively breaks down a molecule to purchasable precursors. The tree search is guided by a policy that suggests possible precursors by utilizing a neural network trained on a library of known reaction templates. - -An introduction video can be found here: [https://youtu.be/r9Dsxm-mcgA](https://youtu.be/r9Dsxm-mcgA) +aizynthfinder is a tool for retrosynthetic planning. The default algorithm is based on a Monte Carlo tree search that recursively breaks down a molecule to purchasable precursors. The tree search is guided by a policy that suggests possible precursors by utilizing a neural network trained on a library of known reaction templates. This setup is completely customizable as the tool +supports multiple search algorithms and expansion policies. ## Prerequisites @@ -18,66 +9,42 @@ Before you begin, ensure you have met the following requirements: * Linux, Windows or macOS platforms are supported - as long as the dependencies are supported on these platforms. -* You have installed [anaconda](https://www.anaconda.com/) or [miniconda](https://docs.conda.io/en/latest/miniconda.html) with python 3.8 - 3.9 +* You have installed [anaconda](https://www.anaconda.com/) or [miniconda](https://docs.conda.io/en/latest/miniconda.html) with python 3.9 - 3.11 The tool has been developed on a Linux platform, but the software has been tested on Windows 10 and macOS Catalina. - ## Installation -### For end-users - -First time, execute the following command in a console or an Anaconda prompt - - conda create "python>=3.8,<3.10" -n aizynth-env - -To install, activate the environment and install the package using pypi - - conda activate aizynth-env - python -m pip install aizynthfinder[all] - -for a smaller package, without all the functionality, you can also type - - python -m pip install aizynthfinder - -### For developers - First clone the repository using Git. Then execute the following commands in the root of the repository conda env create -f env-dev.yml conda activate aizynth-dev - poetry install -E all + poetry install --all-extras the `aizynthfinder` package is now installed in editable mode. + ## Usage -The tool will install the ``aizynthcli`` and ``aizynthapp`` tools +The tool will install the `aizynthcli` and `aizynthapp` tools as interfaces to the algorithm: -``` -aizynthcli --config config.yml --smiles smiles.txt -aizynthapp --config config.yml -``` + aizynthcli --config config_local.yml --smiles smiles.txt + aizynthapp --config config_local.yml -Consult the documentation [here](https://molecularai.github.io/aizynthfinder/) for more information. -To use the tool you need +Consult the documentation [here](https://pages.scp.astrazeneca.net/mai/aizynthfinder/doc/) +for more information. - 1. A stock file - 2. A trained rollout policy network (including the Keras model and the list of unique templates) - 3. A trained filer policy network (optional) +To use tool you need -Such files can be downloaded from [figshare](https://figshare.com/articles/AiZynthFinder_a_fast_robust_and_flexible_open-source_software_for_retrosynthetic_planning/12334577) and [here](https://figshare.com/articles/dataset/A_quick_policy_to_filter_reactions_based_on_feasibility_in_AI-guided_retrosynthetic_planning/13280507) or they can be downloaded automatically using - -``` -download_public_data my_folder -``` - -where ``my_folder`` is the folder that you want download to. -This will create a ``config.yml`` file that you can use with either ``aizynthcli`` or ``aizynthapp``. + 1. A stock file + 2. A trained expansion policy network + 3. A trained filter policy network (optional) + +These files are available on SCP. ## Development @@ -89,7 +56,7 @@ Run the tests using: pytest -v -The full command run on the CI server is available through an `invoke` command +The full command run on Jenkins is available through an `invoke` command invoke full-tests @@ -121,10 +88,11 @@ Please use ``black`` package for formatting, and follow ``pep8`` style guide. ## Contributors -* [@SGenheden](https://www.github.com/SGenheden) -* [@EBjerrum](https://www.github.com/EBjerrum) -* [@A-Thakkar](https://www.github.com/A-Thakkar) -* [@benteb](https://www.github.com/benteb) +* Samuel Genheden +* Lakshidaa Saigiridharan +* Helen Lai +* Esben Bjerrum +* Amol Thakkar The contributors have limited time for support questions, but please do not hesitate to submit an issue (see above). @@ -135,7 +103,4 @@ The software is licensed under the MIT license (see LICENSE file), and is free a ## References 1. Thakkar A, Kogej T, Reymond J-L, et al (2019) Datasets and their influence on the development of computer assisted synthesis planning tools in the pharmaceutical domain. Chem Sci. https://doi.org/10.1039/C9SC04944D -2. Genheden S, Thakkar A, Chadimova V, et al (2020) AiZynthFinder: a fast, robust and flexible open-source software for retrosynthetic planning. J. Cheminf. https://jcheminf.biomedcentral.com/articles/10.1186/s13321-020-00472-1 -3. Genheden S, Engkvist O, Bjerrum E (2020) A Quick Policy to Filter Reactions Based on Feasibility in AI-Guided Retrosynthetic Planning. ChemRxiv. Preprint. https://doi.org/10.26434/chemrxiv.13280495.v1 -4. Genheden S, Engkvist O, Bjerrum E (2021) Clustering of synthetic routes using tree edit distance. J. Chem. Inf. Model. 61:3899–3907 [https://doi.org/10.1021/acs.jcim.1c00232](https://doi.org/10.1021/acs.jcim.1c00232) -5. Genheden S, Engkvist O, Bjerrum E (2022) Fast prediction of distances between synthetic routes with deep learning. Mach. Learn. Sci. Technol. 3:015018 [https://doi.org/10.1088/2632-2153/ac4a91](https://doi.org/10.1088/2632-2153/ac4a91) +2. Genheden S, Thakkar A, Chadimova V, et al (2020) AiZynthFinder: a fast, robust and flexible open-source software for retrosynthetic planning. ChemRxiv. Preprint. https://doi.org/10.26434/chemrxiv.12465371.v1 \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 9195ff6..b6afea3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,7 @@ project = "aizynthfinder" copyright = "2020-2022, Molecular AI group" author = "Molecular AI group" -release = "3.7.0" +release = "4.0.0" # This make sure that the cli_help.txt file is properly formated with open("cli_help.txt", "r") as fileobj: diff --git a/docs/configuration.rst b/docs/configuration.rst index 7e23bd5..3c506f6 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -11,11 +11,8 @@ Simple usage Let's say you have a - * A trained Keras expansion model that is called `full_uspto_model.hdf5` - * A library of unique templates called `full_uspto_templates.hdf5` - -(these could have been created by the training tools, see :doc:`here `) - + * A trained Keras expansion model that is called `uspto_expansion.onnx` + * A library of unique templates called `uspto_templates.csv.gz` * A stock file in HDF5 format, called `zinc_stock.hdf5` (this could have been created by the ``smiles2stock`` tool, see :doc:`here `) @@ -24,14 +21,12 @@ then to use them in the tree search, create a file called `config.yml` that has .. code-block:: yaml - policy: - files: - full_uspto: - - full_uspto_model.hdf5 - - full_uspto_templates.hdf5 + expansion: + full: + - uspto_expansion.onnx + - uspto_templates.csv.gz stock: - files: - zinc: zinc_stock.hdf5 + zinc: zinc_stock.hdf5 Advanced usage @@ -41,93 +36,143 @@ A more detailed configuration file is shown below .. code-block:: yaml - properties: + search: + algorithm: mcts + algorithm_config: + C: 1.4 + default_prior: 0.5 + use_prior: True + prune_cycles_in_search: True + search_reward: state score + max_transforms: 6 iteration_limit: 100 return_first: false time_limit: 120 - C: 1.4 - cutoff_cumulative: 0.995 - cutoff_number: 50 - max_transforms: 6 - policy: - files: - my_policy: - - /path/to/keras/model/weights.hdf5 - - /path/to/hdf5/templates.hdf5 + exclude_target_from_stock: True + expansion: + my_policy: + type: template-based + model: /path/to/keras/model/weights.hdf5 + template: /path/to/hdf5/templates.hdf5 + template_column: retro_template + cutoff_cumulative: 0.995 + cutoff_number: 50 + use_rdchiral: True + use_remote_models: False + my_full_policy: + - /path/to/keras/model/weights.hdf5 + - /path/to/hdf5/templates.hdf5 filter: - files: - my_policy: /path/to/keras/model/weights.hdf5 - reactants_count: - filter_tag: + uspto: + type: quick-filter + model: /path/to/keras/model/weights.hdf5 + exclude_from_policy: rc + filter_cutoff: 0.05 + use_remote_models: False + uspto_full: /path/to/keras/model/weights.hdf5 stock: - files: - stock1: /path/to/stock1.hdf5 - stock2: /path/to/stock1.hdf5 + buyables: + type: inchiset + path: /path/to/stock1.hdf5 + emolecules: /path/to/stock1.hdf5 The (expansion) policy models are specified using two files - * a checkpoint files from Keras in hdf5 format, + * a checkpoint files from Keras in ONNX or hdf5 format, * a HDF5 or a CSV file containing templates. -The filter policy model is specified using a single checkpoint file from Keras in hdf5 format. Any additional -filters can be specified using the classname, and a tag as seen above using ``reactants_count`` with the flag -``filter_tag``. +A key like ``my_policy`` should be set and the configuration contains ``type``, ``model`` and ``template`` that must be provided. +If the other settings are not assigned, their default values are taken. +The policy ``my_full_policy`` exemplifies a short-cut to the template-based expansion model when no other settings need to be +provided, only the ``model`` and ``templates`` can be provided. The default settings will be taken in this case. The template file should be readable by ``pandas`` using the ``table`` key and the ``retro_template`` column. A policy can then be selected using the provided key, like ``my_policy`` in the above example. +The filter policy model is specified using a single checkpoint file. +Any key like ``uspto`` can be set. The settings contains ``type`` and ``model`` that must be provided. If the other +settings are not assigned, their default values are taken. +The filter ``uspto_full`` exemplifies a short-cut to the quick-filter model when no other settings need to be +provided, only the ``model`` can be provided. The default settings will be taken in this case. + + The stock files can be * HDF5 files with the ``table`` key an the ``inchi_key`` column. * A CSV file with a ``inchi_key`` column * A text file a single column In all cases, the column should contain pre-computed inchi keys of the molecules. -The stocks can then be selected using the provided key, like ``stock1`` or ``stock2`` in the above example. +The stocks can be set using any key, like ``buyables`` or ``emolecules`` in the above example. +The ``type`` and ``path`` parameters can also be set along with other parameters. +If no other settings need to be provided, only the ``path`` can be provided, whereby it will be +treated as a +short-cut to the inchiset class.. -The values in the ``properties`` sections are optional, and if missing, default values are provided. These +The values in the ``search`` sections are optional, and if missing, default values are considered. These values can also be taken from environment variables. An example of this can be seen as below: .. code-block:: yaml - properties: + search: iteration_limit: ${ITERATION_LIMIT} - C: ${C} - cutoff_cumulative: ${CUTOFF_CUMULATIVE} - cutoff_number: ${CUTOFF_NUMBER} + algorithm_config: + C: ${C} + time_limit: ${TIME_LIMIT} max_transforms: ${MAX_TRANSFORMS} -These are the available properties: - -========================= ============== =========== -Property Default value Description -========================= ============== =========== -C 1.4 The C value used to balance exploitation and exploration in the upper confidence bound score of the nodes. -cutoff_cumulative 0.995 The accumulative probability of the suggested templates is capped at this value. All other templates above this threshold are discarded. -cutoff_number 50 The maximum number of templates that will be returned from the expansion policy. -max_transforms 6 The maximum depth of the search tree -default_prior 0.5 The prior that is used if policy-provided priors are not used -use_prior True If true, priors from the policy is used instead of the `default_prior` -return_first False If true, the tree search will be terminated as soon as one solution is found -iteration_limit 100 The maximum number of iterations for the tree search -time_limit 120 The maximum number of seconds to complete the tree search -exclude_target_from_stock True If the target is in stock it will be broken down if this property is True -template_column retro_template the column in the template file that contains the templates -filter_cutoff 0.05 the cut-off for the quick-filter policy -prune_cycles_in_search True prevents the MCTS from creating cycles by recreating previously seen molecules when it is expanded -additive_expansion False If true, reactions from all selected expansion policies will be appended, otherwise only the first non-empty expansion will be used -search_algorithm mcts The search algorithm. Can be set to `package.module.ClassName` to use a custom search method -use_rdchiral True If true, will apply templates with RDChiral, otherwise RDKit will be used -use_remote_models False If true, will try to connect to remote Tensorflow servers -post_processing N/A post-processing specifications -========================= ============== =========== - - -The ``post_processing`` property is a dictionary with the following settings - -========================= ============== =========== -Setting Default value Description -========================= ============== =========== -min_routes 5 the minumum number of routes to extract if ``all_routes`` is not set -max_routes 25 the maximum number of routes to extract if ``all_routes`` is not set -all_routes False if True, will extract all solved routes -route_distance_model N/A if set will load the quick route distance model from this checkpoint file -========================= ============== =========== +These are the available ``search`` settings. The ``algorithm_config`` refers to MCTS settings: + +============================================ ============== =========== +Setting Default value Description +============================================ ============== =========== +algorithm mcts The search algorithm. Can be set to `package.module.ClassName` to use a custom search method. +algorithm_config: C 1.4 The C value used to balance exploitation and exploration in the upper confidence bound score of the nodes. +algorithm_config: default_prior 0.5 The prior that is used if policy-provided priors are not used. +algorithm_config: use_prior True If True, priors from the policy is used instead of the `default_prior`. +algorithm_config: prune_cycles_in_search True If True, prevents the MCTS from creating cycles by recreating previously seen molecules when it is expanded. +algorithm_config: search_reward state score The scoring used for the MCTS search algorithm. +algorithm_config: immediate_instantiation [] list of expansion policies for which the MCTS algorithm immediately instantiate the children node upon expansion +algorithm_config: mcts_grouping - if is partial or full the MCTS algorithm will group expansions that produce the same state. If ``partial`` is used the equality will only be determined based on the expandable molecules, whereas ``full`` will check all molecules. +max_transforms 6 The maximum depth of the search tree. +iteration_limit 100 The maximum number of iterations for the tree search. +time_limit 120 The maximum number of seconds to complete the tree search. +return_first False If True, the tree search will be terminated as soon as one solution is found. +exclude_target_from_stock True If True, the target is in stock will be broken down. +============================================ ============== =========== + + +The ``post_processing`` settings are: + +============================================ ============== =========== +Setting Default value Description +============================================ ============== =========== +min_routes 5 The minumum number of routes to extract if ``all_routes`` is not set. +max_routes 25 The maximum number of routes to extract if ``all_routes`` is not set. +all_routes False If True, will extract all solved routes. +route_distance_model N/A If set, will load the quick route distance model from this checkpoint file. +route_scorer state score The scoring for routes when extracting them in the post processing step. +============================================ ============== =========== + + +The ``expansion`` settings are for template-based models: + +============================================ ============== =========== +Setting Default value Description +============================================ ============== =========== +template_column retro_template The column in the template file that contains the templates. +cutoff_cumulative 0.995 The accumulative probability of the suggested templates is capped at this value. All other templates above this threshold are discarded. +cutoff_number 50 The maximum number of templates that will be returned from the expansion policy. +use_rdchiral True If True, will apply templates with RDChiral, otherwise RDKit will be used. +use_remote_models False If True, will try to connect to remote Tensorflow servers. +rescale_prior False If True, will apply a softmax function to the priors. +============================================ ============== =========== + + +The ``filter`` settings are for quick-filter models: + +============================================ ============== =========== +Setting Default value Description +============================================ ============== =========== +exclude_from_policy [] The list of names of the filter policies to exclude. +filter_cutoff 0.05 The cut-off for the quick-filter policy. +use_remote_models False If True, will try to connect to remote Tensorflow servers. +============================================ ============== =========== diff --git a/docs/gui_input.png b/docs/gui_input.png index 928a46cdd409296fb5868f9a0a30137cca051204..b55d7830f29751c0541065ed6a22b3e3b29c7f74 100644 GIT binary patch literal 31756 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 S0x}%}xv8de4WoL;?|%V%(d>Qz literal 37146 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ᶢ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

sNXfC&myrsnG0jVBMcqM- zMIPS-3tW|aH%Ar&shhUw;?U6VM3|){g;+&&4pp1?hjnURMSd8!b@?d;FH|Rdy*jnI zGLAhhFO6y$EnT^IG7CEqkntk$G~)YKp%jY?^muC2&NDcGe03EvEYg&A42QWue~mPd zs4(A*tsYMm#d4qrgx(eR58H!_1_8fMbFJ~Lj_UnCvb+g;C4)zQN4cs(`VBAr*$w?v zbPdc(`)36K6+Zhr4ny@9&iYh@dya}0DZ|qbLoMRQIciQ{(>~1 z`u+hpf&R-t_kN-oZhf&{yEHN3jDckY{?c#D8aJZA;Q28u!`9()VhjJ6(Ql$pF>aT0i(8F;+nrCIXB zJ2R*7PeK`8CMq0TDuL-L0w}-lF=(gDkB?dh!|NB3&LPf#`!ojxnJ+Kj+3Jymb&FJ= z6Foumvg!>my1ii6$vc$&zF=3MDL)5yMxcVxKn45HMYD-j@y6b1mBzbBUM{Dl`4j^v zyYET9<$+9zJPQEwIE4f7wJPd&9vdmmhwa{z&(%lm{-Swu6;S8Arz32Cj-fcY`tIgKOxYwiSD%G2UZq`)7I28OVikc2qcE6lt zI)(f6{<5eA^rM_l)m*HcDA0#52c5T2%lk{cqD^Bi12@XAO7;{tE7qL2SANT^?pth{ z{|AE1k|M=^Q)bt*m8H(EQD85n?j z%a!~6FZvYh>sK?&+w3y}ZM-KOTNs6YHKeQtk?W_&d5$*Dm|S<(cx1Q!l|{E=Vq)UQ zz$2&MCx?%zq~P_{8g%y2P{z^lsz;AFcFZbZ%?@Yb8PoewPR953FJvV&nd-Qb5u(*Z zX|8M53FB|{0pyI;n5Kg+`=0kRaECw}p1_S)ja%R4q&?;zaDbujIJ&pDhjh=7?}@`V z+u25&-~n<+dvli64*>6MmwHx*dXUPd*~9-(+ZuWRG^SCnI=ZN4Hfl6Wory@O_lb@I ztpJ1ifsymhZQs+06Pc>fEXn(E)Vbc& z!R|cfR8X`y1rf0*cvtbOOSryyfaiD*JBm_1Q;?re&&}1I{jTotS9kp~;RKD~XK6NM zvZ$1S*m)f%uZ1Lg8NxGfJnUdoO3d*6$3Tygr<(HH{mQ%1)`zW?(#yBVg^$aTmQ9p( zIr95pD$&}~&TTMTV_m`~F}<;?Tx;02~qS?|2J{jYfU|7|JlRacV(vMZA+!?c@oZt#M zfNp^vv~cO)v;1ioCkM=DOFMIvL$4Ih#rsjX?%XZK<3mq2)Qu z2U-u?g?W=d)Q6f6DHDjsrcY^Q97F3S;aj~j>m==0yFinCf^{TaxYA?-Bkkjt3_+MY0F{viwc}zwNnTiMO5L78^`}=S$L|)X#4yW7QCf`Dt zkc?L@SZp+G$B+9h(XyGT89Z{HjOJ$)JZ*Gyq;<0|_(-w_y*-SqSQ#@~TOe7TFV+zA z${U(cJZSzavExPzyA-IVa(URlrVCUs7DmUinuSpGAXW1Jyf@=Gnc5*S(0+yH-DRNi zDVFFHkfUa7tQ0;d0Mp@JJ>C~&U$u-zl5wlCay?ClgVX2})^NMs^?Lj1K-Zd!e?j94Vc4+r@I?%i;WkZ zG;d?1IbFuUPVIUO2Bo<8T42stFxbeVtv8rbXCP) zdB`eYq*}DIiGpP0aors?UqmKe7Cq+*<p`OP(Wb8AQ?oI^3YdK?XBa2NP3Z?dy z#q-R&@1NnC2gR=FhkaSAPFt%;7HIx&+1rdal3}?Gc!#Q zBM4=@Z*okcH?S7V9Z*A_190(t)jciC7Xzxr98ReEn!jlJnSpU3)a{?#QSDTdl!u~n z?2(dKw?h4sN&b6z5u@zR?-@BRyXf7>-*!^VJ$e4lmyajJs#aEg~=^_U2?u z>cU8i)N&3Tw>RMXWty}t4Mw`MBlXd`8Qd-d5=dD$OEHTA;#dKuX$37{!f?&Z_1Ao- ztMtHDA0)%Io#v&Xh8whQ>-#~efUe?lwS1-fy%PTL{vLninR~>W+`$dw2Sf^^Nlqpm zd(gp9MqT-IPNw84JHr;>SWn|V#fAXC8DP%=o0qx&J8V;%*{hr`SA3 z@9P|uPcAfS~_^aS!%CssE zM%tt60sh%GzpDtkB8}AOLobPx(iM5gE|+WkS&1i0Almak|g`w39@dQy`d;feV@ z0vEp8&3ZKQA)rVV0IL6@>QUZe?NW%a*~8SCk~Z-Elno|CvhOvMwM!aowAZzEVf0D# ztey#r&eg^dWAh|C!bPKB!#P?+>a{cBzdZY-%)N}txB7foRD05>WidR~Pg(d^SK+Q@ z0#>GF&zf|Q70vLC7U`+x=;;v&?YWT(Q4@5UX{n&g>Smh4>W0DjYE`Wv$j;WrOdD(= z$;2D0GKUz>|HBBYFUKCGd;LF~6YLqx^~E(?Of7vL4yyA6|TU zdBQHObN!w2`BG8Ky2NLMYdzUc9aMrQc6fMBQc4a6u7cs-y2;X;lw`1(rV8j#gtJd0mgxQycf~ z-EH4C5r^3h@NPx+-#LAH^7HduX1_+d#>ZAq`FF!f`IPLxiesPFHu0RGc~GYPnx85N z*`H5vz3Uni++Q(`jL|k=W-DNQz$)y;qMw5D82IGnC8Y1J%pJ{!KkQ52YVDuc9Z;_i z*lFx@nQ2{?b{r%%5=SfCn*3T}RnIz^cBcY3#+NcOW<*oELzxtzkmLQnMo7}4ZhSmK zY5cOe%Z%9rEd>K>&&j~8-eM`E49}Rz0gWi&NGiCda${TJ*Yxob4vsj-b$7V(&a#{Q zkW|Tqh7_CB$o=ih!5gn2wYKQz>fQX%f%W*oibMFp9`&QDL9z4YE-d#J2C{2fe)9Zn zJlrRE_v3l49?G?GaY9|~h5DldV!h**lxzh5K>w17By(}yO1>&g3Rp|Gz^|T&j}?@dLqnU?B%3bc@(`rIFB~x1`hQkFZXAk zn9PSdwrCppg7L}U1E>6*XF6nrK0tdf>I64jqg}pF>~v|^?4W&o=U22?55O6%#f-() z)FBcEOzORw@1J+_?KpIqb5u&e51*TGK!Ugm^89)j9!`&a&Pe}Jw=8t$F&&!C?VQo@ zNaZrB$EKh5QzZY3MQaA$>eEh-^rOSg-h+!ZiXg~r)TQkYW^XGa*e+Ze`!2i0iPOQz zCMf+3j4_ML&p*8W5m~dCozTN@b)bLyfOw>WaIzb``-3m%UACy-)s?!uFWGd4mjWwn z+2!-cA1*tcp@H%Ot-EQ~Ydxm~7O7V1b^QEsu`VXJEEkZqn;q<~5ka0S&0_36k79S! z!5zFq%&1qJ$Pf!l7SFZvE=jW90M8Y_#Oz?93r&*B0s8D%6R)ibQ<} z6D|0;kF`Ib1~)X$Kf2S$lXk=HzxSoX81 zr#t;45Gv!2m>E8a#ff8|3wy=oK5!Z(Huz6aM|3vpr9CSdVPd?-Q%3Lnf88X^78LNn z>51c$GNztt6|&Do&8mFzO>5S6h~K!9TznTtC{{iS&0G>QGu|6>gpP_nKK4YA12S!W z?0FVqhC}dfB$#3;{14j>XJbeTnknP=v^Y@$zGud&8N(hyvto&!?-3GOOk$I0!u`fK z!f5bjNFhfQzK7xo?FucJGMf@6^PZkEceSAMkhQpuc3JgqO>JMX8u|4JWQU3i-mcuB zOG%F=E4vgTTBU#AAlbq^3Rti#a@5IxNy7rbmykw-cDeE|N^wv0QT(tJiJsR81&?G$ z5Z-joTw0Unt#w^Js)EO{DyG3I%iVjqNvx9PFmrq_w!<((uiCZ!+Swq+jZo3GzI!O6 z*&Kvq(dLS*zm-OUtTx#MHO*SyoVNE{oYtmh&Gm5WNJ_+0P9qF>vy8h;wNY3s5lioB zBF05|?2SA}-^nq-kFXZJr9NGF?eJs7z1#cwa0D2Pp!(h{F`~sZIqP}E-TpZ%kr)%n2m-$gvdJErqk6xO6|75M!b9$+iA zx-e1o>h!R~GD5JslD>7^c~6kdV6rPQf2Prf6yUhvZ9<1GRuUd5<}DxYCN3Yk7_>bu zg6S*kO4H!zC%wi8n8X?z@5sJ*p{yuan0yC^hD&NY-Hw*7;;}m;dfo95ww`>+4VRvl z0aLU>S_vkO>#KGbV+GYODA=T+weDPOWA6N_`5p`uZTIEC^EnFIVUPKxf2XZ@hMC*k zp*bEvm0+J{XV~Wv``l5(4pm=4gGsNL;Y&5>J(_nSjq?|nKO&5wL6_QUF1N}1xteQv zgBUKU^nv&1M+QHc?L)W589UQ^#;aOZoOia1=8E*o116-SH zb$E}$BsVT*elRHP(`Nqz&YxQEA=_KF_l3DNk^dg`XZka%%04slVdqJFEjG05;cIsC zp#RSlq~hYIzWUK-gKpkHjgvNgMQJ#4u*4qlEJtxSBE|Gb5EKXS2Mu|qvCQ^L@~)@k z4UwSjqS?I}QvSOV?xpJ3dc$jmp{ABgJ(F65Ptmq?4|dVsv)XV(PJd}+5jPxC(m%>RC10M^uHEbA9`dG?1M9#wep(M=6^^!Bm1 zN21#IUYQ8aJbHrfTFj>W(R{aY9?ViNvAZveFfk6wC*Xo9hfFxDuBd&5^={B}nE?k7 zrYZ;^LU0Cah{v=PQJsgC1|^JPbTo>79xiG4!*NJ+YOYL5z#~jLFXVl^pV_!o&tGo& z2W~~x@tIz@hO6FocfBp>h)$lJ|hQ7K-KIek?D-sCg;a z1~+wW;qYFSGxh6&Wj%E()-{whI7r%}c zD2@vg%oaZ^R{RWDx}Cu=Yr-^{Rd~J=2-71hjZ0KLkhxw)g7N<9ZCf_2-7+Th?Q=Su zhrpj+-uTKhSW2)Td}tg;{M(T;TPTGeZ}Mt@iSx@pT(Ta&)9{kEW*nb^kPi|zTZ@x; z!5Cg?yyBP#h_0BMd7`kHxg~7B<#a`7HX@;-hv<2yK)~uU!j`*s@P4+gZf9`&$P{0GNg;buyiAT)>=R98W*>|bidg~Pxn&i951S1Uiw-F-)-6cl|38- z!8AFd3tr{8b6mog?t!9Q%IeHNy+?DFYFd6$eQIq%DOhu37K&d{KAG*%bIesQu-iU& z@A}4vdvepzPhj@eE#)m`gIENM79HHDO4cw5H^&`LjqB<5VJ$Tdeq%9QswIrUDy5bu z4s*;1lC;Ra_>MSM)2Gz+1jQbL&&gl6Z&O+*>u&$RY?de}YhGCEw_a>Wad;Ru{?)@% z;4=UhhCcg*7u>J%DH8Ubct@gn4Msm2dtsu{7H(Ow5poMwW{LU}OP>h3#(P&##`RJA z2Y*ZXYIZK%&UNP_*qK(H9(_;qgLfqlbMABMqN3%4&g4f0#`M^^t@WCgau9v)zsQnE z>$9T*P}@SF+CX35-~rW>JhT4ec|BU`6zB#NXWUEqqsG#?0Mr~!?@SLBht|5m9p<7- zhZ5sM!WBfM(9hS!$dEzM^3vk%u)ebtkM{}e{ViPFx^f?fuX3Dn=t~Jvd7TkuRHs1C zN*hv;qKh*oBK0cFn5$cy87?C=`D0n}D^@-~*yZcX%@dAxa;S>%vY%@k{}h_uGd)u; zz`D0yxsY>lA~;+KU!;pOTTF`xTx9<>_J*N<5Fl_X=y_tlS0pUzmR-gOh(M@H4y0D` zMAZtSII|Om4~cyk)fMDLT?xAeUr6P*g(uz9!g+0%*3w3ZRsyKKLf6*^Y%S&Wg~23` zG0r{$&pGY%ptNDq;d7;VEN>L1Vn#GU78S##pL1M^wfbs3w)T=|NSbk};n%19#=U#r zmg~Ou^KCJ)qF67cpA^$2#=LIVvi73bVYWl8BJpSX6?7#tFltUOn2SNXvq>6}@T?3? zOXs84W-k#c7v(A$Rs{7UOQtkqKPzubLZt4M1evn~g-gmi8*Ympr8uSK?_cX=>r;+# zY|S|o?_mW*J^Rvaf{2e@XSq@;ODS@L>0WA2T6uSI&KbNVf9ILMZjm`(*`VQcGPdub zL|E&7AxFzhF19BInpg);@&oU1fdSAkTlyGqMYR_yGv_q&@2Rfw$)3Kk`j&E&BcAB8 z$WyEDlIp6Ls;2_*-i`6N<{1E}Vr@^u&O8$rrSG_dUwwb6T!c6px8z*QTK70J0|*x^ zS7c3EcJL2!(Y5izvOJry9EUGgF5TH3aSBHvkLok-5&x#In0>ms%&AFl&d!fHuQFS3 zl^ciI>NRC;j#rN&SzEm#jZs~3(!|0XZ5NrDMboQB^alwOm!0CPu(kk+ZOjclml!S;~H2%bG+AL?9mbrF2Z!T9j(u6$01EGKxc5h7Z$Box}mGtt?IZ0mMcCB5uKJCXNi`PLN z;Ohnj!|Yy?ILR)pPZaCYbK;<|B76jI{AzbuAV@8o*AEaYwDb!k?=)-@X9& z@)4~9O9)t}H0Gi3#{?88g>7{i}1EbZH$bb8K%_gw(fC=C#7;G*Apq3p3W z=Xf|xG~xOHbIecx86Lmg<`QTN*fOu14v589_hvO658TP)%UrT{s_XG?hzMLg%h&~N zNqMNBOD)TbQBFQ|3XBdrkiJ=eQR3&LU19Hy@I&T@4Q7GD1NNfbV%C|6yhV<;Zp-R_ zpPK(Fhs|k-D^g`5Wx+0IJGVFcVBR^pa%MBJohot5QSHqXKk?v&3&uu9WgU0LAFsai zRXk?#D=TB+$C&PuE(49U+ZnY?8C78gPuHtoW}bzbFZQT0GgVkkx+|d=7~`n_Dk}J`ZsF@wO4IGb4KFUZE69!Z5Dksbk9E;k?Q8L$U^1Vxm25bKnj=Vr6Y!R^--;k@X+w zYv(oKvn7(gJW~q|erKKuLrwFUTG#|J2SD5F>Tr2*?cRol=h!4JcdD-5mk-3Zp?w$hg?0?8kxrL`W?ZS(g3XPw7_6Xu4x-_E$T)a}%7U~P-t4}?&hrcq zl@pcv)^o_Mv3yB|zOWGywEdNMI{Un)q?X=|rDsaaIl?-~d8>5Or^jT*h{N}%@C#sV z47J-Kyjm@KVbEj-n>%SftDiloMPv5hln50H1AEz?*l8s2z}a4^)@d4+qUs18Dm?iX zBnxb>G3NdLHr0L;#|k%gvG5;TkGjwK-y`EtZsUKwX5arif(7v6PHx?EzVzkHB7O8b z^Pg|7Z37YO_cJ?VUfv^UD+8GSOvVE)FlM+R-d;3Zq-R46yNJr=j}Wrg?zbA$Ip*ll zymR)=t;oSEoVT)j@sMe8+HFV-MIwb4%DdxZ7CUPVVtmE7NuR04Ci4h)B*Wus(U^JZp~oYGD%fl zkwX0?!+txwDSv57z6=&A*jJP-<8(D6(PdN z?yw75P%*|04qozJpd{g(07aQMZS@q`3r2BrcWJBb*E5x2mTsYDb{Q%+pNWFI{K)+m zxb{;A%d|*cg(ec1N~A%!%Zx#7mVXk%96fZ6;5{s(xPD*d+8(yf1AhQj#S>&l5*mRi z&kzpW_(8fqD@ZinWff3fNgoinp{MM)zA;`0=`#2sLB-oXj36M#^9sLkf|@FVy`OYb zJuD9J(yn!YIz>j@_!AgyKcXSc#2=oE!!!l2IR~ym`mIAQHID0y+JxS|t?`8RYhUNW z<%5OxusI;0cd(y~hZFKjhpDFmR=dD+-LZjo#1?7!%DF37^X?HJ+;lw)@C`2T241Ga z3n=^9K3{qEzoC-G=)hI`_7WgU5HH)`18u>Q_X|&#?cb=`-SJP5vAyF81c_0CDcOg2 z)=O(Cpk)%U*h?1%?@Z3FIcoIJQUBSz(mC*}a6@VogR?L`3K&n8vp4Zsq1kwR1H|9w z=H+2yr`r=}#hWXnY@6PnH?g#w&+j)wmMB5>%LJjw^@m!5l0Qk(yySZgYaP))21E5- zN&rZIrR4Z?kwDjec!FG8jFhFI#VgXe?Q;DtdmDhfkU(@hBfisqg3zH%kgnPI5@7o1 zr{b-V6I&<2y?i+X?gfYg?1B0ta~|9WX)*>uwcg$82SL_AU#LHo>e(>7XKQsq$}O z+(O6%mzr{8W8-qpC8%GLA9+j|MAESRM8-(aNaDRf@GT)4HxX%{J%IS*KG1xihpT)^ zjA8%5Z!eBnmMKq08CtY_0VF?qez3F@k|hCs(#5VvEW z9METZ*fN z0j*aWsi#ayydD##Mh3DZ3@9=lTrw2O?0c%tqtt^Xw|*DE@qTJ}BaE6(^3SJ%w^K)S z$h86kuU}T0Y~G{q(Ea*D?N)EWkdGKpD)~Ia|3!|&hszHS5U)5|1dD&G_FL0B45z=z zc-cklx0D}hyL!K*~r>GqAKZ^vjpvf;P8?A6Dk1v%k4H*&AAy0xV#;3t~dD@Wx| zwCM5?#SZpNtJ!V*`tc$~Q_TJifD`*u^JZ5!H$b~OBnQ^6NucTjlsnHLRH>RmU4p2u z&%`?oi^)5A`hcAWdvOz58em*rd4?P!j|(k5+GH0LN`!GT_fjryQ#uET68U9ch*CqK z;dr;CHT}WkO@fS`?T6J9*SCLtrQMH7QGb2_@i9;TGG~yK(VcKXJ5wv)453D^t(nZq zV-oM9oE8Oo-3UL1X_MS=gg@Mb-^dE8`clC3RNCE!|o9dbL)39D@+-wEnw&;aPi3A2I z#W1Au8L&M4=wB^dr{bp{fZYt}?SjSsPkEwG>1UMaE@Hovu`WQNqE13X1Z7_1lZu^p z;M^IhR6!vRrp!D2-svXX=pB*YKaHwP^mSNxakKtuy8M+gh17zS|*BA=-nisa6XoG%H;GV&xgcNOgf8$LH*Z1ZqNn2OKEomrax{e4hAY0&}} zn^BFOp)_vMWP9!e7>(B_ofJHQbJAER=w2^96br&4Kh;)CQ}@Q)7vCBvq}0)>l!OCq zZo4AHW*KU%n*P^WB~n<%EG9&hLmu2E+g&Ivlqkoocveqa7wz8gd&ba@$oZFrr2gJIaMe$F_?ZAd{iqn3nv!{Mb$#8z8Caa<0@XRqz)%j0M%lMeI zUo5|YkKdhxeyH}gD_F{lmVpimM5kq(hHd6(94=9&si9z#;)xRIo}tkrPrr4-WQPQM zJ6^$Lehf;8=P5VbQa5A_5-Q2z<#?Kx6flhS$bx-&YgOh>jHo5wRWnb1%9(V}^cPm+GHMQ5^uiknR}CrTbxFQz+C^_=_oJv-U> zB-DRod)`(NIz^}OAA&QvOAb{OljPzKNw04tGAV_Qb&054^gw6|Ca5|rtU>FxdL*L7 z5hS^~5g5MARh`-)!gRQ>zDl*Pvr6LKjal2T#|NRn&UCAI^+q!m{25h;k@0GhGYXvi0sixoi2s{^ zg5D$B|DNh{^Kc0bD@TDE&oiOjV|&?D4Z+rtJ{&NXO52a*)b~3#iAR zI76Q-S$KjC3EER%x;@##0UVI0g;EZw(pQCsJ9ZddyU-`9jn>{LZud0Roo8c91wD_! z^pi6j0|Fkk;9?nFOMP$ZYT4NS2A$hoVYOq;PeF6@{W-XI>_PYi4zN?57EwF)q~{DQ z~sP7WYZx-)ia$;i53_H|Gq z0}Wun)coRW{#YoGy*2)7h=xn$zwb;eJY}Yu(dso&Hy49wt=S!R?zbeLz(F!{9;MZ{ z=u(;&2?(itndPWg%|O?R8gxhtciv?&N`bgX!Y76Vo!|7&<9GAps!jrF_5(otBcr3I zLZ7dO;d!cr=esk0tF66&l!)rqDBPdwK3CLOF}fO=y!~yR=4~y|Ocnq4d(%{R0Nu>o zSDv;5hkvb4vk|;UWEH1R5^TPxWi6G_pM$a@6TXS>1nDF1&ybLNMXrj`>@ypZhir38+((TG%G##2V? zkO54ms<$FZCe}&;DKjj_NGX~`X$S<+)9*Zb=ol+zsd*v}(SBn^M_N^?7}y3H16R{T zC_vn7V;!(&{Ok4a&i5_wqp8w)VK7OvhjKwRDn~CSxkrK4eVsW>drV->{*rf&j*c0~ z$;F|IUr?TM;Ap;?wN2@oNPy-AmA*LE2D+-C@4hSBv(4~GmDM!^8W4;lK^Fc;Nvo;> zOK%|Q@MBgW2rac$`?DMWWY6lYF7W}LgNoC=eNdIQ3C%ZM;5zyFh4sq8F8si$gg)I9xE&=8OaU+Lg_ z?!Q=FnlQNlgeU7(er{XbQcG47A8&>@hs*XA?y#7HkBOtiGhiyKDns+x@NH+h+3-Sj z|6Gzky>e1%<#p{qH@AG8rTYt!bWuGy=0fEiZhZr3BFCxAgLVS7d$b8Z(S=U|O@Iqn zy;pee#5Ncoq~x8|%zTMq#%;_xP7aL|e*CM>>i*EThTQA<++foFGjkJzpW#IUFITd> zYV9tLx5=|Q(^rqZCOhT`Si=S%dl2CAvboty$!f=LXD#KN98W0uH8(YUgtZ)7>v@&N zmtbB59f5$bPsDyQEwHL1qW6J~;=hK2Yh4AmXiwYF*8p^a@f+FT?iI&%7mx9 zSseLXWWl>vamU9aQsY80U$(u4E>3t6Ag6?AQ!5I*U0>Wfh($!yYUUx%-g$j6AIc7yj=_4^BIqSm|iXuj-x?*}dSf zd!0LUc{vze6biT-Nuc|;b`n<5A)Hd$`O(1Q9h{>OfP_fTi#Cx2(1lTIcax4=4Ip~V z?CdfU&ZQEe^Amork%__2@jzBL+b3C;>T2bW&PG?xbM#d*dV$z4a=u%8u^2pfJwU-% zQ%T!d(KFB)6SDmlWcbdna9mBZs$l}Ep$05oeUgELRDhfP*NnIcAYqLGTb>}NrM-wU z*LO6Z@t`>|;4!d#yi^aCqLFgh*L~(F$x02vI-e#Qoi`7JsQIYjyKCH+(jcZM5Rk0` zN*7`vfbXAQ4xABo4)Qaly-{dxvx10J>O@l{nhcjG0MG7m(KDDkLd%u7mogWU37$} zXac8<>}*eVB%0W3f|>sd^x2=fpyS7Y@9Gdq{PjgceA%Jnz>6aWW)LG7)uNH&3YupU zBt<;2#<}EY-@Y2#y?iAzA-uEY;d-|=?(r9}(1wKHz>TNHUu~Se1q^Z%z$^7uAx{z} zX;Id>P%$gTtd|b70bI+9___!cyk|7(Q&E_u|2(nIL^5;wIsiq6j7D$|Z%9T;JLvRY zpZ+l3aGzUP0aixZgoQKfI1()VvMHw4n?D>zRcjp*KON>aL;$2rpY7i>m`qiRY)z2w z2%j}`%!qdW{`Sl|c&b4#L>z^j3!gH261fZjgDcR_?FzAVH*eb}l$7NmizPU)+(s=p z^8~9P7IqK-6nO#6_3I2J!wRfof8Z`tx;lvIqM4ui;>hlfH{ojgFLeV^m?bva_eX2; zO)I;CYEB`XiGug}#Z8YzMzKi`J1?7l1hkQx+dBLidYo92#eNqhfCb2CXcnM>_&!~# z-Co96;>$gz|6wcX0M65>I~COjoN1#CCfSN(z!kFC;O5A=Yym=bPz5XwghyLPb&$Wx zh3m}`ffLU&nzab`(prJ?&YDX*MH6+*+9Q0#SkG=GfJ+GHRc6Q0k1PEo5V`{i?&|LC zVLSMHAGrdPTm^zMpgf!5)IFcdAD5e7(QJZ1%R&~I5ENnoV10#yqbFr{rWe6WhsHwVg_pfM z$TyCg7i@4Xj(2xom;aeGO}2jp=K8(g3+?w#SQ{6-(Q6T-!CEf`G!wV|>U+&Hvkcz$@C=qzFR4<_(`85uW1- z+6XZ=HRV9aCLf_xGq!B*ru_Vw)&?`87d5sH2PzJH_ZapypXg6MJx0$3#mzyCgQ!|0 z_=VUgP*IinHf6?88a7|lcnb63&czGo94|$xeFK#0gI8SFs}nTFpZ^Ag63ak^Fw}~L zoP}86PB{HE<4indxubMl!e1c4NT1u3iXHK0AmG?27wC7d{W?+qdb>|cK>zU4ayv& zRvv+pTscL6{kUnl2WZUP5!|lKboPhPzuE9FcMTofgI7A_5dqksrCtNM zvd8mEDdI-nQ+;p5Sd*oZzedtv5Uf%lr)T_S)~kt2aZ zH&pksr)!AFB0S(L!7oJ}4q`5x3AZtbqqw(7q9F^3_%A@(PD|b5dx>P5>&=Zt+-Cra z)J@XNsY_w>$-b9zl-t+;^M!^Uh6{e}sq}V{ue7N2ns*N6GjSbvKfrTpu20B7UQV*z zZ`gO*w_jwIrVNVFvjpp%?zybAR#@%L8mujGBPUjPXe{@~T8I{$#=W-HgT}1>>>>f5 z$RLo$-+Mb#JDHuC|A!ZGm?%Z_B*WJ$M_BFDQkO+> zmeafI6K~b$YM7@AH6v@>XLqW81yjuI?UB`Mw&eb z(N5uqFc(5_I6;B;J=9eoRw+NRW@6!XyK?NMgn5;2kB;<-Q$RM6pP_qZrb#ThM7Hn# zS8NCQnIQU5N)tpE{_f%oUw1|=feL*P0LG5}mfnd%OmeoN*r3mNBAP+7##+u*S=a&n zEvOfe9XD*fx^55eoP0o9X{XZ#Zv3s0r=xMo(X0JBXi`R-ulRv}WN1qta1Xff6IUC6 z2c^ZO^y4AmHVE|s6QI%r?@=X?^R@&?+b9KrYZCH*+ya*3WiXBYX&!m6!a}n{??ejT z*cg2Un6sd9z+A^rOXX*WX`ifB+QRJD>o|}+N)sGe(!n(P$cV^SUQB?vSZEzoRFk^y z2vG`czRo@6IOS@&4tg2#TpwP#N+9>dCZr!(JpT9rxN;uKt^59ECF}ojjHcKLZaGN&~D<1wQYV3Vmb+PLY_D8tr1 zv&Q6~KYo2}ld2tBtcWFbo&zS`f&|{N7h*}E0KE>6Ng;k*E%OG(Xjk;$f4;5sGq6xc z6EwC=;{m_=y*XKMg_W<|M)|$DNj8l}$A^zu@4?bG* zInO-)7F1ME?Fyke{_~z1I-iju{$u_A2Lt%`YVr?S@ZZb(|F3_&xtgGdj;LG*m_>al zOLA~xm`j$x{r#_{G0!D%qe04NX0N~PmQbCn>W{~lXZKY)e7l{mc!B<}nUMo$ zdf^~A$7^W3(F~4;yGnLm*}8G@ZP1PB@lnA?piTW}2DRbjTZo(v?ti0q36cOaO6?%O zUPSIszWnUJzKV?vAS%DNMK-o9$j%R~0&MyKcllimuziHmN}-L7O%=T6->Wy<6NUeJ zST;6*&HUcA+1Tj+bDVF_;gw7FYxGWA9ZsN!KHWWK9Lllzh=05FDm|M8CCo7uQ&F@-wx5gKWqg4G(Qi$g$sP3F8P1?zsh!ZXCTS=c$!}>rFO?o&d<|z-;-hp9)qqa z+wDCPpBPv{Ii?o}&i(WH_6PE;#sT@g7p|)rk^`7uOXW~Im$W3Ltos9ns}jIR{sJEv zbV*3`G6%ATJ_Pc)Fuw(xzWXzLgP|Rh($ry|Y!l$T%dwtWGUg6OVL4-Y#YKf@*pf~4 z;!&L7OuT)oROO|z(akX~0?nI8iVeEZcq`&shtzIu%Y5n|0+iEM*kqkLI$l9#Z#!fK)81u(vQL1+WM;rdor8lWqzd8AVEjw6)% zbbXfhBj_v+whPK?hG*M=-j@DFWNGpIW1$vSaV> zGUX32PgR+tINXCN9RkpqInU;S!uzr!{Q^O<6y`q}{a_#4d3A^8f?WyL{8Gdz=r;Ws zue|5KiRnSP8ZV!MtG?ooxAX|7i0Aq+SBfcTBjQ-w)5zVO(vbij)tRHX<+Cu!-%^st z&+wvxa;?sh@YZ(44i~h!KN?cpGN-^nWYD{9j_53LhGspOI=H*XROiYwft@d|EfM9_ zd2`1P-kQ!4#h-FfMU7kx9V1q+;o$Ta_N(H|EkwogOOodof6_$Fp!2X}ITs z!k7b%N+HO9=0L zP=E*k2^m+oj6YuidCu?3rz=?LNsS-ONymk1f`$tfA&zZ3_iLr zC!K8@J~;zva;U&3-J(Osh7XgR;wmQLAWnvO*YOh>)XO$NC{T)eu{Xx?8Gid9yydsf zN+czFvu0tVksvpJ0}QGk zz_?m9It))cbOszFuRI6<8#Jiv3qf)LwYQT0(tV(gyJUM1zWE2vJl2Ij$ktjKv-3#> z>}SyW@fApVM%hyw<$`t;*W2XvDpidvEoazMYW@1F(bj>!i9#K#ZSr5i7*JmN(tQT# zdZ|*E92L=oN182-XR{H*K+iHiW)2Fm@2<{mQF!Ohvs4H#RRR(g-H;uDly+CSU`)P#LGQ2RC^Am4Rz;5&vZ z2zNG|+-sT=0O*BvfZ`8ADI-9jkt*!^dC%~QFO%nzHh3k(hR$?Ha13D*8X)e`D03Ih zF56a|Y)e~VBq>`%K+4iV!${bsBZyhmW^s*tD%M50i4yB89{lc;TORwhB8Oi$;r69lJ^vl2?WKDpz`cUn@G7Oy8@k|uQ@qymiBhB z54$X>=4Nju3q%c*fc2IHjL6-h@U3crBwdD-JUR~_6L-b#C2J`nXw{1`O@iWHfW8?8 z=!iVTWdVm3=n+Vr=~K&!3uRvwu=Gc@n{6)6z_pFO*JZm+H?4JVTQ)x`4Tq8njua>i z#rW;oK}8EICL18#)29Ll=I{yIK`sAa+|U;4wX=x?8dug6ZaM#{6NGnX+Zx^wLuDg} z9`Sfg*DQp-7XV&i9I~onD;e|QJ#ZI!j*&BWX_X7&yKdUI#0*@j*Gx)}=U2=L`_C1D z>>*B%*23p#QW1y+K^f4`}ZRS?a^SMX{BkM_Rmkvxg~%b@Tl0At@L4W5Lx zS{3TELyA=9VyU;~GFSvMhj)X1SPl;%Tg!TCcKos&|N6T_S+SnW2(+oMh2+~I3TieRI03AUF|fp58vig8d&*vUha_1Xg9NYRgc_wj1rtYxIa%rysn z*H8^fJprqqvDiKtC_ezuR?gAJt#Ttn&JjwVrrwdORC^k0Hd4Eh9W`IM?&uA8kAxTc zt_-ib51dO-^p4`vHh<;V^nNjfLrO{V{b0F={U9(zf(09hZ`r9A)C>dJx!?qQWfcgS3wz+ndBt*xQr1eoiJZrs&et!PQY~H&RV4C=2~z;tsHY5 zfv9*;!=;Yvxf!YS(^T4deeR}Q;Pw{g%HQq=`UVA2KxEg|4Ye~-*5I&cnm02b<|?MV zzRLRbs9KAoNrI&pr5@_AApAN6#WfAo;3bJ()TYp48M>}Ma#+$9uX7=5Lp2Gu*<_np#27{5HA?a-9T5kufxN? zAz0^)0{w!#FK;LQ58SfEeTVLduW!%Pv3C^O1O_3yVja1Vc=Bsm`61U3NdV9GW$KB@ z`&-HU)X;r3xHd;2J2^Q8qqOyAFAKvaPa|yRIM=s^`oRr{{9edfL-BhN6`n7Eg)T_G z-LWqCi#NlC6952_B#=k(FsI_zJ`fw%T<{>p@uxmexib2ZM-$QApF1~K+LHX5tus^N z3GG!tq?a$fB%0v-5W=)v(LWqpd!YQR*-wNwNfeil#*NhaB0L7zO?ApmT z#ZnuIB7-hstUkHNLF!EBn=O^{-+uoX2jP+gpCxZ-K_2j5L_g#bi1B`EhNbjt4nlH5 zZa%h`x3Ly^XL34*Y$KGAK>t{si0w05@2}nI71fD5>TLYzpL^p)*0B0O_)gS~)*5Cz zj{&DH4&(Win-w~bsg^BMAAii8=K^EQ1gtQ%jGAi#2m1LVL_^C!Ndi1_kf!-uM|?`X zb3rmVk@_-{z0z?CUPlZCZ4p$L5nEGldjOMc?ErYOi>xC81$+CCo6{cw&uuYCb?RHY zyJs1wF$uO2z0>{9Tb_hwt;LR9xiXnMy^q?Gmpj#s0S2^N2qCF!Ip%;t8TtY&epST@ zbSv$#EM4;%rTd!7LH|6+*y=?eTTq%k(u zpniK%>5qN7+3nQi%3n|}(L7k#NFdUxVrKCbw19W1 zMQ*X^=ndM}|FVtZgV4i6@T~3o0B@XXszSD{8Edbi|-xi`xrv3%i z{F2UdbY^ZSrj*+3TshymP|SY0)WI6wpCy1}) z3ZF{ZGq9-GL$Pj9G@<4Di{D55n3A)u1{|}pRk3jEYf5D#sAtv(?MY0$a==T#4cY+u zRBWKicQTi(Y`ar-HCFCxD|@&f-e}H9-~G8D$0diNbM@Kw($_*$Xf) zKKy>d9)NM_>fNvbXf2YDkM!Utob=HvCqc_|s0{1;<(cqYf=d{?P=CVpl{-R;>#@Mh zl>ydo1G2y*hyWYglJN%lQBEsZElDcSQ2?KpHzIR&2(h?>pwE@n-LsVwDu=UWGa2vyQQ?Px|*N6*+f`ko9KEcoNR&&!w4 zxKxkK;`!yjNJ$-5a^C)FjE3y*Jf9CITm_2i*G9TfaM)EKP_*}*PEJtPguHo0uWx09Rw>^$3>X8X{)gOnNI{*yW6$cP9XGb!VJZ(jGdWPu0&xw*Kw)Q9e$G8j z${qOEsPhHnyE9;rvE;`BgiH-}&%aiH*QZpHH1Gv}a1U&vU9s(yf2#;JdFf{wa+mQ0 zU*TrmsaTP~fi8YYoFgcRQv-H3DN?uE5}8hgb_zW`J!MaQx4L_DL_4uXJ20r?uI?Tsa9lv-iC0K-04Hoi^7y&R*W+Dt6E z=9XJnKcquJV^eT4MYHE+`o;R%ZTBaP#Z4;*zb3rS%uFc$50apJ_8qy{CV}HkH#Q1mi{b|D=oLagonaz&sYP=<+cWi(KVt!N_{!T` z#|D8I1<4pXW^wP5_t1}0x$NHT&OA8S^_u?x8IzWeR;Fvw$HaCT8X`tMx20!xmON^* zK$QGM_1kp}Hji9m@3}Doh$sQvs(MzwC$25CeDalaO(6)7sN_qMRqq7Z6c2%S;)5j! z${d#YUOM1n)2UQ2X%4qLs7e8-k{;kQ{ZW64wwY(zn)Oh={OK^a)ULQVXP&S+$bD{e zC7DK7z$oEUyPsqydR-Z`7iqiCZ((*C+@F>(jyKN9DX9=@kca(U_AP4vyaMu5epJxg z;yp^+aM)bXMA{%{M|USP9PjiBrmy`q)f#`yV({_S%`&hnT6otsH*1xist*&w{H&OD zJpc3IUohfHz^|)=0_dv8l#cwN$i6%?-^u9T5|v{zQK=et;*f1XBN9%dUcYT^1bbms zYHE5pJh%H~pWR&X-$Sc04w~I?xvsI+y6F1Urh6q9dYp1M$!mPYMCg~js7~(A;2MIB z0Z1VO#EOxIM_86723O)o4+Ef6)GIozR_c65#=O7mihE7(i5rBMF z`*?120wc6G2vqa7jFsm0Qv$fh%Zj&P&jr>8HbFH9r|WRGl#xcrRMYlgu*g=UAjv0< z%cvd*buP(!8QW;uM#xTXKwHmpiH~F7a02E^q57O0c4?t-o%pA7p5(rmDuN-C$2V%Gs{p&{03%nJDQ~Q|)+wov4 zy*T{5)un#($McIAE%&_15{E9+g$nmB*f`x3%i|;@JBs6+Mit0yfxy_Z6LUT4>NlrC9v*(e$l|L0(hcl7i})L+ z0ymYC_YRt)@+Nm!ZrS@@@%OTT+AOD<(UhxQJ_@XEjGAZ{miQxo=KKq=XL?hwPxDR_ z;%{ROxRVUxq#kiyO1W73{u$np+{(nuAl%rQ>ne@ZV0J?q?>H2tFqRCm`~vd?qf`b#;HS?Uk;yJYj-9&E~Gbr+yHw3 zj^r@DemLT3^)I!;+cp580+`UpGtcm2o!@i-cUTLllca`DPWDQ`_{*+y zjpj5yuNYMUN)-|m4Ptek&T@lnt(v&8V^=SpbEI8hA#>TaQs`fKR4!Tg80c@U8rDue zNDJRy66e$?r6Bj1Ir6XY;K*klbTakTw@nd)mi?YTkx$&S{0@(YiETaA4qVVG>vLAY= zFpnwj;mN&nN^+{!QMhuA@wgJafs8;OId+~8Kt%hhMV^QpINT|OAAor`e@2P+UXL3I4_WrFw@ zU)0X_w2HrR0+vP%hx}c$Y6H$W(&54=fSv8=>=ist7{nk=t!7vbwJ16FbV|HEu6m~; z$SgTGMV-Yw!`CzB3*@Agf@DA+g`xOde}SDr(^$B=Dtf^VON~F;PPznP*gu}syOe`6RA;I2&mZV`t-(Y7ps5 zyQM=%_Jb7T%3oi&Xf6SU=C46CwM0RU!uPg?%*K1UB~s8M$6tBW^9w&$;T~_R3R-0&(BlWgy<3T~sqr)E8BoJz7XgD78uFLh!!z71})UCC* zXVy|2R~^(0W%wjvGwNw78?jc)9dCdqk)jvmwBD$K3s`=E^9bf%G0f_Y!!M2Z7XeG5 zL>Z}UH6y2f6=v8m0{Rg~hQ*)5Jf9F*b8`gN#oJg?6Z4N>f7%w_v^n~FOrL&H;g>zB zR?WA%_^|zN>chNiuoo4R;f%nmy;|wnO+XoqsGPwk6bDxFxqGsJT5ZNWriZ&AXm2-#*ymEmt0)h-O0 zX167WS)}-ls)oBAl5;rl51ix|66M37^)H&^m7_WDaIz&TY(8ybKB$x@9s;!&fXY^j zL2yieeuP_*!Q>^wLZera|BJ1!4y$_Gx<(L?mXZ`yTDm(VRASTJ zA>GnlQX-(Vo03$zyIaXE-6@T9=eM@r^S<}q_xtZW&%ynxwdR_0%rVBiWLyBFeU|BT{WegI6Y z-`+C?JU%;*Xt(h>C4zH?%|FYcuNz(1?Pl9~hilv%quJXK>B=l(gUd z_~(3p-;^J)5Ff(1H;{sN05~wtkTmGn%aMRb5!#=N>()qlFMk&N-vUmBc zaD`7S_5FPO%;FGzjPU-h5jkcIZGmSL3CpWzEq6`H?oZUFUjrkQvj(^cGxO_`g|}7D zEkm@K*E3umR%zNkHJ`;8!SvdiE?FP%Z@4>Z|M+|Wswp!P2L!#VyF8F*WdL%S1pSib zQ@2aOy`;p-Yr6|8E#>XldaaD8Et9daF&3uH>}oT1RoPv@cwEoT)Y$t10EBtKKrchl zxkQIt<(_mLYpEz+fBt`j&?C?U8haOK)>vETRgJlA8c#$ za{K0DnR9eq-AMZQg=HJbV;|V4fu?~s)VPwtCnQ;XU`IeU$AL!+t$B2`F~2SCa#(fZ zWva_CrT|njOU!8>|L@C?(A$Gka#Nl%Xeb4X7%)m|RhGf17rc)m3p$@C*?ZI%h~vGKV{w*CvTLH4QlpwZw7}n60cXH&w5xk zJ2}a#Q1Z#r5Y0eyOix&`DWK9dw>x8#`rSBe^f$VSK$|b%VoeF^KV&|=D(cbT?d!iP zO6Z^v_N)cmzTYZzOMXCeTs!n4kwtF@?q{zca*=Inl2)mnxHYbCQQ3jRdj1eQ6l86H zHBZZ2%UPK_+<}vfJP;TBrGg929lSE!lF+sgz;_1BvD(~ucmYpsP^@*F0(~HkFYew3 zT*$o)@^huG(YZ=L!babM@|r}TErF4oCZ6bhWwvBRWgCoIV5a1K!Iol|z)xuO^RE0# z>y&uy_&*8)fF3TJodZj|XkF{@`u)7X5*8nGP;UEtUAQ$?c)C00G@JBRtx?un4k|In zNGJsNU7vWLCCxh;n1#k0fjuZ*|@vRo4#y_Ot90h~J@Oiuk?+Szak=3VT^; zIvKC8a(}!Y?fr)QiCbTuc}V-?1z0-OaF=+yg)!3cCNH;={Of=kgSH^^U9G1* zii+|~iqj;ZN=o;>KBQ|uAtvR`St0`snXH27d>WM^s1;T+zf*40#agmmI>D@SrUBgw z;h}T6K>)DX^3uLKrK}xu=TdPuDJVA>)U?4LZ0ve;V~kaSFV6-HqiS;={C!_}SE=fS z<4<0)O3!3PKe8d04{7fQ0|I_uhHXh`(r-P_D9sirw-R6$d@M`&J0dCvRGnYGse9Wk zO+5uUWYsk6_(jf?1mov{)McOMH5K|z*68cuovG9y90!3_bg4)NXxI}%pn=ZOXM&Q8 z6+xh-Vp16E1;OQt_)1*w5o0}zH{KMER}7D?S$W9d4j8)wAxAwL;piA7W4(U6*l9_n z?bSWW6Rwj7!^iVOqIced_#0Me%Kkq|bv?;lB1fl_nbG8-7LrB!0Fg-Z!XfPCQpucO zaCZ~5E!fZgd_0<}c;&s7=hN8A-Ioi|F6v|sJ)vyTv4Euw`~bMl+h1dSz~k1-!{V;LWE=h}d*bN9aCR9|<& zEEEzfp*0WGBBv~A4An}B|X z2Je309CWC_%0GE&5;Pi33JJYk@CzhY zqsDwd5MfwwO^}v$yycKzVpqFl-*l6-P5Wv5qXz`#W?eK{O%=|6@U?HyrBZOVlM0Y# z9Nu772{QT#@>FX;>gV#3p=6cYz?970vygpHA@NjBkExgALL!DjxW95=FN6qhZfl5H z?C(nusq5IG+N(gSRIhk>$(&P#rJ*XrtntK3E+fZs>dV=MWJz^FZ}syX)1z&Jk~5C!eF-1!o{ zfr=N20RlG^?p9&PBN)l7yaAF$Z-RU-$FTYl%LOho%V^V<(@*`4VOgL4j;e z#boxtD3?Jr)tSyc?A};t5uvtR7>(v8&x8Ul$y;F57uhm-wPvdYLs2%$J=5VkwV#g` ztMBH|3l%R`j8h#IF35{-$poeq@!GNgEs?3oO=U?2#-uyLvIC>TITVcfd5H&{-}36X zO=}T<*!x}SfI$wlyNXRa_e+Yi7-n3O&4^TmAw6X@bKB1CdQA}ofzIW+7)}NoJ)IZD1 zvgBc;CqA~lbiS*OdBU|iF)cpAA!SgiT_NqqPgIcK7#Y+L6ZzsJCfg`?2-E&V zuDm)a#hXc=g>j@Sv13CJoVUjZ)UNwpT3=ZlqC%KX((leI4ii4ndcgVv5h*(`#)L7vL(Yp)(I``smJn%n{t(Utk%yr~VENAr>rADz2Oq z6#o2~FVGVm;-q)*PeRMp1l)5P6@oCt$Vxk}u)WWT+Jc=GgXNnD-v(#tuD)k1b`Yjj z22K;IP#!PP*mhC*kmzEx(t&-X&@BIXdEz^_qXxtU-7`|1JxiGEKbb zW67JyruBtUhXSpQy#`=@{bgo=01Aa2`=PpL2uej*AO`Ql(Az|ZrSS1Bbzc^L$95>`$UE_sBTNjT1HAk?tgLdva0m=;os0Ktc+R6&iFxD@60ZE_`iz+{RFox{=WR6@r&8ldc*p@cD578#z5Fz#?{%?~Dd@r>c<~F|5{&evu-7Tm0I3=~sZOqc zZq+afCh;OI64_|GbhY-@=GU7q**_?O!O%|S$O8z;J6bqI2=aL`k{mujA7+TqZ}O}w zW4d%R$$iC=%rg$`iknA0zpy{IWb?hoo3U%KFD!psoT%43dYKb^(6n!dN@=67&9)6| z+X=)7BWlBqlTxQY9uD@aXt@R9x*cn$T$av=BfWOAT>^ z-&9|2-FlCkW}bZFQb}u<&9lrz4Xy&n<)Fy*zC_K-I7C(12_q|&|6D|p7S9WL9znUv z{2#H7A?B?np)t!nmBtceEY@5jX$E6=Z0c6~iyHoe+)jsi+P3#3H@VqEy=c>QhFC2+@xqb=4(~O z@rB|x&+To%Z3Kx9|c=G@s1RsJ)U#()jEaj~bLm>J`yPp;L#z*~p1me=9#R zANgxvniK#do|;8c z9O((=L{D?1OM`0Q5fOV&<= z7XlNHAvtK$_F*qoEnV!c;l)cmd!J#}Eyynu;`GMsSDX z0h^z2`uGS5f@ip*E#44IR}U_ z%c9Ey0*6bH4ElXI$y4v7asYsAzaBNJ8J>eW@BKVPBT^e30@#eX6c)ha@N``?k&bJ# z%1RkCILLA&S1X!ASl5DKonQuVD`S((ipkp`dv`$6{_B>95=_&&`k~;foN$t<90?nB z@1Vu1SY~P%84y*XZ(}&Pu1wv$(CPm&j%A1W>cGc8sUtlNzZ7+xq zrgfS6?9rl!!$$e? zOE+F!f~h6@&oLkG08(HLP{Fq{vuO5nHVJeT1}tj(nRH^eCtbXkJgTYD@1uQrr|zR#X6wHGbeTjcGU<(G%aJ_0gUu&=&kQAOK~2S zE-n}sr%8PTdnkQ!u7-W}+kU{yHyF_`{~%W3wC2F|=jqH)qYu~BLG*y<8Ba3bPaLhT z?D1Lv$_=>$tDFfT->)jC7aN3fGfw7L9?zA0DcBtrI9>3&Ytmr_>>}j0M_oArCm=zx z0K%BiGm4v;$3!lxl5m-424JJVvd+E+yg_HZ6|N^bcM~6^Ny7^B%*KSXKQ2iV769() zM5GCsN25Mrl_vlyRCP=LpmakLm-a0UYz=K!U&SZ4}8Xihr` z?pHu2;$3?c^^+ac(0;$WIr9qUfy!o6T$RNthZGDE#L&5nngk>Zz2G|jBG@Gb?Uj}n=-Nptg+MQ8`)Eui1KY6A)z@uE95KU}#0fBvy>+3WM{d&gMk{N6K!? z>31KnI>((w2TF%8iVq+^oYxf1J=_2jN8{5^CMk4ji4aW3k;Z)MZumF>R0{Vmf`Ta} zfg=Q$2NQ<-gQb6*GDO;a(5gF{%&za>8j!z~TTrU&BeIx3^DM$q)tHqVq1ZC))oikT&Xqiqg z!Cy}Qu2DEZ4EK22X%qVR+7awTz`n-ERLDY&zDP#cp^hGEQ8o{4?n}1gYdq3FjsQD74 zjb2v5ZE(AYdZH;83O{C{!-4^E(f7d^%^o16vFICkocL%&_7o&d);gL2dpRB}RR<~= zFa}kV0RwW0{S&d!3RyWq?CSJ)5x}v*AOgvWn8H0G$g?jjuIR#6!ODsjRuSdesmG}! zpbvZ|1ecm(=u6AuS=huOhKu)HZc|!=F$a@g(KphR;==dHvh_~VrXkp6z0cR0D2~LF z7M_jiUQ&<)zd&mjm5-xmB~e-JU*zAI(totjjjrEdU<3Z=+Ntd`1kmQ_l7?LY-iVA- zNRb}8G&JQEvj}`z0o?eb3FlG|wiguT!tVV?v$%DK-bcEg%ktp?kPFZgh^yG;kM4k) z($1l}Uf%*!JVZNgR7%pE_$25XB~vhi%MTci1z4lAzqfcs;!Y%v`8?(44D^IXX>u%7 zvo=S18V$}D(T4_jlM^w6FzC_18I(iMwJG>Qujlxza1UASk`P5T0B&_Y=l0G{rPTw- zz=OQ1K8VL?=bd=xi%~ju;sP&GwyHM;!Qv6^TNh){xt2S^d0!tgo1a1gud++Ci+u`8 zZa?WcyfBSTlvFH8k$=tb+N}AN3!bzrGnZt5%EAxyFMv8<h^U`cKQlO)sf_5iA-#4lb4#%;H=6S?Y8*Z1W&wSHry)S*Wx#^di{vlS2ldtdl+| zRJ$E(5|7T}<^>~hQfM`JpmJYh2%%hoI;ty57M>eVyLsaAGV)553814gh2to}_%0=C zZXC#TYQPMJmKfZTQ+ZU*rlO-u<3KOM$rDp*qMk*i0odDG`WANdAb;$$s{1N;~h} zBbuvWp~k}S@ABbqn5n66Pq`a@H1EwA5;qLpdHb&SAIVYB_Sg0CpB?SG7}T%pbDAUw zt~>cI?49wNeITLiH+a*C*xS9DChP^Bc1u{;_u=qoPdXrCmY4)qD0n{U#pS*MI_9>n z_OUK8!LGmk>zqqWqW88EOZqkdlJFMAo~RD-+maPb(fE?Ewq_ zm*pQmkyVxRZoU+)MnYxD1iGK`tLm?JT6@!;UZ-zbt-IU?<_q7Bmfs9vM{QDk_@4RO7_xJak zAqlSK3kiF&ELkw>XLd>!<=e}36KH;U2hZvH7y(BGY9T5nghH9Hdtmik0dumV)gVFF z(zt^o`R&xkz>k*)Cl`&-UcDJDqM>dF{ZFP0l*#Q#E_hB-4X#rKvO=8am)23nh|cjG zwSV7LIODiCbJ+X$9B2HK0r+fl`cu-F8jk0e9TODI)s72vC^3c~I@h+Jqf#{jFgSNT zlu?%n<5w@KMpNxp_ZSa~Y(fJ2Vp;ZYZGE>pv^x*-Nc|R(!U#y5Nx(Lh5 zUZL2h3uT94CuMq-`p-19jVynwbtsE_W0{ZL^ZMZaH1f_4d&{r{|7z-7FpyCR(-1Rp z;(d$txyQ@==esp`Oe3{qW0b*bqIap|x88Hn+azu& z>FvdY?JU@@Vm5RLNdLJD5OgDRt@)Q+@xOYP?dq~T*xTKY+3uQ9Ntj>ljqj6t zvRaCA>RFbUZ`c-SHWt~G9>BM`j`_H`(UC9s(Iiz>v_YC3!v#vZEO#sQ%?C@vN6NJ8#pT-23|Xk#)zG&{#y>GFl0- z6T%N%BB>fk)Wt1B+qV z3n#3eC{TEP3DzM=yfG~lTHL#*pOVaF8AF2C-g_TAYH>X<{y}1*>5&_*MkZY9A=7RNJ(!4V3y;bX>kEecI*`ct1rvwxOM#>p(Jz#*x#k-y!Ng zk%rUcb~^_54hfjw`OQ(6x9_99Gq)&%rboX+XFL_7LZ+##mw|l3Np*sxlf zVR3xF&C-c5jUB%61dW5@uf^9d*@??AO#mxzjfh^Oj`)k!cwsmaDmLE`I)}atv;J(c z)Kbo*)tJBE4I`U5)>~6_$S!&otTPGBQh-)=U89<(tO;np3`i^a^^+NS>dcEX z_P?#(H2+d!(?6}<>JiQ%PLWAuvGpzH3yvN^;;&C>s(dWy%4L*zChC1?+aKvp~g6>^p`MisSIh!Sv={C@Fs~J zPGeTwyI(%LZ3OQx9rV?H#fh9ge&>vO7A;clmX#tzV(}Ak-2R}&-kmWZ=U}H|MR$(8R6WkS`}v8f)y1#VRYP>tZm(~&u?S;V`%!gBU7-5x3}$I z%9J5_?i+gXzP8I^ZOec^FB(L*ZLLzyj^QEtPUI5$%a!g(2qg{g!kQ~OqJz=h!kz1` zCcwR3#YQNA;R|3NF>^U;c*+l~j5Td+SU4F2;iNrZGzt(M^?V>PIeq@Q6=Ev!3&e-o zr00Z#+HLH+i3X)vicfb|@?-ybPR9=GQ+!8*RK>;j0$!lpv9rD8K66hb{2u$~6ypAp_P{ z(WYk6cQW$@dajG4f3_K&R@uZCo2hcMM3*Rv^$m?%ztXbA@Kp~m!2)}#co#E5sBT$= zWp*ey*$B9S&kSbaIsCm)rR#5PAz;4j4iLx`sV?GRBACV>O({`CS!eJ04M4e{l1!0v{e4z0uTz^}L+J~R07LJIs5o{5=%&R; zZsZhwJpRc$nrX4U`N7AsGu5T~eyM`XqJIw+42W*i;t#$)wc2`cJ;sV*4lu83ousY8 zdV-}QTBh#pssr1*L;B> zvU185Fd}xa!bdXWhaTXHEcbZ7l9J+o6&N8pLeA0AEREgt;}aEXwe^Tqxa2?g&^b5h zAwF2pR(P?lxd`;c0$}w@w1N^V7zm3^_VnFuZFvLfT*;;TA%tM+J(!b=%=smS&#|4W zpd$Uf4>6_B@u$!9e1@$EjetJAMyw!4vJrwwvRtyC{dYrwEyO9R0x&7=GZIbrTl~U# zsoU9o?kJyF;1`yrCA=m@`YG&B+7;dj>%?s&;WXn)o_UK*rIxR{0o21s7W<_;A56JE zbC|XRPxh3owlhH5TLjc6_Iu@~eF?cl%b*gU7PFXFpbk8 z)SM71daw)Vh1RlAQnqK#1Fh1X8VAr5XYKNd1$yn1ej)1jRnl|x$i}! zbE43rutd3GcYSx)_$&IB}6CyI2;Wt5SEgY?{=zN7iB z>tc+?c7-hUEb7mG#go8)W$kn>adUYxz$LtE)E@G?!hA?z=mA9(ikT+bm^GD#r)Kf@ zSpFzcR>d#={8P(nTVPokjTdUIp;sl-xs!Xg?FlxE7MCA54P}r|yw8zOdC;8~daZfk zdR~qY{yPg@dYy}4n52d5f5&9GjMd7*V1S8 z11K>Jwk7}P{ziajU~mtmA35Q3Rkn<$2F>2NH5)*4GsuY;q4C)xP(k$ee8o=&IVe1c z!X0m-)JVcfs!=i=FW2T%kEU|xZ3d9549SrcYFFiN@-NSGO7pj^T>V;W*L`f9_qe1M zhm2<@q^F3}!cnTwYyf)4j|;Ts8UsDOC1rH#>3^d`_@qSVfN9-yXL=U=xFn=I-4+H_ z^_sc=6(1ypkNruLysj492#VzJ5IE}@1I&Jq>KU%&pK~QVgQ1z}164ruV?nc1+I;04 znO3r#x)^TXYxfcRRyDk|Q3q-^ug8J>&?Gtw?-p|IL9+wTlP#l*!&N^F$;RixVD=FZ zgb>x<-CjW$$b$&?oMQXI&{Y1RMjob~l^K)I4;3DfC||h7Xy5j<3=L7y-N6aXYbK_w z(s{}`utF_Pr(n^-zlj3=f%*FmV!nZ>ws27i%uA+Z6H68(tk9Hwud$*-{?p5{uUi0# zVe6njujorhJLQHu!YjCl9%pVgv3>Mq_^UOPFdsam2xcb}v<@ILw#>AA<+hCy1Z z!$v!BzJzG@Lb(eVI9Ij?frkN7z4+VRS&!{EMHL?DLK(~Xcp5Xs?*iTxhzYfA&o$I& zeOk#UkkAKXRZA{0~!Ok2i2XKE=M)F6aHQ7ctUatAM4TO7gHH0e;pq zapC$!opW}#w)=NJ>_~Sh4mnH-D-mvVZxhJ|{(`gn!S}HfNVu)y>K=6Zd_KSImX2%W zYdafAchfIj9I~V5IeLVK_U8bh4x!E0sVUxEF;cjvzyx=`EYvJ(_ZSrxy0;v*15|`_ zm^y}jNMG9=t0Hpv$t_w724)%Gd%a?hi(@sIe@B;gzplyvZ>VE(c)yo%U9oZ_H1|yy z)kMkq@1r{Moc@AUa-=jNkGB<>9c`quT<3>1U4DXIA2d07*549_T}{kxNH3i%u1A@A zkz2J9ek=WxLt#SD94FB<-0O%)kO(x=rdE3LJg+|+Pg*WCH=$`w96Gh9^A{T)t-oiK z_7*n!{M_r>U5WN-^LST_y*|QHcCX^G9BhBGLR&oS z;3R#zyZmg7P1%z#hn>tZZpHJ6DpF^*`*w=RZ~6 z-{R?`4DxYF)|e!L0@1YI`fFlki?gjG~A=ZaDQ+ z_QSco4HywHh)oPze_wZah~-66_q;1ztJ&VbmXsL}=uiGU zkR`A{Tcb{=3a}o_H_e@_V;7F5;cgth0)oKL^T_(hW)GIFDSK`Yi8b`x+v7C%@JiU6 zV&)dxB$O)FO2!w02%8OWT3phE-vZ=>7f3 ze-@>}vDS1u9w!Q&ewnEPLZ4Yoxrt~G+7b1;rEfqCw-#4&PQ5e&M|{0BdOgO3 z0dgUW5)O8@IS)FAA>r1QXrw03DIXc8mWuhJ6Wyyl&CggtDEH3hG4QLK&jT3^0?_2p z4$yf}g&Zn56x!XzA8nOW`Z7?j3y7FxC~v+aI9z=-G~hFHcw>Olha(Z$^pq)Dx5=~0 ziMk)0_kBSb3=|qK`3GWDb|D;Qv_$fcM}W-t z*@z$!#|`&@{BPPEn(K}!()hM7HqN-~{pZEb*hJ7CgpJ-g;f=-1KXH#w%Bo>h%YUO@ z$d~%w3#BYPS@593++Ub`7WD@+=8Kd(ST*zhs7mYkLFqiv{_WMNV@U2mvXM{!puq!< zQ`1tWsPsNX6XLZbw}jUrG{LlP9(-I%-X-`3oadaKrJc>K3Cudi+v7!RF3%OutEY(6 z%8aFs>bshLx!-#?a)Wr`D}^Wn-vpVkW8hq|V3)h;c$W)od8t5$(#)G%BU-aJrj#gr zU_=*UJi?;^t+nbBj-0e_{qgo-B?u{iBr4ul*T;AWufWRl7-4IyLPF(RDeng#2-670 zN&MD5B+up5L=2r4uXg8H9r)b|adoXo3S!4tj^)RrDYaemFL#gY)jPk)5D)GT&QcJ) z8I?Q3KcI%cy9n`-c<^67Y(Nsp9lN8c-y=d3b$`vd;QTEs$~TY=CN;h1!wm32V>)8g ztLO3sXEF5|xh_UAi{oNP08*)ZrGKWB1Q}Fw`1?y2`Ss<=6UFIzmuI<Dc^))fm-Ud*XKC4gaYh;PK4tgip{6)Kf#j>?QX?p%A|`T*T^F9P ze8ch<9$6j#OZSR+ZM@{D_1tqQwP3;RE1u_H`iZ9(!n zt9FWdM*`je2wovXQMECH83Z%cwoXy+-N9{y)k=ZJXK8bKRuzBzZ$L-pz4xAMtUNuO zmq!J);Wqt>rOY&xBvMEI;BIa@V)G>%Q#otkjUJN*W)23Cahc830GP9w;Y1zI_dSSe zlz(|DG6s~S;9B9Y#o^V&qu^XJd?KPyM3!yLh#(qT>l2zI zJZm3vMddh@uc%YU@wnQyz}7T{+OD*3pzLMT{dyOq=3CMv(FJS;X;6)`fbS#y`tQ1l z5Iq+SR^QO%LZ^?aW;v0J z^#o!t22vy$(!I&MLnu2J-1O(zyDVI2wA$Ve_2fD{i$uyA<`8#Qyjkrl8Jy27tOFC3yta}CE-($?6;MC@ySr6}9Uk82ZT=0*koYcvZ%$Ymvy&0(pDLId z^t9af#*Wt4QSyxoZe^Op?A@@>>#KezUYBGoy&(lOe?Vbo-9 zKM-DV%&<3ah-Ofs^%~35Wd9=n_=~xMSJ&n&zrWWwTYP<4VD5jfTqcRW&zy9bnVAl> zMlG@r9A1QCJgIXsC>`7mYS0*6g$Kk_%Y6MN0qnP>;ty=6lnKkqjvNk*$p_O#jm7bJ zn}mJ6^U+kig#<2@3U!jm*eM?co&+G-P9xycmRb%_+%9&f$!TQ%_hlm?-8+( zbNUT;MU+ieZL2V{MV5+GJE|M@8Y1Vs&(+<#_Avk8P7gMdy{_51pCol=krmd?#aJCa zF$g^(J>m93dGZNNQwu;|7~P}0`;j!N9SlOyEN#UU+L*3l98445CdWzzgrz6o%%K$u z#tRj#w3{P^gAF&3w$4)L;|*fTS43S0D&=tnai6COld=*Xc`qMLH6l`+h%CZ$qi3YbCwhjtnsIf8a;{MW}#b-CQUJhBmQ{cUY7gKQI&_uB z?I#F(xyl*hd-I`;)dlh~Ah5~~j zIJdR-A!^~>G`f6ND$+AN_D7@0*as(~`(X2VhmG`ey!r0X_0c(pOu@AyUzJr3_*i-z zeH8KWJl+~(WD*|%qwy5;RT<(KH3s?d1jxDPi*$Gi7}YU>0TCyB!X2o`D1Z#jx#|vB zogDGGm!=cG<1p%aKRQ|Qwd$nGaK-+*vq6^jiQ~y8EW?-2%T*8@fn++>s=QC1XA?jX z*V`EkU33=LbzSqK!p>*fJx_#~ki-0RE5rBxCLbVjY_!e{xUv7=&L4N3iEP~B>Ly^<}*ULWAizbhq zNqw8?(eHAtD-NjG9$^N0G8@O67KH|PT;qj5%x{`FC(BlR3iVUxJa1XYvz}g4Xjq^} z{lGyq+4~7hrmwwccsniva40~$qO4b@uTPi(C|pX-Lt`USXgk&`AB}H{_bi9A(b8MD z7iGv_Rq|SmJ^)Vse^5U}I$jhrdt#)~Dr2!!ZtF++s(BxVMEXKqw)2w=owo)RZ4FOM4zt>sSgXVMRrB(Dom-7kbWckP|AHGp}l z!0qeVvqW%o9b_;fXIj?*iLo0oubu9O{bP!@%@uTr2L9v6k@;!`(B`KJ>i}Z5AEa7} zU^D`W4X42ZSS}-Sb^z6n&|+9I#5!HlYu4^QSoO98uVNqY-ImwW{i+d19M^yPwU6aS zX;w3lL>2xHaAGuD)UC^Gov}X*a!kX2qi%7TzIVdbRAwMADR~PH?9R|)g0SM%+{4EG zZpF5y&wK|TUt~(h(oO;+t;u2zJv7mAusRI^&S5cL_?e`zZCJQC0glw<{`yGO=XZDG zCIo=2S}?^@PHeWydcq}|W1XNW7Avj2YdN^ihy+v%t&iOh7}fcP9&kj*t%rwwzXM0- zK?cAB_1Fn$TvyUWjU+NQ?THhx9}Bz#6+aai;c3RP?0*lb-I!QP`S)DIL|pLNkJz4G zPPawyR$dkB*2$$mlD)V*{k<)8gmSWlyd8_;yn*0Q=?gk{M?+2;y6b2!;ECrlFo=C7 z(kX(wyWo`L0QTsalXkOr-BC@4|AaVxM_;oK$mng_9kJ_!3K+>#6pOUEIZ2!0O#p$+ zg?+D6;A7baSW`y5ry!^Y0fdIyr}AoZ1O#-kA2Fv^Ba9^oKVp$M14TWgLF&^9KaaiN z51i4+#MK(VmT_OH1#84y(2r5hoq@{{=UMTv7Tq;5*Mp5|Ld}Y94>n6<6BBlaMKMmF zs27`R2e-mH_8X|B@CI-y6c(6ZOSZx4@R^|9!gd z=1%~?HehEu=>B0n>qWl%mmL?pKuU59SnyB=|TAh;tJ~QVfAU5^423?Fh zi2$7ne!_bq)+oT?T?R$opdhXWIiF!O$~fJ4bBhxltdYOeG0R6323Ccn5ZG$ef%II+ z2(m4FuYAQ7?{bJD1X@yPJJ)QI+pTA?QHRJkdq z%0X>?r{j!$<3Y&hD7PjrydT_#q9YA^w>6T7ooEejhH}~--@yxr&I)j?XJO(h{-y6& zXuByc9}<}-dX*W3#2)K=qP>poma`W$MgA7WZJnuBpq?b;!J%HHZOZcv^66RdiG#rL z-onC;4)wiuU)m`0^@*@*TO^Qf^4M4Jp+f%&qLL4TbDu0*q4c#*u5{je7=&t~*W~H` z%*%Ba@SMz!#sTwhVdqm<01j~27%2@ETbXz>$@b-~>D3U9Xr;!36$#ZZ@L~kMvR>a; zvOsSFmf*?0IZ$qE=x`%^+QN@mI^HWh>5n$kZxncSt9s{?_%#3h4F==L_X|2KB7lEk z7Kk7EB5deCeos`_r56OrO>?~T|M<$jK%pDpeQ}sUgNhf{@}K{NoK?TlLTPk0q+r?p zf7c-aw0$TSk_^R)gRM?1N`7`%4?@CRJnArLFWpP)mG@)al- zcN+r0*kSB2*8jMD6_aj+&Eb1WO8@8ISe@EDQK1C^Bjvv@Gq7>~%FMoqWyLtn~Wiq}u6I66u3we{=XKVOML5 z`~W*Rm#wpv%jG$&_%SRKd4DzWbmJg`D3vbE{%;7f2VzZ8ZR62tr9t6Otpd(l52x=8 zy!sb5i+o(bH-aTFx0(h+AP%~>^`pS zadXlE@;F7QysNNy1_LHLwaYdNxv1U3LLL6bB(7%DbTjL1#-CeH!-2STPqaaitW&(6 zwYeP5O2<*^Q+yptca3_-3vQXqo&r`^A&eOaHi>`>VrJIwt7Xc+*W82=I0H~ z3ncBP*=ZEGRJ(TBU|rXDSFu2+qEkR*)IcQTL7?=*>`%qmsk$9l>6uBM?d}#(AXrfR z6Pgr4bFnJ~4ciUy!PPUIUX4B;ybFe3wzZjNw{NtO|Dzx;+nWcaW>~P?$hp2wHM(M+ z@VoyB*%$;+-L(mr^BN|bWlU4}Z`+!CE?WqF2{&%a^L0+A>B|cLEW2gIVA{kBfCQW8 zS!*mdU-@H__>1`LycG&3|Ia^R=3-|9aBc|;Au~FYp4HwE^(Q#r;!niU{Q~>Nk^U~X zww4dn2dF0LeiTH*xyW1NYAwpt|15o6B2d)yuVet8vg{tAeZ zg}272pZ&A4!~Q(N63qEvS&B)k{61WKFq{jC0F6-N=}Jq!lD9%2lll|H|Nd}ChGl;e zJH6_+k6K2TKv_{5aK#q>@t>$wE0*!YlmZh12IGi>o}nWcs6(YwZ39~8ln$52mg`Em z5&!+Ca2yTFW%&{Gq?v%*GXL`!|Ns6IfH<%h$bqxQAu3Gw<-gtrwISaN(C@U>Y;a`; zwCQ#76FTsUJ=p%}lrViQW~z&vB!6-I>+KRS5wRk2n!$rVr8mL{ir+$u20I59lcgD- zDXQT$<2O-&arFmfSl(V=d{1Jh0*UE5Ic^;s=7J}+$bD(Ttpz2Bg02X!q7cRkket>9 za4zv*G2sxiA%H#_hf3$Q+}~$U=Cywb`kx2=oI`xCB>xZq;rUS;hc_Rrslln|aK^s% zYERJZ+WPMH=9^L$%5LonHY3#~FZJ_3cfi2I^9UT|;=8kT5X=1UcYjxEaIWFz0_Da? zPo2rqI<0uGJ3P(`c^obRnMNmg{?x2nP_c91gwTSPbl9e~fbVs!lO*-Me+4)61k*l$ z6fA#}9)C`A|FwbNV_zS%K7FX9r1UyXh#&B^-T}OlKl&U{W%`6jq59qjQYumP0MJ+u zdyV)%?+{Z)*VbwhMsfdV9jC+ceX^(L;l@ZGk0kvBJdf$qJhvD|j@YL|CD`EG;wP-L zjSi%8odA|ep?Ze)uT7)ErdNxQB4WEh9CL0yRo+S!jUbySpm4|F!dXOxKCncU58>i5n<0r2)IBy05 z!ZaD+P)X|QrW}Qx!9QwN#wKVGcY;A`A-iay&0(GY+A6t`bK?aTy|6EPH+53Xce2{$o+rNGz+>3h-48O6MuFU)Q_ljIxT3Yi%piW$sV5rjH zxXV8f`L`N9WrM>KA~3@s;!LOm2zs-YEof|k=fVFfF%PECd{Zk(`1c=)ZyHBi3c^9W zI6@lvie%u2l`VrjT4;GDazT7nu@vuq%3FroiSw_wij}IBrctcR&&jR)%l==-Aw!&I zn(KBELW#`YG_vY9gju^A}UrZy6y0xVYrrKLUPXVyOa%5rgtT+>he`5KZH$FN^ zcK!{*=#Y#~#-Efv_p@bDF)1*a45Dg3kd$TGXxYq{wt2+(9o)ZlWu#6374)kpa>ppo zSokU-hr*NfOsNQCiTl@>eJL zD~MStUk)8Bi3WH~7N8iw)hg^p?e{tP+J=C0TWAl37bfUYlztZKF8ehR6hvL?xC>~< zrIsVKfXzz^z^nFJ$CXltrS>l;@$d-Qk&y>DB;Ns&2Jpfia$LuM7ASF8MEHvv&y#+` zcR*@x2sDH4z-DtF43@(1;%94L=Yz0{VM3Y8J5a1_WI3qqTvb z-;}6ED?}8=^3^(kJ#usmjclg-!7`jAXA?e!%`Ga7@1HL$=MYQ{-u~-!ktQwnCE8LTy+H-clV3s|Et(-f2w^e{ zbT734jrsIU3f-vz(0uQlR*22#W9Sra(}6wt4>?$WnlR{f=E%gigZX0qAi`w0 zJ%j`(fuJ}@;^2-tG(%WYM3Zt-hj&{>&h2f?4+h>83v`<%TQ7;w>EH-duO;%6qZ zfa^{eprCi_7Ey}&3IUJ(C{V^w2?$JIdl`f6+;Y=$?!ga;HGg>Bn#nx2h!iRC4X_03 zOmA802sHsTpg~+*5U>8k=U`lH@o&0y9319@HtmR^R1P$&z|D%6#=7P9vHd>->6?^ z4BCL5BbOutY`e9D!&wbhWC*V4Cfx_a^}5~@a(Z>{?=^#IMP}dbOQ?d`ga?3>_Spe% z1Hn<4@7oga^5LL@^4A6w*uqWMwS*g#z~6A*`*dTZk}Joaqnsm~*bO=rDdx2b;NU@r zEWi5aYnkye!wsBhiP;Gp%XPt7+@Fsh9Zk-U2S&@bgUkT}B;cihfyO4R1e$D|G%uLC zW}1BjUH9f~WsWuT-S!t>;6DKwfLXg*EoPD-34V}4h1mcb(8b{s^UpqIP(ix5FcfRp+>L~sPcgvM zJA-A!gz}Nb5Z`Lli_q0z^7{v1qX-VwvhNryTd9G%2!*{l9bl<^LvIuR>sR~Po&eg( zXk1*G!6v*Kq}pBdzhA6h<{g>Ud~qut5D-~lp5otA+Ns95JJvb&l((HcR7$l-d#upd zF;+>Q%Y=lgj}WP>7r^Qq!L$cd{~VB=A0M8!h-(pEPcBIUL15?V)ii=mK zl=vD@K8BBs;%Bo?(Nl5b%sX?vv2@XBCcs;mSLNbd1dftiK2QGdy9MYZ20YYVaU$p6 zg%rr9)bwB(?f9AU0_j#Y? zet!4w{@wR8J?ge=F~{+Ugz{{WX)ZfhvvKwP6V=D5WusWq4Af(`2f?~aikKAJ8syBr zET=&%>%Y3b2iuzs(@@N<^9@1 za_1;uC=*Cb+*XYmzWuM7eF(*l-sWmA=Gu~Er`;xU{_zR1Cq8zfpn7VO4J&(8W^i4E z`#{KbzI4=4iUq!y>`g~4CL_ncX`Zo1OO9{ipW1X54bNR?K$>jEzl3NJdZZR&pB($g z8kOlSLHmp~*6E2JYtPnw*+5bC=W(S8T4rronR6J(nAP6mG4xCbE;mt7-g<9kelk^a z4`=;0T)fBm0VeTkNAOSjTO+zaX z!Q>lrka)~qeKO3a#p(I&#iLe|sVjTPj7{1)W+rq(GL$1PT}?t_M3LR-t^I^)mi1wJ zj8q7(R9bjLgSbzQ9;#}H-8`RpYIs_mdkaWE@fEja&JJ#OegK&Q(uukZmi_Zv^m6iEH#dM?Kt^{%2TeM*ka3-hgQI-n6pQHWy7cxWYYiwkzKQFjn zkJkUPS0VD3GuR8%DGPF$Q+jyA^T=X=cis7+A{v5+($Hu4`S_fVzpJ@483m619ymDs z;AXIPd{qOnk(~q@OAIK@oGojt$yV*`1=yLFb$O(duIvdx^{C*hBQ(rR*1r=&Kgdv) zt;a*6qy28`m^~=6LG3)SO??qdq=)z(S~5;&{%Z_n``b<7CROy=is1FD^0C<`vvpkL z=s@Siz~4Zj3Tszy(diCq0vt*5&uJI;t@q z53fqrG21(Xt2L7nv)D)fI*qDo_GP8sK+zt4pdIZo3QX%I1QOL$2h7{&qSYR=U<9fME12SUmrp}F zX3~4_LI0kI*fe|e!z9~BqUS?Yg9bTIr=^w#R;`N5+ZX+E31gTf^Bg3#hoK@X?{&O! zS~QSXj=%$wcYX$1P%*XbbLEU+r49#ER8Ci~R+K}$*;kd?X{cvq{6^%| zb|X;KaD5fd;|q{ecz$|KsIfThY<7rQ(J<+HFRUT zE%1)6Zf{tuD_S$MK<|Fpb!FkST9eIqA70^(EEmzZ>FM;~a?M9kLOkTsEpQxWRo3Gz~>&@$@=xRr~c~#MPFJm@3Iv^w?UGK&sYdm6fN=_cWW}Qe$q=@^4lWEV_6rh?1$99?vRf;k>-ld z7aQf?R#{o97Zb%*1=$%l!hUz?ew2GQYWyxDB!;l7Qf8I>)Hr)KRC#T1FMLsAXS!9J z;mlw#z#@?^lp+y&P>s)xk&IILljYB^y|NES7ZIClueNEdD)5)yEpoS^M+$^k*_Ne- zf9!oM9JWi5d1Zk$V1Wg1^a#b9L|mC46?!(C5hjIi@yxyciX&Btsk3t-GjMT`D)@kG zQnfz3gGQ@_yq5RAEuokLogA$3TH}4QP)vqcRIdjxh(KtDS|Dpjzg4?`KHQyk6orWN z3RS#yuqNNYZePGtiz<0qy=8{o2OJmodN*Se*#ezMnwVb9y>DkqQ7oUNTXXf@htTA; zRX>&`IPW^hm5<$eASL6IVGrCEMFaQA6`=Di{Ci1+oQJ(?$8NN44|-Vg;usXAZ|uy` zOV2SNE*!XG{n&60)E5g=WliQ0D&8Y3fVMbD$M3Y=KC)F@#@m(y>b&JSITi8l0ksR`F(Ys1d_*%o)9|Iy0v|=*XYr7Zlj7Lg0LBZ{NbyfD^gE0)l#{RcJ@g2taHr?TGJv`-U*6Z90H6O1#0tAVAVNW`^+}y zsQ5mFhFtFCdkxny*|El$pZW9_r}H@pu3hnBt*FnxGCic9h>u(DiVI4X$=e)ht5Vqg zQ2BPZi*;x!Z|}R{!z#6qq(XN01WDfdz|$D2kfja3P_R=!p!eI$D}{FTB8c?{^tJ?X6u3QM zh%OBLWtT#g#R$ix6_CPpG^Yy{AFe9&k7aAc7fw`4eVVG=#rM8-iFaKPWNPqZS5hz7~4fPvEZ0A zf&bJ_ZsOoSK!FT{FL3yXIkm*PlpL(<&_?LAjrGDZGBN_iuSD-z#LkRT)$}9<0fEQC z(^KJoypQJ1EiEags_{W~H5c=Rb~b3gn9hfz+zHq>!NZOb$q{`ydR!MjcC&#q(*k#- zMO+#3M?+w+1yake!_l+H=FvH_yDZ2vzb_SO2)MW;CrSQYZDqu_I_0uvaEUTEFYlFXf##l6tEu}+8TZ-4UXBwg#VPuNT%&idvX`i^hJ=N!pyICq**{w6Ay4Hxg+9qDhR@ z6;o+RaVnNvisIbuwv|YH1p;Y*B%yG_m>B4%t9UafG* zLIP21s&dJI@bBR&&x|*BIqpMsG7&c53E3`yL%@QcG!Rx8vdeI|3@3eu1XcsZMio`EAOgN81fmO-BfO$i-5al1=N&T%i zO<5Jb#zx~5P%8yo6Vn!BzIOTYgZf+M|RWqGS2I?UI(y zaw|%)=k�-grjlGG3vxu0KdnSfh9QwFfI^7D)W)Q{H1Ohn2e%FR!E{FIq}3(J_05 zlH#&I-454Y!SA=`Gm#$%oOV%+p~PUSHU=g-nvwX3j0+=a8Tk^4n2iC%U<{Ci52Wc! zY>XX&z=KeUNV~OdV^%OX3IFd$5h%Keo;6UF=jXpZufEZmADty_7~lW3{{_rzqJ}Mh UE;-e9o!SD;;FvL?SjRr>KRBYTSO5S3 literal 80139 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 II=ImP2bH%#tN;K2 diff --git a/docs/howto.rst b/docs/howto.rst index e424f44..d13d068 100644 --- a/docs/howto.rst +++ b/docs/howto.rst @@ -14,8 +14,8 @@ The search algorithm is specified in the configuration file. .. code-block:: yaml - properties: - search_algorithm: aizynthfinder.search.retrostar.search_tree.SearchTree + search: + algorithm: aizynthfinder.search.retrostar.search_tree.SearchTree This will use Retro* without a constant-valued oracle function. To specify the oracle function, you can @@ -23,11 +23,15 @@ do .. code-block:: yaml - properties: - search_algorithm: aizynthfinder.search.retrostar.search_tree.SearchTree - molecule_cost: - aizynthfinder.search.retrostar.cost.RetroStarCost: - model_path: retrostar_value_model.pickle + search: + algorithm: aizynthfinder.search.retrostar.search_tree.SearchTree + algorithm_config: + molecule_cost: + cost: aizynthfinder.search.retrostar.cost.RetroStarCost + model_path: retrostar_value_model.pickle + fingerprint_length: 2048 + fingerprint_radius: 2 + dropout_rate: 0.1 The pickle file can be downloaded from `here `_ @@ -40,23 +44,23 @@ can be used together .. code-block:: yaml - properties: - additive_expansion: True - policy: - files: - uspto: - - uspto_keras_model.hdf5 - - uspto_unique_templates.csv.gz - ringbreaker: - - uspto_ringbreaker_keras_model.hdf5 - - uspto_ringbreaker_unique_templates.csv.gz - + expansion: + uspto: + - uspto_keras_model.hdf5 + - uspto_unique_templates.csv.gz + ringbreaker: + - uspto_ringbreaker_keras_model.hdf5 + - uspto_ringbreaker_unique_templates.csv.gz + multi_expansion_strategy: + type: aizynthfinder.context.policy.MultiExpansionStrategy + expansion_strategies: [uspto, ringbreaker] + additive_expansion: True and then to use this with ``aizynthcli`` do something like this .. code-block:: - aizynthcli --smiles smiles.txt --config config.yml --policy uspto ringbreaker + aizynthcli --smiles smiles.txt --config config.yml --policy multi_expansion_strategy Output more routes @@ -68,19 +72,17 @@ This is how you can extract at least 25 routes but not more than 50 per target .. code-block:: yaml - properties: - post_processing: - min_routes: 25 - max_routes: 50 + post_processing: + min_routes: 25 + max_routes: 50 Alternatively, you can extract all solved routes. If a target is unsolved, it will return the number of routes specified by ``min_routes`` and ``max_routes``. .. code-block:: yaml - properties: - post_processing: - min_routes: 5 - max_routes: 10 - all_routes: True + post_processing: + min_routes: 5 + max_routes: 10 + all_routes: True diff --git a/docs/index.rst b/docs/index.rst index be2a965..1ea8fea 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -73,7 +73,6 @@ whereas if the SMILEs is provided on the command-line it is printed directly to stocks scoring howto - training aizynthfinder sequences relationships \ No newline at end of file diff --git a/docs/stocks.rst b/docs/stocks.rst index 9500c09..a100a30 100644 --- a/docs/stocks.rst +++ b/docs/stocks.rst @@ -17,10 +17,10 @@ By adding these lines to the configuration file, the Mongo database will be used .. code-block:: yaml stock: - mongodb: - host: user@myurl.com - database: database_name - collection: compounds + type: mongodb + host: user@myurl.com + database: database_name + collection: compounds If no options are provided to the ``mongodb_stock`` key, the host, database and collection are taken to be `localhost`, @@ -91,7 +91,7 @@ is known by the python interpreter. .. code-block:: stock: - aizynthfinder.contrib.stocks.CriteriaStock + type: aizynthfinder.contrib.stocks.CriteriaStock can be used if the `aizynthfinder.contrib.stocks` is an existing sub-package and module. diff --git a/docs/training.rst b/docs/training.rst deleted file mode 100644 index 9be7a05..0000000 --- a/docs/training.rst +++ /dev/null @@ -1,161 +0,0 @@ -Training -======== - -**------------------------------------------------------------------------------------------------------------------------------------------** - -**The use of this functionality is now discouraged and the users should have a look at the AiZynthTrain package for training their models** - -**------------------------------------------------------------------------------------------------------------------------------------------** - -This page explains the training tools available in the `aizynthfinder` package. - -Prerequisites --------------- - -To start with, one needs a CSV file with templates, i.e. a pre-computed template -library. Tools to create such a library is not included in the `aizynthfinder` package, -because it is a tool that has a wider applicability than the tools provided in this package. -There are for instance tools like RdChiral (https://pubs.acs.org/doi/abs/10.1021/acs.jcim.9b00286). - -The CSV file should contain the following columns in the given order: - -* index - row index, this is ignored -* ID - an ID, this is ignored -* reaction_hash - a unique hash for each unique reaction. Are used to drop duplicates in the data. -* reactants - the SMILES of the reactants -* products - the SMILES of the products -* classification - reaction classification, this is used to add metadata to the tree search -* retro_template - the reaction template for the retro reaction -* template_hash - a unique hash for each unique template. Will be used to filter uncommon templates. -* selectivity - an indicator for selectivity, this is ignored -* outcomes - number of reaction outcomes, this is ignored - -If you do not have all of these columns, or they are in another order, it is possible to -modify the ``library_headers`` setting in the configuration file (see below). However, the -``reaction_hash``, ``reactants``, ``products``, ``retro_template`` and ``template_hash`` -columns are mandatory. - -If you change this setting, you might also consider changing the ``metadata_headers`` that -is a list of columns that is taken from the template library and injected into the tree search. -The default columns are "template_hash" and "classification", so if you for instance don't have -the ``classification`` column in your set, you need to update the ``metadata_headers``. - -Training configuration ----------------------- - -The training is customizable to some extent by a configuration file in YAML format. If not provided, -the settings have default values. There are only a few settings that are of real interest to modify. -They are shown in this snippet: - -.. code-block:: yaml - - output_path: "." - file_prefix: "full_uspto" - batch_size: 256 - epochs: 100 - - -These settings control the output directory, the prefix to all files, -the batch size for training and the number of training epochs. - -For the other settings see the file ``default_training.yml`` in the ``data`` folder of the package. - -`Note!` The filename of the raw template library (discussed above) also needs to start with ``file_prefix`` and -end of with ``_raw_template_library.csv``. - -Pre-processing and training ----------------------------- - -First the template library needs to be pre-processed such that - -* The original library is pruned from templates that occur only a few times -* The template hash is turned into a label vector, i.e. the the target of the fitting -* The products SMILES are turned into fingerprint vectors, i.e. the input for the fitting -* The input and label matrices are split into training, testing and validation sets - -This can be accomplished with - - -.. code-block:: - - preprocess_expansion config.yaml - - -where ``config.yaml`` is your local configuration file for the training (see above). - -Note that this procedure will take some time and might require a lot of memory. - - -Once this is done, you can train the network using - -.. code-block:: - - aizynth_training config.yaml expansion - - -Note that this might take a long time to converge. - -The folder ``checkpoint`` will contain the Keras model that you can use as input -to the tree search algorithm. - -The pre-processing script created a file that ends with ``unique_templates.hdf5`` - -this contains the unique templates and is the second input that you need for the tree search algorithm - - -Filter policy -------------- - -To train a filter policy an array of tools are available. - -First, you need to generate negative data, i.e. reactions that are unfeasible. - -.. code-block:: - - make_false_products config.yml strict - make_false_products config.yml random - make_false_products config.yml recommender - - -The first argument is a configuration file, similar to the one used above with the ``preprocess_expansion`` tool. -The second argument should be "strict", "random" or "recommender" depending on what method you want to use. - -When using the "recommender" method it is important to add the following to the configuration file: - -.. code-block:: yaml - - recommender_model: "some_path/checkpoints/keras_model.hdf" - -which points to the trained "recommender" model (see below). - -The second step is pre-processing the training data: - -.. code-block:: - - preprocess_filter.py config.yaml - - -And the third and final step is the actual training: - - -.. code-block:: - - aizynth_training config.yaml filter - - -The folder ``checkpoint`` will contain the Keras model that you can use as input -to the tree search algorithm. - - -Training recommender model --------------------------- - -Training to recommender model is very similar to training the expansion policy - - -.. code-block:: - - preprocess_recommender config.yaml - aizynth_training config.yaml recommender - - -The folder ``checkpoint`` will contain the Keras model that you can use to generate negative data. \ No newline at end of file diff --git a/env-dev.yml b/env-dev.yml index 6ac21e8..48a9dc2 100644 --- a/env-dev.yml +++ b/env-dev.yml @@ -3,5 +3,5 @@ channels: - https://conda.anaconda.org/conda-forge - defaults dependencies: - - python>=3.8,<3.10 + - python>=3.9,<3.11 - poetry>=1.1.4,<1.4.1 \ No newline at end of file diff --git a/env-users.yml b/env-users.yml index 9552730..a69f86d 100644 --- a/env-users.yml +++ b/env-users.yml @@ -3,8 +3,8 @@ channels: - conda-forge - defaults dependencies: - - python>=3.8,<3.10 + - python>=3.9,<3.11 - git - pip>=20.0 - pip: - - https://github.com/MolecularAI/aizynthfinder/archive/v3.7.0.tar.gz + - git+ssh://git@bitbucket.astrazeneca.net:7999/com/aizynthfinder.git \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 8578278..b7a0b29 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,124 +2,112 @@ [[package]] name = "absl-py" -version = "1.4.0" +version = "2.0.0" description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "absl-py-1.4.0.tar.gz", hash = "sha256:d2c244d01048ba476e7c080bd2c6df5e141d211de80223460d5b3b8a2a58433d"}, - {file = "absl_py-1.4.0-py3-none-any.whl", hash = "sha256:0d3fe606adfa4f7db64792dd4c7aee4ee0c38ab75dfd353b7a83ed3e957fcb47"}, + {file = "absl-py-2.0.0.tar.gz", hash = "sha256:d9690211c5fcfefcdd1a45470ac2b5c5acd45241c3af71eed96bc5441746c0d5"}, + {file = "absl_py-2.0.0-py3-none-any.whl", hash = "sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3"}, ] [[package]] name = "aiohttp" -version = "3.8.4" +version = "3.9.0" description = "Async http client/server framework (asyncio)" category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ce45967538fb747370308d3145aa68a074bdecb4f3a300869590f725ced69c1"}, - {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b744c33b6f14ca26b7544e8d8aadff6b765a80ad6164fb1a430bbadd593dfb1a"}, - {file = "aiohttp-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a45865451439eb320784918617ba54b7a377e3501fb70402ab84d38c2cd891b"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d42d7cba1cec432d47ab13b6637bee393a10f664c425ea7b305d1301ca1a3"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee3c36df21b5714d49fc4580247947aa64bcbe2939d1b77b4c8dcb8f6c9faecc"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:176a64b24c0935869d5bbc4c96e82f89f643bcdf08ec947701b9dbb3c956b7dd"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c844fd628851c0bc309f3c801b3a3d58ce430b2ce5b359cd918a5a76d0b20cb5"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5393fb786a9e23e4799fec788e7e735de18052f83682ce2dfcabaf1c00c2c08e"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e4b09863aae0dc965c3ef36500d891a3ff495a2ea9ae9171e4519963c12ceefd"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:adfbc22e87365a6e564c804c58fc44ff7727deea782d175c33602737b7feadb6"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:147ae376f14b55f4f3c2b118b95be50a369b89b38a971e80a17c3fd623f280c9"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:eafb3e874816ebe2a92f5e155f17260034c8c341dad1df25672fb710627c6949"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6cc15d58053c76eacac5fa9152d7d84b8d67b3fde92709195cb984cfb3475ea"}, - {file = "aiohttp-3.8.4-cp310-cp310-win32.whl", hash = "sha256:59f029a5f6e2d679296db7bee982bb3d20c088e52a2977e3175faf31d6fb75d1"}, - {file = "aiohttp-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:fe7ba4a51f33ab275515f66b0a236bcde4fb5561498fe8f898d4e549b2e4509f"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d8ef1a630519a26d6760bc695842579cb09e373c5f227a21b67dc3eb16cfea4"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b3f2e06a512e94722886c0827bee9807c86a9f698fac6b3aee841fab49bbfb4"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a80464982d41b1fbfe3154e440ba4904b71c1a53e9cd584098cd41efdb188ef"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b631e26df63e52f7cce0cce6507b7a7f1bc9b0c501fcde69742130b32e8782f"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f43255086fe25e36fd5ed8f2ee47477408a73ef00e804cb2b5cba4bf2ac7f5e"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d347a172f866cd1d93126d9b239fcbe682acb39b48ee0873c73c933dd23bd0f"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3fec6a4cb5551721cdd70473eb009d90935b4063acc5f40905d40ecfea23e05"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a37fe8f7c1e6ce8f2d9c411676e4bc633a8462844e38f46156d07a7d401654"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d1e6a862b76f34395a985b3cd39a0d949ca80a70b6ebdea37d3ab39ceea6698a"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd468460eefef601ece4428d3cf4562459157c0f6523db89365202c31b6daebb"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:618c901dd3aad4ace71dfa0f5e82e88b46ef57e3239fc7027773cb6d4ed53531"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:652b1bff4f15f6287550b4670546a2947f2a4575b6c6dff7760eafb22eacbf0b"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80575ba9377c5171407a06d0196b2310b679dc752d02a1fcaa2bc20b235dbf24"}, - {file = "aiohttp-3.8.4-cp311-cp311-win32.whl", hash = "sha256:bbcf1a76cf6f6dacf2c7f4d2ebd411438c275faa1dc0c68e46eb84eebd05dd7d"}, - {file = "aiohttp-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:6e74dd54f7239fcffe07913ff8b964e28b712f09846e20de78676ce2a3dc0bfc"}, - {file = "aiohttp-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:880e15bb6dad90549b43f796b391cfffd7af373f4646784795e20d92606b7a51"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb96fa6b56bb536c42d6a4a87dfca570ff8e52de2d63cabebfd6fb67049c34b6"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a6cadebe132e90cefa77e45f2d2f1a4b2ce5c6b1bfc1656c1ddafcfe4ba8131"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f352b62b45dff37b55ddd7b9c0c8672c4dd2eb9c0f9c11d395075a84e2c40f75"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ab43061a0c81198d88f39aaf90dae9a7744620978f7ef3e3708339b8ed2ef01"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9cb1565a7ad52e096a6988e2ee0397f72fe056dadf75d17fa6b5aebaea05622"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1b3ea7edd2d24538959c1c1abf97c744d879d4e541d38305f9bd7d9b10c9ec41"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7c7837fe8037e96b6dd5cfcf47263c1620a9d332a87ec06a6ca4564e56bd0f36"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3b90467ebc3d9fa5b0f9b6489dfb2c304a1db7b9946fa92aa76a831b9d587e99"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:cab9401de3ea52b4b4c6971db5fb5c999bd4260898af972bf23de1c6b5dd9d71"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d1f9282c5f2b5e241034a009779e7b2a1aa045f667ff521e7948ea9b56e0c5ff"}, - {file = "aiohttp-3.8.4-cp36-cp36m-win32.whl", hash = "sha256:5e14f25765a578a0a634d5f0cd1e2c3f53964553a00347998dfdf96b8137f777"}, - {file = "aiohttp-3.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4c745b109057e7e5f1848c689ee4fb3a016c8d4d92da52b312f8a509f83aa05e"}, - {file = "aiohttp-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aede4df4eeb926c8fa70de46c340a1bc2c6079e1c40ccf7b0eae1313ffd33519"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddaae3f3d32fc2cb4c53fab020b69a05c8ab1f02e0e59665c6f7a0d3a5be54f"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4eb3b82ca349cf6fadcdc7abcc8b3a50ab74a62e9113ab7a8ebc268aad35bb9"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bcb89336efa095ea21b30f9e686763f2be4478f1b0a616969551982c4ee4c3b"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c08e8ed6fa3d477e501ec9db169bfac8140e830aa372d77e4a43084d8dd91ab"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6cd05ea06daca6ad6a4ca3ba7fe7dc5b5de063ff4daec6170ec0f9979f6c332"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7a00a9ed8d6e725b55ef98b1b35c88013245f35f68b1b12c5cd4100dddac333"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:de04b491d0e5007ee1b63a309956eaed959a49f5bb4e84b26c8f5d49de140fa9"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:40653609b3bf50611356e6b6554e3a331f6879fa7116f3959b20e3528783e699"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dbf3a08a06b3f433013c143ebd72c15cac33d2914b8ea4bea7ac2c23578815d6"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854f422ac44af92bfe172d8e73229c270dc09b96535e8a548f99c84f82dde241"}, - {file = "aiohttp-3.8.4-cp37-cp37m-win32.whl", hash = "sha256:aeb29c84bb53a84b1a81c6c09d24cf33bb8432cc5c39979021cc0f98c1292a1a"}, - {file = "aiohttp-3.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:db3fc6120bce9f446d13b1b834ea5b15341ca9ff3f335e4a951a6ead31105480"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fabb87dd8850ef0f7fe2b366d44b77d7e6fa2ea87861ab3844da99291e81e60f"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91f6d540163f90bbaef9387e65f18f73ffd7c79f5225ac3d3f61df7b0d01ad15"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d265f09a75a79a788237d7f9054f929ced2e69eb0bb79de3798c468d8a90f945"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d89efa095ca7d442a6d0cbc755f9e08190ba40069b235c9886a8763b03785da"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dac314662f4e2aa5009977b652d9b8db7121b46c38f2073bfeed9f4049732cd"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe11310ae1e4cd560035598c3f29d86cef39a83d244c7466f95c27ae04850f10"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ddb2a2026c3f6a68c3998a6c47ab6795e4127315d2e35a09997da21865757f8"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e75b89ac3bd27d2d043b234aa7b734c38ba1b0e43f07787130a0ecac1e12228a"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6e601588f2b502c93c30cd5a45bfc665faaf37bbe835b7cfd461753068232074"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a5d794d1ae64e7753e405ba58e08fcfa73e3fad93ef9b7e31112ef3c9a0efb52"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a1f4689c9a1462f3df0a1f7e797791cd6b124ddbee2b570d34e7f38ade0e2c71"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3032dcb1c35bc330134a5b8a5d4f68c1a87252dfc6e1262c65a7e30e62298275"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8189c56eb0ddbb95bfadb8f60ea1b22fcfa659396ea36f6adcc521213cd7b44d"}, - {file = "aiohttp-3.8.4-cp38-cp38-win32.whl", hash = "sha256:33587f26dcee66efb2fff3c177547bd0449ab7edf1b73a7f5dea1e38609a0c54"}, - {file = "aiohttp-3.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:e595432ac259af2d4630008bf638873d69346372d38255774c0e286951e8b79f"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a7bdf9e57126dc345b683c3632e8ba317c31d2a41acd5800c10640387d193ed"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22f6eab15b6db242499a16de87939a342f5a950ad0abaf1532038e2ce7d31567"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7235604476a76ef249bd64cb8274ed24ccf6995c4a8b51a237005ee7a57e8643"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea9eb976ffdd79d0e893869cfe179a8f60f152d42cb64622fca418cd9b18dc2a"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92c0cea74a2a81c4c76b62ea1cac163ecb20fb3ba3a75c909b9fa71b4ad493cf"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:493f5bc2f8307286b7799c6d899d388bbaa7dfa6c4caf4f97ef7521b9cb13719"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a63f03189a6fa7c900226e3ef5ba4d3bd047e18f445e69adbd65af433add5a2"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10c8cefcff98fd9168cdd86c4da8b84baaa90bf2da2269c6161984e6737bf23e"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bca5f24726e2919de94f047739d0a4fc01372801a3672708260546aa2601bf57"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:03baa76b730e4e15a45f81dfe29a8d910314143414e528737f8589ec60cf7391"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8c29c77cc57e40f84acef9bfb904373a4e89a4e8b74e71aa8075c021ec9078c2"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:03543dcf98a6619254b409be2d22b51f21ec66272be4ebda7b04e6412e4b2e14"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17b79c2963db82086229012cff93ea55196ed31f6493bb1ccd2c62f1724324e4"}, - {file = "aiohttp-3.8.4-cp39-cp39-win32.whl", hash = "sha256:34ce9f93a4a68d1272d26030655dd1b58ff727b3ed2a33d80ec433561b03d67a"}, - {file = "aiohttp-3.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:41a86a69bb63bb2fc3dc9ad5ea9f10f1c9c8e282b471931be0268ddd09430b04"}, - {file = "aiohttp-3.8.4.tar.gz", hash = "sha256:bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"}, + {file = "aiohttp-3.9.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6896b8416be9ada4d22cd359d7cb98955576ce863eadad5596b7cdfbf3e17c6c"}, + {file = "aiohttp-3.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1736d87dad8ef46a8ec9cddd349fa9f7bd3a064c47dd6469c0d6763d3d49a4fc"}, + {file = "aiohttp-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c9e5f4d7208cda1a2bb600e29069eecf857e6980d0ccc922ccf9d1372c16f4b"}, + {file = "aiohttp-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8488519aa05e636c5997719fe543c8daf19f538f4fa044f3ce94bee608817cff"}, + {file = "aiohttp-3.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ab16c254e2312efeb799bc3c06897f65a133b38b69682bf75d1f1ee1a9c43a9"}, + {file = "aiohttp-3.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a94bde005a8f926d0fa38b88092a03dea4b4875a61fbcd9ac6f4351df1b57cd"}, + {file = "aiohttp-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b777c9286b6c6a94f50ddb3a6e730deec327e9e2256cb08b5530db0f7d40fd8"}, + {file = "aiohttp-3.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:571760ad7736b34d05597a1fd38cbc7d47f7b65deb722cb8e86fd827404d1f6b"}, + {file = "aiohttp-3.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:deac0a32aec29608eb25d730f4bc5a261a65b6c48ded1ed861d2a1852577c932"}, + {file = "aiohttp-3.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4ee1b4152bc3190cc40ddd6a14715e3004944263ea208229ab4c297712aa3075"}, + {file = "aiohttp-3.9.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:3607375053df58ed6f23903aa10cf3112b1240e8c799d243bbad0f7be0666986"}, + {file = "aiohttp-3.9.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:65b0a70a25456d329a5e1426702dde67be0fb7a4ead718005ba2ca582d023a94"}, + {file = "aiohttp-3.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a2eb5311a37fe105aa35f62f75a078537e1a9e4e1d78c86ec9893a3c97d7a30"}, + {file = "aiohttp-3.9.0-cp310-cp310-win32.whl", hash = "sha256:2cbc14a13fb6b42d344e4f27746a4b03a2cb0c1c3c5b932b0d6ad8881aa390e3"}, + {file = "aiohttp-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ac9669990e2016d644ba8ae4758688534aabde8dbbc81f9af129c3f5f01ca9cd"}, + {file = "aiohttp-3.9.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f8e05f5163528962ce1d1806fce763ab893b1c5b7ace0a3538cd81a90622f844"}, + {file = "aiohttp-3.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4afa8f71dba3a5a2e1e1282a51cba7341ae76585345c43d8f0e624882b622218"}, + {file = "aiohttp-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f929f4c9b9a00f3e6cc0587abb95ab9c05681f8b14e0fe1daecfa83ea90f8318"}, + {file = "aiohttp-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28185e36a78d247c55e9fbea2332d16aefa14c5276a582ce7a896231c6b1c208"}, + {file = "aiohttp-3.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a486ddf57ab98b6d19ad36458b9f09e6022de0381674fe00228ca7b741aacb2f"}, + {file = "aiohttp-3.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70e851f596c00f40a2f00a46126c95c2e04e146015af05a9da3e4867cfc55911"}, + {file = "aiohttp-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5b7bf8fe4d39886adc34311a233a2e01bc10eb4e842220235ed1de57541a896"}, + {file = "aiohttp-3.9.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c67a51ea415192c2e53e4e048c78bab82d21955b4281d297f517707dc836bf3d"}, + {file = "aiohttp-3.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:694df243f394629bcae2d8ed94c589a181e8ba8604159e6e45e7b22e58291113"}, + {file = "aiohttp-3.9.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3dd8119752dd30dd7bca7d4bc2a92a59be6a003e4e5c2cf7e248b89751b8f4b7"}, + {file = "aiohttp-3.9.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:eb6dfd52063186ac97b4caa25764cdbcdb4b10d97f5c5f66b0fa95052e744eb7"}, + {file = "aiohttp-3.9.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:d97c3e286d0ac9af6223bc132dc4bad6540b37c8d6c0a15fe1e70fb34f9ec411"}, + {file = "aiohttp-3.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:816f4db40555026e4cdda604a1088577c1fb957d02f3f1292e0221353403f192"}, + {file = "aiohttp-3.9.0-cp311-cp311-win32.whl", hash = "sha256:3abf0551874fecf95f93b58f25ef4fc9a250669a2257753f38f8f592db85ddea"}, + {file = "aiohttp-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:e18d92c3e9e22553a73e33784fcb0ed484c9874e9a3e96c16a8d6a1e74a0217b"}, + {file = "aiohttp-3.9.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:99ae01fb13a618b9942376df77a1f50c20a281390dad3c56a6ec2942e266220d"}, + {file = "aiohttp-3.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:05857848da443c8c12110d99285d499b4e84d59918a21132e45c3f0804876994"}, + {file = "aiohttp-3.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:317719d7f824eba55857fe0729363af58e27c066c731bc62cd97bc9c3d9c7ea4"}, + {file = "aiohttp-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1e3b3c107ccb0e537f309f719994a55621acd2c8fdf6d5ce5152aed788fb940"}, + {file = "aiohttp-3.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45820ddbb276113ead8d4907a7802adb77548087ff5465d5c554f9aa3928ae7d"}, + {file = "aiohttp-3.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05a183f1978802588711aed0dea31e697d760ce9055292db9dc1604daa9a8ded"}, + {file = "aiohttp-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a4cd44788ea0b5e6bb8fa704597af3a30be75503a7ed1098bc5b8ffdf6c982"}, + {file = "aiohttp-3.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673343fbc0c1ac44d0d2640addc56e97a052504beacd7ade0dc5e76d3a4c16e8"}, + {file = "aiohttp-3.9.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e8a3b79b6d186a9c99761fd4a5e8dd575a48d96021f220ac5b5fa856e5dd029"}, + {file = "aiohttp-3.9.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6777a390e41e78e7c45dab43a4a0196c55c3b8c30eebe017b152939372a83253"}, + {file = "aiohttp-3.9.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7ae5f99a32c53731c93ac3075abd3e1e5cfbe72fc3eaac4c27c9dd64ba3b19fe"}, + {file = "aiohttp-3.9.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:f1e4f254e9c35d8965d377e065c4a8a55d396fe87c8e7e8429bcfdeeb229bfb3"}, + {file = "aiohttp-3.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11ca808f9a6b63485059f5f6e164ef7ec826483c1212a44f268b3653c91237d8"}, + {file = "aiohttp-3.9.0-cp312-cp312-win32.whl", hash = "sha256:de3cc86f4ea8b4c34a6e43a7306c40c1275e52bfa9748d869c6b7d54aa6dad80"}, + {file = "aiohttp-3.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca4fddf84ac7d8a7d0866664936f93318ff01ee33e32381a115b19fb5a4d1202"}, + {file = "aiohttp-3.9.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f09960b5bb1017d16c0f9e9f7fc42160a5a49fa1e87a175fd4a2b1a1833ea0af"}, + {file = "aiohttp-3.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8303531e2c17b1a494ffaeba48f2da655fe932c4e9a2626c8718403c83e5dd2b"}, + {file = "aiohttp-3.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4790e44f46a4aa07b64504089def5744d3b6780468c4ec3a1a36eb7f2cae9814"}, + {file = "aiohttp-3.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1d7edf74a36de0e5ca50787e83a77cf352f5504eb0ffa3f07000a911ba353fb"}, + {file = "aiohttp-3.9.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94697c7293199c2a2551e3e3e18438b4cba293e79c6bc2319f5fd652fccb7456"}, + {file = "aiohttp-3.9.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a1b66dbb8a7d5f50e9e2ea3804b01e766308331d0cac76eb30c563ac89c95985"}, + {file = "aiohttp-3.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9623cfd9e85b76b83ef88519d98326d4731f8d71869867e47a0b979ffec61c73"}, + {file = "aiohttp-3.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f32c86dc967ab8c719fd229ce71917caad13cc1e8356ee997bf02c5b368799bf"}, + {file = "aiohttp-3.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f50b4663c3e0262c3a361faf440761fbef60ccdde5fe8545689a4b3a3c149fb4"}, + {file = "aiohttp-3.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dcf71c55ec853826cd70eadb2b6ac62ec577416442ca1e0a97ad875a1b3a0305"}, + {file = "aiohttp-3.9.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:42fe4fd9f0dfcc7be4248c162d8056f1d51a04c60e53366b0098d1267c4c9da8"}, + {file = "aiohttp-3.9.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76a86a9989ebf82ee61e06e2bab408aec4ea367dc6da35145c3352b60a112d11"}, + {file = "aiohttp-3.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f9e09a1c83521d770d170b3801eea19b89f41ccaa61d53026ed111cb6f088887"}, + {file = "aiohttp-3.9.0-cp38-cp38-win32.whl", hash = "sha256:a00ce44c21612d185c5275c5cba4bab8d7c1590f248638b667ed8a782fa8cd6f"}, + {file = "aiohttp-3.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:d5b9345ab92ebe6003ae11d8092ce822a0242146e6fa270889b9ba965457ca40"}, + {file = "aiohttp-3.9.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98d21092bf2637c5fa724a428a69e8f5955f2182bff61f8036827cf6ce1157bf"}, + {file = "aiohttp-3.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:35a68cd63ca6aaef5707888f17a70c36efe62b099a4e853d33dc2e9872125be8"}, + {file = "aiohttp-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d7f6235c7475658acfc1769d968e07ab585c79f6ca438ddfecaa9a08006aee2"}, + {file = "aiohttp-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db04d1de548f7a62d1dd7e7cdf7c22893ee168e22701895067a28a8ed51b3735"}, + {file = "aiohttp-3.9.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:536b01513d67d10baf6f71c72decdf492fb7433c5f2f133e9a9087379d4b6f31"}, + {file = "aiohttp-3.9.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c8b0a6487e8109427ccf638580865b54e2e3db4a6e0e11c02639231b41fc0f"}, + {file = "aiohttp-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7276fe0017664414fdc3618fca411630405f1aaf0cc3be69def650eb50441787"}, + {file = "aiohttp-3.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23170247ef89ffa842a02bbfdc425028574d9e010611659abeb24d890bc53bb8"}, + {file = "aiohttp-3.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b1a2ea8252cacc7fd51df5a56d7a2bb1986ed39be9397b51a08015727dfb69bd"}, + {file = "aiohttp-3.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2d71abc15ff7047412ef26bf812dfc8d0d1020d664617f4913df2df469f26b76"}, + {file = "aiohttp-3.9.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:2d820162c8c2bdbe97d328cd4f417c955ca370027dce593345e437b2e9ffdc4d"}, + {file = "aiohttp-3.9.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:2779f5e7c70f7b421915fd47db332c81de365678180a9f3ab404088f87ba5ff9"}, + {file = "aiohttp-3.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:366bc870d7ac61726f32a489fbe3d1d8876e87506870be66b01aeb84389e967e"}, + {file = "aiohttp-3.9.0-cp39-cp39-win32.whl", hash = "sha256:1df43596b826022b14998f0460926ce261544fedefe0d2f653e1b20f49e96454"}, + {file = "aiohttp-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:9c196b30f1b1aa3363a69dd69079ae9bec96c2965c4707eaa6914ba099fb7d4f"}, + {file = "aiohttp-3.9.0.tar.gz", hash = "sha256:09f23292d29135025e19e8ff4f0a68df078fe4ee013bca0105b2e803989de92d"}, ] [package.dependencies] aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" +async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<4.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" yarl = ">=1.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns", "cchardet"] +speedups = ["Brotli", "aiodns", "brotlicffi"] [[package]] name = "aiosignal" @@ -150,19 +138,17 @@ files = [ [[package]] name = "alembic" -version = "1.10.3" +version = "1.12.1" description = "A database migration tool for SQLAlchemy." category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "alembic-1.10.3-py3-none-any.whl", hash = "sha256:b2e0a6cfd3a8ce936a1168320bcbe94aefa3f4463cd773a968a55071beb3cd37"}, - {file = "alembic-1.10.3.tar.gz", hash = "sha256:32a69b13a613aeb7e8093f242da60eff9daed13c0df02fff279c1b06c32965d2"}, + {file = "alembic-1.12.1-py3-none-any.whl", hash = "sha256:47d52e3dfb03666ed945becb723d6482e52190917fdb47071440cfdba05d92cb"}, + {file = "alembic-1.12.1.tar.gz", hash = "sha256:bca5877e9678b454706347bc10b97cb7d67f300320fa5c3a94423e8266e2823f"}, ] [package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.9\""} -importlib-resources = {version = "*", markers = "python_version < \"3.9\""} Mako = "*" SQLAlchemy = ">=1.3.0" typing-extensions = ">=4" @@ -172,24 +158,25 @@ tz = ["python-dateutil"] [[package]] name = "anyio" -version = "3.6.2" +version = "4.1.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" category = "main" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.8" files = [ - {file = "anyio-3.6.2-py3-none-any.whl", hash = "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"}, - {file = "anyio-3.6.2.tar.gz", hash = "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421"}, + {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"}, + {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"}, ] [package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16,<0.22)"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] [[package]] name = "appnope" @@ -217,23 +204,24 @@ files = [ [[package]] name = "argon2-cffi" -version = "21.3.0" -description = "The secure Argon2 password hashing algorithm." +version = "23.1.0" +description = "Argon2 for Python" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, - {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, + {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, + {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, ] [package.dependencies] argon2-cffi-bindings = "*" [package.extras] -dev = ["cogapp", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "pre-commit", "pytest", "sphinx", "sphinx-notfound-page", "tomli"] -docs = ["furo", "sphinx", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] +dev = ["argon2-cffi[tests,typing]", "tox (>4)"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] +tests = ["hypothesis", "pytest"] +typing = ["mypy"] [[package]] name = "argon2-cffi-bindings" @@ -275,29 +263,34 @@ tests = ["pytest"] [[package]] name = "arrow" -version = "1.2.3" +version = "1.3.0" description = "Better dates & times for Python" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "arrow-1.2.3-py3-none-any.whl", hash = "sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2"}, - {file = "arrow-1.2.3.tar.gz", hash = "sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1"}, + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, ] [package.dependencies] python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (>=1.0.0,<2.0.0)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (>=3.0.0,<4.0.0)"] [[package]] name = "astroid" -version = "2.15.2" +version = "2.15.8" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.2-py3-none-any.whl", hash = "sha256:dea89d9f99f491c66ac9c04ebddf91e4acf8bd711722175fe6245c0725cc19bb"}, - {file = "astroid-2.15.2.tar.gz", hash = "sha256:6e61b85c891ec53b07471aec5878f4ac6446a41e590ede0f2ce095f39f7d49dd"}, + {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, + {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, ] [package.dependencies] @@ -307,21 +300,22 @@ wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""} [[package]] name = "asttokens" -version = "2.2.1" +version = "2.4.1" description = "Annotate AST trees with source code positions" category = "main" optional = false python-versions = "*" files = [ - {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"}, - {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"}, + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, ] [package.dependencies] -six = "*" +six = ">=1.12.0" [package.extras] -test = ["astroid", "pytest"] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] [[package]] name = "astunparse" @@ -341,14 +335,14 @@ wheel = ">=0.23.0,<1.0" [[package]] name = "async-timeout" -version = "4.0.2" +version = "4.0.3" description = "Timeout context manager for asyncio programs" category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, - {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, ] [[package]] @@ -364,61 +358,49 @@ files = [ [[package]] name = "attrs" -version = "22.2.0" +version = "23.1.0" description = "Classes Without Boilerplate" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, ] [package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] [[package]] name = "autopage" -version = "0.5.1" +version = "0.5.2" description = "A library to provide automatic paging for console output" category = "main" optional = true python-versions = ">=3.6" files = [ - {file = "autopage-0.5.1-py3-none-any.whl", hash = "sha256:0fbf5efbe78d466a26753e1dee3272423a3adc989d6a778c700e89a3f8ff0d88"}, - {file = "autopage-0.5.1.tar.gz", hash = "sha256:01be3ee61bb714e9090fcc5c10f4cf546c396331c620c6ae50a2321b28ed3199"}, + {file = "autopage-0.5.2-py3-none-any.whl", hash = "sha256:f5eae54dd20ccc8b1ff611263fc87bc46608a9cde749bbcfc93339713a429c55"}, + {file = "autopage-0.5.2.tar.gz", hash = "sha256:826996d74c5aa9f4b6916195547312ac6384bac3810b8517063f293248257b72"}, ] [[package]] name = "babel" -version = "2.12.1" +version = "2.13.1" description = "Internationalization utilities" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, - {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, + {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, + {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, ] -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - -[[package]] -name = "backcall" -version = "0.2.0" -description = "Specifications for callback functions passed in to an API" -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, -] +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] name = "beautifulsoup4" @@ -477,14 +459,14 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bleach" -version = "6.0.0" +version = "6.1.0" description = "An easy safelist-based HTML-sanitizing tool." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "bleach-6.0.0-py3-none-any.whl", hash = "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4"}, - {file = "bleach-6.0.0.tar.gz", hash = "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414"}, + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, ] [package.dependencies] @@ -492,138 +474,137 @@ six = ">=1.9.0" webencodings = "*" [package.extras] -css = ["tinycss2 (>=1.1.0,<1.2)"] +css = ["tinycss2 (>=1.1.0,<1.3)"] [[package]] name = "blosc2" -version = "2.0.0" -description = "Python wrapper for the C-Blosc2 library." -category = "main" -optional = false -python-versions = ">=3.8, <4" -files = [ - {file = "blosc2-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4085e5c1df186e1747d8a8578b0cc1c8b7668391d635e9f89e17156912fba85a"}, - {file = "blosc2-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cec4c0570543921ce6b8c9ffdbf9f2170de37ecaf8e2b213e867e3130b81f205"}, - {file = "blosc2-2.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fbecd7ef4876811719aa58d84e4b414f430f329162c18578b870f5e77b59864"}, - {file = "blosc2-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96dd63eb7641594208e6a865fd60a0bdde24568a180180beb8af4d6608796f3a"}, - {file = "blosc2-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:659e18d5e606a0ca4d80766f86d87e640818051911d01679eed11022243a7e4f"}, - {file = "blosc2-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c58990ab2bcd0f412496acf1d05c65d955d963197bbaa57b10b2ace31c29181a"}, - {file = "blosc2-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f206e6a01a8167b441bf886ff022eb20e0f085b09300f49f3018f566c14d918a"}, - {file = "blosc2-2.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ec63269428aa3fb45f7d4881b2d11b428c4cb62e854caf54a767a64da4df83e"}, - {file = "blosc2-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98ab1cd57f9d7422f1636a6b290f2940113ee8be26bfe3823e8c011826972b9c"}, - {file = "blosc2-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:54c5614b18f9f01473758fa64e3bc699adbe31b307a45eca0e07fa2204e4d4a1"}, - {file = "blosc2-2.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f465b8ab54ecde6b8654672a50a4c3699aafd8e2de0dfcd84ed53f8a34c1734a"}, - {file = "blosc2-2.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0497793f55db0b75de08eb4c047a0bc5b96dbe5e405b53803dd3368e36336188"}, - {file = "blosc2-2.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5c52649837d514669107c77e8f172e9e5ecfa030eef0d378bb47ce1689921c9"}, - {file = "blosc2-2.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8eb02f67d4ed8ac8f0ce5f3c8cafc0059255bb6899fd35127e4076925640f239"}, - {file = "blosc2-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:32c365bf744353103ed91dc1f03889de03b986588181601594aa7ee773818cb4"}, - {file = "blosc2-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d98e850f0de55e15c402c6e27105ba850f8954e784e30a7f8bde89eb70a08574"}, - {file = "blosc2-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6545d6d7e7365a2a3533d4bdf7095856443aed7d5ddc577ecd0e78083790bff1"}, - {file = "blosc2-2.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c193959a984e7814833c8be6b9026d7744d2cff4d450476561583a87152e13e"}, - {file = "blosc2-2.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea3396de7757092d502fb297a44a8d019d92e750e5aebcd9d39a157fde8785b3"}, - {file = "blosc2-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:ef018926b55799cf23345127dde8f29356b4451b3e067e1b07f0d186213bd821"}, - {file = "blosc2-2.0.0.tar.gz", hash = "sha256:f19b0b3674f6c825b490f00d8264b0c540c2cdc11ec7e81178d38b83c57790a1"}, +version = "2.3.1" +description = "Python wrapper for the C-Blosc2 library" +category = "main" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "blosc2-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70d7b5993ed6af56d2d76a82edd03d06fdd7eb6f735f1daeca63ddbd99bde16c"}, + {file = "blosc2-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f1f0e3f15f7755637a6681e746b760e9d46ed61d8b53fa5e59a1b22b73f67a96"}, + {file = "blosc2-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a690d3ee5d68296874e5069865118f577a0d1dc5697edb19394e174ab88506fc"}, + {file = "blosc2-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a7e9e71daaaa5ab12c9766801a3884c21e8829c07131416faa6bd9c2af5f797"}, + {file = "blosc2-2.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2acd72742a21fe2ad8f77e92bc493af5aecbe62e08bbb7324c5ae1f61d53c3a"}, + {file = "blosc2-2.3.1-cp310-cp310-win32.whl", hash = "sha256:946c755b48cc088e02ddc327407cd9d06f8afd20f315eb4dccdab116b3a1add6"}, + {file = "blosc2-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:b4ba2f1c7af60efb414783fd13b61491e3c542dfe1415c8416210d6759873e7c"}, + {file = "blosc2-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de07c31c65b3abcd62338dcf929f67aa81e9eb8dbaa6b6d52e4dd6a18962a781"}, + {file = "blosc2-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62354c09aa8ba12a63e7dfb23659f40866752eb2f2d3f55ebc65485f9f7cdefc"}, + {file = "blosc2-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d000a6b42044e970de18495007b0a3de2d13385fad3b3bc48c9376b1531a3b"}, + {file = "blosc2-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bd982b437be5a3d21dc7f6dfa1e9febe056be090c21208c8422bb2013d36046"}, + {file = "blosc2-2.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b4f479cd4e7d95eedb69ff72d803a2e8b1eabdc5724b2da7bd5a6f4d73c96833"}, + {file = "blosc2-2.3.1-cp311-cp311-win32.whl", hash = "sha256:be5daf95854fa14eb6c0f1de86f1afe388c9a5cb6dd2be05c31163796bddfef8"}, + {file = "blosc2-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:545c580935b568c8e1b476b75902b27e886d7f7975e1f6e6518b69b063150910"}, + {file = "blosc2-2.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:afb4b46ea0597cc90ae40f51d7bdb9460d91dcfd45f88f89dce89b808b209102"}, + {file = "blosc2-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b392772e333a890bd42abad30ef1ba0dfdd03b734fed001c55382019d8b1c1aa"}, + {file = "blosc2-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b0dfd563a2bbcbc3c5f2f10fec53862a4bc02d0e7057dfb1bec45bb7a26122d"}, + {file = "blosc2-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dbaa098b3c10a161280498a063ea7d381a3b7dbdb17a6c66810372640db9075"}, + {file = "blosc2-2.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f1a0c3e0c95eb88b86fb06b59baeaeff1baf3f6c30da6b7627fc9a7520b4c010"}, + {file = "blosc2-2.3.1-cp312-cp312-win32.whl", hash = "sha256:66abff3be98d9d1399c91a1c6b9aff5bf1c3dc98197d34c9e67d098f575ec194"}, + {file = "blosc2-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:1a973bb5f4ba8f17e094b2aec92679b5d0ce9ef01ca2e4c6373771297f342b62"}, + {file = "blosc2-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ff61c594d96c6830dd5b7928a12d7562330b7e31d89cd4794aea7354c89ae71a"}, + {file = "blosc2-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976d4d4525ab1475414e2dd44375d88da4a5c395b2334c3d5ede0b7fd836f8b5"}, + {file = "blosc2-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba13b4491680d65c4caccffd83d54dcc17e8236b9241710a0cc3cded56a5d9bf"}, + {file = "blosc2-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec79f835cb5bbb6ccd45261de73451976487c9d34a3be39b2b2b2582873c237d"}, + {file = "blosc2-2.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:14d70bf7c7a819b286b0cceca778ecd4f5dc0ca31ee288496e838de6f3d1fd46"}, + {file = "blosc2-2.3.1-cp39-cp39-win32.whl", hash = "sha256:a2ea0b358e60a23138556fdc24abdbf557247280b35445634178f2f0f1241a17"}, + {file = "blosc2-2.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:042164f59f5949745438edcf52a1720e6a142f5494ddba2bdd6646acf88d35d3"}, + {file = "blosc2-2.3.1.tar.gz", hash = "sha256:d76b839ecfe2044f6ba43db9db95d223b37deb9225b5f337718caace62e70002"}, ] [package.dependencies] msgpack = "*" +ndindex = ">=1.4" +numpy = ">=1.20.3" +py-cpuinfo = "*" [[package]] name = "cachetools" -version = "5.3.0" +version = "5.3.2" description = "Extensible memoizing collections and decorators" category = "main" optional = true -python-versions = "~=3.7" +python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.0-py3-none-any.whl", hash = "sha256:429e1a1e845c008ea6c85aa35d4b98b65d6a9763eeef3e37e92728a12d1de9d4"}, - {file = "cachetools-5.3.0.tar.gz", hash = "sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14"}, + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, ] [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] [[package]] name = "cffi" -version = "1.15.1" +version = "1.16.0" description = "Foreign Function Interface for Python calling C code." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, ] [package.dependencies] @@ -631,99 +612,114 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -731,14 +727,14 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "cliff" -version = "4.2.0" +version = "4.4.0" description = "Command Line Interface Formulation Framework" category = "main" optional = true python-versions = ">=3.8" files = [ - {file = "cliff-4.2.0-py3-none-any.whl", hash = "sha256:5538a03299f40f83268ba102ed513c2a693ffeb6ac01de7cc119ae9cfc55e55d"}, - {file = "cliff-4.2.0.tar.gz", hash = "sha256:97fc31e93552e3bec664be9d55ad7f90dc2ab42aad8df29a5b985b644c9b8cf2"}, + {file = "cliff-4.4.0-py3-none-any.whl", hash = "sha256:bcad956095df58956eb6931cbfd99cae607d0dd516c9669b3967e77800ce920d"}, + {file = "cliff-4.4.0.tar.gz", hash = "sha256:aa8d404aa2d6b4d8639c61bd6dc47acb3656ebc3fc025b1b7bb07af2baef785f"}, ] [package.dependencies] @@ -751,14 +747,14 @@ stevedore = ">=2.0.1" [[package]] name = "cmaes" -version = "0.9.1" +version = "0.10.0" description = "Lightweight Covariance Matrix Adaptation Evolution Strategy (CMA-ES) implementation for Python 3." category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "cmaes-0.9.1-py3-none-any.whl", hash = "sha256:6e2930b6a99dd94621bf62966c13d29e6a7f90a909b4e4266010d5f3a7fb74b8"}, - {file = "cmaes-0.9.1.tar.gz", hash = "sha256:d122f8d46377f643a150c85ffc81c4e33909a34cfdcb522ee7a6fb17ea4f232c"}, + {file = "cmaes-0.10.0-py3-none-any.whl", hash = "sha256:72cea747ad37b1780b0eb6f3c098cee33907fafbf6690c0c02db1e010cab72f6"}, + {file = "cmaes-0.10.0.tar.gz", hash = "sha256:48afc70df027114739872b50489ae6b32461c307b92d084a63c7090a9742faf9"}, ] [package.dependencies] @@ -840,158 +836,146 @@ development = ["black", "flake8", "mypy", "pytest", "types-colorama"] [[package]] name = "comm" -version = "0.1.3" +version = "0.2.0" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "comm-0.1.3-py3-none-any.whl", hash = "sha256:16613c6211e20223f215fc6d3b266a247b6e2641bf4e0a3ad34cb1aff2aa3f37"}, - {file = "comm-0.1.3.tar.gz", hash = "sha256:a61efa9daffcfbe66fd643ba966f846a624e4e6d6767eda9cf6e993aadaab93e"}, + {file = "comm-0.2.0-py3-none-any.whl", hash = "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001"}, + {file = "comm-0.2.0.tar.gz", hash = "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be"}, ] [package.dependencies] -traitlets = ">=5.3" +traitlets = ">=4" [package.extras] -lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"] test = ["pytest"] -typing = ["mypy (>=0.990)"] [[package]] name = "contourpy" -version = "1.0.7" +version = "1.2.0" description = "Python library for calculating contours of 2D quadrilateral grids" category = "main" optional = true -python-versions = ">=3.8" -files = [ - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:95c3acddf921944f241b6773b767f1cbce71d03307270e2d769fd584d5d1092d"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc1464c97579da9f3ab16763c32e5c5d5bb5fa1ec7ce509a4ca6108b61b84fab"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8acf74b5d383414401926c1598ed77825cd530ac7b463ebc2e4f46638f56cce6"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c71fdd8f1c0f84ffd58fca37d00ca4ebaa9e502fb49825484da075ac0b0b803"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f99e9486bf1bb979d95d5cffed40689cb595abb2b841f2991fc894b3452290e8"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f4d8941a9564cda3f7fa6a6cd9b32ec575830780677932abdec7bcb61717b0"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9e20e5a1908e18aaa60d9077a6d8753090e3f85ca25da6e25d30dc0a9e84c2c6"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a877ada905f7d69b2a31796c4b66e31a8068b37aa9b78832d41c82fc3e056ddd"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6381fa66866b0ea35e15d197fc06ac3840a9b2643a6475c8fff267db8b9f1e69"}, - {file = "contourpy-1.0.7-cp310-cp310-win32.whl", hash = "sha256:3c184ad2433635f216645fdf0493011a4667e8d46b34082f5a3de702b6ec42e3"}, - {file = "contourpy-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:3caea6365b13119626ee996711ab63e0c9d7496f65641f4459c60a009a1f3e80"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed33433fc3820263a6368e532f19ddb4c5990855e4886088ad84fd7c4e561c71"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38e2e577f0f092b8e6774459317c05a69935a1755ecfb621c0a98f0e3c09c9a5"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae90d5a8590e5310c32a7630b4b8618cef7563cebf649011da80874d0aa8f414"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130230b7e49825c98edf0b428b7aa1125503d91732735ef897786fe5452b1ec2"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58569c491e7f7e874f11519ef46737cea1d6eda1b514e4eb5ac7dab6aa864d02"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d43960d809c4c12508a60b66cb936e7ed57d51fb5e30b513934a4a23874fae"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:152fd8f730c31fd67fe0ffebe1df38ab6a669403da93df218801a893645c6ccc"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9056c5310eb1daa33fc234ef39ebfb8c8e2533f088bbf0bc7350f70a29bde1ac"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a9d7587d2fdc820cc9177139b56795c39fb8560f540bba9ceea215f1f66e1566"}, - {file = "contourpy-1.0.7-cp311-cp311-win32.whl", hash = "sha256:4ee3ee247f795a69e53cd91d927146fb16c4e803c7ac86c84104940c7d2cabf0"}, - {file = "contourpy-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:5caeacc68642e5f19d707471890f037a13007feba8427eb7f2a60811a1fc1350"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd7dc0e6812b799a34f6d12fcb1000539098c249c8da54f3566c6a6461d0dbad"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0f9d350b639db6c2c233d92c7f213d94d2e444d8e8fc5ca44c9706cf72193772"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e96a08b62bb8de960d3a6afbc5ed8421bf1a2d9c85cc4ea73f4bc81b4910500f"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:031154ed61f7328ad7f97662e48660a150ef84ee1bc8876b6472af88bf5a9b98"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e9ebb4425fc1b658e13bace354c48a933b842d53c458f02c86f371cecbedecc"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb8f6d08ca7998cf59eaf50c9d60717f29a1a0a09caa46460d33b2924839dbd"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6c180d89a28787e4b73b07e9b0e2dac7741261dbdca95f2b489c4f8f887dd810"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b8d587cc39057d0afd4166083d289bdeff221ac6d3ee5046aef2d480dc4b503c"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:769eef00437edf115e24d87f8926955f00f7704bede656ce605097584f9966dc"}, - {file = "contourpy-1.0.7-cp38-cp38-win32.whl", hash = "sha256:62398c80ef57589bdbe1eb8537127321c1abcfdf8c5f14f479dbbe27d0322e66"}, - {file = "contourpy-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:57119b0116e3f408acbdccf9eb6ef19d7fe7baf0d1e9aaa5381489bc1aa56556"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30676ca45084ee61e9c3da589042c24a57592e375d4b138bd84d8709893a1ba4"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e927b3868bd1e12acee7cc8f3747d815b4ab3e445a28d2e5373a7f4a6e76ba1"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:366a0cf0fc079af5204801786ad7a1c007714ee3909e364dbac1729f5b0849e5"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ba9bb365446a22411f0673abf6ee1fea3b2cf47b37533b970904880ceb72f3"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b0bf0c30d432278793d2141362ac853859e87de0a7dee24a1cea35231f0d50"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7281244c99fd7c6f27c1c6bfafba878517b0b62925a09b586d88ce750a016d2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6d0f9e1d39dbfb3977f9dd79f156c86eb03e57a7face96f199e02b18e58d32a"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f6979d20ee5693a1057ab53e043adffa1e7418d734c1532e2d9e915b08d8ec2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5dd34c1ae752515318224cba7fc62b53130c45ac6a1040c8b7c1a223c46e8967"}, - {file = "contourpy-1.0.7-cp39-cp39-win32.whl", hash = "sha256:c5210e5d5117e9aec8c47d9156d1d3835570dd909a899171b9535cb4a3f32693"}, - {file = "contourpy-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:60835badb5ed5f4e194a6f21c09283dd6e007664a86101431bf870d9e86266c4"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ce41676b3d0dd16dbcfabcc1dc46090aaf4688fd6e819ef343dbda5a57ef0161"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a011cf354107b47c58ea932d13b04d93c6d1d69b8b6dce885e642531f847566"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31a55dccc8426e71817e3fe09b37d6d48ae40aae4ecbc8c7ad59d6893569c436"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f8ff4db108815addd900a74df665e135dbbd6547a8a69333a68e1f6e368ac2"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efe99298ba37e37787f6a2ea868265465410822f7bea163edcc1bd3903354ea9"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a1e97b86f73715e8670ef45292d7cc033548266f07d54e2183ecb3c87598888f"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc331c13902d0f50845099434cd936d49d7a2ca76cb654b39691974cb1e4812d"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24847601071f740837aefb730e01bd169fbcaa610209779a78db7ebb6e6a7051"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abf298af1e7ad44eeb93501e40eb5a67abbf93b5d90e468d01fc0c4451971afa"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:64757f6460fc55d7e16ed4f1de193f362104285c667c112b50a804d482777edd"}, - {file = "contourpy-1.0.7.tar.gz", hash = "sha256:d8165a088d31798b59e91117d1f5fc3df8168d8b48c4acc10fc0df0d0bdbcc5e"}, +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, ] [package.dependencies] -numpy = ">=1.16" +numpy = ">=1.20,<2.0" [package.extras] -bokeh = ["bokeh", "chromedriver", "selenium"] -docs = ["furo", "sphinx-copybutton"] -mypy = ["contourpy[bokeh]", "docutils-stubs", "mypy (==0.991)", "types-Pillow"] -test = ["Pillow", "matplotlib", "pytest"] -test-no-images = ["pytest"] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.2.3" +version = "7.3.2" description = "Code coverage measurement for Python" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"}, - {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"}, - {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"}, - {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"}, - {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"}, - {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"}, - {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"}, - {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"}, - {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"}, - {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"}, - {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"}, - {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"}, - {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"}, - {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"}, - {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"}, - {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"}, - {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"}, - {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"}, - {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"}, - {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"}, - {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"}, - {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"}, - {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"}, - {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"}, - {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"}, - {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"}, - {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"}, - {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"}, - {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"}, - {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"}, - {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"}, - {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"}, - {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"}, - {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"}, - {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"}, - {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"}, - {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"}, - {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"}, - {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"}, - {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"}, - {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"}, - {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"}, - {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"}, - {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"}, - {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"}, - {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"}, - {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"}, - {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"}, - {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"}, - {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"}, - {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"}, + {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, + {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, + {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, + {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, + {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, + {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, + {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, + {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, + {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, + {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, + {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, + {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, + {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, + {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, ] [package.extras] @@ -999,92 +983,46 @@ toml = ["tomli"] [[package]] name = "cycler" -version = "0.11.0" +version = "0.12.1" description = "Composable style cycles" category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, - {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, ] -[[package]] -name = "cython" -version = "0.29.34" -description = "The Cython compiler for writing C extensions for the Python language." -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "Cython-0.29.34-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:742544024ddb74314e2d597accdb747ed76bd126e61fcf49940a5b5be0a8f381"}, - {file = "Cython-0.29.34-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:03daae07f8cbf797506446adae512c3dd86e7f27a62a541fa1ee254baf43e32c"}, - {file = "Cython-0.29.34-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5a8de3e793a576e40ca9b4f5518610cd416273c7dc5e254115656b6e4ec70663"}, - {file = "Cython-0.29.34-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:60969d38e6a456a67e7ef8ae20668eff54e32ba439d4068ccf2854a44275a30f"}, - {file = "Cython-0.29.34-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:21b88200620d80cfe193d199b259cdad2b9af56f916f0f7f474b5a3631ca0caa"}, - {file = "Cython-0.29.34-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:308c8f1e58bf5e6e8a1c4dcf8abbd2d13d0f9b1e582f4d9ae8b89857342d8bb5"}, - {file = "Cython-0.29.34-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:d8f822fb6ecd5d88c42136561f82960612421154fc5bf23c57103a367bb91356"}, - {file = "Cython-0.29.34-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56866323f1660cecb4d5ff3a1fba92a56b91b7cfae0a8253777aa4bdb3bdf9a8"}, - {file = "Cython-0.29.34-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e971db8aeb12e7c0697cefafe65eefcc33ff1224ae3d8c7f83346cbc42c6c270"}, - {file = "Cython-0.29.34-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4401270b0dc464c23671e2e9d52a60985f988318febaf51b047190e855bbe7d"}, - {file = "Cython-0.29.34-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:dce0a36d163c05ae8b21200059511217d79b47baf2b7b0f926e8367bd7a3cc24"}, - {file = "Cython-0.29.34-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dbd79221869ee9a6ccc4953b2c8838bb6ae08ab4d50ea4b60d7894f03739417b"}, - {file = "Cython-0.29.34-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a0f4229df10bc4545ebbeaaf96ebb706011d8b333e54ed202beb03f2bee0a50e"}, - {file = "Cython-0.29.34-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fd1ea21f1cebf33ae288caa0f3e9b5563a709f4df8925d53bad99be693fc0d9b"}, - {file = "Cython-0.29.34-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:d7ef5f68f4c5baa93349ea54a352f8716d18bee9a37f3e93eff38a5d4e9b7262"}, - {file = "Cython-0.29.34-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:459994d1de0f99bb18fad9f2325f760c4b392b1324aef37bcc1cd94922dfce41"}, - {file = "Cython-0.29.34-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:1d6c809e2f9ce5950bbc52a1d2352ef3d4fc56186b64cb0d50c8c5a3c1d17661"}, - {file = "Cython-0.29.34-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f674ceb5f722d364395f180fbac273072fc1a266aab924acc9cfd5afc645aae1"}, - {file = "Cython-0.29.34-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9489de5b2044dcdfd9d6ca8242a02d560137b3c41b1f5ae1c4f6707d66d6e44d"}, - {file = "Cython-0.29.34-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5c121dc185040f4333bfded68963b4529698e1b6d994da56be32c97a90c896b6"}, - {file = "Cython-0.29.34-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:b6149f7cc5b31bccb158c5b968e5a8d374fdc629792e7b928a9b66e08b03fca5"}, - {file = "Cython-0.29.34-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0ab3cbf3d62b0354631a45dc93cfcdf79098663b1c65a6033af4a452b52217a7"}, - {file = "Cython-0.29.34-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:4a2723447d1334484681d5aede34184f2da66317891f94b80e693a2f96a8f1a7"}, - {file = "Cython-0.29.34-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e40cf86aadc29ecd1cb6de67b0d9488705865deea4fc185c7ad56d7a6fc78703"}, - {file = "Cython-0.29.34-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8c3cd8bb8e880a3346f5685601004d96e0a2221e73edcaeea57ea848618b4ac6"}, - {file = "Cython-0.29.34-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0e9032cd650b0cb1d2c2ef2623f5714c14d14c28d7647d589c3eeed0baf7428e"}, - {file = "Cython-0.29.34-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bdb3285660e3068438791ace7dd7b1efd6b442a10b5c8d7a4f0c9d184d08c8ed"}, - {file = "Cython-0.29.34-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a8ad755f9364e720f10a36734a1c7a5ced5c679446718b589259261438a517c9"}, - {file = "Cython-0.29.34-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:7595d29eaee95633dd8060f50f0e54b27472d01587659557ebcfe39da3ea946b"}, - {file = "Cython-0.29.34-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e6ef7879668214d80ea3914c17e7d4e1ebf4242e0dd4dabe95ca5ccbe75589a5"}, - {file = "Cython-0.29.34-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ccb223b5f0fd95d8d27561efc0c14502c0945f1a32274835831efa5d5baddfc1"}, - {file = "Cython-0.29.34-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:11b1b278b8edef215caaa5250ad65a10023bfa0b5a93c776552248fc6f60098d"}, - {file = "Cython-0.29.34-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5718319a01489688fdd22ddebb8e2fcbbd60be5f30de4336ea7063c3ae29fbe5"}, - {file = "Cython-0.29.34-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:cfb2302ef617d647ee590a4c0a00ba3c2da05f301dcefe7721125565d2e51351"}, - {file = "Cython-0.29.34-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:67b850cf46b861bc27226d31e1d87c0e69869a02f8d3cc5d5bef549764029879"}, - {file = "Cython-0.29.34-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0963266dad685812c1dbb758fcd4de78290e3adc7db271c8664dcde27380b13e"}, - {file = "Cython-0.29.34-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7879992487d9060a61393eeefe00d299210256928dce44d887b6be313d342bac"}, - {file = "Cython-0.29.34-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:44733366f1604b0c327613b6918469284878d2f5084297d10d26072fc6948d51"}, - {file = "Cython-0.29.34-py2.py3-none-any.whl", hash = "sha256:be4f6b7be75a201c290c8611c0978549c60353890204573078e865423dbe3c83"}, - {file = "Cython-0.29.34.tar.gz", hash = "sha256:1909688f5d7b521a60c396d20bba9e47a1b2d2784bfb085401e1e1e7d29a29a8"}, -] +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "debugpy" -version = "1.6.7" +version = "1.8.0" description = "An implementation of the Debug Adapter Protocol for Python" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"}, - {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"}, - {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"}, - {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"}, - {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"}, - {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"}, - {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"}, - {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"}, - {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"}, - {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"}, - {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"}, - {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"}, - {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"}, - {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"}, - {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"}, - {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"}, - {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"}, - {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"}, + {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"}, + {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"}, + {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"}, + {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"}, + {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"}, + {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"}, + {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"}, + {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"}, + {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"}, + {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"}, + {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"}, + {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"}, + {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"}, + {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"}, + {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"}, + {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"}, + {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"}, + {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"}, ] [[package]] @@ -1113,32 +1051,32 @@ files = [ [[package]] name = "deprecated" -version = "1.2.13" +version = "1.2.14" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "Deprecated-1.2.13-py2.py3-none-any.whl", hash = "sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"}, - {file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"}, + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, ] [package.dependencies] wrapt = ">=1.10,<2" [package.extras] -dev = ["PyTest", "PyTest (<5)", "PyTest-Cov", "PyTest-Cov (<2.6)", "bump2version (<1)", "configparser (<5)", "importlib-metadata (<3)", "importlib-resources (<4)", "sphinx (<2)", "sphinxcontrib-websupport (<2)", "tox", "zipp (<2)"] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] [[package]] name = "dill" -version = "0.3.6" -description = "serialize all of python" +version = "0.3.7" +description = "serialize all of Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, + {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, + {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] [package.extras] @@ -1157,30 +1095,57 @@ files = [ ] [[package]] -name = "executing" +name = "entrypoints" +version = "0.4" +description = "Discover and load entry points from installed packages." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, + {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, +] + +[[package]] +name = "exceptiongroup" version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "executing" +version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, - {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, ] [package.extras] -tests = ["asttokens", "littleutils", "pytest", "rich"] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] [[package]] name = "fastjsonschema" -version = "2.16.3" +version = "2.19.0" description = "Fastest Python implementation of JSON schema" category = "main" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.16.3-py3-none-any.whl", hash = "sha256:04fbecc94300436f628517b05741b7ea009506ce8f946d40996567c669318490"}, - {file = "fastjsonschema-2.16.3.tar.gz", hash = "sha256:4a30d6315a68c253cfa8f963b9697246315aa3db89f98b97235e345dedfb0b8e"}, + {file = "fastjsonschema-2.19.0-py3-none-any.whl", hash = "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e"}, + {file = "fastjsonschema-2.19.0.tar.gz", hash = "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225"}, ] [package.extras] @@ -1188,30 +1153,70 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "flatbuffers" -version = "23.3.3" +version = "23.5.26" description = "The FlatBuffers serialization format for Python" category = "main" optional = false python-versions = "*" files = [ - {file = "flatbuffers-23.3.3-py2.py3-none-any.whl", hash = "sha256:5ad36d376240090757e8f0a2cfaf6abcc81c6536c0dc988060375fd0899121f8"}, - {file = "flatbuffers-23.3.3.tar.gz", hash = "sha256:cabd87c4882f37840f6081f094b2c5bc28cefc2a6357732746936d055ab45c3d"}, + {file = "flatbuffers-23.5.26-py2.py3-none-any.whl", hash = "sha256:c0ff356da363087b915fde4b8b45bdda73432fc17cddb3c8157472eab1422ad1"}, + {file = "flatbuffers-23.5.26.tar.gz", hash = "sha256:9ea1144cac05ce5d86e2859f431c6cd5e66cd9c78c558317c7955fb8d4c78d89"}, ] [[package]] name = "fonttools" -version = "4.39.3" +version = "4.45.1" description = "Tools to manipulate font files" category = "main" optional = true python-versions = ">=3.8" files = [ - {file = "fonttools-4.39.3-py3-none-any.whl", hash = "sha256:64c0c05c337f826183637570ac5ab49ee220eec66cf50248e8df527edfa95aeb"}, - {file = "fonttools-4.39.3.zip", hash = "sha256:9234b9f57b74e31b192c3fc32ef1a40750a8fbc1cd9837a7b7bfc4ca4a5c51d7"}, + {file = "fonttools-4.45.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:45fa321c458ea29224067700954ec44493ae869b47e7c5485a350a149a19fb53"}, + {file = "fonttools-4.45.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0dc7617d96b1e668eea9250e1c1fe62d0c78c3f69573ce7e3332cc40e6d84356"}, + {file = "fonttools-4.45.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ed3bda541e86725f6b4e1b94213f13ed1ae51a5a1f167028534cedea38c010"}, + {file = "fonttools-4.45.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f4a5870e3b56788fb196da8cf30d0dfd51a76dc3b907861d018165f76ae4c2"}, + {file = "fonttools-4.45.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a3c11d9687479f01eddef729aa737abcdea0a44fdaffb62a930a18892f186c9b"}, + {file = "fonttools-4.45.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:316cec50581e844c3ab69d7c82455b54c7cf18236b2f09e722faf665fbfcac58"}, + {file = "fonttools-4.45.1-cp310-cp310-win32.whl", hash = "sha256:e2277cba9f0b525e30de2a9ad3cb4219aa4bc697230c1645666b0deee9f914f0"}, + {file = "fonttools-4.45.1-cp310-cp310-win_amd64.whl", hash = "sha256:1b9e9ad2bcded9a1431afaa57c8d3c39143ac1f050862d66bddd863c515464a2"}, + {file = "fonttools-4.45.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff6a698bdd435d24c379f6e8a54908cd9bb7dda23719084d56bf8c87709bf3bd"}, + {file = "fonttools-4.45.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c980d60cd6ec1376206fe55013d166e5627ad0b149b5c81e74eaa913ab6134f"}, + {file = "fonttools-4.45.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a12dee6523c02ca78aeedd0a5e12bfa9b7b29896350edd5241542897b072ae23"}, + {file = "fonttools-4.45.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37cd1ced6efb3dd6fe82e9f9bf92fd74ac58a5aefc284045f59ecd517a5fb9ab"}, + {file = "fonttools-4.45.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e3d24248221bd7151dfff0d88b1b5da02dccd7134bd576ce8888199827bbaa19"}, + {file = "fonttools-4.45.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba6c23591427844dfb0a13658f1718489de75de6a46b64234584c0d17573162d"}, + {file = "fonttools-4.45.1-cp311-cp311-win32.whl", hash = "sha256:cebcddbe9351b67166292b4f71ffdbfcce01ba4b07d4267824eb46b277aeb19a"}, + {file = "fonttools-4.45.1-cp311-cp311-win_amd64.whl", hash = "sha256:f22eb69996a0bd49f76bdefb30be54ce8dbb89a0d1246874d610f05c2aa2e69e"}, + {file = "fonttools-4.45.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:794de93e83297db7b4943f2431e206d8b1ea69cb3ae14638a49cc50332bf0db8"}, + {file = "fonttools-4.45.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4ba17822a6681d06849078daaf6e03eccc9f467efe7c4c60280e28a78e8e5df9"}, + {file = "fonttools-4.45.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e50f794d09df0675da8d9dbd7c66bfcab2f74a708343aabcad41936d26556891"}, + {file = "fonttools-4.45.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b07b857d4f9de3199a8c3d1b1bf2078c0f37447891ca1a8d9234106b9a27aff"}, + {file = "fonttools-4.45.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:777ba42b94a27bb7fb2b4082522fccfd345667c32a56011e1c3e105979af5b79"}, + {file = "fonttools-4.45.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:21e96b99878348c74aa58059b8578d7586f9519cbcdadacf56486737038aa043"}, + {file = "fonttools-4.45.1-cp312-cp312-win32.whl", hash = "sha256:5cbf02cda8465b69769d07385f5d11e7bba19954e7787792f46fe679ec755ebb"}, + {file = "fonttools-4.45.1-cp312-cp312-win_amd64.whl", hash = "sha256:800e354e0c3afaeb8d9552769773d02f228e98c37b8cb03041157c3d0687cffc"}, + {file = "fonttools-4.45.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6eb2c54f7a07c92108daabcf02caf31df97825738db02a28270633946bcda4d0"}, + {file = "fonttools-4.45.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:43a3d267334109ff849c37cf3629476b5feb392ef1d2e464a167b83de8cd599c"}, + {file = "fonttools-4.45.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e1aefc2bf3c43e0f33f995f828a7bbeff4adc9393a7760b11456dbcf14388f6"}, + {file = "fonttools-4.45.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f53a19dcdd5737440839b8394eeebb35da9ec8109f7926cb6456639b5b58e47"}, + {file = "fonttools-4.45.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a17706b9cc24b27721613fe5773d93331ab7f0ecaca9955aead89c6b843d3a7"}, + {file = "fonttools-4.45.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fb36e5f40191274a95938b40c0a1fa7f895e36935aea8709e1d6deff0b2d0d4f"}, + {file = "fonttools-4.45.1-cp38-cp38-win32.whl", hash = "sha256:46eabddec12066829b8a1efe45ae552ba2f1796981ecf538d5f68284c354c589"}, + {file = "fonttools-4.45.1-cp38-cp38-win_amd64.whl", hash = "sha256:b6de2f0fcd3302fb82f94801002cb473959e998c14c24ec28234adb674aed345"}, + {file = "fonttools-4.45.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:392d0e3cc23daee910193625f7cf1b387aff9dd5b6f1a5f4a925680acb6dcbc2"}, + {file = "fonttools-4.45.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4b9544b1346d99848ac0e9b05b5d45ee703d7562fc4c9c48cf4b781de9632e57"}, + {file = "fonttools-4.45.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8717db3e4895e4820ade64ea379187738827ee60748223cb0438ef044ee208c6"}, + {file = "fonttools-4.45.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e29d5f298d616a93a4c5963682dc6cc8cc09f6d89cad2c29019fc5fb3b4d9472"}, + {file = "fonttools-4.45.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cb472905da3049960e80fc1cf808231880d79727a8410e156bf3e5063a1c574f"}, + {file = "fonttools-4.45.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ba299f1fbaa2a1e33210aaaf6fa816d4059e4d3cfe2ae9871368d4ab548c1c6a"}, + {file = "fonttools-4.45.1-cp39-cp39-win32.whl", hash = "sha256:105099968b58a5b4cef6f3eb409db8ea8578b302a9d05e23fecba1b8b0177b5f"}, + {file = "fonttools-4.45.1-cp39-cp39-win_amd64.whl", hash = "sha256:847f3f49dd3423e5a678c098e2ba92c7f4955d4aab3044f6a507b0bb0ecb07e0"}, + {file = "fonttools-4.45.1-py3-none-any.whl", hash = "sha256:3bdd7dfca8f6c9f4779384064027e8477ad6a037d6a327b09381f43e0247c6f3"}, + {file = "fonttools-4.45.1.tar.gz", hash = "sha256:6e441286d55fe7ec7c4fb36812bf914924813776ff514b744b510680fc2733f2"}, ] [package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] interpolatable = ["munkres", "scipy"] lxml = ["lxml (>=4.0,<5)"] @@ -1221,7 +1226,7 @@ repacker = ["uharfbuzz (>=0.23.0)"] symfont = ["sympy"] type1 = ["xattr"] ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=15.0.0)"] +unicode = ["unicodedata2 (>=15.1.0)"] woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] [[package]] @@ -1238,98 +1243,85 @@ files = [ [[package]] name = "frozenlist" -version = "1.3.3" +version = "1.4.0" description = "A list-like structure which implements collections.abc.MutableSequence" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"}, - {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"}, - {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"}, - {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"}, - {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"}, - {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"}, - {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"}, - {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"}, - {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"}, - {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"}, - {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"}, - {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"}, - {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"}, - {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"}, - {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"}, - {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"}, - {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"}, - {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"}, - {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"}, - {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"}, - {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"}, - {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"}, - {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"}, - {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, + {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, + {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, + {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, + {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, + {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, + {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, + {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, + {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, + {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, ] [[package]] name = "fsspec" -version = "2023.4.0" +version = "2023.10.0" description = "File-system specification" category = "main" optional = true python-versions = ">=3.8" files = [ - {file = "fsspec-2023.4.0-py3-none-any.whl", hash = "sha256:f398de9b49b14e9d84d2c2d11b7b67121bc072fe97b930c4e5668ac3917d8307"}, - {file = "fsspec-2023.4.0.tar.gz", hash = "sha256:bf064186cd8808f0b2f6517273339ba0a0c8fb1b7048991c28bc67f58b8b67cd"}, + {file = "fsspec-2023.10.0-py3-none-any.whl", hash = "sha256:346a8f024efeb749d2a5fca7ba8854474b1ff9af7c3faaf636a4548781136529"}, + {file = "fsspec-2023.10.0.tar.gz", hash = "sha256:330c66757591df346ad3091a53bd907e15348c2ba17d63fd54f5c39c4457d2a5"}, ] [package.dependencies] @@ -1374,43 +1366,42 @@ files = [ [[package]] name = "google-auth" -version = "2.17.2" +version = "2.23.4" description = "Google Authentication Library" category = "main" optional = true -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" +python-versions = ">=3.7" files = [ - {file = "google-auth-2.17.2.tar.gz", hash = "sha256:295c80ebb95eac74003c07a696cf3ef6b414e9230ae8894f3843f8215fd2aa56"}, - {file = "google_auth-2.17.2-py2.py3-none-any.whl", hash = "sha256:544536a43d44dff0f64222e4d027d124989fcb9c10979687e589e1694fba9c94"}, + {file = "google-auth-2.23.4.tar.gz", hash = "sha256:79905d6b1652187def79d491d6e23d0cbb3a21d3c7ba0dbaa9c8a01906b13ff3"}, + {file = "google_auth-2.23.4-py2.py3-none-any.whl", hash = "sha256:d4bbc92fe4b8bfd2f3e8d88e5ba7085935da208ee38a134fc280e7ce682a05f2"}, ] [package.dependencies] cachetools = ">=2.0.0,<6.0" pyasn1-modules = ">=0.2.1" -rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""} -six = ">=1.9.0" +rsa = ">=3.1.4,<5" [package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "requests (>=2.20.0,<3.0.0dev)"] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0dev)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] [[package]] name = "google-auth-oauthlib" -version = "0.4.6" +version = "1.0.0" description = "Google Authentication Library" category = "main" optional = true python-versions = ">=3.6" files = [ - {file = "google-auth-oauthlib-0.4.6.tar.gz", hash = "sha256:a90a072f6993f2c327067bf65270046384cda5a8ecb20b94ea9a687f1f233a7a"}, - {file = "google_auth_oauthlib-0.4.6-py2.py3-none-any.whl", hash = "sha256:3f2a6e802eebbb6fb736a370fbf3b055edcb6b52878bf2f26330b5e041316c73"}, + {file = "google-auth-oauthlib-1.0.0.tar.gz", hash = "sha256:e375064964820b47221a7e1b7ee1fd77051b6323c3f9e3e19785f78ab67ecfc5"}, + {file = "google_auth_oauthlib-1.0.0-py2.py3-none-any.whl", hash = "sha256:95880ca704928c300f48194d1770cf5b1462835b6e49db61445a520f793fd5fb"}, ] [package.dependencies] -google-auth = ">=1.0.0" +google-auth = ">=2.15.0" requests-oauthlib = ">=0.7.0" [package.extras] @@ -1434,173 +1425,179 @@ six = "*" [[package]] name = "greenlet" -version = "2.0.2" +version = "3.0.1" description = "Lightweight in-process concurrent programming" category = "main" optional = true -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -files = [ - {file = "greenlet-2.0.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d"}, - {file = "greenlet-2.0.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9"}, - {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, - {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, - {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, - {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470"}, - {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a"}, - {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, - {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, - {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, - {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19"}, - {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3"}, - {file = "greenlet-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5"}, - {file = "greenlet-2.0.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6"}, - {file = "greenlet-2.0.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43"}, - {file = "greenlet-2.0.2-cp35-cp35m-win32.whl", hash = "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a"}, - {file = "greenlet-2.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394"}, - {file = "greenlet-2.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75"}, - {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf"}, - {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292"}, - {file = "greenlet-2.0.2-cp36-cp36m-win32.whl", hash = "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9"}, - {file = "greenlet-2.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f"}, - {file = "greenlet-2.0.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73"}, - {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86"}, - {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33"}, - {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, - {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, - {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857"}, - {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a"}, - {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, - {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, - {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, - {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b"}, - {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8"}, - {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9"}, - {file = "greenlet-2.0.2-cp39-cp39-win32.whl", hash = "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5"}, - {file = "greenlet-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564"}, - {file = "greenlet-2.0.2.tar.gz", hash = "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0"}, +python-versions = ">=3.7" +files = [ + {file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"}, + {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"}, + {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"}, + {file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"}, + {file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"}, + {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"}, + {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"}, + {file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"}, + {file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"}, + {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"}, + {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"}, + {file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de"}, + {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166"}, + {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36"}, + {file = "greenlet-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1"}, + {file = "greenlet-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8"}, + {file = "greenlet-3.0.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9"}, + {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e"}, + {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a"}, + {file = "greenlet-3.0.1-cp38-cp38-win32.whl", hash = "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd"}, + {file = "greenlet-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6"}, + {file = "greenlet-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d"}, + {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8"}, + {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546"}, + {file = "greenlet-3.0.1-cp39-cp39-win32.whl", hash = "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57"}, + {file = "greenlet-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619"}, + {file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"}, ] [package.extras] -docs = ["Sphinx", "docutils (<0.18)"] +docs = ["Sphinx"] test = ["objgraph", "psutil"] [[package]] name = "grpcio" -version = "1.53.0" +version = "1.59.3" description = "HTTP/2-based RPC framework" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "grpcio-1.53.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:752d2949b40e12e6ad3ed8cc552a65b54d226504f6b1fb67cab2ccee502cc06f"}, - {file = "grpcio-1.53.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8a48fd3a7222be226bb86b7b413ad248f17f3101a524018cdc4562eeae1eb2a3"}, - {file = "grpcio-1.53.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f3e837d29f0e1b9d6e7b29d569e2e9b0da61889e41879832ea15569c251c303a"}, - {file = "grpcio-1.53.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef7d30242409c3aa5839b501e877e453a2c8d3759ca8230dd5a21cda029f046"}, - {file = "grpcio-1.53.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6f90698b5d1c5dd7b3236cd1fa959d7b80e17923f918d5be020b65f1c78b173"}, - {file = "grpcio-1.53.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a96c3c7f564b263c5d7c0e49a337166c8611e89c4c919f66dba7b9a84abad137"}, - {file = "grpcio-1.53.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ee81349411648d1abc94095c68cd25e3c2812e4e0367f9a9355be1e804a5135c"}, - {file = "grpcio-1.53.0-cp310-cp310-win32.whl", hash = "sha256:fdc6191587de410a184550d4143e2b24a14df495c86ca15e59508710681690ac"}, - {file = "grpcio-1.53.0-cp310-cp310-win_amd64.whl", hash = "sha256:658ffe1e39171be00490db5bd3b966f79634ac4215a1eb9a85c6cd6783bf7f6e"}, - {file = "grpcio-1.53.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:1b172e6d497191940c4b8d75b53de82dc252e15b61de2951d577ec5b43316b29"}, - {file = "grpcio-1.53.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:82434ba3a5935e47908bc861ce1ebc43c2edfc1001d235d6e31e5d3ed55815f7"}, - {file = "grpcio-1.53.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:1c734a2d4843e4e14ececf5600c3c4750990ec319e1299db7e4f0d02c25c1467"}, - {file = "grpcio-1.53.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6a2ead3de3b2d53119d473aa2f224030257ef33af1e4ddabd4afee1dea5f04c"}, - {file = "grpcio-1.53.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a34d6e905f071f9b945cabbcc776e2055de1fdb59cd13683d9aa0a8f265b5bf9"}, - {file = "grpcio-1.53.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eaf8e3b97caaf9415227a3c6ca5aa8d800fecadd526538d2bf8f11af783f1550"}, - {file = "grpcio-1.53.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:da95778d37be8e4e9afca771a83424f892296f5dfb2a100eda2571a1d8bbc0dc"}, - {file = "grpcio-1.53.0-cp311-cp311-win32.whl", hash = "sha256:e4f513d63df6336fd84b74b701f17d1bb3b64e9d78a6ed5b5e8a198bbbe8bbfa"}, - {file = "grpcio-1.53.0-cp311-cp311-win_amd64.whl", hash = "sha256:ddb2511fbbb440ed9e5c9a4b9b870f2ed649b7715859fd6f2ebc585ee85c0364"}, - {file = "grpcio-1.53.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:2a912397eb8d23c177d6d64e3c8bc46b8a1c7680b090d9f13a640b104aaec77c"}, - {file = "grpcio-1.53.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:55930c56b8f5b347d6c8c609cc341949a97e176c90f5cbb01d148d778f3bbd23"}, - {file = "grpcio-1.53.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:6601d812105583948ab9c6e403a7e2dba6e387cc678c010e74f2d6d589d1d1b3"}, - {file = "grpcio-1.53.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c705e0c21acb0e8478a00e7e773ad0ecdb34bd0e4adc282d3d2f51ba3961aac7"}, - {file = "grpcio-1.53.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba074af9ca268ad7b05d3fc2b920b5fb3c083da94ab63637aaf67f4f71ecb755"}, - {file = "grpcio-1.53.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:14817de09317dd7d3fbc8272864288320739973ef0f4b56bf2c0032349da8cdf"}, - {file = "grpcio-1.53.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c7ad9fbedb93f331c2e9054e202e95cf825b885811f1bcbbdfdc301e451442db"}, - {file = "grpcio-1.53.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dad5b302a4c21c604d88a5d441973f320134e6ff6a84ecef9c1139e5ffd466f6"}, - {file = "grpcio-1.53.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:fa8eaac75d3107e3f5465f2c9e3bbd13db21790c6e45b7de1756eba16b050aca"}, - {file = "grpcio-1.53.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:104a2210edd3776c38448b4f76c2f16e527adafbde171fc72a8a32976c20abc7"}, - {file = "grpcio-1.53.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:dbc1ba968639c1d23476f75c356e549e7bbf2d8d6688717dcab5290e88e8482b"}, - {file = "grpcio-1.53.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95952d3fe795b06af29bb8ec7bbf3342cdd867fc17b77cc25e6733d23fa6c519"}, - {file = "grpcio-1.53.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f144a790f14c51b8a8e591eb5af40507ffee45ea6b818c2482f0457fec2e1a2e"}, - {file = "grpcio-1.53.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0698c094688a2dd4c7c2f2c0e3e142cac439a64d1cef6904c97f6cde38ba422f"}, - {file = "grpcio-1.53.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6b6d60b0958be711bab047e9f4df5dbbc40367955f8651232bfdcdd21450b9ab"}, - {file = "grpcio-1.53.0-cp38-cp38-win32.whl", hash = "sha256:1948539ce78805d4e6256ab0e048ec793956d54787dc9d6777df71c1d19c7f81"}, - {file = "grpcio-1.53.0-cp38-cp38-win_amd64.whl", hash = "sha256:df9ba1183b3f649210788cf80c239041dddcb375d6142d8bccafcfdf549522cd"}, - {file = "grpcio-1.53.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:19caa5b7282a89b799e63776ff602bb39604f7ca98db6df27e2de06756ae86c3"}, - {file = "grpcio-1.53.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:b5bd026ac928c96cc23149e6ef79183125542062eb6d1ccec34c0a37e02255e7"}, - {file = "grpcio-1.53.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:7dc8584ca6c015ad82e186e82f4c0fe977394588f66b8ecfc4ec873285314619"}, - {file = "grpcio-1.53.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2eddaae8af625e45b5c8500dcca1043264d751a6872cde2eda5022df8a336959"}, - {file = "grpcio-1.53.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5fb6f3d7824696c1c9f2ad36ddb080ba5a86f2d929ef712d511b4d9972d3d27"}, - {file = "grpcio-1.53.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8270d1dc2c98ab57e6dbf36fa187db8df4c036f04a398e5d5e25b4e01a766d70"}, - {file = "grpcio-1.53.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:976a7f24eb213e8429cab78d5e120500dfcdeb01041f1f5a77b17b9101902615"}, - {file = "grpcio-1.53.0-cp39-cp39-win32.whl", hash = "sha256:9c84a481451e7174f3a764a44150f93b041ab51045aa33d7b5b68b6979114e48"}, - {file = "grpcio-1.53.0-cp39-cp39-win_amd64.whl", hash = "sha256:6beb84f83360ff29a3654f43f251ec11b809dcb5524b698d711550243debd289"}, - {file = "grpcio-1.53.0.tar.gz", hash = "sha256:a4952899b4931a6ba12951f9a141ef3e74ff8a6ec9aa2dc602afa40f63595e33"}, + {file = "grpcio-1.59.3-cp310-cp310-linux_armv7l.whl", hash = "sha256:aca028a6c7806e5b61e5f9f4232432c52856f7fcb98e330b20b6bc95d657bdcc"}, + {file = "grpcio-1.59.3-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:19ad26a7967f7999c8960d2b9fe382dae74c55b0c508c613a6c2ba21cddf2354"}, + {file = "grpcio-1.59.3-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:72b71dad2a3d1650e69ad42a5c4edbc59ee017f08c32c95694172bc501def23c"}, + {file = "grpcio-1.59.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0f0a11d82d0253656cc42e04b6a149521e02e755fe2e4edd21123de610fd1d4"}, + {file = "grpcio-1.59.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60cddafb70f9a2c81ba251b53b4007e07cca7389e704f86266e22c4bffd8bf1d"}, + {file = "grpcio-1.59.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6c75a1fa0e677c1d2b6d4196ad395a5c381dfb8385f07ed034ef667cdcdbcc25"}, + {file = "grpcio-1.59.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e1d8e01438d5964a11167eec1edb5f85ed8e475648f36c834ed5db4ffba24ac8"}, + {file = "grpcio-1.59.3-cp310-cp310-win32.whl", hash = "sha256:c4b0076f0bf29ee62335b055a9599f52000b7941f577daa001c7ef961a1fbeab"}, + {file = "grpcio-1.59.3-cp310-cp310-win_amd64.whl", hash = "sha256:b1f00a3e6e0c3dccccffb5579fc76ebfe4eb40405ba308505b41ef92f747746a"}, + {file = "grpcio-1.59.3-cp311-cp311-linux_armv7l.whl", hash = "sha256:3996aaa21231451161dc29df6a43fcaa8b332042b6150482c119a678d007dd86"}, + {file = "grpcio-1.59.3-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:cb4e9cbd9b7388fcb06412da9f188c7803742d06d6f626304eb838d1707ec7e3"}, + {file = "grpcio-1.59.3-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:8022ca303d6c694a0d7acfb2b472add920217618d3a99eb4b14edc7c6a7e8fcf"}, + {file = "grpcio-1.59.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b36683fad5664283755a7f4e2e804e243633634e93cd798a46247b8e54e3cb0d"}, + {file = "grpcio-1.59.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8239b853226e4824e769517e1b5232e7c4dda3815b200534500338960fcc6118"}, + {file = "grpcio-1.59.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0511af8653fbda489ff11d542a08505d56023e63cafbda60e6e00d4e0bae86ea"}, + {file = "grpcio-1.59.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e78dc982bda74cef2ddfce1c91d29b96864c4c680c634e279ed204d51e227473"}, + {file = "grpcio-1.59.3-cp311-cp311-win32.whl", hash = "sha256:6a5c3a96405966c023e139c3bcccb2c7c776a6f256ac6d70f8558c9041bdccc3"}, + {file = "grpcio-1.59.3-cp311-cp311-win_amd64.whl", hash = "sha256:ed26826ee423b11477297b187371cdf4fa1eca874eb1156422ef3c9a60590dd9"}, + {file = "grpcio-1.59.3-cp312-cp312-linux_armv7l.whl", hash = "sha256:45dddc5cb5227d30fa43652d8872dc87f086d81ab4b500be99413bad0ae198d7"}, + {file = "grpcio-1.59.3-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:1736496d74682e53dd0907fd515f2694d8e6a96c9a359b4080b2504bf2b2d91b"}, + {file = "grpcio-1.59.3-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:ddbd1a16138e52e66229047624de364f88a948a4d92ba20e4e25ad7d22eef025"}, + {file = "grpcio-1.59.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcfa56f8d031ffda902c258c84c4b88707f3a4be4827b4e3ab8ec7c24676320d"}, + {file = "grpcio-1.59.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2eb8f0c7c0c62f7a547ad7a91ba627a5aa32a5ae8d930783f7ee61680d7eb8d"}, + {file = "grpcio-1.59.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8d993399cc65e3a34f8fd48dd9ad7a376734564b822e0160dd18b3d00c1a33f9"}, + {file = "grpcio-1.59.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0bd141f4f41907eb90bda74d969c3cb21c1c62779419782a5b3f5e4b5835718"}, + {file = "grpcio-1.59.3-cp312-cp312-win32.whl", hash = "sha256:33b8fd65d4e97efa62baec6171ce51f9cf68f3a8ba9f866f4abc9d62b5c97b79"}, + {file = "grpcio-1.59.3-cp312-cp312-win_amd64.whl", hash = "sha256:0e735ed002f50d4f3cb9ecfe8ac82403f5d842d274c92d99db64cfc998515e07"}, + {file = "grpcio-1.59.3-cp37-cp37m-linux_armv7l.whl", hash = "sha256:ea40ce4404e7cca0724c91a7404da410f0144148fdd58402a5942971e3469b94"}, + {file = "grpcio-1.59.3-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:83113bcc393477b6f7342b9f48e8a054330c895205517edc66789ceea0796b53"}, + {file = "grpcio-1.59.3-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:73afbac602b8f1212a50088193601f869b5073efa9855b3e51aaaec97848fc8a"}, + {file = "grpcio-1.59.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:575d61de1950b0b0699917b686b1ca108690702fcc2df127b8c9c9320f93e069"}, + {file = "grpcio-1.59.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cd76057b5c9a4d68814610ef9226925f94c1231bbe533fdf96f6181f7d2ff9e"}, + {file = "grpcio-1.59.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:95d6fd804c81efe4879e38bfd84d2b26e339a0a9b797e7615e884ef4686eb47b"}, + {file = "grpcio-1.59.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0d42048b8a3286ea4134faddf1f9a59cf98192b94aaa10d910a25613c5eb5bfb"}, + {file = "grpcio-1.59.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4619fea15c64bcdd9d447cdbdde40e3d5f1da3a2e8ae84103d94a9c1df210d7e"}, + {file = "grpcio-1.59.3-cp38-cp38-linux_armv7l.whl", hash = "sha256:95b5506e70284ac03b2005dd9ffcb6708c9ae660669376f0192a710687a22556"}, + {file = "grpcio-1.59.3-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:9e17660947660ccfce56c7869032910c179a5328a77b73b37305cd1ee9301c2e"}, + {file = "grpcio-1.59.3-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:00912ce19914d038851be5cd380d94a03f9d195643c28e3ad03d355cc02ce7e8"}, + {file = "grpcio-1.59.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e58b3cadaa3c90f1efca26ba33e0d408b35b497307027d3d707e4bcd8de862a6"}, + {file = "grpcio-1.59.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d787ecadea865bdf78f6679f6f5bf4b984f18f659257ba612979df97a298b3c3"}, + {file = "grpcio-1.59.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0814942ba1bba269db4e760a34388640c601dece525c6a01f3b4ff030cc0db69"}, + {file = "grpcio-1.59.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fb111aa99d3180c361a35b5ae1e2c63750220c584a1344229abc139d5c891881"}, + {file = "grpcio-1.59.3-cp38-cp38-win32.whl", hash = "sha256:eb8ba504c726befe40a356ecbe63c6c3c64c9a439b3164f5a718ec53c9874da0"}, + {file = "grpcio-1.59.3-cp38-cp38-win_amd64.whl", hash = "sha256:cdbc6b32fadab9bebc6f49d3e7ec4c70983c71e965497adab7f87de218e84391"}, + {file = "grpcio-1.59.3-cp39-cp39-linux_armv7l.whl", hash = "sha256:c82ca1e4be24a98a253d6dbaa216542e4163f33f38163fc77964b0f0d255b552"}, + {file = "grpcio-1.59.3-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:36636babfda14f9e9687f28d5b66d349cf88c1301154dc71c6513de2b6c88c59"}, + {file = "grpcio-1.59.3-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:5f9b2e591da751ac7fdd316cc25afafb7a626dededa9b414f90faad7f3ccebdb"}, + {file = "grpcio-1.59.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a93a82876a4926bf451db82ceb725bd87f42292bacc94586045261f501a86994"}, + {file = "grpcio-1.59.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce31fa0bfdd1f2bb15b657c16105c8652186eab304eb512e6ae3b99b2fdd7d13"}, + {file = "grpcio-1.59.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:16da0e40573962dab6cba16bec31f25a4f468e6d05b658e589090fe103b03e3d"}, + {file = "grpcio-1.59.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d1a17372fd425addd5812049fa7374008ffe689585f27f802d0935522cf4b7"}, + {file = "grpcio-1.59.3-cp39-cp39-win32.whl", hash = "sha256:52cc38a7241b5f7b4a91aaf9000fdd38e26bb00d5e8a71665ce40cfcee716281"}, + {file = "grpcio-1.59.3-cp39-cp39-win_amd64.whl", hash = "sha256:b491e5bbcad3020a96842040421e508780cade35baba30f402df9d321d1c423e"}, + {file = "grpcio-1.59.3.tar.gz", hash = "sha256:7800f99568a74a06ebdccd419dd1b6e639b477dcaf6da77ea702f8fb14ce5f80"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.53.0)"] +protobuf = ["grpcio-tools (>=1.59.3)"] [[package]] name = "h5py" -version = "3.8.0" +version = "3.10.0" description = "Read and write HDF5 files from Python" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "h5py-3.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:533d7dad466ddb7e3b30af274b630eb7c1a6e4ddf01d1c373a0334dc2152110a"}, - {file = "h5py-3.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c873ba9fd4fa875ad62ce0e4891725e257a8fe7f5abdbc17e51a5d54819be55c"}, - {file = "h5py-3.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98a240cd4c1bfd568aaa52ec42d263131a2582dab82d74d3d42a0d954cac12be"}, - {file = "h5py-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3389b63222b1c7a158bb7fe69d11ca00066740ec5574596d47a2fe5317f563a"}, - {file = "h5py-3.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:7f3350fc0a8407d668b13247861c2acd23f7f5fe7d060a3ad9b0820f5fcbcae0"}, - {file = "h5py-3.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db03e3f2c716205fbdabb34d0848459840585225eb97b4f08998c743821ca323"}, - {file = "h5py-3.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:36761693efbe53df179627a775476dcbc37727d6e920958277a7efbc18f1fb73"}, - {file = "h5py-3.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a506fc223def428f4329e7e1f9fe1c8c593eab226e7c0942c8d75308ad49950"}, - {file = "h5py-3.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33b15aae79e9147aebe1d0e54099cbcde8d65e3e227cd5b59e49b1272aa0e09d"}, - {file = "h5py-3.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:9f6f6ffadd6bfa9b2c5b334805eb4b19ca0a5620433659d8f7fb86692c40a359"}, - {file = "h5py-3.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8f55d9c6c84d7d09c79fb85979e97b81ec6071cc776a97eb6b96f8f6ec767323"}, - {file = "h5py-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b685453e538b2b5934c58a644ac3f3b3d0cec1a01b6fb26d57388e9f9b674ad0"}, - {file = "h5py-3.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:377865821fe80ad984d003723d6f8890bd54ceeb5981b43c0313b9df95411b30"}, - {file = "h5py-3.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:0fef76e10b9216657fa37e7edff6d8be0709b25bd5066474c229b56cf0098df9"}, - {file = "h5py-3.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ffc344ec9984d2cd3ca0265007299a8bac8d85c1ad48f4639d8d3aed2af171"}, - {file = "h5py-3.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bacaa1c16810dd2b3e4417f8e730971b7c4d53d234de61fe4a918db78e80e1e4"}, - {file = "h5py-3.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bae730580ae928de409d63cbe4fdca4c82c3ad2bed30511d19d34e995d63c77e"}, - {file = "h5py-3.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47f757d1b76f0ecb8aa0508ec8d1b390df67a8b67ee2515dc1b046f3a1596ea"}, - {file = "h5py-3.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f891b17e3a3e974e93f9e34e7cca9f530806543571ce078998676a555837d91d"}, - {file = "h5py-3.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:290e00fa2de74a10688d1bac98d5a9cdd43f14f58e562c580b5b3dfbd358ecae"}, - {file = "h5py-3.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:03890b1c123d024fb0239a3279737d5432498c1901c354f8b10d8221d1d16235"}, - {file = "h5py-3.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7865de06779b14d98068da387333ad9bf2756b5b579cc887fac169bc08f87c3"}, - {file = "h5py-3.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49bc857635f935fa30e92e61ac1e87496df8f260a6945a3235e43a9890426866"}, - {file = "h5py-3.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:5fd2252d1fc364ba0e93dd0b7089f4906b66805cb4e6aca7fa8874ac08649647"}, - {file = "h5py-3.8.0.tar.gz", hash = "sha256:6fead82f0c4000cf38d53f9c030780d81bfa0220218aee13b90b7701c937d95f"}, + {file = "h5py-3.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b963fb772964fc1d1563c57e4e2e874022ce11f75ddc6df1a626f42bd49ab99f"}, + {file = "h5py-3.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:012ab448590e3c4f5a8dd0f3533255bc57f80629bf7c5054cf4c87b30085063c"}, + {file = "h5py-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:781a24263c1270a62cd67be59f293e62b76acfcc207afa6384961762bb88ea03"}, + {file = "h5py-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f42e6c30698b520f0295d70157c4e202a9e402406f50dc08f5a7bc416b24e52d"}, + {file = "h5py-3.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:93dd840bd675787fc0b016f7a05fc6efe37312a08849d9dd4053fd0377b1357f"}, + {file = "h5py-3.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2381e98af081b6df7f6db300cd88f88e740649d77736e4b53db522d8874bf2dc"}, + {file = "h5py-3.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:667fe23ab33d5a8a6b77970b229e14ae3bb84e4ea3382cc08567a02e1499eedd"}, + {file = "h5py-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90286b79abd085e4e65e07c1bd7ee65a0f15818ea107f44b175d2dfe1a4674b7"}, + {file = "h5py-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c013d2e79c00f28ffd0cc24e68665ea03ae9069e167087b2adb5727d2736a52"}, + {file = "h5py-3.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:92273ce69ae4983dadb898fd4d3bea5eb90820df953b401282ee69ad648df684"}, + {file = "h5py-3.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c97d03f87f215e7759a354460fb4b0d0f27001450b18b23e556e7856a0b21c3"}, + {file = "h5py-3.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86df4c2de68257b8539a18646ceccdcf2c1ce6b1768ada16c8dcfb489eafae20"}, + {file = "h5py-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba9ab36be991119a3ff32d0c7cbe5faf9b8d2375b5278b2aea64effbeba66039"}, + {file = "h5py-3.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:2c8e4fda19eb769e9a678592e67eaec3a2f069f7570c82d2da909c077aa94339"}, + {file = "h5py-3.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:492305a074327e8d2513011fa9fffeb54ecb28a04ca4c4227d7e1e9616d35641"}, + {file = "h5py-3.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9450464b458cca2c86252b624279115dcaa7260a40d3cb1594bf2b410a2bd1a3"}, + {file = "h5py-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd6f6d1384a9f491732cee233b99cd4bfd6e838a8815cc86722f9d2ee64032af"}, + {file = "h5py-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3074ec45d3dc6e178c6f96834cf8108bf4a60ccb5ab044e16909580352010a97"}, + {file = "h5py-3.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:212bb997a91e6a895ce5e2f365ba764debeaef5d2dca5c6fb7098d66607adf99"}, + {file = "h5py-3.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5dfc65ac21fa2f630323c92453cadbe8d4f504726ec42f6a56cf80c2f90d6c52"}, + {file = "h5py-3.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d4682b94fd36ab217352be438abd44c8f357c5449b8995e63886b431d260f3d3"}, + {file = "h5py-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aece0e2e1ed2aab076c41802e50a0c3e5ef8816d60ece39107d68717d4559824"}, + {file = "h5py-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43a61b2c2ad65b1fabc28802d133eed34debcc2c8b420cb213d3d4ef4d3e2229"}, + {file = "h5py-3.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:ae2f0201c950059676455daf92700eeb57dcf5caaf71b9e1328e6e6593601770"}, + {file = "h5py-3.10.0.tar.gz", hash = "sha256:d93adc48ceeb33347eb24a634fb787efc7ae4644e6ea4ba733d099605045c049"}, ] [package.dependencies] -numpy = ">=1.14.5" +numpy = ">=1.17.3" [[package]] name = "humanfriendly" @@ -1643,14 +1640,14 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.3.0" +version = "6.8.0" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.3.0-py3-none-any.whl", hash = "sha256:8f8bd2af397cf33bd344d35cfe7f489219b7d14fc79a3f854b75b8417e9226b0"}, - {file = "importlib_metadata-6.3.0.tar.gz", hash = "sha256:23c2bcae4762dfb0bbe072d358faec24957901d75b6c4ab11172c0c982532402"}, + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, ] [package.dependencies] @@ -1659,26 +1656,26 @@ zipp = ">=0.5" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "importlib-resources" -version = "5.12.0" +version = "6.1.1" description = "Read resources from Python packages" category = "main" -optional = false -python-versions = ">=3.7" +optional = true +python-versions = ">=3.8" files = [ - {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"}, - {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"}, + {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, + {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] [[package]] name = "iniconfig" @@ -1706,14 +1703,14 @@ files = [ [[package]] name = "ipykernel" -version = "6.22.0" +version = "6.27.0" description = "IPython Kernel for Jupyter" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.22.0-py3-none-any.whl", hash = "sha256:1ae6047c1277508933078163721bbb479c3e7292778a04b4bacf0874550977d6"}, - {file = "ipykernel-6.22.0.tar.gz", hash = "sha256:302558b81f1bc22dc259fb2a0c5c7cf2f4c0bdb21b50484348f7bafe7fb71421"}, + {file = "ipykernel-6.27.0-py3-none-any.whl", hash = "sha256:4388caa3c2cba0a381e20d289545e88a8aef1fe57a884d4c018718ec8c23c121"}, + {file = "ipykernel-6.27.0.tar.gz", hash = "sha256:7f4986f606581be73bfb32dc7a1ac9fa0e804c9be50ddf1c7a119413e982693f"}, ] [package.dependencies] @@ -1740,25 +1737,24 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio" [[package]] name = "ipython" -version = "8.12.0" +version = "8.17.2" description = "IPython: Productive Interactive Computing" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "ipython-8.12.0-py3-none-any.whl", hash = "sha256:1c183bf61b148b00bcebfa5d9b39312733ae97f6dad90d7e9b4d86c8647f498c"}, - {file = "ipython-8.12.0.tar.gz", hash = "sha256:a950236df04ad75b5bc7f816f9af3d74dc118fd42f2ff7e80e8e60ca1f182e2d"}, + {file = "ipython-8.17.2-py3-none-any.whl", hash = "sha256:1e4d1d666a023e3c93585ba0d8e962867f7a111af322efff6b9c58062b3e5444"}, + {file = "ipython-8.17.2.tar.gz", hash = "sha256:126bb57e1895594bb0d91ea3090bbd39384f6fe87c3d57fd558d0670f50339bb"}, ] [package.dependencies] appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" pygments = ">=2.4.0" stack-data = "*" @@ -1766,17 +1762,17 @@ traitlets = ">=5" typing-extensions = {version = "*", markers = "python_version < \"3.10\""} [package.extras] -all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] black = ["black"] -doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] [[package]] name = "ipython-genutils" @@ -1792,23 +1788,23 @@ files = [ [[package]] name = "ipywidgets" -version = "7.7.5" +version = "7.8.1" description = "IPython HTML widgets for Jupyter" category = "main" optional = false python-versions = "*" files = [ - {file = "ipywidgets-7.7.5-py2.py3-none-any.whl", hash = "sha256:d9644e473282ca28a6bc0327372bcad7a41877d0092fea1ed70bd15f28be9270"}, - {file = "ipywidgets-7.7.5.tar.gz", hash = "sha256:2392943ed30253c84ac36f23f707fa1c9d34461ae5356944481a84d5b08d69b2"}, + {file = "ipywidgets-7.8.1-py2.py3-none-any.whl", hash = "sha256:29f7056d368bf0a7b35d51cf0c56b58582da57c78bb9f765965fef7c332e807c"}, + {file = "ipywidgets-7.8.1.tar.gz", hash = "sha256:050b87bb9ac11641859af4c36cdb639ca072fb5e121f0f1a401f8a80f9fa008d"}, ] [package.dependencies] -ipykernel = ">=4.5.1" +comm = ">=0.1.3" ipython = {version = ">=4.0.0", markers = "python_version >= \"3.3\""} ipython-genutils = ">=0.2.0,<0.3.0" jupyterlab-widgets = {version = ">=1.0.0,<3", markers = "python_version >= \"3.6\""} traitlets = ">=4.3.1" -widgetsnbextension = ">=3.6.4,<3.7.0" +widgetsnbextension = ">=3.6.6,<3.7.0" [package.extras] test = ["ipykernel", "mock", "pytest (>=3.6.0)", "pytest-cov"] @@ -1848,23 +1844,23 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] name = "jedi" -version = "0.18.2" +version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, - {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, ] [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.8.3,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" @@ -1886,51 +1882,51 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "joblib" -version = "1.2.0" +version = "1.3.2" description = "Lightweight pipelining with Python functions" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "joblib-1.2.0-py3-none-any.whl", hash = "sha256:091138ed78f800342968c523bdde947e7a305b8594b910a0fea2ab83c3c6d385"}, - {file = "joblib-1.2.0.tar.gz", hash = "sha256:e1cee4a79e4af22881164f218d4311f60074197fb707e082e803b61f6d137018"}, + {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, + {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, ] [[package]] name = "jsonpointer" -version = "2.3" +version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ - {file = "jsonpointer-2.3-py2.py3-none-any.whl", hash = "sha256:51801e558539b4e9cd268638c078c6c5746c9ac96bc38152d443400e4f3793e9"}, - {file = "jsonpointer-2.3.tar.gz", hash = "sha256:97cba51526c829282218feb99dab1b1e6bdf8efd1c43dc9d57be093c0d69c99a"}, + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] name = "jsonschema" -version = "4.17.3" +version = "4.20.0" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, + {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"}, + {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"}, ] [package.dependencies] -attrs = ">=17.4.0" +attrs = ">=22.2.0" fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rpds-py = ">=0.7.1" uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} @@ -1938,6 +1934,21 @@ webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-n format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +[[package]] +name = "jsonschema-specifications" +version = "2023.11.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.11.1-py3-none-any.whl", hash = "sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779"}, + {file = "jsonschema_specifications-2023.11.1.tar.gz", hash = "sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + [[package]] name = "jupyter" version = "1.0.0" @@ -1961,27 +1972,28 @@ qtconsole = "*" [[package]] name = "jupyter-client" -version = "8.1.0" +version = "7.4.9" description = "Jupyter protocol implementation and client libraries" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "jupyter_client-8.1.0-py3-none-any.whl", hash = "sha256:d5b8e739d7816944be50f81121a109788a3d92732ecf1ad1e4dadebc948818fe"}, - {file = "jupyter_client-8.1.0.tar.gz", hash = "sha256:3fbab64100a0dcac7701b1e0f1a4412f1ccb45546ff2ad9bc4fcbe4e19804811"}, + {file = "jupyter_client-7.4.9-py3-none-any.whl", hash = "sha256:214668aaea208195f4c13d28eb272ba79f945fc0cf3f11c7092c20b2ca1980e7"}, + {file = "jupyter_client-7.4.9.tar.gz", hash = "sha256:52be28e04171f07aed8f20e1616a5a552ab9fee9cbbe6c1896ae170c3880d392"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" +entrypoints = "*" +jupyter-core = ">=4.9.2" +nest-asyncio = ">=1.5.4" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" tornado = ">=6.2" -traitlets = ">=5.3" +traitlets = "*" [package.extras] -docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["codecov", "coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] +doc = ["ipykernel", "myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] +test = ["codecov", "coverage", "ipykernel (>=6.12)", "ipython", "mypy", "pre-commit", "pytest", "pytest-asyncio (>=0.18)", "pytest-cov", "pytest-timeout"] [[package]] name = "jupyter-console" @@ -2010,14 +2022,14 @@ test = ["flaky", "pexpect", "pytest"] [[package]] name = "jupyter-core" -version = "5.3.0" +version = "5.5.0" description = "Jupyter core package. A base package on which Jupyter projects rely." category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_core-5.3.0-py3-none-any.whl", hash = "sha256:d4201af84559bc8c70cead287e1ab94aeef3c512848dde077b7684b54d67730d"}, - {file = "jupyter_core-5.3.0.tar.gz", hash = "sha256:6db75be0c83edbf1b7c9f91ec266a9a24ef945da630f3120e1a0046dc13713fc"}, + {file = "jupyter_core-5.5.0-py3-none-any.whl", hash = "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805"}, + {file = "jupyter_core-5.5.0.tar.gz", hash = "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3"}, ] [package.dependencies] @@ -2026,25 +2038,26 @@ pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_ traitlets = ">=5.3" [package.extras] -docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] [[package]] name = "jupyter-events" -version = "0.6.3" +version = "0.9.0" description = "Jupyter Event System library" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jupyter_events-0.6.3-py3-none-any.whl", hash = "sha256:57a2749f87ba387cd1bfd9b22a0875b889237dbf2edc2121ebb22bde47036c17"}, - {file = "jupyter_events-0.6.3.tar.gz", hash = "sha256:9a6e9995f75d1b7146b436ea24d696ce3a35bfa8bfe45e0c33c334c79464d0b3"}, + {file = "jupyter_events-0.9.0-py3-none-any.whl", hash = "sha256:d853b3c10273ff9bc8bb8b30076d65e2c9685579db736873de6c2232dde148bf"}, + {file = "jupyter_events-0.9.0.tar.gz", hash = "sha256:81ad2e4bc710881ec274d31c6c50669d71bbaa5dd9d01e600b56faa85700d399"}, ] [package.dependencies] -jsonschema = {version = ">=3.2.0", extras = ["format-nongpl"]} +jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} python-json-logger = ">=2.0.4" pyyaml = ">=5.3" +referencing = "*" rfc3339-validator = "*" rfc3986-validator = ">=0.1.1" traitlets = ">=5.3" @@ -2052,18 +2065,18 @@ traitlets = ">=5.3" [package.extras] cli = ["click", "rich"] docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] -test = ["click", "coverage", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "pytest-cov", "rich"] +test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] [[package]] name = "jupyter-server" -version = "2.5.0" +version = "2.10.1" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.5.0-py3-none-any.whl", hash = "sha256:e6bc1e9e96d7c55b9ce9699ff6cb9a910581fe7349e27c40389acb67632e24c0"}, - {file = "jupyter_server-2.5.0.tar.gz", hash = "sha256:9fde612791f716fd34d610cd939704a9639643744751ba66e7ee8fdc9cead07e"}, + {file = "jupyter_server-2.10.1-py3-none-any.whl", hash = "sha256:20519e355d951fc5e1b6ac5952854fe7620d0cfb56588fa4efe362a758977ed3"}, + {file = "jupyter_server-2.10.1.tar.gz", hash = "sha256:e6da2657a954a7879eed28cc08e0817b01ffd81d7eab8634660397b55f926472"}, ] [package.dependencies] @@ -2072,23 +2085,24 @@ argon2-cffi = "*" jinja2 = "*" jupyter-client = ">=7.4.4" jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -jupyter-events = ">=0.4.0" +jupyter-events = ">=0.9.0" jupyter-server-terminals = "*" nbconvert = ">=6.4.4" nbformat = ">=5.3.0" +overrides = "*" packaging = "*" prometheus-client = "*" pywinpty = {version = "*", markers = "os_name == \"nt\""} pyzmq = ">=24" -send2trash = "*" +send2trash = ">=1.8.2" terminado = ">=0.8.3" tornado = ">=6.2.0" traitlets = ">=5.6.0" websocket-client = "*" [package.extras] -docs = ["docutils (<0.20)", "ipykernel", "jinja2", "jupyter-client", "jupyter-server", "mistune (<1.0.0)", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] -test = ["ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.4)", "pytest-timeout", "requests"] +docs = ["ipykernel", "jinja2", "jupyter-client", "jupyter-server", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.4)", "pytest-timeout", "requests"] [[package]] name = "jupyter-server-terminals" @@ -2112,42 +2126,42 @@ test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", [[package]] name = "jupyterlab-pygments" -version = "0.2.2" +version = "0.3.0" description = "Pygments theme using JupyterLab CSS variables" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, - {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, ] [[package]] name = "jupyterlab-widgets" -version = "1.1.4" +version = "1.1.7" description = "A JupyterLab extension." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "jupyterlab_widgets-1.1.4-py3-none-any.whl", hash = "sha256:769eb7bfef7e8ab70a7737104555531b09bcfba982f89465d2ae67b99b3f3e81"}, - {file = "jupyterlab_widgets-1.1.4.tar.gz", hash = "sha256:ea6e7612725e94d0966d64c6344910686f4bf8610533cd40daeba6980659b14d"}, + {file = "jupyterlab_widgets-1.1.7-py3-none-any.whl", hash = "sha256:0c4548cf42032e490447e4180f2c7d49ba5c30b42164992b38fb8c9d56c4e1b2"}, + {file = "jupyterlab_widgets-1.1.7.tar.gz", hash = "sha256:318dab34267915d658e7b0dc57433ff0ce0d52b3e283986b73b66f7ab9017ae8"}, ] [[package]] name = "jupytext" -version = "1.14.5" +version = "1.15.2" description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts" category = "main" optional = false python-versions = "~=3.6" files = [ - {file = "jupytext-1.14.5-py3-none-any.whl", hash = "sha256:a5dbe60d0ea158bbf82c2bce74aba8d0c220ad7edcda09e017c5eba229b34dc8"}, - {file = "jupytext-1.14.5.tar.gz", hash = "sha256:976e66be8056459a2067e0ec3ff68cc31e00c31895faf9eb893022d319e8f5b4"}, + {file = "jupytext-1.15.2-py3-none-any.whl", hash = "sha256:ef2a1a3eb8f63d84a3b3772014bdfbe238e4e12a30c4309b8c89e0a54adeb7d1"}, + {file = "jupytext-1.15.2.tar.gz", hash = "sha256:c9976e24d834e991906c1de55af4b6d512d764f6372aabae45fc1ea72b589173"}, ] [package.dependencies] -markdown-it-py = ">=1.0.0,<3.0.0" +markdown-it-py = ">=1.0.0" mdit-py-plugins = "*" nbformat = "*" pyyaml = "*" @@ -2159,91 +2173,128 @@ toml = ["toml"] [[package]] name = "keras" -version = "2.11.0" +version = "2.13.1" description = "Deep learning for humans." category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "keras-2.11.0-py2.py3-none-any.whl", hash = "sha256:38c6fff0ea9a8b06a2717736565c92a73c8cd9b1c239e7125ccb188b7848f65e"}, + {file = "keras-2.13.1-py3-none-any.whl", hash = "sha256:5ce5f706f779fa7330e63632f327b75ce38144a120376b2ae1917c00fa6136af"}, + {file = "keras-2.13.1.tar.gz", hash = "sha256:5df12cc241a015a11b65ddb452c0eeb2744fce21d9b54ba48db87492568ccc68"}, ] [[package]] name = "kiwisolver" -version = "1.4.4" +version = "1.4.5" description = "A fast implementation of the Cassowary constraint solver" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win32.whl", hash = "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win32.whl", hash = "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win32.whl", hash = "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win32.whl", hash = "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win32.whl", hash = "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"}, - {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] [[package]] @@ -2294,54 +2345,57 @@ files = [ [[package]] name = "libclang" -version = "16.0.0" +version = "16.0.6" description = "Clang Python Bindings, mirrored from the official LLVM repo: https://github.com/llvm/llvm-project/tree/main/clang/bindings/python, to make the installation process easier." category = "main" optional = true python-versions = "*" files = [ - {file = "libclang-16.0.0-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:65258a6bb3e7dc31dc9b26f8d42f53c9d3b959643ade291fcd1aef4855303ca6"}, - {file = "libclang-16.0.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:af55a4aa86fdfe6b2ec68bc8cfe5fdac6c448d591ca7648be86ca17099b41ca8"}, - {file = "libclang-16.0.0-py2.py3-none-manylinux2010_x86_64.whl", hash = "sha256:a043138caaf2cb076ebb060c6281ec95612926645d425c691991fc9df00e8a24"}, - {file = "libclang-16.0.0-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:eb59652cb0559c0e71784ff4c8ba24c14644becc907b1446563ecfaa622d523b"}, - {file = "libclang-16.0.0-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:7b6686b67a0daa84b4c614bcc119578329fc4fbb52b919565b7376b507c4793b"}, - {file = "libclang-16.0.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2adce42ae652f312245b8f4eda6f30b4076fb61f7619f2dfd0a0c31dee4c32b9"}, - {file = "libclang-16.0.0-py2.py3-none-win_amd64.whl", hash = "sha256:ee20bf93e3dd330f71fc50cdbf13b92ced0aec8e540be64251db53502a9b33f7"}, - {file = "libclang-16.0.0-py2.py3-none-win_arm64.whl", hash = "sha256:bf4628fc4da7a1dd06a244f9b8e121c5ec68076a763c59d6b13cbb103acc935b"}, + {file = "libclang-16.0.6-1-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:88bc7e7b393c32e41e03ba77ef02fdd647da1f764c2cd028e69e0837080b79f6"}, + {file = "libclang-16.0.6-1-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:d80ed5827736ed5ec2bcedf536720476fd9d4fa4c79ef0cb24aea4c59332f361"}, + {file = "libclang-16.0.6-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:da9e47ebc3f0a6d90fb169ef25f9fbcd29b4a4ef97a8b0e3e3a17800af1423f4"}, + {file = "libclang-16.0.6-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:e1a5ad1e895e5443e205568c85c04b4608e4e973dae42f4dfd9cb46c81d1486b"}, + {file = "libclang-16.0.6-py2.py3-none-manylinux2010_x86_64.whl", hash = "sha256:9dcdc730939788b8b69ffd6d5d75fe5366e3ee007f1e36a99799ec0b0c001492"}, + {file = "libclang-16.0.6-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:8130482120500476a027171f8f3c8dfc2536b591716eea71fc5da22cae13131b"}, + {file = "libclang-16.0.6-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:1e940048f51d0b0999099a9b78629ab8a64b62af5e9ff1b2b062439c21ee244d"}, + {file = "libclang-16.0.6-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f04e3060ae1f207f234d0608900c99c50edcb743e5e18276d78da2ddd727d39f"}, + {file = "libclang-16.0.6-py2.py3-none-win_amd64.whl", hash = "sha256:daab4a11dae228f1efa9efa3fe638b493b14d8d52c71fb3c7019e2f1df4514c2"}, + {file = "libclang-16.0.6-py2.py3-none-win_arm64.whl", hash = "sha256:4a9acbfd9c135a72f80d5dbff7588dfb0c81458244a89b9e83526e8595880e0a"}, + {file = "libclang-16.0.6.tar.gz", hash = "sha256:4acdde39dfe410c877b4ccc0d4b57eb952100e4ee26bbdf6cfdb88e2033a7d31"}, ] [[package]] name = "lightning-utilities" -version = "0.8.0" +version = "0.10.0" description = "PyTorch Lightning Sample project." category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "lightning-utilities-0.8.0.tar.gz", hash = "sha256:8e5d95c7c57f026cdfed7c154303e88c93a7a5e868c9944cb02cf71f1db29720"}, - {file = "lightning_utilities-0.8.0-py3-none-any.whl", hash = "sha256:22aa107b51c8f50ccef54d08885eb370903eb04148cddb2891b9c65c59de2a6e"}, + {file = "lightning-utilities-0.10.0.tar.gz", hash = "sha256:9e31617eccbbadc6b737a2432fd7076ff8e24957f9c63aeba2530b189e19319c"}, + {file = "lightning_utilities-0.10.0-py3-none-any.whl", hash = "sha256:84d09b11fe9bc16c803ae5e412874748239d73ad2f3d1b90862f99ce15a03aa0"}, ] [package.dependencies] packaging = ">=17.1" +setuptools = "*" typing-extensions = "*" [package.extras] cli = ["fire"] -docs = ["sphinx (>=4.0,<5.0)"] -test = ["coverage (==6.5.0)"] -typing = ["mypy (>=1.0.0)"] +docs = ["requests (>=2.0.0)"] +typing = ["mypy (>=1.0.0)", "types-setuptools"] [[package]] name = "mako" -version = "1.2.4" +version = "1.3.0" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Mako-1.2.4-py3-none-any.whl", hash = "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818"}, - {file = "Mako-1.2.4.tar.gz", hash = "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"}, + {file = "Mako-1.3.0-py3-none-any.whl", hash = "sha256:57d4e997349f1a92035aa25c17ace371a4213f2ca42f99bee9a602500cfd54d9"}, + {file = "Mako-1.3.0.tar.gz", hash = "sha256:e3a9d388fd00e87043edbe8792f45880ac0114e9c4adc69f6e9bfb2c55e3b11b"}, ] [package.dependencies] @@ -2354,32 +2408,33 @@ testing = ["pytest"] [[package]] name = "markdown" -version = "3.4.3" +version = "3.5.1" description = "Python implementation of John Gruber's Markdown." category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Markdown-3.4.3-py3-none-any.whl", hash = "sha256:065fd4df22da73a625f14890dd77eb8040edcbd68794bcd35943be14490608b2"}, - {file = "Markdown-3.4.3.tar.gz", hash = "sha256:8bf101198e004dc93e84a12a7395e31aac6a9c9942848ae1d99b9d72cf9b3520"}, + {file = "Markdown-3.5.1-py3-none-any.whl", hash = "sha256:5874b47d4ee3f0b14d764324d2c94c03ea66bee56f2d929da9f2508d65e722dc"}, + {file = "Markdown-3.5.1.tar.gz", hash = "sha256:b65d7beb248dc22f2e8a31fb706d93798093c308dc1aba295aedeb9d41a813bd"}, ] [package.dependencies] importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} [package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] [[package]] name = "markdown-it-py" -version = "2.2.0" +version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, - {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, ] [package.dependencies] @@ -2392,118 +2447,115 @@ compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0 linkify = ["linkify-it-py (>=1,<3)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.2" +version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"}, - {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"}, - {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"}, - {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"}, - {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"}, - {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"}, - {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] [[package]] name = "matplotlib" -version = "3.7.1" +version = "3.8.2" description = "Python plotting package" category = "main" optional = true -python-versions = ">=3.8" -files = [ - {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:95cbc13c1fc6844ab8812a525bbc237fa1470863ff3dace7352e910519e194b1"}, - {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:08308bae9e91aca1ec6fd6dda66237eef9f6294ddb17f0d0b3c863169bf82353"}, - {file = "matplotlib-3.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:544764ba51900da4639c0f983b323d288f94f65f4024dc40ecb1542d74dc0500"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56d94989191de3fcc4e002f93f7f1be5da476385dde410ddafbb70686acf00ea"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99bc9e65901bb9a7ce5e7bb24af03675cbd7c70b30ac670aa263240635999a4"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb7d248c34a341cd4c31a06fd34d64306624c8cd8d0def7abb08792a5abfd556"}, - {file = "matplotlib-3.7.1-cp310-cp310-win32.whl", hash = "sha256:ce463ce590f3825b52e9fe5c19a3c6a69fd7675a39d589e8b5fbe772272b3a24"}, - {file = "matplotlib-3.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:3d7bc90727351fb841e4d8ae620d2d86d8ed92b50473cd2b42ce9186104ecbba"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:770a205966d641627fd5cf9d3cb4b6280a716522cd36b8b284a8eb1581310f61"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f67bfdb83a8232cb7a92b869f9355d677bce24485c460b19d01970b64b2ed476"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2bf092f9210e105f414a043b92af583c98f50050559616930d884387d0772aba"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89768d84187f31717349c6bfadc0e0d8c321e8eb34522acec8a67b1236a66332"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83111e6388dec67822e2534e13b243cc644c7494a4bb60584edbff91585a83c6"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a867bf73a7eb808ef2afbca03bcdb785dae09595fbe550e1bab0cd023eba3de0"}, - {file = "matplotlib-3.7.1-cp311-cp311-win32.whl", hash = "sha256:fbdeeb58c0cf0595efe89c05c224e0a502d1aa6a8696e68a73c3efc6bc354304"}, - {file = "matplotlib-3.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:c0bd19c72ae53e6ab979f0ac6a3fafceb02d2ecafa023c5cca47acd934d10be7"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:6eb88d87cb2c49af00d3bbc33a003f89fd9f78d318848da029383bfc08ecfbfb"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:cf0e4f727534b7b1457898c4f4ae838af1ef87c359b76dcd5330fa31893a3ac7"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:46a561d23b91f30bccfd25429c3c706afe7d73a5cc64ef2dfaf2b2ac47c1a5dc"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8704726d33e9aa8a6d5215044b8d00804561971163563e6e6591f9dcf64340cc"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4cf327e98ecf08fcbb82685acaf1939d3338548620ab8dfa02828706402c34de"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:617f14ae9d53292ece33f45cba8503494ee199a75b44de7717964f70637a36aa"}, - {file = "matplotlib-3.7.1-cp38-cp38-win32.whl", hash = "sha256:7c9a4b2da6fac77bcc41b1ea95fadb314e92508bf5493ceff058e727e7ecf5b0"}, - {file = "matplotlib-3.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:14645aad967684e92fc349493fa10c08a6da514b3d03a5931a1bac26e6792bd1"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:81a6b377ea444336538638d31fdb39af6be1a043ca5e343fe18d0f17e098770b"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:28506a03bd7f3fe59cd3cd4ceb2a8d8a2b1db41afede01f66c42561b9be7b4b7"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c587963b85ce41e0a8af53b9b2de8dddbf5ece4c34553f7bd9d066148dc719c"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bf26ade3ff0f27668989d98c8435ce9327d24cffb7f07d24ef609e33d582439"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:def58098f96a05f90af7e92fd127d21a287068202aa43b2a93476170ebd99e87"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f883a22a56a84dba3b588696a2b8a1ab0d2c3d41be53264115c71b0a942d8fdb"}, - {file = "matplotlib-3.7.1-cp39-cp39-win32.whl", hash = "sha256:4f99e1b234c30c1e9714610eb0c6d2f11809c9c78c984a613ae539ea2ad2eb4b"}, - {file = "matplotlib-3.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:3ba2af245e36990facf67fde840a760128ddd71210b2ab6406e640188d69d136"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3032884084f541163f295db8a6536e0abb0db464008fadca6c98aaf84ccf4717"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a2cb34336110e0ed8bb4f650e817eed61fa064acbefeb3591f1b33e3a84fd96"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b867e2f952ed592237a1828f027d332d8ee219ad722345b79a001f49df0936eb"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:57bfb8c8ea253be947ccb2bc2d1bb3862c2bccc662ad1b4626e1f5e004557042"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:438196cdf5dc8d39b50a45cb6e3f6274edbcf2254f85fa9b895bf85851c3a613"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21e9cff1a58d42e74d01153360de92b326708fb205250150018a52c70f43c290"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75d4725d70b7c03e082bbb8a34639ede17f333d7247f56caceb3801cb6ff703d"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:97cc368a7268141afb5690760921765ed34867ffb9655dd325ed207af85c7529"}, - {file = "matplotlib-3.7.1.tar.gz", hash = "sha256:7b73305f25eab4541bd7ee0b96d87e53ae9c9f1823be5659b806cd85786fe882"}, +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"}, + {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"}, + {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"}, + {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"}, + {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"}, + {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"}, + {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"}, + {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"}, + {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"}, + {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"}, + {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"}, ] [package.dependencies] @@ -2511,10 +2563,10 @@ contourpy = ">=1.0.1" cycler = ">=0.10" fonttools = ">=4.22.0" importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} -kiwisolver = ">=1.0.1" -numpy = ">=1.20" +kiwisolver = ">=1.3.1" +numpy = ">=1.21,<2" packaging = ">=20.0" -pillow = ">=6.2.0" +pillow = ">=8" pyparsing = ">=2.3.1" python-dateutil = ">=2.7" @@ -2547,22 +2599,22 @@ files = [ [[package]] name = "mdit-py-plugins" -version = "0.3.5" +version = "0.4.0" description = "Collection of plugins for markdown-it-py" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"}, - {file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"}, + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, ] [package.dependencies] -markdown-it-py = ">=1.0.0,<3.0.0" +markdown-it-py = ">=1.0.0,<4.0.0" [package.extras] code-style = ["pre-commit"] -rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] +rtd = ["myst-parser", "sphinx-book-theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] @@ -2579,16 +2631,77 @@ files = [ [[package]] name = "mistune" -version = "2.0.5" -description = "A sane Markdown parser with useful plugins and renderers" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" category = "main" optional = false +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, +] + +[[package]] +name = "molbloom" +version = "2.1.0" +description = "Purchaseable SMILES filter" +category = "main" +optional = true python-versions = "*" files = [ - {file = "mistune-2.0.5-py2.py3-none-any.whl", hash = "sha256:bad7f5d431886fcbaf5f758118ecff70d31f75231b34024a1341120340a65ce8"}, - {file = "mistune-2.0.5.tar.gz", hash = "sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34"}, + {file = "molbloom-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6d59d4aa40eb2098d1627967670b0e9c4f9cc0291cc8e897e98f150229aa5318"}, + {file = "molbloom-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:48be11ff1edf517f9e780d728a0111505bfd920f99ff4e210143ec8ecff42e9e"}, + {file = "molbloom-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ea404eb8a99159f6050b470c94894c9a1d8c4c81799a92117f2e2e1dbc05db2"}, + {file = "molbloom-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f31694a2594987657649c7e3291acdfcc6adec2317bd5e8803fc86cc831f7512"}, + {file = "molbloom-2.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fa3ffe54c252fc6915b79a8fc19e91a2ffe578d92bfa1d6c21d552abafaa208"}, + {file = "molbloom-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8242208cdd5cbbab084d0a9a6c7a9a4d9ca35432f6ffe0a2d084caa310c753fd"}, + {file = "molbloom-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:039ffa32abe6ec0c8845a607fb02d73f8f6c753bed59596f168e845762706fe9"}, + {file = "molbloom-2.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1a7d2cb09a5d61f3d9a37d0558ffd769b338edb151ab17612a51e83eaacc3d79"}, + {file = "molbloom-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9b3e364a7b8ea2f5d2d369d98417c7cb39ffb038dfd99050715ca7ce680277dc"}, + {file = "molbloom-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77104f6e32f1e844ad7029c59f12679c2cc03c82c4b9bc837d5bd90c0648e03c"}, + {file = "molbloom-2.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:316077791bf1eab241b82524c9d2c98afc4823752080bdc5f62a75701efe1c57"}, + {file = "molbloom-2.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f84ebd2cb77c1bcd17952b17de8ae12a0fe6ac9f75a282c16063ef49170b80cf"}, + {file = "molbloom-2.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:78271771bcc93d3bc40722fd577e19df0f169a4c59bf674d942da2ee059d91d8"}, + {file = "molbloom-2.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:73ca2218def73398345a3fd04c5f25093ced2739c69c5e820240f41c77fc2e80"}, + {file = "molbloom-2.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b2241cbe8bf50750dd7441a8fb96c3111b4a81ca6725ef681bbf9aab923838ef"}, + {file = "molbloom-2.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ee08e4df933c69f13301791b56ebdd6d205d569fcd34fa8c4755a1c3e1470ba"}, + {file = "molbloom-2.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9828b7fe8b61f59af3a9b1d184a5862974219226aa4ede7be4f50820b1b0a7a7"}, + {file = "molbloom-2.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:82b0e4e9c5f1d57bbed2fdd7d7f9543ebef6c7e2853419f16829d471876b0be2"}, + {file = "molbloom-2.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:935e3bb98adda64b62628834c9cb58d44f2809c4976efffc6af6f1fbcececa9b"}, + {file = "molbloom-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:abbd156987507eb739f420f44c363d972ed7d789997b24948a95f0152fa8880a"}, + {file = "molbloom-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35e2a304ce740c09d7262fbfa414430faf39136d919887ea7133ab44fd55e252"}, + {file = "molbloom-2.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95d6b0c593d10b288fe3d30b9ab6e7f10272dd46f3e49464036b1b2763dbca1e"}, + {file = "molbloom-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:767ec2cf9e3c7a94b6261b92c019010fdf61fbd72e9cb12e023245a75b0a4ee5"}, + {file = "molbloom-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:51b701b64a62d8d4f9ec9d7c022bf3dce6f91e7f37290b78e668633fc28cdb88"}, + {file = "molbloom-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a54ae18528220d92dc7f02613d1b8c92a1a056600091e69d07b20508cf9bf7f5"}, + {file = "molbloom-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e5c5d475460841fecf5b1fefc6d42474cac2e817fd289b3c7be09aed9dffdefb"}, + {file = "molbloom-2.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3af69766521753238ef0d832f3daa32942a4bad04eaf13b427c2d51033c2a4fa"}, + {file = "molbloom-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92797d5160daf369d354e4335d46e05d8bb72d1c1581a9c551c3ecc1767ebc8c"}, + {file = "molbloom-2.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9effd177849c9c8c4e9cddae2294705a301fd2c99c6f062783311b7ea18484e7"}, + {file = "molbloom-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5046d57f4bc80c8f121a5491165955b162324356d56be255158c1e0e2774c1ba"}, + {file = "molbloom-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f88a910122e41e0df4ac602270ffd96fad4ee9d14ee0db3b17e75022d231d721"}, + {file = "molbloom-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:20cfb86ce96bec43138a2d9357bae4d71c53f46b2fd2afed288a4591c7b4ef96"}, + {file = "molbloom-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b704fed1968b68f2d7c0ae4abfceeb58418bee8891f0e83f3dfe184f9015bb2"}, + {file = "molbloom-2.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:344cc3633e6ab6aa64dd1bb18095d1c9b2b9c1927f68f4478e4294fd216aeef7"}, + {file = "molbloom-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11286b6a8319a4fcc3ac493c1aecdd5dc7d2589f5c4d12c663031349e04f0ec3"}, + {file = "molbloom-2.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d8d961003b7bf308776a999ab2bd6281cb4902f8c6b505707fe0acf6f22ab62"}, + {file = "molbloom-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:292dec78a88452b477a555d4a33f7b4ff77fb63d36ef1b06ccc639cbaf74d347"}, + {file = "molbloom-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b5068f8d1373644a2b695b20d375c535a359987124772fc3b475c4ccf3fb86e0"}, + {file = "molbloom-2.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6cab0506370f590c502d6655628aedca5217f6d574682f22407a1786c48fba83"}, + {file = "molbloom-2.1.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d24071c39d915bacfa50e842eee5509371db04b4c7a92fef61ae2eff57db0d3"}, + {file = "molbloom-2.1.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:802a4023666699c8adba4c37eeb9378dd6a041f814080674c9a7b61a72476023"}, + {file = "molbloom-2.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e0eb9381b8776ea34032c3cafb645e7835feefe09d57db9015152c587828af1f"}, + {file = "molbloom-2.1.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d2a6a5a80a4592f422ac2070bae2b92aaff7476b1377120c4f2704b8628ab1a"}, + {file = "molbloom-2.1.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f92bfe2f0f51b86f8a3331e25342c274c4e05120ee8977c09c00ac42ca165"}, + {file = "molbloom-2.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e93e3b3043592fb15b08c4196047df9d68c6d3b7ac665aa03f57ce8bf92c52d1"}, + {file = "molbloom-2.1.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b9758d433e1bf3e1d97b1c291a04b3f01be18fd7c5264128062fee975ef7b87"}, + {file = "molbloom-2.1.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:295aec7b5eb611d040c6b66c8d6f96c1a04f71edb1227fd901bcbff4dd13a40a"}, + {file = "molbloom-2.1.0.tar.gz", hash = "sha256:bd2eeb88ab935f04091e3f92604331b608f1ef36243fcf60fc2380029e1c03c6"}, ] +[package.dependencies] +importlib-resources = "*" + [[package]] name = "mpmath" version = "1.3.0" @@ -2609,75 +2722,68 @@ tests = ["pytest (>=4.6)"] [[package]] name = "msgpack" -version = "1.0.5" +version = "1.0.7" description = "MessagePack serializer" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:525228efd79bb831cf6830a732e2e80bc1b05436b086d4264814b4b2955b2fa9"}, - {file = "msgpack-1.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f8d8b3bf1ff2672567d6b5c725a1b347fe838b912772aa8ae2bf70338d5a198"}, - {file = "msgpack-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdc793c50be3f01106245a61b739328f7dccc2c648b501e237f0699fe1395b81"}, - {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cb47c21a8a65b165ce29f2bec852790cbc04936f502966768e4aae9fa763cb7"}, - {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e42b9594cc3bf4d838d67d6ed62b9e59e201862a25e9a157019e171fbe672dd3"}, - {file = "msgpack-1.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:55b56a24893105dc52c1253649b60f475f36b3aa0fc66115bffafb624d7cb30b"}, - {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1967f6129fc50a43bfe0951c35acbb729be89a55d849fab7686004da85103f1c"}, - {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a97bf595a232c3ee6d57ddaadd5453d174a52594bf9c21d10407e2a2d9b3bd"}, - {file = "msgpack-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d25dd59bbbbb996eacf7be6b4ad082ed7eacc4e8f3d2df1ba43822da9bfa122a"}, - {file = "msgpack-1.0.5-cp310-cp310-win32.whl", hash = "sha256:382b2c77589331f2cb80b67cc058c00f225e19827dbc818d700f61513ab47bea"}, - {file = "msgpack-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:4867aa2df9e2a5fa5f76d7d5565d25ec76e84c106b55509e78c1ede0f152659a"}, - {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9f5ae84c5c8a857ec44dc180a8b0cc08238e021f57abdf51a8182e915e6299f0"}, - {file = "msgpack-1.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e6ca5d5699bcd89ae605c150aee83b5321f2115695e741b99618f4856c50898"}, - {file = "msgpack-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5494ea30d517a3576749cad32fa27f7585c65f5f38309c88c6d137877fa28a5a"}, - {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ab2f3331cb1b54165976a9d976cb251a83183631c88076613c6c780f0d6e45a"}, - {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28592e20bbb1620848256ebc105fc420436af59515793ed27d5c77a217477705"}, - {file = "msgpack-1.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe5c63197c55bce6385d9aee16c4d0641684628f63ace85f73571e65ad1c1e8d"}, - {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed40e926fa2f297e8a653c954b732f125ef97bdd4c889f243182299de27e2aa9"}, - {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b2de4c1c0538dcb7010902a2b97f4e00fc4ddf2c8cda9749af0e594d3b7fa3d7"}, - {file = "msgpack-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf22a83f973b50f9d38e55c6aade04c41ddda19b00c4ebc558930d78eecc64ed"}, - {file = "msgpack-1.0.5-cp311-cp311-win32.whl", hash = "sha256:c396e2cc213d12ce017b686e0f53497f94f8ba2b24799c25d913d46c08ec422c"}, - {file = "msgpack-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c4c68d87497f66f96d50142a2b73b97972130d93677ce930718f68828b382e2"}, - {file = "msgpack-1.0.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a2b031c2e9b9af485d5e3c4520f4220d74f4d222a5b8dc8c1a3ab9448ca79c57"}, - {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f837b93669ce4336e24d08286c38761132bc7ab29782727f8557e1eb21b2080"}, - {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1d46dfe3832660f53b13b925d4e0fa1432b00f5f7210eb3ad3bb9a13c6204a6"}, - {file = "msgpack-1.0.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:366c9a7b9057e1547f4ad51d8facad8b406bab69c7d72c0eb6f529cf76d4b85f"}, - {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4c075728a1095efd0634a7dccb06204919a2f67d1893b6aa8e00497258bf926c"}, - {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:f933bbda5a3ee63b8834179096923b094b76f0c7a73c1cfe8f07ad608c58844b"}, - {file = "msgpack-1.0.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:36961b0568c36027c76e2ae3ca1132e35123dcec0706c4b7992683cc26c1320c"}, - {file = "msgpack-1.0.5-cp36-cp36m-win32.whl", hash = "sha256:b5ef2f015b95f912c2fcab19c36814963b5463f1fb9049846994b007962743e9"}, - {file = "msgpack-1.0.5-cp36-cp36m-win_amd64.whl", hash = "sha256:288e32b47e67f7b171f86b030e527e302c91bd3f40fd9033483f2cacc37f327a"}, - {file = "msgpack-1.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:137850656634abddfb88236008339fdaba3178f4751b28f270d2ebe77a563b6c"}, - {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c05a4a96585525916b109bb85f8cb6511db1c6f5b9d9cbcbc940dc6b4be944b"}, - {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a62ec00b636583e5cb6ad313bbed36bb7ead5fa3a3e38938503142c72cba4f"}, - {file = "msgpack-1.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef8108f8dedf204bb7b42994abf93882da1159728a2d4c5e82012edd92c9da9f"}, - {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1835c84d65f46900920b3708f5ba829fb19b1096c1800ad60bae8418652a951d"}, - {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e57916ef1bd0fee4f21c4600e9d1da352d8816b52a599c46460e93a6e9f17086"}, - {file = "msgpack-1.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:17358523b85973e5f242ad74aa4712b7ee560715562554aa2134d96e7aa4cbbf"}, - {file = "msgpack-1.0.5-cp37-cp37m-win32.whl", hash = "sha256:cb5aaa8c17760909ec6cb15e744c3ebc2ca8918e727216e79607b7bbce9c8f77"}, - {file = "msgpack-1.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:ab31e908d8424d55601ad7075e471b7d0140d4d3dd3272daf39c5c19d936bd82"}, - {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b72d0698f86e8d9ddf9442bdedec15b71df3598199ba33322d9711a19f08145c"}, - {file = "msgpack-1.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:379026812e49258016dd84ad79ac8446922234d498058ae1d415f04b522d5b2d"}, - {file = "msgpack-1.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:332360ff25469c346a1c5e47cbe2a725517919892eda5cfaffe6046656f0b7bb"}, - {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:476a8fe8fae289fdf273d6d2a6cb6e35b5a58541693e8f9f019bfe990a51e4ba"}, - {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9985b214f33311df47e274eb788a5893a761d025e2b92c723ba4c63936b69b1"}, - {file = "msgpack-1.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48296af57cdb1d885843afd73c4656be5c76c0c6328db3440c9601a98f303d87"}, - {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:addab7e2e1fcc04bd08e4eb631c2a90960c340e40dfc4a5e24d2ff0d5a3b3edb"}, - {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:916723458c25dfb77ff07f4c66aed34e47503b2eb3188b3adbec8d8aa6e00f48"}, - {file = "msgpack-1.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:821c7e677cc6acf0fd3f7ac664c98803827ae6de594a9f99563e48c5a2f27eb0"}, - {file = "msgpack-1.0.5-cp38-cp38-win32.whl", hash = "sha256:1c0f7c47f0087ffda62961d425e4407961a7ffd2aa004c81b9c07d9269512f6e"}, - {file = "msgpack-1.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:bae7de2026cbfe3782c8b78b0db9cbfc5455e079f1937cb0ab8d133496ac55e1"}, - {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:20c784e66b613c7f16f632e7b5e8a1651aa5702463d61394671ba07b2fc9e025"}, - {file = "msgpack-1.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:266fa4202c0eb94d26822d9bfd7af25d1e2c088927fe8de9033d929dd5ba24c5"}, - {file = "msgpack-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18334484eafc2b1aa47a6d42427da7fa8f2ab3d60b674120bce7a895a0a85bdd"}, - {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57e1f3528bd95cc44684beda696f74d3aaa8a5e58c816214b9046512240ef437"}, - {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:586d0d636f9a628ddc6a17bfd45aa5b5efaf1606d2b60fa5d87b8986326e933f"}, - {file = "msgpack-1.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a740fa0e4087a734455f0fc3abf5e746004c9da72fbd541e9b113013c8dc3282"}, - {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3055b0455e45810820db1f29d900bf39466df96ddca11dfa6d074fa47054376d"}, - {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a61215eac016f391129a013c9e46f3ab308db5f5ec9f25811e811f96962599a8"}, - {file = "msgpack-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:362d9655cd369b08fda06b6657a303eb7172d5279997abe094512e919cf74b11"}, - {file = "msgpack-1.0.5-cp39-cp39-win32.whl", hash = "sha256:ac9dd47af78cae935901a9a500104e2dea2e253207c924cc95de149606dc43cc"}, - {file = "msgpack-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:06f5174b5f8ed0ed919da0e62cbd4ffde676a374aba4020034da05fab67b9164"}, - {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, + {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862"}, + {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329"}, + {file = "msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b"}, + {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6"}, + {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee"}, + {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d"}, + {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d"}, + {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1"}, + {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681"}, + {file = "msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9"}, + {file = "msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415"}, + {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84"}, + {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93"}, + {file = "msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8"}, + {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46"}, + {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b"}, + {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e"}, + {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002"}, + {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c"}, + {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e"}, + {file = "msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1"}, + {file = "msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82"}, + {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b"}, + {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4"}, + {file = "msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee"}, + {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5"}, + {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672"}, + {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075"}, + {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba"}, + {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c"}, + {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5"}, + {file = "msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9"}, + {file = "msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf"}, + {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95"}, + {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0"}, + {file = "msgpack-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7"}, + {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d"}, + {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524"}, + {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc"}, + {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc"}, + {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf"}, + {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c"}, + {file = "msgpack-1.0.7-cp38-cp38-win32.whl", hash = "sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2"}, + {file = "msgpack-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c"}, + {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f"}, + {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81"}, + {file = "msgpack-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc"}, + {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d"}, + {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7"}, + {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61"}, + {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819"}, + {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd"}, + {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f"}, + {file = "msgpack-1.0.7-cp39-cp39-win32.whl", hash = "sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad"}, + {file = "msgpack-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3"}, + {file = "msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87"}, ] [[package]] @@ -2766,49 +2872,50 @@ files = [ [[package]] name = "mypy" -version = "1.2.0" +version = "1.7.0" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mypy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d"}, - {file = "mypy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba"}, - {file = "mypy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e"}, - {file = "mypy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a"}, - {file = "mypy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128"}, - {file = "mypy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41"}, - {file = "mypy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb"}, - {file = "mypy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937"}, - {file = "mypy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9"}, - {file = "mypy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602"}, - {file = "mypy-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140"}, - {file = "mypy-1.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336"}, - {file = "mypy-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e"}, - {file = "mypy-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119"}, - {file = "mypy-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a"}, - {file = "mypy-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950"}, - {file = "mypy-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6"}, - {file = "mypy-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5"}, - {file = "mypy-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8"}, - {file = "mypy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed"}, - {file = "mypy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f"}, - {file = "mypy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521"}, - {file = "mypy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238"}, - {file = "mypy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48"}, - {file = "mypy-1.2.0-py3-none-any.whl", hash = "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394"}, - {file = "mypy-1.2.0.tar.gz", hash = "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1"}, + {file = "mypy-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5da84d7bf257fd8f66b4f759a904fd2c5a765f70d8b52dde62b521972a0a2357"}, + {file = "mypy-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a3637c03f4025f6405737570d6cbfa4f1400eb3c649317634d273687a09ffc2f"}, + {file = "mypy-1.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b633f188fc5ae1b6edca39dae566974d7ef4e9aaaae00bc36efe1f855e5173ac"}, + {file = "mypy-1.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d6ed9a3997b90c6f891138e3f83fb8f475c74db4ccaa942a1c7bf99e83a989a1"}, + {file = "mypy-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:1fe46e96ae319df21359c8db77e1aecac8e5949da4773c0274c0ef3d8d1268a9"}, + {file = "mypy-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:df67fbeb666ee8828f675fee724cc2cbd2e4828cc3df56703e02fe6a421b7401"}, + {file = "mypy-1.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a79cdc12a02eb526d808a32a934c6fe6df07b05f3573d210e41808020aed8b5d"}, + {file = "mypy-1.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f65f385a6f43211effe8c682e8ec3f55d79391f70a201575def73d08db68ead1"}, + {file = "mypy-1.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e81ffd120ee24959b449b647c4b2fbfcf8acf3465e082b8d58fd6c4c2b27e46"}, + {file = "mypy-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:f29386804c3577c83d76520abf18cfcd7d68264c7e431c5907d250ab502658ee"}, + {file = "mypy-1.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:87c076c174e2c7ef8ab416c4e252d94c08cd4980a10967754f91571070bf5fbe"}, + {file = "mypy-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cb8d5f6d0fcd9e708bb190b224089e45902cacef6f6915481806b0c77f7786d"}, + {file = "mypy-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93e76c2256aa50d9c82a88e2f569232e9862c9982095f6d54e13509f01222fc"}, + {file = "mypy-1.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cddee95dea7990e2215576fae95f6b78a8c12f4c089d7e4367564704e99118d3"}, + {file = "mypy-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:d01921dbd691c4061a3e2ecdbfbfad029410c5c2b1ee88946bf45c62c6c91210"}, + {file = "mypy-1.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:185cff9b9a7fec1f9f7d8352dff8a4c713b2e3eea9c6c4b5ff7f0edf46b91e41"}, + {file = "mypy-1.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7b1e399c47b18feb6f8ad4a3eef3813e28c1e871ea7d4ea5d444b2ac03c418"}, + {file = "mypy-1.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9fe455ad58a20ec68599139ed1113b21f977b536a91b42bef3ffed5cce7391"}, + {file = "mypy-1.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d0fa29919d2e720c8dbaf07d5578f93d7b313c3e9954c8ec05b6d83da592e5d9"}, + {file = "mypy-1.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b53655a295c1ed1af9e96b462a736bf083adba7b314ae775563e3fb4e6795f5"}, + {file = "mypy-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1b06b4b109e342f7dccc9efda965fc3970a604db70f8560ddfdee7ef19afb05"}, + {file = "mypy-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bf7a2f0a6907f231d5e41adba1a82d7d88cf1f61a70335889412dec99feeb0f8"}, + {file = "mypy-1.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551d4a0cdcbd1d2cccdcc7cb516bb4ae888794929f5b040bb51aae1846062901"}, + {file = "mypy-1.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55d28d7963bef00c330cb6461db80b0b72afe2f3c4e2963c99517cf06454e665"}, + {file = "mypy-1.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:870bd1ffc8a5862e593185a4c169804f2744112b4a7c55b93eb50f48e7a77010"}, + {file = "mypy-1.7.0-py3-none-any.whl", hash = "sha256:96650d9a4c651bc2a4991cf46f100973f656d69edc7faf91844e87fe627f7e96"}, + {file = "mypy-1.7.0.tar.gz", hash = "sha256:1e280b5697202efa698372d2f39e9a6713a0395a756b1c6bd48995f8d72690dc"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=3.10" +typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] +mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] @@ -2825,14 +2932,14 @@ files = [ [[package]] name = "nbclassic" -version = "0.5.5" +version = "1.0.0" description = "Jupyter Notebook as a Jupyter Server extension." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "nbclassic-0.5.5-py3-none-any.whl", hash = "sha256:47791b04dbcb89bf7fde910a3d848fd4793a4248a8936202453631a87da37d51"}, - {file = "nbclassic-0.5.5.tar.gz", hash = "sha256:d2c91adc7909b0270c73e3e253d3687a6704b4f0a94bc156a37c85eba09f4d37"}, + {file = "nbclassic-1.0.0-py3-none-any.whl", hash = "sha256:f99e4769b4750076cd4235c044b61232110733322384a94a63791d2e7beacc66"}, + {file = "nbclassic-1.0.0.tar.gz", hash = "sha256:0ae11eb2319455d805596bf320336cda9554b41d99ab9a3c31bf8180bffa30e3"}, ] [package.dependencies] @@ -2846,7 +2953,7 @@ jupyter-server = ">=1.8" nbconvert = ">=5" nbformat = "*" nest-asyncio = ">=1.5" -notebook-shim = ">=0.1.0" +notebook-shim = ">=0.2.3" prometheus-client = "*" pyzmq = ">=17" Send2Trash = ">=1.8.0" @@ -2861,56 +2968,56 @@ test = ["coverage", "nbval", "pytest", "pytest-cov", "pytest-jupyter", "pytest-p [[package]] name = "nbclient" -version = "0.7.3" +version = "0.9.0" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." category = "main" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "nbclient-0.7.3-py3-none-any.whl", hash = "sha256:8fa96f7e36693d5e83408f5e840f113c14a45c279befe609904dbe05dad646d1"}, - {file = "nbclient-0.7.3.tar.gz", hash = "sha256:26e41c6dca4d76701988bc34f64e1bfc2413ae6d368f13d7b5ac407efb08c755"}, + {file = "nbclient-0.9.0-py3-none-any.whl", hash = "sha256:a3a1ddfb34d4a9d17fc744d655962714a866639acd30130e9be84191cd97cd15"}, + {file = "nbclient-0.9.0.tar.gz", hash = "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e"}, ] [package.dependencies] jupyter-client = ">=6.1.12" jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" nbformat = ">=5.1" -traitlets = ">=5.3" +traitlets = ">=5.4" [package.extras] dev = ["pre-commit"] docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] -test = ["flaky", "ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] [[package]] name = "nbconvert" -version = "7.3.1" +version = "7.11.0" description = "Converting Jupyter Notebooks" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "nbconvert-7.3.1-py3-none-any.whl", hash = "sha256:d2e95904666f1ff77d36105b9de4e0801726f93b862d5b28f69e93d99ad3b19c"}, - {file = "nbconvert-7.3.1.tar.gz", hash = "sha256:78685362b11d2e8058e70196fe83b09abed8df22d3e599cf271f4d39fdc48b9e"}, + {file = "nbconvert-7.11.0-py3-none-any.whl", hash = "sha256:d1d417b7f34a4e38887f8da5bdfd12372adf3b80f995d57556cb0972c68909fe"}, + {file = "nbconvert-7.11.0.tar.gz", hash = "sha256:abedc01cf543177ffde0bfc2a69726d5a478f6af10a332fc1bf29fcb4f0cf000"}, ] [package.dependencies] beautifulsoup4 = "*" -bleach = "*" +bleach = "!=5.0.0" defusedxml = "*" importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} jinja2 = ">=3.0" jupyter-core = ">=4.7" jupyterlab-pygments = "*" markupsafe = ">=2.0" -mistune = ">=2.0.3,<3" +mistune = ">=2.0.3,<4" nbclient = ">=0.5.0" -nbformat = ">=5.1" +nbformat = ">=5.7" packaging = "*" pandocfilters = ">=1.4.1" pygments = ">=2.4.1" tinycss2 = "*" -traitlets = ">=5.0" +traitlets = ">=5.1" [package.extras] all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] @@ -2918,19 +3025,19 @@ docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sp qtpdf = ["nbconvert[qtpng]"] qtpng = ["pyqtwebengine (>=5.15)"] serve = ["tornado (>=6.1)"] -test = ["ipykernel", "ipywidgets (>=7)", "pre-commit", "pytest", "pytest-dependency"] -webpdf = ["pyppeteer (>=1,<1.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest"] +webpdf = ["playwright"] [[package]] name = "nbformat" -version = "5.8.0" +version = "5.9.2" description = "The Jupyter Notebook format" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "nbformat-5.8.0-py3-none-any.whl", hash = "sha256:d910082bd3e0bffcf07eabf3683ed7dda0727a326c446eeb2922abe102e65162"}, - {file = "nbformat-5.8.0.tar.gz", hash = "sha256:46dac64c781f1c34dfd8acba16547024110348f9fc7eab0f31981c2a3dc48d1f"}, + {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"}, + {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"}, ] [package.dependencies] @@ -2943,16 +3050,31 @@ traitlets = ">=5.1" docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] test = ["pep440", "pre-commit", "pytest", "testpath"] +[[package]] +name = "ndindex" +version = "1.7" +description = "A Python library for manipulating indices of ndarrays." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ndindex-1.7-py3-none-any.whl", hash = "sha256:4c0555d352ac9947b0f022562aea9f5d57fa06743ea069669138f75a88b42884"}, + {file = "ndindex-1.7.tar.gz", hash = "sha256:bf9bd0b76eeada1c8275e04091f8291869ed2b373b7af48e56faf7579fd2efd2"}, +] + +[package.extras] +arrays = ["numpy"] + [[package]] name = "nest-asyncio" -version = "1.5.6" +version = "1.5.8" description = "Patch asyncio to allow nested event loops" category = "main" optional = false python-versions = ">=3.5" files = [ - {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, - {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, + {file = "nest_asyncio-1.5.8-py3-none-any.whl", hash = "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d"}, + {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, ] [[package]] @@ -2976,14 +3098,14 @@ test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "notebook" -version = "6.5.4" +version = "6.5.6" description = "A web-based notebook environment for interactive computing" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "notebook-6.5.4-py3-none-any.whl", hash = "sha256:dd17e78aefe64c768737b32bf171c1c766666a21cc79a44d37a1700771cab56f"}, - {file = "notebook-6.5.4.tar.gz", hash = "sha256:517209568bd47261e2def27a140e97d49070602eea0d226a696f42a7f16c9a4e"}, + {file = "notebook-6.5.6-py3-none-any.whl", hash = "sha256:c1e2eb2e3b6079a0552a04974883a48d04c3c05792170d64a4b23d707d453181"}, + {file = "notebook-6.5.6.tar.gz", hash = "sha256:b4625a4b7a597839dd3156b140d5ba2c7123761f98245a3290f67a8b8ee048d9"}, ] [package.dependencies] @@ -2991,14 +3113,14 @@ argon2-cffi = "*" ipykernel = "*" ipython-genutils = "*" jinja2 = "*" -jupyter-client = ">=5.3.4" +jupyter-client = ">=5.3.4,<8" jupyter-core = ">=4.6.1" nbclassic = ">=0.4.7" nbconvert = ">=5" nbformat = "*" nest-asyncio = ">=1.5" prometheus-client = "*" -pyzmq = ">=17" +pyzmq = ">=17,<25" Send2Trash = ">=1.8.0" terminado = ">=0.8.3" tornado = ">=6.1" @@ -3011,60 +3133,59 @@ test = ["coverage", "nbval", "pytest", "pytest-cov", "requests", "requests-unixs [[package]] name = "notebook-shim" -version = "0.2.2" +version = "0.2.3" description = "A shim layer for notebook traits and config" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "notebook_shim-0.2.2-py3-none-any.whl", hash = "sha256:9c6c30f74c4fbea6fce55c1be58e7fd0409b1c681b075dcedceb005db5026949"}, - {file = "notebook_shim-0.2.2.tar.gz", hash = "sha256:090e0baf9a5582ff59b607af523ca2db68ff216da0c69956b62cab2ef4fc9c3f"}, + {file = "notebook_shim-0.2.3-py3-none-any.whl", hash = "sha256:a83496a43341c1674b093bfcebf0fe8e74cbe7eda5fd2bbc56f8e39e1486c0c7"}, + {file = "notebook_shim-0.2.3.tar.gz", hash = "sha256:f69388ac283ae008cd506dda10d0288b09a017d822d5e8c7129a152cbd3ce7e9"}, ] [package.dependencies] jupyter-server = ">=1.8,<3" [package.extras] -test = ["pytest", "pytest-console-scripts", "pytest-tornasync"] +test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] [[package]] name = "numexpr" -version = "2.8.4" +version = "2.8.7" description = "Fast numerical expression evaluator for NumPy" category = "main" optional = false -python-versions = ">=3.7" -files = [ - {file = "numexpr-2.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a75967d46b6bd56455dd32da6285e5ffabe155d0ee61eef685bbfb8dafb2e484"}, - {file = "numexpr-2.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db93cf1842f068247de631bfc8af20118bf1f9447cd929b531595a5e0efc9346"}, - {file = "numexpr-2.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bca95f4473b444428061d4cda8e59ac564dc7dc6a1dea3015af9805c6bc2946"}, - {file = "numexpr-2.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e34931089a6bafc77aaae21f37ad6594b98aa1085bb8b45d5b3cd038c3c17d9"}, - {file = "numexpr-2.8.4-cp310-cp310-win32.whl", hash = "sha256:f3a920bfac2645017110b87ddbe364c9c7a742870a4d2f6120b8786c25dc6db3"}, - {file = "numexpr-2.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:6931b1e9d4f629f43c14b21d44f3f77997298bea43790cfcdb4dd98804f90783"}, - {file = "numexpr-2.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9400781553541f414f82eac056f2b4c965373650df9694286b9bd7e8d413f8d8"}, - {file = "numexpr-2.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ee9db7598dd4001138b482342b96d78110dd77cefc051ec75af3295604dde6a"}, - {file = "numexpr-2.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff5835e8af9a212e8480003d731aad1727aaea909926fd009e8ae6a1cba7f141"}, - {file = "numexpr-2.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:655d84eb09adfee3c09ecf4a89a512225da153fdb7de13c447404b7d0523a9a7"}, - {file = "numexpr-2.8.4-cp311-cp311-win32.whl", hash = "sha256:5538b30199bfc68886d2be18fcef3abd11d9271767a7a69ff3688defe782800a"}, - {file = "numexpr-2.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:3f039321d1c17962c33079987b675fb251b273dbec0f51aac0934e932446ccc3"}, - {file = "numexpr-2.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c867cc36cf815a3ec9122029874e00d8fbcef65035c4a5901e9b120dd5d626a2"}, - {file = "numexpr-2.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:059546e8f6283ccdb47c683101a890844f667fa6d56258d48ae2ecf1b3875957"}, - {file = "numexpr-2.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:845a6aa0ed3e2a53239b89c1ebfa8cf052d3cc6e053c72805e8153300078c0b1"}, - {file = "numexpr-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:a38664e699526cb1687aefd9069e2b5b9387da7feac4545de446141f1ef86f46"}, - {file = "numexpr-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eaec59e9bf70ff05615c34a8b8d6c7bd042bd9f55465d7b495ea5436f45319d0"}, - {file = "numexpr-2.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b318541bf3d8326682ebada087ba0050549a16d8b3fa260dd2585d73a83d20a7"}, - {file = "numexpr-2.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b076db98ca65eeaf9bd224576e3ac84c05e451c0bd85b13664b7e5f7b62e2c70"}, - {file = "numexpr-2.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f12cc851240f7911a47c91aaf223dba753e98e46dff3017282e633602e76a7"}, - {file = "numexpr-2.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c368aa35ae9b18840e78b05f929d3a7b3abccdba9630a878c7db74ca2368339"}, - {file = "numexpr-2.8.4-cp38-cp38-win32.whl", hash = "sha256:b96334fc1748e9ec4f93d5fadb1044089d73fb08208fdb8382ed77c893f0be01"}, - {file = "numexpr-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:a6d2d7740ae83ba5f3531e83afc4b626daa71df1ef903970947903345c37bd03"}, - {file = "numexpr-2.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:77898fdf3da6bb96aa8a4759a8231d763a75d848b2f2e5c5279dad0b243c8dfe"}, - {file = "numexpr-2.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df35324666b693f13a016bc7957de7cc4d8801b746b81060b671bf78a52b9037"}, - {file = "numexpr-2.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ac9cfe6d0078c5fc06ba1c1bbd20b8783f28c6f475bbabd3cad53683075cab"}, - {file = "numexpr-2.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3a1f6b24214a1ab826e9c1c99edf1686c8e307547a9aef33910d586f626d01"}, - {file = "numexpr-2.8.4-cp39-cp39-win32.whl", hash = "sha256:7d71add384adc9119568d7e9ffa8a35b195decae81e0abf54a2b7779852f0637"}, - {file = "numexpr-2.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:9f096d707290a6a00b6ffdaf581ee37331109fb7b6c8744e9ded7c779a48e517"}, - {file = "numexpr-2.8.4.tar.gz", hash = "sha256:d5432537418d18691b9115d615d6daa17ee8275baef3edf1afbbf8bc69806147"}, +python-versions = ">=3.9" +files = [ + {file = "numexpr-2.8.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d88531ffea3ea9287e8a1665c6a2d0206d3f4660d5244423e2a134a7f0ce5fba"}, + {file = "numexpr-2.8.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db1065ba663a854115cf1f493afd7206e2efcef6643129e8061e97a51ad66ebb"}, + {file = "numexpr-2.8.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4546416004ff2e7eb9cf52c2d7ab82732b1b505593193ee9f93fa770edc5230"}, + {file = "numexpr-2.8.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb2f473fdfd09d17db3038e34818d05b6bc561a36785aa927d6c0e06bccc9911"}, + {file = "numexpr-2.8.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5496fc9e3ae214637cbca1ab556b0e602bd3afe9ff4c943a29c482430972cda8"}, + {file = "numexpr-2.8.7-cp310-cp310-win32.whl", hash = "sha256:d43f1f0253a6f2db2f76214e6f7ae9611b422cba3f7d4c86415d7a78bbbd606f"}, + {file = "numexpr-2.8.7-cp310-cp310-win_amd64.whl", hash = "sha256:cf5f112bce5c5966c47cc33700bc14ce745c8351d437ed57a9574fff581f341a"}, + {file = "numexpr-2.8.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:32934d51b5bc8a6636436326da79ed380e2f151989968789cf65b1210572cb46"}, + {file = "numexpr-2.8.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f021ac93cb3dd5d8ba2882627b615b1f58cb089dcc85764c6fbe7a549ed21b0c"}, + {file = "numexpr-2.8.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dccf572763517db6562fb7b17db46aacbbf62a9ca0a66672872f4f71aee7b186"}, + {file = "numexpr-2.8.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11121b14ee3179bade92e823f25f1b94e18716d33845db5081973331188c3338"}, + {file = "numexpr-2.8.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81451962d4145a46dba189df65df101d4d1caddb6efe6ebfe05982cd9f62b2cf"}, + {file = "numexpr-2.8.7-cp311-cp311-win32.whl", hash = "sha256:da55ba845b847cc33c4bf81cee4b1bddfb0831118cabff8db62888ab8697ec34"}, + {file = "numexpr-2.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:fd93b88d5332069916fa00829ea1b972b7e73abcb1081eee5c905a514b8b59e3"}, + {file = "numexpr-2.8.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5340d2c86d83f52e1a3e7fd97c37d358ae99af9de316bdeeab2565b9b1e622ca"}, + {file = "numexpr-2.8.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3bdf8cbc00c77a46230c765d242f92d35905c239b20c256c48dbac91e49f253"}, + {file = "numexpr-2.8.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d46c47e361fa60966a3339cb4f463ae6151ce7d78ed38075f06e8585d2c8929f"}, + {file = "numexpr-2.8.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a371cfc1670a18eea2d5c70abaa95a0e8824b70d28da884bad11931266e3a0ca"}, + {file = "numexpr-2.8.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:47a249cecd1382d482a5bf1fac0d11392fb2ed0f7d415ebc4cd901959deb1ec9"}, + {file = "numexpr-2.8.7-cp312-cp312-win32.whl", hash = "sha256:b8a5b2c21c26b62875bf819d375d798b96a32644e3c28bd4ce7789ed1fb489da"}, + {file = "numexpr-2.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:f29f4d08d9b0ed6fa5d32082971294b2f9131b8577c2b7c36432ed670924313f"}, + {file = "numexpr-2.8.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ecaa5be24cf8fa0f00108e9dfa1021b7510e9dd9d159b8d8bc7c7ddbb995b31"}, + {file = "numexpr-2.8.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a84284e0a407ca52980fd20962e89aff671c84cd6e73458f2e29ea2aa206356"}, + {file = "numexpr-2.8.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e838289e3b7bbe100b99e35496e6cc4cc0541c2207078941ee5a1d46e6b925ae"}, + {file = "numexpr-2.8.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0983052f308ea75dd232eb7f4729eed839db8fe8d82289940342b32cc55b15d0"}, + {file = "numexpr-2.8.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8bf005acd7f1985c71b1b247aaac8950d6ea05a0fe0bbbbf3f96cd398b136daa"}, + {file = "numexpr-2.8.7-cp39-cp39-win32.whl", hash = "sha256:56ec95f8d1db0819e64987dcf1789acd500fa4ea396eeabe4af6efdcb8902d07"}, + {file = "numexpr-2.8.7-cp39-cp39-win_amd64.whl", hash = "sha256:c7bf60fc1a9c90a9cb21c4c235723e579bff70c8d5362228cb2cf34426104ba2"}, + {file = "numexpr-2.8.7.tar.gz", hash = "sha256:596eeb3bbfebc912f4b6eaaf842b61ba722cebdb8bc42dfefa657d3a74953849"}, ] [package.dependencies] @@ -3072,40 +3193,40 @@ numpy = ">=1.13.3" [[package]] name = "numpy" -version = "1.24.2" +version = "1.24.3" description = "Fundamental package for array computing in Python" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "numpy-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d"}, - {file = "numpy-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5"}, - {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253"}, - {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978"}, - {file = "numpy-1.24.2-cp310-cp310-win32.whl", hash = "sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9"}, - {file = "numpy-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0"}, - {file = "numpy-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a"}, - {file = "numpy-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0"}, - {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281"}, - {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910"}, - {file = "numpy-1.24.2-cp311-cp311-win32.whl", hash = "sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95"}, - {file = "numpy-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04"}, - {file = "numpy-1.24.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2"}, - {file = "numpy-1.24.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5"}, - {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a"}, - {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96"}, - {file = "numpy-1.24.2-cp38-cp38-win32.whl", hash = "sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d"}, - {file = "numpy-1.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756"}, - {file = "numpy-1.24.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a"}, - {file = "numpy-1.24.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f"}, - {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb"}, - {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780"}, - {file = "numpy-1.24.2-cp39-cp39-win32.whl", hash = "sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468"}, - {file = "numpy-1.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f"}, - {file = "numpy-1.24.2.tar.gz", hash = "sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22"}, + {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, + {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, + {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, + {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, + {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, + {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, + {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, + {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, + {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, + {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, + {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, + {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, + {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, + {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, + {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, + {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, + {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, + {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, + {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, + {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, + {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, + {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, + {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, + {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, + {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, ] [[package]] @@ -3192,43 +3313,36 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "onnxruntime" -version = "1.14.1" +version = "1.16.3" description = "ONNX Runtime is a runtime accelerator for Machine Learning models" category = "main" optional = false python-versions = "*" files = [ - {file = "onnxruntime-1.14.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:193ef1ac512e530c6e6e259c26e67212e2cd3f2bfaad6ff935ed3f4281053056"}, - {file = "onnxruntime-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d2853bbb36cb272d99f6c225e5040eb0ddb37a667fce20d186ecdf0a6fac8af8"}, - {file = "onnxruntime-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e1b173365c6894616b8207e23cbb891da9638c5373668d6653e4081ef5f04d0"}, - {file = "onnxruntime-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24bf0401c5f92be7230ac660ff07ba06f7c175e99e225d5d48ff09062a3b76e9"}, - {file = "onnxruntime-1.14.1-cp310-cp310-manylinux_2_27_aarch64.whl", hash = "sha256:0a2d09260bbdbe1df678e0a237a5f7b1a44fd11a2f52688d8b6a53a9d03a26db"}, - {file = "onnxruntime-1.14.1-cp310-cp310-manylinux_2_27_x86_64.whl", hash = "sha256:d99d35b9d5c3f46cad1673a39cc753fb57d60784369b59e6f8cd3dfb77df1885"}, - {file = "onnxruntime-1.14.1-cp310-cp310-win32.whl", hash = "sha256:f400356df1b27d9adc5513319e8a89753e48ef0d6c5084caf5db8e132f46e7e8"}, - {file = "onnxruntime-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:96a4059dbab162fe5cdb6750f8c70b2106ef2de5d49a7f72085171937d0e36d3"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:fa23df6a349218636290f9fe56d7baaceb1a50cf92255234d495198b47d92327"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc70e44d9e123d126648da24ffb39e56464272a1660a3eb91f4f5b74263be3ba"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deff8138045a3affb6be064b598e3ec69a88e4d445359c50464ee5379b8eaf19"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-manylinux_2_27_aarch64.whl", hash = "sha256:7c02acdc1107cbf698dcbf6dadc6f5b6aa179e7fa9a026251e99cf8613bd3129"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-manylinux_2_27_x86_64.whl", hash = "sha256:6efa3b2f4b1eaa6c714c07861993bfd9bb33bd73cdbcaf5b4aadcf1ec13fcaf7"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:72fc0acc82c54bf03eba065ad9025baa438c00c54a2ee0beb8ae4b6085cd3a0d"}, - {file = "onnxruntime-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4d6f08ea40d63ccf90f203f4a2a498f4e590737dcaf16867075cc8e0a86c5554"}, - {file = "onnxruntime-1.14.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:c2d9e8f1bc6037f14d8aaa480492792c262fc914936153e40b06b3667bb25549"}, - {file = "onnxruntime-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e7424d3befdd95b537c90787bbfaa053b2bb19eb60135abb898cb0e099d7d7ad"}, - {file = "onnxruntime-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9066d275e6e41d0597e234d2d88c074d4325e650c74a9527a52cadbcf42a0fe2"}, - {file = "onnxruntime-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8224d3c1f2cd0b899cea7b5a39f28b971debe0da30fcbc61382801d97d6f5740"}, - {file = "onnxruntime-1.14.1-cp38-cp38-manylinux_2_27_aarch64.whl", hash = "sha256:f4ac52ff4ac793683ebd1fbd1ee24197e3b4ca825ee68ff739296a820867debe"}, - {file = "onnxruntime-1.14.1-cp38-cp38-manylinux_2_27_x86_64.whl", hash = "sha256:b1dd8cdd3be36c32ddd8f5763841ed571c3e81da59439a622947bd97efee6e77"}, - {file = "onnxruntime-1.14.1-cp38-cp38-win32.whl", hash = "sha256:95d0f0cd95360c07f1c3ba20962b9bb813627df4bfc1b4b274e1d40044df5ad1"}, - {file = "onnxruntime-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:de40a558e00fc00f92e298d5be99eb8075dba51368dabcb259670a00f4670e56"}, - {file = "onnxruntime-1.14.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:c65b587a42a89fceceaad367bd69d071ee5c9c7010b76e2adac5e9efd9356fb5"}, - {file = "onnxruntime-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e47ef6a2c6e6dd6ff48bc13f2331d124dff00e1d76627624bb3268c8058f19c"}, - {file = "onnxruntime-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0afd0f671d068dd99b9d071d88e93a9a57a5ed59af440c0f4d65319ee791603f"}, - {file = "onnxruntime-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc65e9061349cdf98ce16b37722b557109f16076632fbfed9a3151895cfd3bb7"}, - {file = "onnxruntime-1.14.1-cp39-cp39-manylinux_2_27_aarch64.whl", hash = "sha256:2ff17c71187391a71e6ccc78ca89aed83bcaed1c085c95267ab1a70897868bdd"}, - {file = "onnxruntime-1.14.1-cp39-cp39-manylinux_2_27_x86_64.whl", hash = "sha256:9b795189916942ce848192200dde5b1f32799ee6c84fc600969a44d88e8a5404"}, - {file = "onnxruntime-1.14.1-cp39-cp39-win32.whl", hash = "sha256:17ca3100112af045118750d24643a01ed4e6d86071a8efaef75cc1d434ea64aa"}, - {file = "onnxruntime-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:b5e8c489329ba0fa0639dfd7ec02d6b07cece1bab52ef83884b537247efbda74"}, + {file = "onnxruntime-1.16.3-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:3bc41f323ac77acfed190be8ffdc47a6a75e4beeb3473fbf55eeb075ccca8df2"}, + {file = "onnxruntime-1.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:212741b519ee61a4822c79c47147d63a8b0ffde25cd33988d3d7be9fbd51005d"}, + {file = "onnxruntime-1.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f91f5497fe3df4ceee2f9e66c6148d9bfeb320cd6a71df361c66c5b8bac985a"}, + {file = "onnxruntime-1.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef2b1fc269cabd27f129fb9058917d6fdc89b188c49ed8700f300b945c81f889"}, + {file = "onnxruntime-1.16.3-cp310-cp310-win32.whl", hash = "sha256:f36b56a593b49a3c430be008c2aea6658d91a3030115729609ec1d5ffbaab1b6"}, + {file = "onnxruntime-1.16.3-cp310-cp310-win_amd64.whl", hash = "sha256:3c467eaa3d2429c026b10c3d17b78b7f311f718ef9d2a0d6938e5c3c2611b0cf"}, + {file = "onnxruntime-1.16.3-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:a225bb683991001d111f75323d355b3590e75e16b5e0f07a0401e741a0143ea1"}, + {file = "onnxruntime-1.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9aded21fe3d898edd86be8aa2eb995aa375e800ad3dfe4be9f618a20b8ee3630"}, + {file = "onnxruntime-1.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00cccc37a5195c8fca5011b9690b349db435986bd508eb44c9fce432da9228a4"}, + {file = "onnxruntime-1.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e253e572021563226a86f1c024f8f70cdae28f2fb1cc8c3a9221e8b1ce37db5"}, + {file = "onnxruntime-1.16.3-cp311-cp311-win32.whl", hash = "sha256:a82a8f0b4c978d08f9f5c7a6019ae51151bced9fd91e5aaa0c20a9e4ac7a60b6"}, + {file = "onnxruntime-1.16.3-cp311-cp311-win_amd64.whl", hash = "sha256:78d81d9af457a1dc90db9a7da0d09f3ccb1288ea1236c6ab19f0ca61f3eee2d3"}, + {file = "onnxruntime-1.16.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:04ebcd29c20473596a1412e471524b2fb88d55e6301c40b98dd2407b5911595f"}, + {file = "onnxruntime-1.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9996bab0f202a6435ab867bc55598f15210d0b72794d5de83712b53d564084ae"}, + {file = "onnxruntime-1.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b8f5083f903408238883821dd8c775f8120cb4a604166dbdabe97f4715256d5"}, + {file = "onnxruntime-1.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c2dcf1b70f8434abb1116fe0975c00e740722aaf321997195ea3618cc00558e"}, + {file = "onnxruntime-1.16.3-cp38-cp38-win32.whl", hash = "sha256:d4a0151e1accd04da6711f6fd89024509602f82c65a754498e960b032359b02d"}, + {file = "onnxruntime-1.16.3-cp38-cp38-win_amd64.whl", hash = "sha256:e8aa5bba78afbd4d8a2654b14ec7462ff3ce4a6aad312a3c2d2c2b65009f2541"}, + {file = "onnxruntime-1.16.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:6829dc2a79d48c911fedaf4c0f01e03c86297d32718a3fdee7a282766dfd282a"}, + {file = "onnxruntime-1.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:76f876c53bfa912c6c242fc38213a6f13f47612d4360bc9d599bd23753e53161"}, + {file = "onnxruntime-1.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4137e5d443e2dccebe5e156a47f1d6d66f8077b03587c35f11ee0c7eda98b533"}, + {file = "onnxruntime-1.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c56695c1a343c7c008b647fff3df44da63741fbe7b6003ef576758640719be7b"}, + {file = "onnxruntime-1.16.3-cp39-cp39-win32.whl", hash = "sha256:985a029798744ce4743fcf8442240fed35c8e4d4d30ec7d0c2cdf1388cd44408"}, + {file = "onnxruntime-1.16.3-cp39-cp39-win_amd64.whl", hash = "sha256:28ff758b17ce3ca6bcad3d936ec53bd7f5482e7630a13f6dcae518eba8f71d85"}, ] [package.dependencies] @@ -3294,16 +3408,28 @@ optional = ["bokeh (<2.0.0)", "matplotlib (>=3.0.0)", "pandas", "plotly (>=4.0.0 testing = ["allennlp (>=2.2.0,<2.7.0)", "bokeh (<2.0.0)", "botorch (>=0.4.0)", "catalyst (>=21.3)", "chainer (>=5.0.0)", "cma", "fakeredis", "fastai", "lightgbm", "matplotlib (>=3.0.0)", "mlflow", "mpi4py", "mxnet", "pandas", "plotly (>=4.0.0)", "pytest", "pytorch-ignite", "pytorch-lightning (>=1.0.2)", "scikit-learn (>=0.24.2,<1.0.0)", "scikit-optimize", "skorch", "tensorflow", "tensorflow-datasets", "torch (==1.8.0)", "torch (==1.8.0+cpu)", "torchaudio (==0.8.0)", "torchvision (==0.9.0)", "torchvision (==0.9.0+cpu)", "xgboost"] tests = ["fakeredis", "pytest"] +[[package]] +name = "overrides" +version = "7.4.0" +description = "A decorator to automatically detect mismatch when overriding a method." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "overrides-7.4.0-py3-none-any.whl", hash = "sha256:3ad24583f86d6d7a49049695efe9933e67ba62f0c7625d53c59fa832ce4b8b7d"}, + {file = "overrides-7.4.0.tar.gz", hash = "sha256:9502a3cca51f4fac40b5feca985b6703a5c1f6ad815588a7ca9e285b9dca6757"}, +] + [[package]] name = "packaging" -version = "23.0" +version = "23.2" description = "Core utilities for Python packages" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] [[package]] @@ -3344,7 +3470,10 @@ files = [ ] [package.dependencies] -numpy = {version = ">=1.20.3", markers = "python_version < \"3.10\""} +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, +] python-dateutil = ">=2.8.1" pytz = ">=2020.1" @@ -3381,26 +3510,26 @@ testing = ["docopt", "pytest (<6.0.0)"] [[package]] name = "pathspec" -version = "0.11.1" +version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] [[package]] name = "pbr" -version = "5.11.1" +version = "6.0.0" description = "Python Build Reasonableness" category = "main" optional = true python-versions = ">=2.6" files = [ - {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, - {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, + {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"}, + {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"}, ] [[package]] @@ -3418,18 +3547,6 @@ files = [ [package.dependencies] ptyprocess = ">=0.5" -[[package]] -name = "pickleshare" -version = "0.7.5" -description = "Tiny 'shelve'-like database with concurrency support" -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, -] - [[package]] name = "pillow" version = "9.5.0" @@ -3510,44 +3627,32 @@ files = [ docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] -[[package]] -name = "pkgutil-resolve-name" -version = "1.3.10" -description = "Resolve a name to an object." -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, - {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, -] - [[package]] name = "platformdirs" -version = "3.2.0" +version = "4.0.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, - {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, + {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, + {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, ] [package.extras] @@ -3556,14 +3661,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prettytable" -version = "3.7.0" +version = "3.9.0" description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "prettytable-3.7.0-py3-none-any.whl", hash = "sha256:f4aaf2ed6e6062a82fd2e6e5289bbbe705ec2788fe401a3a1f62a1cea55526d2"}, - {file = "prettytable-3.7.0.tar.gz", hash = "sha256:ef8334ee40b7ec721651fc4d37ecc7bb2ef55fde5098d994438f0dfdaa385c0c"}, + {file = "prettytable-3.9.0-py3-none-any.whl", hash = "sha256:a71292ab7769a5de274b146b276ce938786f56c31cf7cea88b6f3775d82fe8c8"}, + {file = "prettytable-3.9.0.tar.gz", hash = "sha256:f4ed94803c23073a90620b201965e5dc0bccf1760b7a7eaf3158cab8aaffdf34"}, ] [package.dependencies] @@ -3574,14 +3679,14 @@ tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"] [[package]] name = "prometheus-client" -version = "0.16.0" +version = "0.19.0" description = "Python client for the Prometheus monitoring system." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.16.0-py3-none-any.whl", hash = "sha256:0836af6eb2c8f4fed712b2f279f6c0a8bbab29f9f4aa15276b91c7cb0d1616ab"}, - {file = "prometheus_client-0.16.0.tar.gz", hash = "sha256:a03e35b359f14dd1630898543e2120addfdeacd1a6069c1367ae90fd93ad3f48"}, + {file = "prometheus_client-0.19.0-py3-none-any.whl", hash = "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92"}, + {file = "prometheus_client-0.19.0.tar.gz", hash = "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1"}, ] [package.extras] @@ -3589,14 +3694,14 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.38" +version = "3.0.41" description = "Library for building powerful interactive command lines in Python" category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"}, - {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"}, + {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, + {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, ] [package.dependencies] @@ -3604,61 +3709,49 @@ wcwidth = "*" [[package]] name = "protobuf" -version = "3.19.6" -description = "Protocol Buffers" +version = "4.25.1" +description = "" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "protobuf-3.19.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:010be24d5a44be7b0613750ab40bc8b8cedc796db468eae6c779b395f50d1fa1"}, - {file = "protobuf-3.19.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11478547958c2dfea921920617eb457bc26867b0d1aa065ab05f35080c5d9eb6"}, - {file = "protobuf-3.19.6-cp310-cp310-win32.whl", hash = "sha256:559670e006e3173308c9254d63facb2c03865818f22204037ab76f7a0ff70b5f"}, - {file = "protobuf-3.19.6-cp310-cp310-win_amd64.whl", hash = "sha256:347b393d4dd06fb93a77620781e11c058b3b0a5289262f094379ada2920a3730"}, - {file = "protobuf-3.19.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a8ce5ae0de28b51dff886fb922012dad885e66176663950cb2344c0439ecb473"}, - {file = "protobuf-3.19.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b0d02163c4e67279ddb6dc25e063db0130fc299aefabb5d481053509fae5c8"}, - {file = "protobuf-3.19.6-cp36-cp36m-win32.whl", hash = "sha256:30f5370d50295b246eaa0296533403961f7e64b03ea12265d6dfce3a391d8992"}, - {file = "protobuf-3.19.6-cp36-cp36m-win_amd64.whl", hash = "sha256:0c0714b025ec057b5a7600cb66ce7c693815f897cfda6d6efb58201c472e3437"}, - {file = "protobuf-3.19.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5057c64052a1f1dd7d4450e9aac25af6bf36cfbfb3a1cd89d16393a036c49157"}, - {file = "protobuf-3.19.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:bb6776bd18f01ffe9920e78e03a8676530a5d6c5911934c6a1ac6eb78973ecb6"}, - {file = "protobuf-3.19.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84a04134866861b11556a82dd91ea6daf1f4925746b992f277b84013a7cc1229"}, - {file = "protobuf-3.19.6-cp37-cp37m-win32.whl", hash = "sha256:4bc98de3cdccfb5cd769620d5785b92c662b6bfad03a202b83799b6ed3fa1fa7"}, - {file = "protobuf-3.19.6-cp37-cp37m-win_amd64.whl", hash = "sha256:aa3b82ca1f24ab5326dcf4ea00fcbda703e986b22f3d27541654f749564d778b"}, - {file = "protobuf-3.19.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2b2d2913bcda0e0ec9a784d194bc490f5dc3d9d71d322d070b11a0ade32ff6ba"}, - {file = "protobuf-3.19.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d0b635cefebd7a8a0f92020562dead912f81f401af7e71f16bf9506ff3bdbb38"}, - {file = "protobuf-3.19.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a552af4dc34793803f4e735aabe97ffc45962dfd3a237bdde242bff5a3de684"}, - {file = "protobuf-3.19.6-cp38-cp38-win32.whl", hash = "sha256:0469bc66160180165e4e29de7f445e57a34ab68f49357392c5b2f54c656ab25e"}, - {file = "protobuf-3.19.6-cp38-cp38-win_amd64.whl", hash = "sha256:91d5f1e139ff92c37e0ff07f391101df77e55ebb97f46bbc1535298d72019462"}, - {file = "protobuf-3.19.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c0ccd3f940fe7f3b35a261b1dd1b4fc850c8fde9f74207015431f174be5976b3"}, - {file = "protobuf-3.19.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:30a15015d86b9c3b8d6bf78d5b8c7749f2512c29f168ca259c9d7727604d0e39"}, - {file = "protobuf-3.19.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:878b4cd080a21ddda6ac6d1e163403ec6eea2e206cf225982ae04567d39be7b0"}, - {file = "protobuf-3.19.6-cp39-cp39-win32.whl", hash = "sha256:5a0d7539a1b1fb7e76bf5faa0b44b30f812758e989e59c40f77a7dab320e79b9"}, - {file = "protobuf-3.19.6-cp39-cp39-win_amd64.whl", hash = "sha256:bbf5cea5048272e1c60d235c7bd12ce1b14b8a16e76917f371c718bd3005f045"}, - {file = "protobuf-3.19.6-py2.py3-none-any.whl", hash = "sha256:14082457dc02be946f60b15aad35e9f5c69e738f80ebbc0900a19bc83734a5a4"}, - {file = "protobuf-3.19.6.tar.gz", hash = "sha256:5f5540d57a43042389e87661c6eaa50f47c19c6176e8cf1c4f287aeefeccb5c4"}, + {file = "protobuf-4.25.1-cp310-abi3-win32.whl", hash = "sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7"}, + {file = "protobuf-4.25.1-cp310-abi3-win_amd64.whl", hash = "sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b"}, + {file = "protobuf-4.25.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd"}, + {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb"}, + {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7"}, + {file = "protobuf-4.25.1-cp38-cp38-win32.whl", hash = "sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd"}, + {file = "protobuf-4.25.1-cp38-cp38-win_amd64.whl", hash = "sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0"}, + {file = "protobuf-4.25.1-cp39-cp39-win32.whl", hash = "sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510"}, + {file = "protobuf-4.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10"}, + {file = "protobuf-4.25.1-py3-none-any.whl", hash = "sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6"}, + {file = "protobuf-4.25.1.tar.gz", hash = "sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2"}, ] [[package]] name = "psutil" -version = "5.9.4" +version = "5.9.6" description = "Cross-platform lib for process and system monitoring in Python." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, - {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, - {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, - {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, - {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, - {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, - {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, - {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, - {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, - {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, - {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, - {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, - {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, - {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, + {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, + {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, + {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, + {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, + {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, + {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, + {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, + {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, + {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, + {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, ] [package.extras] @@ -3695,7 +3788,7 @@ tests = ["pytest"] name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3717,30 +3810,30 @@ files = [ [[package]] name = "pyasn1" -version = "0.4.8" -description = "ASN.1 types and codecs" +version = "0.5.1" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" category = "main" optional = true -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, - {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, + {file = "pyasn1-0.5.1-py2.py3-none-any.whl", hash = "sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58"}, + {file = "pyasn1-0.5.1.tar.gz", hash = "sha256:6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c"}, ] [[package]] name = "pyasn1-modules" -version = "0.2.8" -description = "A collection of ASN.1-based protocols modules." +version = "0.3.0" +description = "A collection of ASN.1-based protocols modules" category = "main" optional = true -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, - {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, + {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, + {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"}, ] [package.dependencies] -pyasn1 = ">=0.4.6,<0.5.0" +pyasn1 = ">=0.4.6,<0.6.0" [[package]] name = "pycparser" @@ -3756,48 +3849,48 @@ files = [ [[package]] name = "pydantic" -version = "1.10.7" +version = "1.10.13" description = "Data validation and settings management using python type hints" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, - {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, - {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, - {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, - {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, - {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, - {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, - {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, - {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, - {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, + {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, + {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, + {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, + {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, + {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, + {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, + {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, + {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, ] [package.dependencies] @@ -3809,33 +3902,34 @@ email = ["email-validator (>=1.0.3)"] [[package]] name = "pygments" -version = "2.15.0" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.15.0-py3-none-any.whl", hash = "sha256:77a3299119af881904cd5ecd1ac6a66214b6e9bed1f2db16993b54adede64094"}, - {file = "Pygments-2.15.0.tar.gz", hash = "sha256:f7e36cffc4c517fbc252861b9a6e4644ca0e5abadf9a113c72d1358ad09b9500"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "2.17.2" +version = "2.17.7" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "pylint-2.17.2-py3-none-any.whl", hash = "sha256:001cc91366a7df2970941d7e6bbefcbf98694e00102c1f121c531a814ddc2ea8"}, - {file = "pylint-2.17.2.tar.gz", hash = "sha256:1b647da5249e7c279118f657ca28b6aaebb299f86bf92affc632acf199f7adbb"}, + {file = "pylint-2.17.7-py3-none-any.whl", hash = "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87"}, + {file = "pylint-2.17.7.tar.gz", hash = "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad"}, ] [package.dependencies] -astroid = ">=2.15.2,<=2.17.0-dev0" +astroid = ">=2.15.8,<=2.17.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = {version = ">=0.2", markers = "python_version < \"3.11\""} isort = ">=4.2.5,<6" @@ -3980,14 +4074,14 @@ zstd = ["zstandard"] [[package]] name = "pyparsing" -version = "3.0.9" +version = "3.1.1" description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "main" optional = true python-versions = ">=3.6.8" files = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, ] [package.extras] @@ -4016,43 +4110,6 @@ files = [ {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, ] -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, - {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, - {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, - {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, - {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, - {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, -] - [[package]] name = "pytest" version = "6.2.5" @@ -4116,14 +4173,14 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-datadir" -version = "1.4.1" +version = "1.5.0" description = "pytest plugin for test data directories and files" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pytest-datadir-1.4.1.tar.gz", hash = "sha256:9f7a3c4def6ac4cac3cc8181139ab53bd2667231052bd40cb07081748d4420f0"}, - {file = "pytest_datadir-1.4.1-py3-none-any.whl", hash = "sha256:095f441782b1b907587eca7227fdbae94be43f1c96b4b2cbcc6801a4645be1af"}, + {file = "pytest-datadir-1.5.0.tar.gz", hash = "sha256:1617ed92f9afda0c877e4eac91904b5f779d24ba8f5e438752e3ae39d8d2ee3f"}, + {file = "pytest_datadir-1.5.0-py3-none-any.whl", hash = "sha256:34adf361bcc7b37961bbc1dfa8d25a4829e778bab461703c38a5c50ca9c36dc8"}, ] [package.dependencies] @@ -4147,14 +4204,14 @@ pytest = ">=5.4.0" [[package]] name = "pytest-mock" -version = "3.10.0" +version = "3.12.0" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, - {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, + {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, + {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, ] [package.dependencies] @@ -4192,14 +4249,14 @@ files = [ [[package]] name = "pytorch-lightning" -version = "1.9.4" +version = "1.9.5" description = "PyTorch Lightning is the lightweight PyTorch wrapper for ML researchers. Scale your models. Write less boilerplate." category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "pytorch-lightning-1.9.4.tar.gz", hash = "sha256:188a7f4468acf23512e7f4903253d86fc7929a49f0c09d699872e364162001e8"}, - {file = "pytorch_lightning-1.9.4-py3-none-any.whl", hash = "sha256:a2d2bd7657716087c294b076fe385ed17879764d6daaad0a541394a8f7164f93"}, + {file = "pytorch-lightning-1.9.5.tar.gz", hash = "sha256:925fe7b80ddf04859fa385aa493b260be4000b11a2f22447afb4a932d1f07d26"}, + {file = "pytorch_lightning-1.9.5-py3-none-any.whl", hash = "sha256:06821558158623c5d2ecf5d3d0374dc8bd661e0acd3acf54a6d6f71737c156c5"}, ] [package.dependencies] @@ -4214,17 +4271,17 @@ tqdm = ">=4.57.0" typing-extensions = ">=4.0.0" [package.extras] -all = ["colossalai (>=0.2.0)", "deepspeed (>=0.6.0)", "fairscale (>=0.4.5)", "gym[classic-control] (>=0.17.0)", "hivemind (==1.1.5)", "horovod (>=0.21.2,!=0.24.0)", "hydra-core (>=1.0.5)", "ipython[all] (<8.7.1)", "jsonargparse[signatures] (>=4.18.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "rich (>=10.14.0,!=10.15.0.a)", "tensorboardX (>=2.2)", "torchvision (>=0.11.1)"] +all = ["colossalai (>=0.2.0)", "deepspeed (>=0.6.0)", "fairscale (>=0.4.5)", "gym[classic-control] (>=0.17.0)", "hivemind (==1.1.5)", "horovod (>=0.21.2,!=0.24.0)", "hydra-core (>=1.0.5)", "ipython[all] (<8.7.1)", "jsonargparse[signatures] (>=4.18.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "rich (>=10.14.0,!=10.15.0.a)", "tensorboardX (>=2.2)", "torchmetrics (>=0.10.0)", "torchvision (>=0.11.1)"] colossalai = ["colossalai (>=0.2.0)"] deepspeed = ["deepspeed (>=0.6.0)"] -dev = ["cloudpickle (>=1.3)", "codecov (==2.1.12)", "colossalai (>=0.2.0)", "coverage (==6.5.0)", "deepspeed (>=0.6.0)", "fairscale (>=0.4.5)", "fastapi (<0.87.0)", "gym[classic-control] (>=0.17.0)", "hivemind (==1.1.5)", "horovod (>=0.21.2,!=0.24.0)", "hydra-core (>=1.0.5)", "ipython[all] (<8.7.1)", "jsonargparse[signatures] (>=4.18.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "onnxruntime (<1.14.0)", "pandas (>1.0)", "pre-commit (==2.20.0)", "protobuf (<=3.20.1)", "psutil (<5.9.5)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-forked (==1.4.0)", "pytest-rerunfailures (==10.3)", "rich (>=10.14.0,!=10.15.0.a)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "tensorboardX (>=2.2)", "torchvision (>=0.11.1)", "uvicorn (<0.19.1)"] -examples = ["gym[classic-control] (>=0.17.0)", "ipython[all] (<8.7.1)", "torchvision (>=0.11.1)"] +dev = ["cloudpickle (>=1.3)", "codecov (==2.1.12)", "colossalai (>=0.2.0)", "coverage (==6.5.0)", "deepspeed (>=0.6.0)", "fairscale (>=0.4.5)", "fastapi (<0.87.0)", "gym[classic-control] (>=0.17.0)", "hivemind (==1.1.5)", "horovod (>=0.21.2,!=0.24.0)", "hydra-core (>=1.0.5)", "ipython[all] (<8.7.1)", "jsonargparse[signatures] (>=4.18.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "onnx (<1.14.0)", "onnxruntime (<1.14.0)", "pandas (>1.0)", "pre-commit (==2.20.0)", "protobuf (<=3.20.1)", "psutil (<5.9.5)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-forked (==1.4.0)", "pytest-rerunfailures (==10.3)", "rich (>=10.14.0,!=10.15.0.a)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "tensorboardX (>=2.2)", "torchmetrics (>=0.10.0)", "torchvision (>=0.11.1)", "uvicorn (<0.19.1)"] +examples = ["gym[classic-control] (>=0.17.0)", "ipython[all] (<8.7.1)", "torchmetrics (>=0.10.0)", "torchvision (>=0.11.1)"] extra = ["hydra-core (>=1.0.5)", "jsonargparse[signatures] (>=4.18.0)", "matplotlib (>3.1)", "omegaconf (>=2.0.5)", "rich (>=10.14.0,!=10.15.0.a)", "tensorboardX (>=2.2)"] fairscale = ["fairscale (>=0.4.5)"] hivemind = ["hivemind (==1.1.5)"] horovod = ["horovod (>=0.21.2,!=0.24.0)"] strategies = ["colossalai (>=0.2.0)", "deepspeed (>=0.6.0)", "fairscale (>=0.4.5)", "hivemind (==1.1.5)", "horovod (>=0.21.2,!=0.24.0)"] -test = ["cloudpickle (>=1.3)", "codecov (==2.1.12)", "coverage (==6.5.0)", "fastapi (<0.87.0)", "onnxruntime (<1.14.0)", "pandas (>1.0)", "pre-commit (==2.20.0)", "protobuf (<=3.20.1)", "psutil (<5.9.5)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-forked (==1.4.0)", "pytest-rerunfailures (==10.3)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "uvicorn (<0.19.1)"] +test = ["cloudpickle (>=1.3)", "codecov (==2.1.12)", "coverage (==6.5.0)", "fastapi (<0.87.0)", "onnx (<1.14.0)", "onnxruntime (<1.14.0)", "pandas (>1.0)", "pre-commit (==2.20.0)", "protobuf (<=3.20.1)", "psutil (<5.9.5)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-forked (==1.4.0)", "pytest-rerunfailures (==10.3)", "scikit-learn (>0.22.1)", "tensorboard (>=2.9.1)", "uvicorn (<0.19.1)"] [[package]] name = "pytorch-tree-lstm" @@ -4244,14 +4301,14 @@ torch = "*" [[package]] name = "pytz" -version = "2023.3" +version = "2023.3.post1" description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] [[package]] @@ -4280,181 +4337,188 @@ files = [ [[package]] name = "pywinpty" -version = "2.0.10" +version = "2.0.12" description = "Pseudo terminal support for Windows from Python." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pywinpty-2.0.10-cp310-none-win_amd64.whl", hash = "sha256:4c7d06ad10f6e92bc850a467f26d98f4f30e73d2fe5926536308c6ae0566bc16"}, - {file = "pywinpty-2.0.10-cp311-none-win_amd64.whl", hash = "sha256:7ffbd66310b83e42028fc9df7746118978d94fba8c1ebf15a7c1275fdd80b28a"}, - {file = "pywinpty-2.0.10-cp37-none-win_amd64.whl", hash = "sha256:38cb924f2778b5751ef91a75febd114776b3af0ae411bc667be45dd84fc881d3"}, - {file = "pywinpty-2.0.10-cp38-none-win_amd64.whl", hash = "sha256:902d79444b29ad1833b8d5c3c9aabdfd428f4f068504430df18074007c8c0de8"}, - {file = "pywinpty-2.0.10-cp39-none-win_amd64.whl", hash = "sha256:3c46aef80dd50979aff93de199e4a00a8ee033ba7a03cadf0a91fed45f0c39d7"}, - {file = "pywinpty-2.0.10.tar.gz", hash = "sha256:cdbb5694cf8c7242c2ecfaca35c545d31fa5d5814c3d67a4e628f803f680ebea"}, + {file = "pywinpty-2.0.12-cp310-none-win_amd64.whl", hash = "sha256:21319cd1d7c8844fb2c970fb3a55a3db5543f112ff9cfcd623746b9c47501575"}, + {file = "pywinpty-2.0.12-cp311-none-win_amd64.whl", hash = "sha256:853985a8f48f4731a716653170cd735da36ffbdc79dcb4c7b7140bce11d8c722"}, + {file = "pywinpty-2.0.12-cp312-none-win_amd64.whl", hash = "sha256:1617b729999eb6713590e17665052b1a6ae0ad76ee31e60b444147c5b6a35dca"}, + {file = "pywinpty-2.0.12-cp38-none-win_amd64.whl", hash = "sha256:189380469ca143d06e19e19ff3fba0fcefe8b4a8cc942140a6b863aed7eebb2d"}, + {file = "pywinpty-2.0.12-cp39-none-win_amd64.whl", hash = "sha256:7520575b6546db23e693cbd865db2764097bd6d4ef5dc18c92555904cd62c3d4"}, + {file = "pywinpty-2.0.12.tar.gz", hash = "sha256:8197de460ae8ebb7f5d1701dfa1b5df45b157bb832e92acba316305e18ca00dd"}, ] [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] name = "pyzmq" -version = "25.0.2" +version = "24.0.1" description = "Python bindings for 0MQ" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "pyzmq-25.0.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ac178e666c097c8d3deb5097b58cd1316092fc43e8ef5b5fdb259b51da7e7315"}, - {file = "pyzmq-25.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:659e62e1cbb063151c52f5b01a38e1df6b54feccfa3e2509d44c35ca6d7962ee"}, - {file = "pyzmq-25.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8280ada89010735a12b968ec3ea9a468ac2e04fddcc1cede59cb7f5178783b9c"}, - {file = "pyzmq-25.0.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9b5eeb5278a8a636bb0abdd9ff5076bcbb836cd2302565df53ff1fa7d106d54"}, - {file = "pyzmq-25.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a2e5fe42dfe6b73ca120b97ac9f34bfa8414feb15e00e37415dbd51cf227ef6"}, - {file = "pyzmq-25.0.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:827bf60e749e78acb408a6c5af6688efbc9993e44ecc792b036ec2f4b4acf485"}, - {file = "pyzmq-25.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7b504ae43d37e282301da586529e2ded8b36d4ee2cd5e6db4386724ddeaa6bbc"}, - {file = "pyzmq-25.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb1f69a0a2a2b1aae8412979dd6293cc6bcddd4439bf07e4758d864ddb112354"}, - {file = "pyzmq-25.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b9c9cc965cdf28381e36da525dcb89fc1571d9c54800fdcd73e3f73a2fc29bd"}, - {file = "pyzmq-25.0.2-cp310-cp310-win32.whl", hash = "sha256:24abbfdbb75ac5039205e72d6c75f10fc39d925f2df8ff21ebc74179488ebfca"}, - {file = "pyzmq-25.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6a821a506822fac55d2df2085a52530f68ab15ceed12d63539adc32bd4410f6e"}, - {file = "pyzmq-25.0.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:9af0bb0277e92f41af35e991c242c9c71920169d6aa53ade7e444f338f4c8128"}, - {file = "pyzmq-25.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:54a96cf77684a3a537b76acfa7237b1e79a8f8d14e7f00e0171a94b346c5293e"}, - {file = "pyzmq-25.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88649b19ede1cab03b96b66c364cbbf17c953615cdbc844f7f6e5f14c5e5261c"}, - {file = "pyzmq-25.0.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:715cff7644a80a7795953c11b067a75f16eb9fc695a5a53316891ebee7f3c9d5"}, - {file = "pyzmq-25.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:312b3f0f066b4f1d17383aae509bacf833ccaf591184a1f3c7a1661c085063ae"}, - {file = "pyzmq-25.0.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d488c5c8630f7e782e800869f82744c3aca4aca62c63232e5d8c490d3d66956a"}, - {file = "pyzmq-25.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:38d9f78d69bcdeec0c11e0feb3bc70f36f9b8c44fc06e5d06d91dc0a21b453c7"}, - {file = "pyzmq-25.0.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3059a6a534c910e1d5d068df42f60d434f79e6cc6285aa469b384fa921f78cf8"}, - {file = "pyzmq-25.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6526d097b75192f228c09d48420854d53dfbc7abbb41b0e26f363ccb26fbc177"}, - {file = "pyzmq-25.0.2-cp311-cp311-win32.whl", hash = "sha256:5c5fbb229e40a89a2fe73d0c1181916f31e30f253cb2d6d91bea7927c2e18413"}, - {file = "pyzmq-25.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:ed15e3a2c3c2398e6ae5ce86d6a31b452dfd6ad4cd5d312596b30929c4b6e182"}, - {file = "pyzmq-25.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:032f5c8483c85bf9c9ca0593a11c7c749d734ce68d435e38c3f72e759b98b3c9"}, - {file = "pyzmq-25.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:374b55516393bfd4d7a7daa6c3b36d6dd6a31ff9d2adad0838cd6a203125e714"}, - {file = "pyzmq-25.0.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:08bfcc21b5997a9be4fefa405341320d8e7f19b4d684fb9c0580255c5bd6d695"}, - {file = "pyzmq-25.0.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1a843d26a8da1b752c74bc019c7b20e6791ee813cd6877449e6a1415589d22ff"}, - {file = "pyzmq-25.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b48616a09d7df9dbae2f45a0256eee7b794b903ddc6d8657a9948669b345f220"}, - {file = "pyzmq-25.0.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d4427b4a136e3b7f85516c76dd2e0756c22eec4026afb76ca1397152b0ca8145"}, - {file = "pyzmq-25.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:26b0358e8933990502f4513c991c9935b6c06af01787a36d133b7c39b1df37fa"}, - {file = "pyzmq-25.0.2-cp36-cp36m-win32.whl", hash = "sha256:c8fedc3ccd62c6b77dfe6f43802057a803a411ee96f14e946f4a76ec4ed0e117"}, - {file = "pyzmq-25.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:2da6813b7995b6b1d1307329c73d3e3be2fd2d78e19acfc4eff2e27262732388"}, - {file = "pyzmq-25.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a35960c8b2f63e4ef67fd6731851030df68e4b617a6715dd11b4b10312d19fef"}, - {file = "pyzmq-25.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2a0b880ab40aca5a878933376cb6c1ec483fba72f7f34e015c0f675c90b20"}, - {file = "pyzmq-25.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:85762712b74c7bd18e340c3639d1bf2f23735a998d63f46bb6584d904b5e401d"}, - {file = "pyzmq-25.0.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:64812f29d6eee565e129ca14b0c785744bfff679a4727137484101b34602d1a7"}, - {file = "pyzmq-25.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:510d8e55b3a7cd13f8d3e9121edf0a8730b87d925d25298bace29a7e7bc82810"}, - {file = "pyzmq-25.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b164cc3c8acb3d102e311f2eb6f3c305865ecb377e56adc015cb51f721f1dda6"}, - {file = "pyzmq-25.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:28fdb9224a258134784a9cf009b59265a9dde79582fb750d4e88a6bcbc6fa3dc"}, - {file = "pyzmq-25.0.2-cp37-cp37m-win32.whl", hash = "sha256:dd771a440effa1c36d3523bc6ba4e54ff5d2e54b4adcc1e060d8f3ca3721d228"}, - {file = "pyzmq-25.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:9bdc40efb679b9dcc39c06d25629e55581e4c4f7870a5e88db4f1c51ce25e20d"}, - {file = "pyzmq-25.0.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:1f82906a2d8e4ee310f30487b165e7cc8ed09c009e4502da67178b03083c4ce0"}, - {file = "pyzmq-25.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:21ec0bf4831988af43c8d66ba3ccd81af2c5e793e1bf6790eb2d50e27b3c570a"}, - {file = "pyzmq-25.0.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbce982a17c88d2312ec2cf7673985d444f1beaac6e8189424e0a0e0448dbb3"}, - {file = "pyzmq-25.0.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9e1d2f2d86fc75ed7f8845a992c5f6f1ab5db99747fb0d78b5e4046d041164d2"}, - {file = "pyzmq-25.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2e92ff20ad5d13266bc999a29ed29a3b5b101c21fdf4b2cf420c09db9fb690e"}, - {file = "pyzmq-25.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edbbf06cc2719889470a8d2bf5072bb00f423e12de0eb9ffec946c2c9748e149"}, - {file = "pyzmq-25.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77942243ff4d14d90c11b2afd8ee6c039b45a0be4e53fb6fa7f5e4fd0b59da39"}, - {file = "pyzmq-25.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ab046e9cb902d1f62c9cc0eca055b1d11108bdc271caf7c2171487298f229b56"}, - {file = "pyzmq-25.0.2-cp38-cp38-win32.whl", hash = "sha256:ad761cfbe477236802a7ab2c080d268c95e784fe30cafa7e055aacd1ca877eb0"}, - {file = "pyzmq-25.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:8560756318ec7c4c49d2c341012167e704b5a46d9034905853c3d1ade4f55bee"}, - {file = "pyzmq-25.0.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:ab2c056ac503f25a63f6c8c6771373e2a711b98b304614151dfb552d3d6c81f6"}, - {file = "pyzmq-25.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cca8524b61c0eaaa3505382dc9b9a3bc8165f1d6c010fdd1452c224225a26689"}, - {file = "pyzmq-25.0.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb9f7eae02d3ac42fbedad30006b7407c984a0eb4189a1322241a20944d61e5"}, - {file = "pyzmq-25.0.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5eaeae038c68748082137d6896d5c4db7927e9349237ded08ee1bbd94f7361c9"}, - {file = "pyzmq-25.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a31992a8f8d51663ebf79df0df6a04ffb905063083d682d4380ab8d2c67257c"}, - {file = "pyzmq-25.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6a979e59d2184a0c8f2ede4b0810cbdd86b64d99d9cc8a023929e40dce7c86cc"}, - {file = "pyzmq-25.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1f124cb73f1aa6654d31b183810febc8505fd0c597afa127c4f40076be4574e0"}, - {file = "pyzmq-25.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:65c19a63b4a83ae45d62178b70223adeee5f12f3032726b897431b6553aa25af"}, - {file = "pyzmq-25.0.2-cp39-cp39-win32.whl", hash = "sha256:83d822e8687621bed87404afc1c03d83fa2ce39733d54c2fd52d8829edb8a7ff"}, - {file = "pyzmq-25.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:24683285cc6b7bf18ad37d75b9db0e0fefe58404e7001f1d82bf9e721806daa7"}, - {file = "pyzmq-25.0.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a4b4261eb8f9ed71f63b9eb0198dd7c934aa3b3972dac586d0ef502ba9ab08b"}, - {file = "pyzmq-25.0.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:62ec8d979f56c0053a92b2b6a10ff54b9ec8a4f187db2b6ec31ee3dd6d3ca6e2"}, - {file = "pyzmq-25.0.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:affec1470351178e892121b3414c8ef7803269f207bf9bef85f9a6dd11cde264"}, - {file = "pyzmq-25.0.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffc71111433bd6ec8607a37b9211f4ef42e3d3b271c6d76c813669834764b248"}, - {file = "pyzmq-25.0.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6fadc60970714d86eff27821f8fb01f8328dd36bebd496b0564a500fe4a9e354"}, - {file = "pyzmq-25.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:269968f2a76c0513490aeb3ba0dc3c77b7c7a11daa894f9d1da88d4a0db09835"}, - {file = "pyzmq-25.0.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f7c8b8368e84381ae7c57f1f5283b029c888504aaf4949c32e6e6fb256ec9bf0"}, - {file = "pyzmq-25.0.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25e6873a70ad5aa31e4a7c41e5e8c709296edef4a92313e1cd5fc87bbd1874e2"}, - {file = "pyzmq-25.0.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b733076ff46e7db5504c5e7284f04a9852c63214c74688bdb6135808531755a3"}, - {file = "pyzmq-25.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a6f6ae12478fdc26a6d5fdb21f806b08fa5403cd02fd312e4cb5f72df078f96f"}, - {file = "pyzmq-25.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:67da1c213fbd208906ab3470cfff1ee0048838365135a9bddc7b40b11e6d6c89"}, - {file = "pyzmq-25.0.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531e36d9fcd66f18de27434a25b51d137eb546931033f392e85674c7a7cea853"}, - {file = "pyzmq-25.0.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34a6fddd159ff38aa9497b2e342a559f142ab365576284bc8f77cb3ead1f79c5"}, - {file = "pyzmq-25.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b491998ef886662c1f3d49ea2198055a9a536ddf7430b051b21054f2a5831800"}, - {file = "pyzmq-25.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5d496815074e3e3d183fe2c7fcea2109ad67b74084c254481f87b64e04e9a471"}, - {file = "pyzmq-25.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:56a94ab1d12af982b55ca96c6853db6ac85505e820d9458ac76364c1998972f4"}, - {file = "pyzmq-25.0.2.tar.gz", hash = "sha256:6b8c1bbb70e868dc88801aa532cae6bd4e3b5233784692b786f17ad2962e5149"}, + {file = "pyzmq-24.0.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:28b119ba97129d3001673a697b7cce47fe6de1f7255d104c2f01108a5179a066"}, + {file = "pyzmq-24.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bcbebd369493d68162cddb74a9c1fcebd139dfbb7ddb23d8f8e43e6c87bac3a6"}, + {file = "pyzmq-24.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae61446166983c663cee42c852ed63899e43e484abf080089f771df4b9d272ef"}, + {file = "pyzmq-24.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f7ac99b15270db8d53f28c3c7b968612993a90a5cf359da354efe96f5372b4"}, + {file = "pyzmq-24.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9dca7c3956b03b7663fac4d150f5e6d4f6f38b2462c1e9afd83bcf7019f17913"}, + {file = "pyzmq-24.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8c78bfe20d4c890cb5580a3b9290f700c570e167d4cdcc55feec07030297a5e3"}, + {file = "pyzmq-24.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:48f721f070726cd2a6e44f3c33f8ee4b24188e4b816e6dd8ba542c8c3bb5b246"}, + {file = "pyzmq-24.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:afe1f3bc486d0ce40abb0a0c9adb39aed3bbac36ebdc596487b0cceba55c21c1"}, + {file = "pyzmq-24.0.1-cp310-cp310-win32.whl", hash = "sha256:3e6192dbcefaaa52ed81be88525a54a445f4b4fe2fffcae7fe40ebb58bd06bfd"}, + {file = "pyzmq-24.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:86de64468cad9c6d269f32a6390e210ca5ada568c7a55de8e681ca3b897bb340"}, + {file = "pyzmq-24.0.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:838812c65ed5f7c2bd11f7b098d2e5d01685a3f6d1f82849423b570bae698c00"}, + {file = "pyzmq-24.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfb992dbcd88d8254471760879d48fb20836d91baa90f181c957122f9592b3dc"}, + {file = "pyzmq-24.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7abddb2bd5489d30ffeb4b93a428130886c171b4d355ccd226e83254fcb6b9ef"}, + {file = "pyzmq-24.0.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94010bd61bc168c103a5b3b0f56ed3b616688192db7cd5b1d626e49f28ff51b3"}, + {file = "pyzmq-24.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8242543c522d84d033fe79be04cb559b80d7eb98ad81b137ff7e0a9020f00ace"}, + {file = "pyzmq-24.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ccb94342d13e3bf3ffa6e62f95b5e3f0bc6bfa94558cb37f4b3d09d6feb536ff"}, + {file = "pyzmq-24.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6640f83df0ae4ae1104d4c62b77e9ef39be85ebe53f636388707d532bee2b7b8"}, + {file = "pyzmq-24.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a180dbd5ea5d47c2d3b716d5c19cc3fb162d1c8db93b21a1295d69585bfddac1"}, + {file = "pyzmq-24.0.1-cp311-cp311-win32.whl", hash = "sha256:624321120f7e60336be8ec74a172ae7fba5c3ed5bf787cc85f7e9986c9e0ebc2"}, + {file = "pyzmq-24.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:1724117bae69e091309ffb8255412c4651d3f6355560d9af312d547f6c5bc8b8"}, + {file = "pyzmq-24.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:15975747462ec49fdc863af906bab87c43b2491403ab37a6d88410635786b0f4"}, + {file = "pyzmq-24.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b947e264f0e77d30dcbccbb00f49f900b204b922eb0c3a9f0afd61aaa1cedc3d"}, + {file = "pyzmq-24.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ec91f1bad66f3ee8c6deb65fa1fe418e8ad803efedd69c35f3b5502f43bd1dc"}, + {file = "pyzmq-24.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:db03704b3506455d86ec72c3358a779e9b1d07b61220dfb43702b7b668edcd0d"}, + {file = "pyzmq-24.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e7e66b4e403c2836ac74f26c4b65d8ac0ca1eef41dfcac2d013b7482befaad83"}, + {file = "pyzmq-24.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7a23ccc1083c260fa9685c93e3b170baba45aeed4b524deb3f426b0c40c11639"}, + {file = "pyzmq-24.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fa0ae3275ef706c0309556061185dd0e4c4cd3b7d6f67ae617e4e677c7a41e2e"}, + {file = "pyzmq-24.0.1-cp36-cp36m-win32.whl", hash = "sha256:f01de4ec083daebf210531e2cca3bdb1608dbbbe00a9723e261d92087a1f6ebc"}, + {file = "pyzmq-24.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:de4217b9eb8b541cf2b7fde4401ce9d9a411cc0af85d410f9d6f4333f43640be"}, + {file = "pyzmq-24.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:78068e8678ca023594e4a0ab558905c1033b2d3e806a0ad9e3094e231e115a33"}, + {file = "pyzmq-24.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77c2713faf25a953c69cf0f723d1b7dd83827b0834e6c41e3fb3bbc6765914a1"}, + {file = "pyzmq-24.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bb4af15f305056e95ca1bd086239b9ebc6ad55e9f49076d27d80027f72752f6"}, + {file = "pyzmq-24.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0f14cffd32e9c4c73da66db97853a6aeceaac34acdc0fae9e5bbc9370281864c"}, + {file = "pyzmq-24.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0108358dab8c6b27ff6b985c2af4b12665c1bc659648284153ee501000f5c107"}, + {file = "pyzmq-24.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d66689e840e75221b0b290b0befa86f059fb35e1ee6443bce51516d4d61b6b99"}, + {file = "pyzmq-24.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ae08ac90aa8fa14caafc7a6251bd218bf6dac518b7bff09caaa5e781119ba3f2"}, + {file = "pyzmq-24.0.1-cp37-cp37m-win32.whl", hash = "sha256:8421aa8c9b45ea608c205db9e1c0c855c7e54d0e9c2c2f337ce024f6843cab3b"}, + {file = "pyzmq-24.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54d8b9c5e288362ec8595c1d98666d36f2070fd0c2f76e2b3c60fbad9bd76227"}, + {file = "pyzmq-24.0.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:acbd0a6d61cc954b9f535daaa9ec26b0a60a0d4353c5f7c1438ebc88a359a47e"}, + {file = "pyzmq-24.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:47b11a729d61a47df56346283a4a800fa379ae6a85870d5a2e1e4956c828eedc"}, + {file = "pyzmq-24.0.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abe6eb10122f0d746a0d510c2039ae8edb27bc9af29f6d1b05a66cc2401353ff"}, + {file = "pyzmq-24.0.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:07bec1a1b22dacf718f2c0e71b49600bb6a31a88f06527dfd0b5aababe3fa3f7"}, + {file = "pyzmq-24.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d945a85b70da97ae86113faf9f1b9294efe66bd4a5d6f82f2676d567338b66"}, + {file = "pyzmq-24.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1b7928bb7580736ffac5baf814097be342ba08d3cfdfb48e52773ec959572287"}, + {file = "pyzmq-24.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b946da90dc2799bcafa682692c1d2139b2a96ec3c24fa9fc6f5b0da782675330"}, + {file = "pyzmq-24.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c8840f064b1fb377cffd3efeaad2b190c14d4c8da02316dae07571252d20b31f"}, + {file = "pyzmq-24.0.1-cp38-cp38-win32.whl", hash = "sha256:4854f9edc5208f63f0841c0c667260ae8d6846cfa233c479e29fdc85d42ebd58"}, + {file = "pyzmq-24.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:42d4f97b9795a7aafa152a36fe2ad44549b83a743fd3e77011136def512e6c2a"}, + {file = "pyzmq-24.0.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:52afb0ac962963fff30cf1be775bc51ae083ef4c1e354266ab20e5382057dd62"}, + {file = "pyzmq-24.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bad8210ad4df68c44ff3685cca3cda448ee46e20d13edcff8909eba6ec01ca4"}, + {file = "pyzmq-24.0.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dabf1a05318d95b1537fd61d9330ef4313ea1216eea128a17615038859da3b3b"}, + {file = "pyzmq-24.0.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5bd3d7dfd9cd058eb68d9a905dec854f86649f64d4ddf21f3ec289341386c44b"}, + {file = "pyzmq-24.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8012bce6836d3f20a6c9599f81dfa945f433dab4dbd0c4917a6fb1f998ab33d"}, + {file = "pyzmq-24.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c31805d2c8ade9b11feca4674eee2b9cce1fec3e8ddb7bbdd961a09dc76a80ea"}, + {file = "pyzmq-24.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3104f4b084ad5d9c0cb87445cc8cfd96bba710bef4a66c2674910127044df209"}, + {file = "pyzmq-24.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:df0841f94928f8af9c7a1f0aaaffba1fb74607af023a152f59379c01c53aee58"}, + {file = "pyzmq-24.0.1-cp39-cp39-win32.whl", hash = "sha256:a435ef8a3bd95c8a2d316d6e0ff70d0db524f6037411652803e118871d703333"}, + {file = "pyzmq-24.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:2032d9cb994ce3b4cba2b8dfae08c7e25bc14ba484c770d4d3be33c27de8c45b"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bb5635c851eef3a7a54becde6da99485eecf7d068bd885ac8e6d173c4ecd68b0"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:83ea1a398f192957cb986d9206ce229efe0ee75e3c6635baff53ddf39bd718d5"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:941fab0073f0a54dc33d1a0460cb04e0d85893cb0c5e1476c785000f8b359409"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e8f482c44ccb5884bf3f638f29bea0f8dc68c97e38b2061769c4cb697f6140d"}, + {file = "pyzmq-24.0.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:613010b5d17906c4367609e6f52e9a2595e35d5cc27d36ff3f1b6fa6e954d944"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:65c94410b5a8355cfcf12fd600a313efee46ce96a09e911ea92cf2acf6708804"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:20e7eeb1166087db636c06cae04a1ef59298627f56fb17da10528ab52a14c87f"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2712aee7b3834ace51738c15d9ee152cc5a98dc7d57dd93300461b792ab7b43"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a7c280185c4da99e0cc06c63bdf91f5b0b71deb70d8717f0ab870a43e376db8"}, + {file = "pyzmq-24.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:858375573c9225cc8e5b49bfac846a77b696b8d5e815711b8d4ba3141e6e8879"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:80093b595921eed1a2cead546a683b9e2ae7f4a4592bb2ab22f70d30174f003a"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f3f3154fde2b1ff3aa7b4f9326347ebc89c8ef425ca1db8f665175e6d3bd42f"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abb756147314430bee5d10919b8493c0ccb109ddb7f5dfd2fcd7441266a25b75"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44e706bac34e9f50779cb8c39f10b53a4d15aebb97235643d3112ac20bd577b4"}, + {file = "pyzmq-24.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:687700f8371643916a1d2c61f3fdaa630407dd205c38afff936545d7b7466066"}, + {file = "pyzmq-24.0.1.tar.gz", hash = "sha256:216f5d7dbb67166759e59b0479bca82b8acf9bed6015b526b8eb10143fb08e77"}, ] [package.dependencies] cffi = {version = "*", markers = "implementation_name == \"pypy\""} +py = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "qtconsole" -version = "5.4.2" +version = "5.5.1" description = "Jupyter Qt console" category = "main" optional = false -python-versions = ">= 3.7" +python-versions = ">= 3.8" files = [ - {file = "qtconsole-5.4.2-py3-none-any.whl", hash = "sha256:30975c6a7d7941dd646d00a23e5982db49beaa60c3920bb243727d43da805f12"}, - {file = "qtconsole-5.4.2.tar.gz", hash = "sha256:dc935780da276a2ab31a7a08a8cf327a2ea47fa27e21d485073251a7eeb16167"}, + {file = "qtconsole-5.5.1-py3-none-any.whl", hash = "sha256:8c75fa3e9b4ed884880ff7cea90a1b67451219279ec33deaee1d59e3df1a5d2b"}, + {file = "qtconsole-5.5.1.tar.gz", hash = "sha256:a0e806c6951db9490628e4df80caec9669b65149c7ba40f9bf033c025a5b56bc"}, ] [package.dependencies] ipykernel = ">=4.1" -ipython-genutils = "*" jupyter-client = ">=4.1" jupyter-core = "*" packaging = "*" pygments = "*" pyzmq = ">=17.1" -qtpy = ">=2.0.1" +qtpy = ">=2.4.0" traitlets = "<5.2.1 || >5.2.1,<5.2.2 || >5.2.2" [package.extras] @@ -4463,14 +4527,14 @@ test = ["flaky", "pytest", "pytest-qt"] [[package]] name = "qtpy" -version = "2.3.1" +version = "2.4.1" description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "QtPy-2.3.1-py3-none-any.whl", hash = "sha256:5193d20e0b16e4d9d3bc2c642d04d9f4e2c892590bd1b9c92bfe38a95d5a2e12"}, - {file = "QtPy-2.3.1.tar.gz", hash = "sha256:a8c74982d6d172ce124d80cafd39653df78989683f760f2281ba91a6e7b9de8b"}, + {file = "QtPy-2.4.1-py3-none-any.whl", hash = "sha256:1c1d8c4fa2c884ae742b069151b0abe15b3f70491f3972698c683b8e38de839b"}, + {file = "QtPy-2.4.1.tar.gz", hash = "sha256:a5a15ffd519550a1361bdc56ffc07fda56a6af7292f17c7b395d4083af632987"}, ] [package.dependencies] @@ -4529,23 +4593,39 @@ files = [ numpy = "*" Pillow = "*" +[[package]] +name = "referencing" +version = "0.31.0" +description = "JSON Referencing + Python" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.31.0-py3-none-any.whl", hash = "sha256:381b11e53dd93babb55696c71cf42aef2d36b8a150c49bf0bc301e36d536c882"}, + {file = "referencing-0.31.0.tar.gz", hash = "sha256:cc28f2c88fbe7b961a7817a0abc034c09a1e36358f82fedb4ffdf29a25398863"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "requests" -version = "2.28.2" +version = "2.31.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" files = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -4599,14 +4679,14 @@ files = [ [[package]] name = "route-distances" -version = "1.1.0" +version = "1.1.1" description = "Models for calculating distances between synthesis routes" category = "main" optional = true -python-versions = ">=3.8,<3.10" +python-versions = ">=3.9,<3.11" files = [ - {file = "route-distances-1.1.0.tar.gz", hash = "sha256:2a2e115768d4fbeb84920e5c920e25942bbed1fed49574321c1265e89abdb482"}, - {file = "route_distances-1.1.0-py3-none-any.whl", hash = "sha256:a7cf2a3b36df0af082f02230f616823a6a8bb0793f979c1f31a017b6ec6e0bab"}, + {file = "route_distances-1.1.1-py3-none-any.whl", hash = "sha256:edf5b95d265ebfa5b82c3b055d157a326c77fc71c54c04271920f4525cc2cb72"}, + {file = "route_distances-1.1.1.tar.gz", hash = "sha256:ef20b699f0e39f7b7f87dee6dcbcd6842de66461418632d5f7ee896939ac7d5c"}, ] [package.dependencies] @@ -4622,6 +4702,115 @@ scikit-learn = ">0.21.0" tables = ">=3.6.0,<4.0.0" torch = ">=1.7.1,<2.0.0" +[[package]] +name = "rpds-py" +version = "0.13.1" +description = "Python bindings to Rust's persistent data structures (rpds)" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.13.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:83feb0f682d75a09ddc11aa37ba5c07dd9b824b22915207f6176ea458474ff75"}, + {file = "rpds_py-0.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa84bbe22ffa108f91631935c28a623001e335d66e393438258501e618fb0dde"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e04f8c76b8d5c70695b4e8f1d0b391d8ef91df00ef488c6c1ffb910176459bc6"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:032c242a595629aacace44128f9795110513ad27217b091e834edec2fb09e800"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91276caef95556faeb4b8f09fe4439670d3d6206fee78d47ddb6e6de837f0b4d"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d22f2cb82e0b40e427a74a93c9a4231335bbc548aed79955dde0b64ea7f88146"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c9e2794329ef070844ff9bfc012004aeddc0468dc26970953709723f76c8a5"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c797ea56f36c6f248656f0223b11307fdf4a1886f3555eba371f34152b07677f"}, + {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:82dbcd6463e580bcfb7561cece35046aaabeac5a9ddb775020160b14e6c58a5d"}, + {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:736817dbbbd030a69a1faf5413a319976c9c8ba8cdcfa98c022d3b6b2e01eca6"}, + {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1f36a1e80ef4ed1996445698fd91e0d3e54738bf597c9995118b92da537d7a28"}, + {file = "rpds_py-0.13.1-cp310-none-win32.whl", hash = "sha256:4f13d3f6585bd07657a603780e99beda96a36c86acaba841f131e81393958336"}, + {file = "rpds_py-0.13.1-cp310-none-win_amd64.whl", hash = "sha256:545e94c84575057d3d5c62634611858dac859702b1519b6ffc58eca7fb1adfcf"}, + {file = "rpds_py-0.13.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bfe72b249264cc1ff2f3629be240d7d2fdc778d9d298087cdec8524c91cd11f"}, + {file = "rpds_py-0.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edc91c50e17f5cd945d821f0f1af830522dba0c10267c3aab186dc3dbaab8def"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2eca04a365be380ca1f8fa48b334462e19e3382c0bb7386444d8ca43aa01c481"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e3ac5b602fea378243f993d8b707189f9061e55ebb4e56cb9fdef8166060f28"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfb5d2ab183c0efe5e7b8917e4eaa2e837aacafad8a69b89aa6bc81550eed857"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d9793d46d3e6522ae58e9321032827c9c0df1e56cbe5d3de965facb311aed6aa"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cd935c0220d012a27c20135c140f9cdcbc6249d5954345c81bfb714071b985c"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:37b08df45f02ff1866043b95096cbe91ac99de05936dd09d6611987a82a3306a"}, + {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad666a904212aa9a6c77da7dce9d5170008cda76b7776e6731928b3f8a0d40fa"}, + {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8a6ad8429340e0a4de89353447c6441329def3632e7b2293a7d6e873217d3c2b"}, + {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7c40851b659d958c5245c1236e34f0d065cc53dca8d978b49a032c8e0adfda6e"}, + {file = "rpds_py-0.13.1-cp311-none-win32.whl", hash = "sha256:4145172ab59b6c27695db6d78d040795f635cba732cead19c78cede74800949a"}, + {file = "rpds_py-0.13.1-cp311-none-win_amd64.whl", hash = "sha256:46a07a258bda12270de02b34c4884f200f864bba3dcd6e3a37fef36a168b859d"}, + {file = "rpds_py-0.13.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:ba4432301ad7eeb1b00848cf46fae0e5fecfd18a8cb5fdcf856c67985f79ecc7"}, + {file = "rpds_py-0.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d22e0660de24bd8e9ac82f4230a22a5fe4e397265709289d61d5fb333839ba50"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76a8374b294e4ccb39ccaf11d39a0537ed107534139c00b4393ca3b542cc66e5"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7d152ec7bb431040af2500e01436c9aa0d993f243346f0594a15755016bf0be1"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74a2044b870df7c9360bb3ce7e12f9ddf8e72e49cd3a353a1528cbf166ad2383"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:960e7e460fda2d0af18c75585bbe0c99f90b8f09963844618a621b804f8c3abe"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37f79f4f1f06cc96151f4a187528c3fd4a7e1065538a4af9eb68c642365957f7"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd4ea56c9542ad0091dfdef3e8572ae7a746e1e91eb56c9e08b8d0808b40f1d1"}, + {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0290712eb5603a725769b5d857f7cf15cf6ca93dda3128065bbafe6fdb709beb"}, + {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0b70c1f800059c92479dc94dda41288fd6607f741f9b1b8f89a21a86428f6383"}, + {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3dd5fb7737224e1497c886fb3ca681c15d9c00c76171f53b3c3cc8d16ccfa7fb"}, + {file = "rpds_py-0.13.1-cp312-none-win32.whl", hash = "sha256:74be3b215a5695690a0f1a9f68b1d1c93f8caad52e23242fcb8ba56aaf060281"}, + {file = "rpds_py-0.13.1-cp312-none-win_amd64.whl", hash = "sha256:f47eef55297799956464efc00c74ae55c48a7b68236856d56183fe1ddf866205"}, + {file = "rpds_py-0.13.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e4a45ba34f904062c63049a760790c6a2fa7a4cc4bd160d8af243b12371aaa05"}, + {file = "rpds_py-0.13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:20147996376be452cd82cd6c17701daba69a849dc143270fa10fe067bb34562a"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b9535aa22ab023704cfc6533e968f7e420affe802d85e956d8a7b4c0b0b5ea"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d4fa1eeb9bea6d9b64ac91ec51ee94cc4fc744955df5be393e1c923c920db2b0"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b2415d5a7b7ee96aa3a54d4775c1fec140476a17ee12353806297e900eaeddc"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:577d40a72550eac1386b77b43836151cb61ff6700adacda2ad4d883ca5a0b6f2"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af2d1648eb625a460eee07d3e1ea3a4a6e84a1fb3a107f6a8e95ac19f7dcce67"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b769396eb358d6b55dbf78f3f7ca631ca1b2fe02136faad5af74f0111b4b6b7"}, + {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:249c8e0055ca597707d71c5ad85fd2a1c8fdb99386a8c6c257e1b47b67a9bec1"}, + {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:fe30ef31172bdcf946502a945faad110e8fff88c32c4bec9a593df0280e64d8a"}, + {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2647192facf63be9ed2d7a49ceb07efe01dc6cfb083bd2cc53c418437400cb99"}, + {file = "rpds_py-0.13.1-cp38-none-win32.whl", hash = "sha256:4011d5c854aa804c833331d38a2b6f6f2fe58a90c9f615afdb7aa7cf9d31f721"}, + {file = "rpds_py-0.13.1-cp38-none-win_amd64.whl", hash = "sha256:7cfae77da92a20f56cf89739a557b76e5c6edc094f6ad5c090b9e15fbbfcd1a4"}, + {file = "rpds_py-0.13.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:e9be1f7c5f9673616f875299339984da9447a40e3aea927750c843d6e5e2e029"}, + {file = "rpds_py-0.13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:839676475ac2ccd1532d36af3d10d290a2ca149b702ed464131e450a767550df"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90031658805c63fe488f8e9e7a88b260ea121ba3ee9cdabcece9c9ddb50da39"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ba9fbc5d6e36bfeb5292530321cc56c4ef3f98048647fabd8f57543c34174ec"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08832078767545c5ee12561ce980714e1e4c6619b5b1e9a10248de60cddfa1fd"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19f5aa7f5078d35ed8e344bcba40f35bc95f9176dddb33fc4f2084e04289fa63"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80080972e1d000ad0341c7cc58b6855c80bd887675f92871221451d13a975072"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ee352691c4434eb1c01802e9daa5edcc1007ff15023a320e2693fed6a661b"}, + {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d20da6b4c7aa9ee75ad0730beaba15d65157f5beeaca54a038bb968f92bf3ce3"}, + {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:faa12a9f34671a30ea6bb027f04ec4e1fb8fa3fb3ed030893e729d4d0f3a9791"}, + {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7cf241dbb50ea71c2e628ab2a32b5bfcd36e199152fc44e5c1edb0b773f1583e"}, + {file = "rpds_py-0.13.1-cp39-none-win32.whl", hash = "sha256:dab979662da1c9fbb464e310c0b06cb5f1d174d09a462553af78f0bfb3e01920"}, + {file = "rpds_py-0.13.1-cp39-none-win_amd64.whl", hash = "sha256:a2b3c79586636f1fa69a7bd59c87c15fca80c0d34b5c003d57f2f326e5276575"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5967fa631d0ed9f8511dede08bc943a9727c949d05d1efac4ac82b2938024fb7"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8308a8d49d1354278d5c068c888a58d7158a419b2e4d87c7839ed3641498790c"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0580faeb9def6d0beb7aa666294d5604e569c4e24111ada423cf9936768d95c"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2da81c1492291c1a90987d76a47c7b2d310661bf7c93a9de0511e27b796a8b46"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c9a1dc5e898ce30e2f9c0aa57181cddd4532b22b7780549441d6429d22d3b58"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4ae6f423cb7d1c6256b7482025ace2825728f53b7ac58bcd574de6ee9d242c2"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc3179e0815827cf963e634095ae5715ee73a5af61defbc8d6ca79f1bdae1d1d"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d9f8930092558fd15c9e07198625efb698f7cc00b3dc311c83eeec2540226a8"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d1d388d2f5f5a6065cf83c54dd12112b7389095669ff395e632003ae8999c6b8"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:08b335fb0c45f0a9e2478a9ece6a1bfb00b6f4c4780f9be3cf36479c5d8dd374"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d11afdc5992bbd7af60ed5eb519873690d921425299f51d80aa3099ed49f2bcc"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:8c1f6c8df23be165eb0cb78f305483d00c6827a191e3a38394c658d5b9c80bbd"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:528e2afaa56d815d2601b857644aeb395afe7e59212ab0659906dc29ae68d9a6"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df2af1180b8eeececf4f819d22cc0668bfadadfd038b19a90bd2fb2ee419ec6f"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88956c993a20201744282362e3fd30962a9d86dc4f1dcf2bdb31fab27821b61f"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee70ee5f4144a45a9e6169000b5b525d82673d5dab9f7587eccc92794814e7ac"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5fd099acaee2325f01281a130a39da08d885e4dedf01b84bf156ec2737d78fe"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9656a09653b18b80764647d585750df2dff8928e03a706763ab40ec8c4872acc"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ba239bb37663b2b4cd08e703e79e13321512dccd8e5f0e9451d9e53a6b8509a"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3f55ae773abd96b1de25fc5c3fb356f491bd19116f8f854ba705beffc1ddc3c5"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f4b15a163448ec79241fb2f1bc5a8ae1a4a304f7a48d948d208a2935b26bf8a5"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1a3b2583c86bbfbf417304eeb13400ce7f8725376dc7d3efbf35dc5d7052ad48"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f1059ca9a51c936c9a8d46fbc2c9a6b4c15ab3f13a97f1ad32f024b39666ba85"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f55601fb58f92e4f4f1d05d80c24cb77505dc42103ddfd63ddfdc51d3da46fa2"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcfd5f91b882eedf8d9601bd21261d6ce0e61a8c66a7152d1f5df08d3f643ab1"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6574f619e8734140d96c59bfa8a6a6e7a3336820ccd1bfd95ffa610673b650a2"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4b9d3f5c48bbe8d9e3758e498b3c34863f2c9b1ac57a4e6310183740e59c980"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdd6f8738e1f1d9df5b1603bb03cb30e442710e5672262b95d0f9fcb4edb0dab"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8c2bf286e5d755a075e5e97ba56b3de08cccdad6b323ab0b21cc98875176b03"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d4b390ee70ca9263b331ccfaf9819ee20e90dfd0201a295e23eb64a005dbef"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:db8d0f0ad92f74feb61c4e4a71f1d573ef37c22ef4dc19cab93e501bfdad8cbd"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2abd669a39be69cdfe145927c7eb53a875b157740bf1e2d49e9619fc6f43362e"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c173f529666bab8e3f948b74c6d91afa22ea147e6ebae49a48229d9020a47c4"}, + {file = "rpds_py-0.13.1.tar.gz", hash = "sha256:264f3a5906c62b9df3a00ad35f6da1987d321a053895bd85f9d5c708de5c0fbf"}, +] + [[package]] name = "rsa" version = "4.9" @@ -4639,96 +4828,105 @@ pyasn1 = ">=0.1.3" [[package]] name = "scikit-learn" -version = "1.2.2" +version = "1.3.2" description = "A set of python modules for machine learning and data mining" category = "main" optional = true python-versions = ">=3.8" files = [ - {file = "scikit-learn-1.2.2.tar.gz", hash = "sha256:8429aea30ec24e7a8c7ed8a3fa6213adf3814a6efbea09e16e0a0c71e1a1a3d7"}, - {file = "scikit_learn-1.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99cc01184e347de485bf253d19fcb3b1a3fb0ee4cea5ee3c43ec0cc429b6d29f"}, - {file = "scikit_learn-1.2.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:e6e574db9914afcb4e11ade84fab084536a895ca60aadea3041e85b8ac963edb"}, - {file = "scikit_learn-1.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fe83b676f407f00afa388dd1fdd49e5c6612e551ed84f3b1b182858f09e987d"}, - {file = "scikit_learn-1.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e2642baa0ad1e8f8188917423dd73994bf25429f8893ddbe115be3ca3183584"}, - {file = "scikit_learn-1.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ad66c3848c0a1ec13464b2a95d0a484fd5b02ce74268eaa7e0c697b904f31d6c"}, - {file = "scikit_learn-1.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfeaf8be72117eb61a164ea6fc8afb6dfe08c6f90365bde2dc16456e4bc8e45f"}, - {file = "scikit_learn-1.2.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:fe0aa1a7029ed3e1dcbf4a5bc675aa3b1bc468d9012ecf6c6f081251ca47f590"}, - {file = "scikit_learn-1.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:065e9673e24e0dc5113e2dd2b4ca30c9d8aa2fa90f4c0597241c93b63130d233"}, - {file = "scikit_learn-1.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf036ea7ef66115e0d49655f16febfa547886deba20149555a41d28f56fd6d3c"}, - {file = "scikit_learn-1.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:8b0670d4224a3c2d596fd572fb4fa673b2a0ccfb07152688ebd2ea0b8c61025c"}, - {file = "scikit_learn-1.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9c710ff9f9936ba8a3b74a455ccf0dcf59b230caa1e9ba0223773c490cab1e51"}, - {file = "scikit_learn-1.2.2-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:2dd3ffd3950e3d6c0c0ef9033a9b9b32d910c61bd06cb8206303fb4514b88a49"}, - {file = "scikit_learn-1.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44b47a305190c28dd8dd73fc9445f802b6ea716669cfc22ab1eb97b335d238b1"}, - {file = "scikit_learn-1.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:953236889928d104c2ef14027539f5f2609a47ebf716b8cbe4437e85dce42744"}, - {file = "scikit_learn-1.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:7f69313884e8eb311460cc2f28676d5e400bd929841a2c8eb8742ae78ebf7c20"}, - {file = "scikit_learn-1.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8156db41e1c39c69aa2d8599ab7577af53e9e5e7a57b0504e116cc73c39138dd"}, - {file = "scikit_learn-1.2.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fe175ee1dab589d2e1033657c5b6bec92a8a3b69103e3dd361b58014729975c3"}, - {file = "scikit_learn-1.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d5312d9674bed14f73773d2acf15a3272639b981e60b72c9b190a0cffed5bad"}, - {file = "scikit_learn-1.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea061bf0283bf9a9f36ea3c5d3231ba2176221bbd430abd2603b1c3b2ed85c89"}, - {file = "scikit_learn-1.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:6477eed40dbce190f9f9e9d0d37e020815825b300121307942ec2110302b66a3"}, + {file = "scikit-learn-1.3.2.tar.gz", hash = "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05"}, + {file = "scikit_learn-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1"}, + {file = "scikit_learn-1.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a"}, + {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c"}, + {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161"}, + {file = "scikit_learn-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c"}, + {file = "scikit_learn-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66"}, + {file = "scikit_learn-1.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157"}, + {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb"}, + {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433"}, + {file = "scikit_learn-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b"}, + {file = "scikit_learn-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028"}, + {file = "scikit_learn-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5"}, + {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525"}, + {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c"}, + {file = "scikit_learn-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107"}, + {file = "scikit_learn-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a19f90f95ba93c1a7f7924906d0576a84da7f3b2282ac3bfb7a08a32801add93"}, + {file = "scikit_learn-1.3.2-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:b8692e395a03a60cd927125eef3a8e3424d86dde9b2370d544f0ea35f78a8073"}, + {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15e1e94cc23d04d39da797ee34236ce2375ddea158b10bee3c343647d615581d"}, + {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:785a2213086b7b1abf037aeadbbd6d67159feb3e30263434139c98425e3dcfcf"}, + {file = "scikit_learn-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:64381066f8aa63c2710e6b56edc9f0894cc7bf59bd71b8ce5613a4559b6145e0"}, + {file = "scikit_learn-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6c43290337f7a4b969d207e620658372ba3c1ffb611f8bc2b6f031dc5c6d1d03"}, + {file = "scikit_learn-1.3.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:dc9002fc200bed597d5d34e90c752b74df516d592db162f756cc52836b38fe0e"}, + {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d08ada33e955c54355d909b9c06a4789a729977f165b8bae6f225ff0a60ec4a"}, + {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f0ae4b79b0ff9cca0bf3716bcc9915bdacff3cebea15ec79652d1cc4fa5c9"}, + {file = "scikit_learn-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:ed932ea780517b00dae7431e031faae6b49b20eb6950918eb83bd043237950e0"}, ] [package.dependencies] joblib = ">=1.1.1" -numpy = ">=1.17.3" -scipy = ">=1.3.2" +numpy = ">=1.17.3,<2.0" +scipy = ">=1.5.0" threadpoolctl = ">=2.0.0" [package.extras] benchmark = ["matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "pandas (>=1.0.5)"] -docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.10.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=4.0.1)", "sphinx-gallery (>=0.7.0)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] -examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.10.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"] -tests = ["black (>=22.3.0)", "flake8 (>=3.8.2)", "matplotlib (>=3.1.3)", "mypy (>=0.961)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=5.3.1)", "pytest-cov (>=2.9.0)", "scikit-image (>=0.16.2)"] +docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.10.1)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] +examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"] +tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.0.272)", "scikit-image (>=0.16.2)"] [[package]] name = "scipy" -version = "1.10.1" +version = "1.11.4" description = "Fundamental algorithms for scientific computing in Python" category = "main" optional = true -python-versions = "<3.12,>=3.8" -files = [ - {file = "scipy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019"}, - {file = "scipy-1.10.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2"}, - {file = "scipy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d"}, - {file = "scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f"}, - {file = "scipy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601"}, - {file = "scipy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea"}, - {file = "scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5"}, +python-versions = ">=3.9" +files = [ + {file = "scipy-1.11.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc9a714581f561af0848e6b69947fda0614915f072dfd14142ed1bfe1b806710"}, + {file = "scipy-1.11.4-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:cf00bd2b1b0211888d4dc75656c0412213a8b25e80d73898083f402b50f47e41"}, + {file = "scipy-1.11.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9999c008ccf00e8fbcce1236f85ade5c569d13144f77a1946bef8863e8f6eb4"}, + {file = "scipy-1.11.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:933baf588daa8dc9a92c20a0be32f56d43faf3d1a60ab11b3f08c356430f6e56"}, + {file = "scipy-1.11.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8fce70f39076a5aa62e92e69a7f62349f9574d8405c0a5de6ed3ef72de07f446"}, + {file = "scipy-1.11.4-cp310-cp310-win_amd64.whl", hash = "sha256:6550466fbeec7453d7465e74d4f4b19f905642c89a7525571ee91dd7adabb5a3"}, + {file = "scipy-1.11.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f313b39a7e94f296025e3cffc2c567618174c0b1dde173960cf23808f9fae4be"}, + {file = "scipy-1.11.4-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1b7c3dca977f30a739e0409fb001056484661cb2541a01aba0bb0029f7b68db8"}, + {file = "scipy-1.11.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00150c5eae7b610c32589dda259eacc7c4f1665aedf25d921907f4d08a951b1c"}, + {file = "scipy-1.11.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530f9ad26440e85766509dbf78edcfe13ffd0ab7fec2560ee5c36ff74d6269ff"}, + {file = "scipy-1.11.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5e347b14fe01003d3b78e196e84bd3f48ffe4c8a7b8a1afbcb8f5505cb710993"}, + {file = "scipy-1.11.4-cp311-cp311-win_amd64.whl", hash = "sha256:acf8ed278cc03f5aff035e69cb511741e0418681d25fbbb86ca65429c4f4d9cd"}, + {file = "scipy-1.11.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:028eccd22e654b3ea01ee63705681ee79933652b2d8f873e7949898dda6d11b6"}, + {file = "scipy-1.11.4-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c6ff6ef9cc27f9b3db93a6f8b38f97387e6e0591600369a297a50a8e96e835d"}, + {file = "scipy-1.11.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b030c6674b9230d37c5c60ab456e2cf12f6784596d15ce8da9365e70896effc4"}, + {file = "scipy-1.11.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad669df80528aeca5f557712102538f4f37e503f0c5b9541655016dd0932ca79"}, + {file = "scipy-1.11.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce7fff2e23ab2cc81ff452a9444c215c28e6305f396b2ba88343a567feec9660"}, + {file = "scipy-1.11.4-cp312-cp312-win_amd64.whl", hash = "sha256:36750b7733d960d7994888f0d148d31ea3017ac15eef664194b4ef68d36a4a97"}, + {file = "scipy-1.11.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e619aba2df228a9b34718efb023966da781e89dd3d21637b27f2e54db0410d7"}, + {file = "scipy-1.11.4-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:f3cd9e7b3c2c1ec26364856f9fbe78695fe631150f94cd1c22228456404cf1ec"}, + {file = "scipy-1.11.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d10e45a6c50211fe256da61a11c34927c68f277e03138777bdebedd933712fea"}, + {file = "scipy-1.11.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91af76a68eeae0064887a48e25c4e616fa519fa0d38602eda7e0f97d65d57937"}, + {file = "scipy-1.11.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6df1468153a31cf55ed5ed39647279beb9cfb5d3f84369453b49e4b8502394fd"}, + {file = "scipy-1.11.4-cp39-cp39-win_amd64.whl", hash = "sha256:ee410e6de8f88fd5cf6eadd73c135020bfbbbdfcd0f6162c36a7638a1ea8cc65"}, + {file = "scipy-1.11.4.tar.gz", hash = "sha256:90a2b78e7f5733b9de748f589f09225013685f9b218275257f8a8168ededaeaa"}, ] [package.dependencies] -numpy = ">=1.19.5,<1.27.0" +numpy = ">=1.21.6,<1.28.0" [package.extras] -dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", "rich-click", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] +dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] name = "send2trash" -version = "1.8.0" -description = "Send file to trash natively under Mac OS X, Windows and Linux." +version = "1.8.2" +description = "Send file to trash natively under Mac OS X, Windows and Linux" category = "main" optional = false -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ - {file = "Send2Trash-1.8.0-py3-none-any.whl", hash = "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08"}, - {file = "Send2Trash-1.8.0.tar.gz", hash = "sha256:d2c24762fd3759860a0aff155e45871447ea58d2be6bdd39b5c8f966a0c99c2d"}, + {file = "Send2Trash-1.8.2-py3-none-any.whl", hash = "sha256:a384719d99c07ce1eefd6905d2decb6f8b7ed054025bb0e618919f945de4f679"}, + {file = "Send2Trash-1.8.2.tar.gz", hash = "sha256:c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312"}, ] [package.extras] @@ -4738,20 +4936,20 @@ win32 = ["pywin32"] [[package]] name = "setuptools" -version = "67.6.1" +version = "69.0.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"}, - {file = "setuptools-67.6.1.tar.gz", hash = "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a"}, + {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, + {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -4791,14 +4989,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.4" +version = "2.5" description = "A modern CSS selector implementation for Beautiful Soup." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "soupsieve-2.4-py3-none-any.whl", hash = "sha256:49e5368c2cda80ee7e84da9dbe3e110b70a4575f196efb74e51b94549d921955"}, - {file = "soupsieve-2.4.tar.gz", hash = "sha256:e28dba9ca6c7c00173e34e4ba57448f0688bb681b7c5e8bf4971daafc093d69a"}, + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, ] [[package]] @@ -4934,53 +5132,61 @@ test = ["pytest"] [[package]] name = "sqlalchemy" -version = "2.0.9" +version = "2.0.23" description = "Database Abstraction Library" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:734805708632e3965c2c40081f9a59263c29ffa27cba9b02d4d92dfd57ba869f"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8d3ece5960b3e821e43a4927cc851b6e84a431976d3ffe02aadb96519044807e"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d118e233f416d713aac715e2c1101e17f91e696ff315fc9efbc75b70d11e740"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f005245e1cb9b8ca53df73ee85e029ac43155e062405015e49ec6187a2e3fb44"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:34eb96c1de91d8f31e988302243357bef3f7785e1b728c7d4b98bd0c117dafeb"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7e472e9627882f2d75b87ff91c5a2bc45b31a226efc7cc0a054a94fffef85862"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-win32.whl", hash = "sha256:0a865b5ec4ba24f57c33b633b728e43fde77b968911a6046443f581b25d29dd9"}, - {file = "SQLAlchemy-2.0.9-cp310-cp310-win_amd64.whl", hash = "sha256:6e84ab63d25d8564d7a8c05dc080659931a459ee27f6ed1cf4c91f292d184038"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db4bd1c4792da753f914ff0b688086b9a8fd78bb9bc5ae8b6d2e65f176b81eb9"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ad5363a1c65fde7b7466769d4261126d07d872fc2e816487ae6cec93da604b6b"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebc4eeb1737a5a9bdb0c24f4c982319fa6edd23cdee27180978c29cbb026f2bd"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbda1da8d541904ba262825a833c9f619e93cb3fd1156be0a5e43cd54d588dcd"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d5327f54a9c39e7871fc532639616f3777304364a0bb9b89d6033ad34ef6c5f8"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ac6a0311fb21a99855953f84c43fcff4bdca27a2ffcc4f4d806b26b54b5cddc9"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-win32.whl", hash = "sha256:d209594e68bec103ad5243ecac1b40bf5770c9ebf482df7abf175748a34f4853"}, - {file = "SQLAlchemy-2.0.9-cp311-cp311-win_amd64.whl", hash = "sha256:865392a50a721445156809c1a6d6ab6437be70c1c2599f591a8849ed95d3c693"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0b49f1f71d7a44329a43d3edd38cc5ee4c058dfef4487498393d16172007954b"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a019f723b6c1e6b3781be00fb9e0844bc6156f9951c836ff60787cc3938d76"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9838bd247ee42eb74193d865e48dd62eb50e45e3fdceb0fdef3351133ee53dcf"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:78612edf4ba50d407d0eb3a64e9ec76e6efc2b5d9a5c63415d53e540266a230a"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f61ab84956dc628c8dfe9d105b6aec38afb96adae3e5e7da6085b583ff6ea789"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-win32.whl", hash = "sha256:07950fc82f844a2de67ddb4e535f29b65652b4d95e8b847823ce66a6d540a41d"}, - {file = "SQLAlchemy-2.0.9-cp37-cp37m-win_amd64.whl", hash = "sha256:e62c4e762d6fd2901692a093f208a6a6575b930e9458ad58c2a7f080dd6132da"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b3e5864eba71a3718236a120547e52c8da2ccb57cc96cecd0480106a0c799c92"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d06e119cf79a3d80ab069f064a07152eb9ba541d084bdaee728d8a6f03fd03d"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee2946042cc7851842d7a086a92b9b7b494cbe8c3e7e4627e27bc912d3a7655e"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13f984a190d249769a050634b248aef8991acc035e849d02b634ea006c028fa8"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e4780be0f19e5894c17f75fc8de2fe1ae233ab37827125239ceb593c6f6bd1e2"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:68ed381bc340b4a3d373dbfec1a8b971f6350139590c4ca3cb722fdb50035777"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-win32.whl", hash = "sha256:aa5c270ece17c0c0e0a38f2530c16b20ea05d8b794e46c79171a86b93b758891"}, - {file = "SQLAlchemy-2.0.9-cp38-cp38-win_amd64.whl", hash = "sha256:1b69666e25cc03c602d9d3d460e1281810109e6546739187044fc256c67941ef"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6e27189ff9aebfb2c02fd252c629ea58657e7a5ff1a321b7fc9c2bf6dc0b5f3"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8239ce63a90007bce479adf5460d48c1adae4b933d8e39a4eafecfc084e503c"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f759eccb66e6d495fb622eb7f4ac146ae674d829942ec18b7f5a35ddf029597"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246712af9fc761d6c13f4f065470982e175d902e77aa4218c9cb9fc9ff565a0c"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6b72dccc5864ea95c93e0a9c4e397708917fb450f96737b4a8395d009f90b868"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:93c78d42c14aa9a9e0866eacd5b48df40a50d0e2790ee377af7910d224afddcf"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-win32.whl", hash = "sha256:f49c5d3c070a72ecb96df703966c9678dda0d4cb2e2736f88d15f5e1203b4159"}, - {file = "SQLAlchemy-2.0.9-cp39-cp39-win_amd64.whl", hash = "sha256:4c3020afb144572c7bfcba9d7cce57ad42bff6e6115dffcfe2d4ae6d444a214f"}, - {file = "SQLAlchemy-2.0.9-py3-none-any.whl", hash = "sha256:e730603cae5747bc6d6dece98b45a57d647ed553c8d5ecef602697b1c1501cf2"}, - {file = "SQLAlchemy-2.0.9.tar.gz", hash = "sha256:95719215e3ec7337b9f57c3c2eda0e6a7619be194a5166c07c1e599f6afc20fa"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:638c2c0b6b4661a4fd264f6fb804eccd392745c5887f9317feb64bb7cb03b3ea"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3b5036aa326dc2df50cba3c958e29b291a80f604b1afa4c8ce73e78e1c9f01d"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:787af80107fb691934a01889ca8f82a44adedbf5ef3d6ad7d0f0b9ac557e0c34"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c14eba45983d2f48f7546bb32b47937ee2cafae353646295f0e99f35b14286ab"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0666031df46b9badba9bed00092a1ffa3aa063a5e68fa244acd9f08070e936d3"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89a01238fcb9a8af118eaad3ffcc5dedaacbd429dc6fdc43fe430d3a941ff965"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-win32.whl", hash = "sha256:cabafc7837b6cec61c0e1e5c6d14ef250b675fa9c3060ed8a7e38653bd732ff8"}, + {file = "SQLAlchemy-2.0.23-cp310-cp310-win_amd64.whl", hash = "sha256:87a3d6b53c39cd173990de2f5f4b83431d534a74f0e2f88bd16eabb5667e65c6"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d5578e6863eeb998980c212a39106ea139bdc0b3f73291b96e27c929c90cd8e1"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62d9e964870ea5ade4bc870ac4004c456efe75fb50404c03c5fd61f8bc669a72"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c80c38bd2ea35b97cbf7c21aeb129dcbebbf344ee01a7141016ab7b851464f8e"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75eefe09e98043cff2fb8af9796e20747ae870c903dc61d41b0c2e55128f958d"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd45a5b6c68357578263d74daab6ff9439517f87da63442d244f9f23df56138d"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a86cb7063e2c9fb8e774f77fbf8475516d270a3e989da55fa05d08089d77f8c4"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-win32.whl", hash = "sha256:b41f5d65b54cdf4934ecede2f41b9c60c9f785620416e8e6c48349ab18643855"}, + {file = "SQLAlchemy-2.0.23-cp311-cp311-win_amd64.whl", hash = "sha256:9ca922f305d67605668e93991aaf2c12239c78207bca3b891cd51a4515c72e22"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0f7fb0c7527c41fa6fcae2be537ac137f636a41b4c5a4c58914541e2f436b45"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c424983ab447dab126c39d3ce3be5bee95700783204a72549c3dceffe0fc8f4"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f508ba8f89e0a5ecdfd3761f82dda2a3d7b678a626967608f4273e0dba8f07ac"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6463aa765cf02b9247e38b35853923edbf2f6fd1963df88706bc1d02410a5577"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e599a51acf3cc4d31d1a0cf248d8f8d863b6386d2b6782c5074427ebb7803bda"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd54601ef9cc455a0c61e5245f690c8a3ad67ddb03d3b91c361d076def0b4c60"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-win32.whl", hash = "sha256:42d0b0290a8fb0165ea2c2781ae66e95cca6e27a2fbe1016ff8db3112ac1e846"}, + {file = "SQLAlchemy-2.0.23-cp312-cp312-win_amd64.whl", hash = "sha256:227135ef1e48165f37590b8bfc44ed7ff4c074bf04dc8d6f8e7f1c14a94aa6ca"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:14aebfe28b99f24f8a4c1346c48bc3d63705b1f919a24c27471136d2f219f02d"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e983fa42164577d073778d06d2cc5d020322425a509a08119bdcee70ad856bf"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e0dc9031baa46ad0dd5a269cb7a92a73284d1309228be1d5935dac8fb3cae24"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5f94aeb99f43729960638e7468d4688f6efccb837a858b34574e01143cf11f89"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:63bfc3acc970776036f6d1d0e65faa7473be9f3135d37a463c5eba5efcdb24c8"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-win32.whl", hash = "sha256:f48ed89dd11c3c586f45e9eec1e437b355b3b6f6884ea4a4c3111a3358fd0c18"}, + {file = "SQLAlchemy-2.0.23-cp37-cp37m-win_amd64.whl", hash = "sha256:1e018aba8363adb0599e745af245306cb8c46b9ad0a6fc0a86745b6ff7d940fc"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64ac935a90bc479fee77f9463f298943b0e60005fe5de2aa654d9cdef46c54df"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c4722f3bc3c1c2fcc3702dbe0016ba31148dd6efcd2a2fd33c1b4897c6a19693"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af79c06825e2836de21439cb2a6ce22b2ca129bad74f359bddd173f39582bf5"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:683ef58ca8eea4747737a1c35c11372ffeb84578d3aab8f3e10b1d13d66f2bc4"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d4041ad05b35f1f4da481f6b811b4af2f29e83af253bf37c3c4582b2c68934ab"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aeb397de65a0a62f14c257f36a726945a7f7bb60253462e8602d9b97b5cbe204"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-win32.whl", hash = "sha256:42ede90148b73fe4ab4a089f3126b2cfae8cfefc955c8174d697bb46210c8306"}, + {file = "SQLAlchemy-2.0.23-cp38-cp38-win_amd64.whl", hash = "sha256:964971b52daab357d2c0875825e36584d58f536e920f2968df8d581054eada4b"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:616fe7bcff0a05098f64b4478b78ec2dfa03225c23734d83d6c169eb41a93e55"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e680527245895aba86afbd5bef6c316831c02aa988d1aad83c47ffe92655e74"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9585b646ffb048c0250acc7dad92536591ffe35dba624bb8fd9b471e25212a35"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4895a63e2c271ffc7a81ea424b94060f7b3b03b4ea0cd58ab5bb676ed02f4221"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc1d21576f958c42d9aec68eba5c1a7d715e5fc07825a629015fe8e3b0657fb0"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:967c0b71156f793e6662dd839da54f884631755275ed71f1539c95bbada9aaab"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-win32.whl", hash = "sha256:0a8c6aa506893e25a04233bc721c6b6cf844bafd7250535abb56cb6cc1368884"}, + {file = "SQLAlchemy-2.0.23-cp39-cp39-win_amd64.whl", hash = "sha256:f3420d00d2cb42432c1d0e44540ae83185ccbbc67a6054dcc8ab5387add6620b"}, + {file = "SQLAlchemy-2.0.23-py3-none-any.whl", hash = "sha256:31952bbc527d633b9479f5f81e8b9dfada00b91d6baba021a869095f1a97006d"}, + {file = "SQLAlchemy-2.0.23.tar.gz", hash = "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69"}, ] [package.dependencies] @@ -4988,7 +5194,8 @@ greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or typing-extensions = ">=4.2.0" [package.extras] -aiomysql = ["aiomysql", "greenlet (!=0.4.17)"] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] +aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] asyncio = ["greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] @@ -4999,7 +5206,7 @@ mssql-pyodbc = ["pyodbc"] mypy = ["mypy (>=0.910)"] mysql = ["mysqlclient (>=1.4.0)"] mysql-connector = ["mysql-connector-python"] -oracle = ["cx-oracle (>=7)"] +oracle = ["cx-oracle (>=8)"] oracle-oracledb = ["oracledb (>=1.0.1)"] postgresql = ["psycopg2 (>=2.7)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] @@ -5007,19 +5214,20 @@ postgresql-pg8000 = ["pg8000 (>=1.29.1)"] postgresql-psycopg = ["psycopg (>=3.0.7)"] postgresql-psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3-binary"] [[package]] name = "stack-data" -version = "0.6.2" +version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" category = "main" optional = false python-versions = "*" files = [ - {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, - {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, ] [package.dependencies] @@ -5032,14 +5240,14 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "stevedore" -version = "5.0.0" +version = "5.1.0" description = "Manage dynamic plugins for Python applications" category = "main" optional = true python-versions = ">=3.8" files = [ - {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"}, - {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"}, + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, ] [package.dependencies] @@ -5047,14 +5255,14 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" [[package]] name = "sympy" -version = "1.11.1" +version = "1.12" description = "Computer algebra system (CAS) in Python" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "sympy-1.11.1-py3-none-any.whl", hash = "sha256:938f984ee2b1e8eae8a07b884c8b7a1146010040fccddc6539c54f401c8f6fcf"}, - {file = "sympy-1.11.1.tar.gz", hash = "sha256:e32380dce63cb7c0108ed525570092fd45168bdae2faa17e528221ef72e88658"}, + {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, + {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, ] [package.dependencies] @@ -5062,205 +5270,205 @@ mpmath = ">=0.19" [[package]] name = "tables" -version = "3.8.0" +version = "3.9.1" description = "Hierarchical datasets for Python" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "tables-3.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:01e82e40f9845f71de137b4472210909e35c440bbcd0858bdd2871715daef4c7"}, - {file = "tables-3.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db185d855afd45a7259ddd0b53e5f2f8993bb134b370002c6c19532f27ce92ac"}, - {file = "tables-3.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70a3585a268beee6d0e71bfc9abec98da84d168182f350a2ffa1ae5e42798c18"}, - {file = "tables-3.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:117cf0f73ee2a5cba5c2b04e4aca375779aec66045aa63128e043dc608f2023b"}, - {file = "tables-3.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2861cd3ef9eb95eead7530e4de49fd130954871e7e6d2e288012797cb9d7c2e8"}, - {file = "tables-3.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e9bdbfbe025b6c751976382123c5f5cbd8fab6956aed776b0e8c889669e90d3"}, - {file = "tables-3.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0821007048f2af8c1a21eb3d832072046c5df366e39587a7c7e4afad14e73fc"}, - {file = "tables-3.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:b9370c2a4dc0051aad6b71de4f1f9b0b8b60d30b662df5c742434f2b5c6a005e"}, - {file = "tables-3.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e19686fad4e8f5a91c3dc1eb4b7ea928838e86fefa474c63c5787a125ea79fc7"}, - {file = "tables-3.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:239f15fa9881c257b5c0d9fb4cb8832778af1c5c8c1db6f6722466f8f26541e2"}, - {file = "tables-3.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83a74cac3c0629a0e83570d465f88843ef3609ef56a8ef9a49ee85ab3b8f02f"}, - {file = "tables-3.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:a5ccb80651c5fad6ac744e2a756b28cfac78eab3b8503f4a2320ee6653b3bee9"}, - {file = "tables-3.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3375bfafc6cf305d13617a572ab3fffc51fae2fbe0f6efce9407a41f79970b62"}, - {file = "tables-3.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:254a4d5c2009c7ebe4293b02b8d91ea60837bff85a3c0a40cd075b8f12b1e6c3"}, - {file = "tables-3.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da3c96456c473fb977cf6dbca9e889710ac020df1fa5b9ebb7f676e83996337d"}, - {file = "tables-3.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:72da9404094ef8277bf62fce8873e8dc141cee9a8763ec8e7080b2d0de206094"}, - {file = "tables-3.8.0.tar.gz", hash = "sha256:34f3fa2366ce20b18f1df573a77c1d27306ce1f2a41d9f9eff621b5192ea8788"}, + {file = "tables-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:784c1ffe7f972e69a9c97c0f164064e43617727668df4333802a7f23cfb06ee3"}, + {file = "tables-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af92f1e63b9fcadea621ab544540b7312553ea4f9456cf3d2728b48346fa557c"}, + {file = "tables-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f725f69d49f414736de24616b4ffa400127b86417bd14a11854aacd2a505b4d"}, + {file = "tables-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:e346249116b2eb95dd9277336c12f0d10d5328a5a3e8e16c74faa3c815817dc3"}, + {file = "tables-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f49e899247b541ed69d12fef10b5505b97243317a91b93927328c19a15d38671"}, + {file = "tables-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d1f2c947d63019db20728c6ecec39a1c900be00a65cae8025ac770148b641e8"}, + {file = "tables-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb89fab4a3c3cd98bd781913234e1f67464ff6e17662180cf718e67645a09271"}, + {file = "tables-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:aa176e1c72b0f935b0e607218ea8302378a39ed4fef5a544ebbd8d0523b56b86"}, + {file = "tables-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f482aaaa4b12d394421013cd4617d3e8a53a8d4a7a872454f7a13fb16c51a68e"}, + {file = "tables-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1813c0eced77540598987db32ce9e619d02b6032acdc3f59590d83c13bdb910c"}, + {file = "tables-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a64ce39652a2e2934f6d41500b2c6f8d4922e2022f1361e2302f3e85df4e2393"}, + {file = "tables-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:b49015aa8f576c6d5108c4aeb4d430bfcfc91ee8d0cca4d03e574e5485ffdc8b"}, + {file = "tables-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:50140091af9d60eb3f806d3ee43f542beae569888c37ae96d6a1c887c389d8c8"}, + {file = "tables-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:282a0747b3ce4e3108bcd443361e031c9817bf7e84358317723a51b9c02c5655"}, + {file = "tables-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0295123272bb49efbebdc9b1e2b72baa99c5761b78fccacedbf44c52a5fa51ac"}, + {file = "tables-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:22084019437c504917ba8c0b2af75419e3d5c8ffc6d2ef4cd44031f06939518c"}, + {file = "tables-3.9.1.tar.gz", hash = "sha256:48331503cd509c9f1f95cf2f5c64a57c48c0aa5141423f0eca352965c4f9bf81"}, ] [package.dependencies] -blosc2 = ">=2.0.0,<2.1.0" -cython = ">=0.29.21" +blosc2 = ">=2.2.8" numexpr = ">=2.6.2" numpy = ">=1.19.0" packaging = "*" py-cpuinfo = "*" [package.extras] -doc = ["ipython", "numpydoc", "sphinx (>=1.1)", "sphinx-rtd-theme"] +doc = ["ipython", "numpydoc", "sphinx (>=1.1,<6)", "sphinx-rtd-theme"] [[package]] name = "tensorboard" -version = "2.11.2" +version = "2.13.0" description = "TensorBoard lets you watch Tensors Flow" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tensorboard-2.11.2-py3-none-any.whl", hash = "sha256:cbaa2210c375f3af1509f8571360a19ccc3ded1d9641533414874b5deca47e89"}, + {file = "tensorboard-2.13.0-py3-none-any.whl", hash = "sha256:ab69961ebddbddc83f5fa2ff9233572bdad5b883778c35e4fe94bf1798bd8481"}, ] [package.dependencies] absl-py = ">=0.4" google-auth = ">=1.6.3,<3" -google-auth-oauthlib = ">=0.4.1,<0.5" -grpcio = ">=1.24.3" +google-auth-oauthlib = ">=0.5,<1.1" +grpcio = ">=1.48.2" markdown = ">=2.6.8" numpy = ">=1.12.0" -protobuf = ">=3.9.2,<4" +protobuf = ">=3.19.6" requests = ">=2.21.0,<3" setuptools = ">=41.0.0" -tensorboard-data-server = ">=0.6.0,<0.7.0" -tensorboard-plugin-wit = ">=1.6.0" +tensorboard-data-server = ">=0.7.0,<0.8.0" werkzeug = ">=1.0.1" wheel = ">=0.26" [[package]] name = "tensorboard-data-server" -version = "0.6.1" +version = "0.7.2" description = "Fast data loading for TensorBoard" category = "main" optional = true -python-versions = ">=3.6" -files = [ - {file = "tensorboard_data_server-0.6.1-py3-none-any.whl", hash = "sha256:809fe9887682d35c1f7d1f54f0f40f98bb1f771b14265b453ca051e2ce58fca7"}, - {file = "tensorboard_data_server-0.6.1-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:fa8cef9be4fcae2f2363c88176638baf2da19c5ec90addb49b1cde05c95c88ee"}, - {file = "tensorboard_data_server-0.6.1-py3-none-manylinux2010_x86_64.whl", hash = "sha256:d8237580755e58eff68d1f3abefb5b1e39ae5c8b127cc40920f9c4fb33f4b98a"}, -] - -[[package]] -name = "tensorboard-plugin-wit" -version = "1.8.1" -description = "What-If Tool TensorBoard plugin." -category = "main" -optional = true -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "tensorboard_plugin_wit-1.8.1-py3-none-any.whl", hash = "sha256:ff26bdd583d155aa951ee3b152b3d0cffae8005dc697f72b44a8e8c2a77a8cbe"}, + {file = "tensorboard_data_server-0.7.2-py3-none-any.whl", hash = "sha256:7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb"}, + {file = "tensorboard_data_server-0.7.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9fe5d24221b29625dbc7328b0436ca7fc1c23de4acf4d272f1180856e32f9f60"}, + {file = "tensorboard_data_server-0.7.2-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:ef687163c24185ae9754ed5650eb5bc4d84ff257aabdc33f0cc6f74d8ba54530"}, ] [[package]] name = "tensorflow" -version = "2.11.1" +version = "2.13.1" description = "TensorFlow is an open source machine learning framework for everyone." category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tensorflow-2.11.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:ac0e46c5de7985def49e4f688a0ca4180949a4d5dc62b89e9c6640db3c3982ba"}, - {file = "tensorflow-2.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45b1669c523fa6dc240688bffe79f08dfbb76bf5e23a7fe10e722ba658637a44"}, - {file = "tensorflow-2.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a96595e0c068d54717405fa12f36b4a5bb0a9fc53fb9065155a92cff944b35b"}, - {file = "tensorflow-2.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:13197f18f31a52d3f2eac28743d1b06abb8efd86017f184110a1b16841b745b1"}, - {file = "tensorflow-2.11.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9f030f1bc9e7763fa03ec5738323c42021ababcd562fe861b3a3f41e9ff10e43"}, - {file = "tensorflow-2.11.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f12855c1e8373c1327650061fd6a9a3d3772e1bac8241202ea8ccb56213d005"}, - {file = "tensorflow-2.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cd4279cb500074a8ab28af116af7f060f0b015651bef552769d51e55d6fd5c"}, - {file = "tensorflow-2.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:f5a2f75f28cd5fb615a5306f2091eac7da3a8fff949ab8804ec06b8e3682f837"}, - {file = "tensorflow-2.11.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:ea93246ad6c90ff0422f06a82164836fe8098989a8a65c3b02c720eadbe15dde"}, - {file = "tensorflow-2.11.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ba6b3c2f68037e965a19427a1f2a5f0351b7ceae6c686938a8485b08e1e1f3"}, - {file = "tensorflow-2.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ddd5c61f68d8125c985370de96a24a80aee5e3f1604efacec7e1c34ca72de24"}, - {file = "tensorflow-2.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d8834df3f72d7eab56bc2f34f2e52b82d705776b80b36bf5470b7538c9865c"}, + {file = "tensorflow-2.13.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:17b9a82d69abc487ebad503d61acd11fb24f3b0105be669b5319e55f90f0ca21"}, + {file = "tensorflow-2.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f2935ea4bdf37c1840f4d6ed1ddbb4990dc5ae68e1bc8bba4587bac413195c2f"}, + {file = "tensorflow-2.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dd6555e9248bace921a311ff05d88239a6b7e96bcd024c5df4c2eaeb1678ac3"}, + {file = "tensorflow-2.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cd54d7cf979de0e407db182eea27dbed37361af5c329c2dbf71c486be3e432b"}, + {file = "tensorflow-2.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2ab5efb2d0e888a1f65539f495744aaab542ae5e36ed33e50e98cf8b9f088c2c"}, + {file = "tensorflow-2.13.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:dbd7c5c427dacdea1ce2dce29b9a7b3c7409d314fa6f413b7fe58ed5635af754"}, + {file = "tensorflow-2.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:a3e1e42dd286adf0fd91cf68a405a30a21a2c8c09b9515b91faa5704a09ff803"}, + {file = "tensorflow-2.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf37fa1b434568b8c853ffdeeff9e477237495d2f2bbdb0eac61a6bcac779e8"}, + {file = "tensorflow-2.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2f109daa5d0cbabb3df5fdebcde0ca895d891e18d03e08cb6742c96a6be7012"}, + {file = "tensorflow-2.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:c23ebcaa2131062a9bf6fe2634aef8c95f9c043b2dc814bc2f8765ba7a4e3612"}, + {file = "tensorflow-2.13.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:56f35d88c419d59ed5e2823f1c69d794c8f28b77f3aed5300e454e7513a6228e"}, + {file = "tensorflow-2.13.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:89959a3a31f17c3a0099d7e3c48b20a02eb01f3c1dbf96c6cc5fbf84a623e176"}, + {file = "tensorflow-2.13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e42cdf625125c9ef99d29310774617990915cd046125ef5e9624799659a7d3e8"}, + {file = "tensorflow-2.13.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deb204fc8c98ceff81f0f776ffb5172e1a6892143c7bfee90a865e9d5e4bbee2"}, + {file = "tensorflow-2.13.1-cp38-cp38-win_amd64.whl", hash = "sha256:46024ba77aaf5c0b578aadf0c75320e539e135ddfe731a1ee241b039c332e565"}, + {file = "tensorflow-2.13.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:fbb68c8ea407f515393ef50bd8ccbbc01914cc76f39e2ca18c238a3189230f71"}, + {file = "tensorflow-2.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:69add96604b9a4e8e8e00505953478027964445d8eb8d7541538ef38159b7f27"}, + {file = "tensorflow-2.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3bf992bf62cf628f5ff57694312037885ba8cc7b8b0d51b3d772e350a717d2d0"}, + {file = "tensorflow-2.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04538df649aa0be5050695cdb0c8f2c26e6122ca04c7c1e4471b23c0d6c490cf"}, + {file = "tensorflow-2.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:884dbafa213f8bea7869977f88bfb404051b65aa17dc7927ff4bfe47e3fc839b"}, ] [package.dependencies] absl-py = ">=1.0.0" astunparse = ">=1.6.0" -flatbuffers = ">=2.0" +flatbuffers = ">=23.1.21" gast = ">=0.2.1,<=0.4.0" google-pasta = ">=0.1.1" grpcio = ">=1.24.3,<2.0" h5py = ">=2.9.0" -keras = ">=2.11.0,<2.12" +keras = ">=2.13.1,<2.14" libclang = ">=13.0.0" -numpy = ">=1.20" +numpy = ">=1.22,<=1.24.3" opt-einsum = ">=2.3.2" packaging = "*" -protobuf = ">=3.9.2,<3.20" +protobuf = ">=3.20.3,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" setuptools = "*" six = ">=1.12.0" -tensorboard = ">=2.11,<2.12" -tensorflow-estimator = ">=2.11.0,<2.12" +tensorboard = ">=2.13,<2.14" +tensorflow-estimator = ">=2.13.0,<2.14" tensorflow-io-gcs-filesystem = {version = ">=0.23.1", markers = "platform_machine != \"arm64\" or platform_system != \"Darwin\""} termcolor = ">=1.1.0" -typing-extensions = ">=3.6.6" +typing-extensions = ">=3.6.6,<4.6.0" wrapt = ">=1.11.0" [[package]] name = "tensorflow-estimator" -version = "2.11.0" +version = "2.13.0" description = "TensorFlow Estimator." category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "tensorflow_estimator-2.11.0-py2.py3-none-any.whl", hash = "sha256:ea3b64acfff3d9a244f06178c9bdedcbdd3f125b67d0888dba8229498d06468b"}, + {file = "tensorflow_estimator-2.13.0-py2.py3-none-any.whl", hash = "sha256:6f868284eaa654ae3aa7cacdbef2175d0909df9fcf11374f5166f8bf475952aa"}, ] [[package]] name = "tensorflow-io-gcs-filesystem" -version = "0.32.0" +version = "0.34.0" description = "TensorFlow IO" category = "main" optional = true python-versions = ">=3.7, <3.12" files = [ - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:74a7e25e83d4117a7ebb09a3f247553a5497393ab48c3ee0cf0d17b405026817"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:045d51bba586390d0545fcd8a18727d62b175eb142f6f4c6d719d39de40774cd"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db682e9a510c27dd35710ba5a2c62c371e25b727741b2fe3a920355fa501e947"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:7f15fd22e592661b10de317be2f42a0f84be7bfc5e6a565fcfcb04b60d625b78"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:336d9b3fe6b55aea149c4f6aa1fd6ffaf27d4e5c37e55a182340b47caba38846"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842f5f09cd756bdb3b4d0b5571b3a6f72fd534d42da938b9acf0ef462995eada"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:1ce80e1555d6ee88dda67feddf366cc8b30252b5837a7a17303df7b06a71fc2e"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05e65d3cb6c93a7929b384d86c6369c63cbbab8a770440a3d95e094878403f9f"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:21de7dcc06eb1e7de3c022b0072d90ba35ef886578149663437aa7a6fb5bf6b3"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:79fdd02103b8ae9f8b89af41f744c013fa1caaea709de19833917795e3063857"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5635df0bbe40f971dc1b946e3372744b0bdfda45c38ffcd28ef53a32bb8da4da"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:122be149e5f6a030f5c2901be0cc3cb07619232f7b03889e2cdf3da1c0d4f92f"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8214cdf85bea694160f9035ff395221c1e25e119784ccb4c104919b1f5dec84e"}, - {file = "tensorflow_io_gcs_filesystem-0.32.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28202492d904a6e280cf27560791e87ac1c7566000db82065d63a70c27008af2"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:d831702fbb270996b27cda7fde06e0825b2ea81fd8dd3ead35242f4f8b3889b8"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:b9a93fcb01db269bc845a1ced431f3c61201755ce5f9ec4885760f30122276ef"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5813c336b4f7cb0a01ff4cc6cbd3edf11ef67305baf0e3cf634911b702f493f8"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b035f4c92639657b6d376929d550ac3dee9e6c0523eb434eefe0a27bae3d05b"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:a17a616d2c7fae83de4424404815843507d40d4eb0d507c636a5493a20c3d958"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:ec4604c99cbb5b708f4516dee27aa655abae222b876c98b740f4c2f89dd5c001"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cbe26c4a3332589c7b724f147df453b5c226993aa8d346a15536358d77b364c4"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e6353123a5b51397950138a118876af833a7db66b531123bb86f82e80ab0e72"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f211d2b3db8f9931765992b607b71cbfb98c8cd6169079d004a67a94ab10ecb4"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:d3feba2dd76f7c188137c34642d68d378f0eed81636cb95090ecb1496722707c"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:44ad387a812a78e7424bb8bee3820521ae1c044bddf72b1e163e8df95c124a74"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:7f60183473f0ca966451bb1d1bb5dc29b3cf9c74d1d0e7f2ed46760ed56bd4af"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:3f346b287ed2400e09b13cfd8524222fd70a66aadb9164c645286c2087007e9f"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:027a07553367187f918a99661f63ae0506b91b77a70bee9c7ccaf3920bf7cfe7"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d8664bddbe4e7b56ce94db8b93ea9077a158fb5e15364e11e29f93015ceea24"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:182b0fbde7e9a537fda0b354c28b0b6c035736728de8fe2db7ef49cf90352014"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:0dafed144673e1173528768fe208a7c5a6e8edae40208381cac420ee7c918ec9"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:396bfff61b49f80b86ddebe0c76ae0f2731689cee49ad7d782625180b50b13af"}, + {file = "tensorflow_io_gcs_filesystem-0.34.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b20622f8572fcb6c93e8f7d626327472f263e47ebd63d2153ef09162ef5ef7b5"}, ] [package.extras] -tensorflow = ["tensorflow (>=2.12.0,<2.13.0)"] -tensorflow-aarch64 = ["tensorflow-aarch64 (>=2.12.0,<2.13.0)"] -tensorflow-cpu = ["tensorflow-cpu (>=2.12.0,<2.13.0)"] -tensorflow-gpu = ["tensorflow-gpu (>=2.12.0,<2.13.0)"] -tensorflow-rocm = ["tensorflow-rocm (>=2.12.0,<2.13.0)"] +tensorflow = ["tensorflow (>=2.13.0,<2.14.0)"] +tensorflow-aarch64 = ["tensorflow-aarch64 (>=2.13.0,<2.14.0)"] +tensorflow-cpu = ["tensorflow-cpu (>=2.13.0,<2.14.0)"] +tensorflow-gpu = ["tensorflow-gpu (>=2.13.0,<2.14.0)"] +tensorflow-rocm = ["tensorflow-rocm (>=2.13.0,<2.14.0)"] [[package]] name = "tensorflow-serving-api" -version = "2.11.1" +version = "2.13.1" description = "TensorFlow Serving Python API." category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tensorflow_serving_api-2.11.1-py2.py3-none-any.whl", hash = "sha256:42dbf8b694b7e9cede6b7288739f05f744f0b11976e1c500d0c93c5f216d255a"}, + {file = "tensorflow_serving_api-2.13.1-py2.py3-none-any.whl", hash = "sha256:b01548d671d37aa57f111cae2a621beac26d89cfdb2794c1150132e8f398e7e7"}, ] [package.dependencies] grpcio = ">=1.24.3,<2.0" -protobuf = ">=3.9.2,<3.20" -tensorflow = ">=2.11.1,<3" +protobuf = ">=3.20.3,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" +tensorflow = ">=2.13.1,<3" [[package]] name = "termcolor" -version = "2.2.0" +version = "2.3.0" description = "ANSI color formatting for output in terminal" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "termcolor-2.2.0-py3-none-any.whl", hash = "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7"}, - {file = "termcolor-2.2.0.tar.gz", hash = "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a"}, + {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, + {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, ] [package.extras] @@ -5268,14 +5476,14 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "terminado" -version = "0.17.1" +version = "0.18.0" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "terminado-0.17.1-py3-none-any.whl", hash = "sha256:8650d44334eba354dd591129ca3124a6ba42c3d5b70df5051b6921d506fdaeae"}, - {file = "terminado-0.17.1.tar.gz", hash = "sha256:6ccbbcd3a4f8a25a5ec04991f39a0b8db52dfcd487ea0e578d977e6752380333"}, + {file = "terminado-0.18.0-py3-none-any.whl", hash = "sha256:87b0d96642d0fe5f5abd7783857b9cab167f221a39ff98e3b9619a788a3c0f2e"}, + {file = "terminado-0.18.0.tar.gz", hash = "sha256:1ea08a89b835dd1b8c0c900d92848147cef2537243361b2e3f4dc15df9b6fded"}, ] [package.dependencies] @@ -5286,17 +5494,18 @@ tornado = ">=6.1.0" [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] +typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] [[package]] name = "threadpoolctl" -version = "3.1.0" +version = "3.2.0" description = "threadpoolctl" category = "main" optional = true -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "threadpoolctl-3.1.0-py3-none-any.whl", hash = "sha256:8b99adda265feb6773280df41eece7b2e6561b772d21ffd52e372f999024907b"}, - {file = "threadpoolctl-3.1.0.tar.gz", hash = "sha256:a335baacfaa4400ae1f0d8e3a58d6674d2f8828e3716bb2802c44955ad391380"}, + {file = "threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032"}, + {file = "threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355"}, ] [[package]] @@ -5355,14 +5564,14 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.7" +version = "0.12.3" description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, - {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, + {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, + {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, ] [[package]] @@ -5408,88 +5617,102 @@ opt-einsum = ["opt-einsum (>=3.3)"] [[package]] name = "torchmetrics" -version = "0.11.4" +version = "1.2.0" description = "PyTorch native Metrics" category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "torchmetrics-0.11.4-py3-none-any.whl", hash = "sha256:45f892f3534e91f3ad9e2488d1b05a93b7cb76b7d037969435a41a1f24750d9a"}, - {file = "torchmetrics-0.11.4.tar.gz", hash = "sha256:1fe45a14b44dd65d90199017dd5a4b5a128d56a8a311da7916c402c18c671494"}, + {file = "torchmetrics-1.2.0-py3-none-any.whl", hash = "sha256:da2cb18822b285786d082c40efb9e1d861aac425f58230234fe6ce233cf002f8"}, + {file = "torchmetrics-1.2.0.tar.gz", hash = "sha256:7eb28340bde45e13187a9ad54a4a7010a50417815d8181a5df6131f116ffe1b7"}, ] [package.dependencies] -numpy = ">=1.17.2" -packaging = "*" +lightning-utilities = ">=0.8.0" +numpy = ">1.20.0" torch = ">=1.8.1" -typing-extensions = {version = "*", markers = "python_version < \"3.9\""} [package.extras] -all = ["lpips (<=0.1.4)", "nltk (>=3.6)", "pycocotools (>2.0.0)", "pystoi (<=0.3.3)", "regex (>=2021.9.24)", "scipy (>1.0.0)", "torch-fidelity (<=0.3.0)", "torchvision (>=0.8)", "tqdm (>=4.41.0)", "transformers (>=4.10.0)"] -audio = ["pystoi (<=0.3.3)"] +all = ["SciencePlots (>=2.0.0)", "lpips (<=0.1.4)", "matplotlib (>=3.2.0)", "mypy (==1.5.1)", "nltk (>=3.6)", "piq (<=0.8.0)", "pycocotools (>2.0.0)", "pystoi (>=0.3.0)", "regex (>=2021.9.24)", "scipy (>1.0.0)", "torch-fidelity (<=0.4.0)", "torchaudio (>=0.10.0)", "torchvision (>=0.8)", "tqdm (>=4.41.0)", "transformers (>4.4.0)", "transformers (>=4.10.0)", "types-PyYAML", "types-emoji", "types-protobuf", "types-requests", "types-setuptools", "types-six", "types-tabulate"] +audio = ["pystoi (>=0.3.0)", "torchaudio (>=0.10.0)"] detection = ["pycocotools (>2.0.0)", "torchvision (>=0.8)"] -image = ["lpips (<=0.1.4)", "scipy (>1.0.0)", "torch-fidelity (<=0.3.0)", "torchvision (>=0.8)"] -multimodal = ["transformers (>=4.10.0)"] -test = ["bert-score (==0.3.13)", "cloudpickle (>1.3)", "coverage (>5.2)", "dython (<=0.7.3)", "fast-bss-eval (>=0.1.0)", "fire (<=0.5.0)", "huggingface-hub (<0.7)", "jiwer (>=2.3.0)", "kornia (>=0.6.7)", "mir-eval (>=0.6)", "mypy (==0.982)", "netcal (>1.0.0)", "pandas (>1.0.0)", "phmdoctest (>=1.1.1)", "psutil (<=5.9.4)", "pypesq (>1.2)", "pytest (>=6.0.0)", "pytest-cov (>2.10)", "pytest-doctestplus (>=0.9.0)", "pytest-rerunfailures (>=10.0)", "pytest-timeout (<=2.1.0)", "pytorch-msssim (==0.2.1)", "requests (<=2.28.2)", "rouge-score (>0.1.0)", "sacrebleu (>=2.0.0)", "scikit-image (>0.17.1)", "scikit-learn (>1.0)", "scipy (>1.0.0)", "torch-complex (<=0.4.3)", "transformers (>4.4.0)", "types-PyYAML", "types-emoji", "types-protobuf", "types-requests", "types-setuptools", "types-six", "types-tabulate"] -text = ["nltk (>=3.6)", "regex (>=2021.9.24)", "tqdm (>=4.41.0)"] +dev = ["SciencePlots (>=2.0.0)", "bert-score (==0.3.13)", "cloudpickle (>1.3)", "coverage (==7.3.1)", "dython (<=0.7.4)", "fairlearn", "fast-bss-eval (>=0.1.0)", "faster-coco-eval (>=1.3.3)", "fire (<=0.5.0)", "huggingface-hub (<0.18)", "jiwer (>=2.3.0)", "kornia (>=0.6.7)", "lpips (<=0.1.4)", "matplotlib (>=3.2.0)", "mir-eval (>=0.6)", "mypy (==1.5.1)", "netcal (>1.0.0)", "nltk (>=3.6)", "numpy (<1.25.0)", "pandas (>1.0.0)", "pandas (>=1.4.0)", "phmdoctest (==1.4.0)", "piq (<=0.8.0)", "psutil (<=5.9.5)", "pycocotools (>2.0.0)", "pystoi (>=0.3.0)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-doctestplus (==1.0.0)", "pytest-rerunfailures (==12.0)", "pytest-timeout (==2.1.0)", "pytorch-msssim (==1.0.0)", "regex (>=2021.9.24)", "requests (<=2.31.0)", "rouge-score (>0.1.0)", "sacrebleu (>=2.0.0)", "scikit-image (>=0.19.0)", "scikit-learn (>=1.1.1)", "scipy (>1.0.0)", "sewar (>=0.4.4)", "statsmodels (>0.13.5)", "torch-complex (<=0.4.3)", "torch-fidelity (<=0.4.0)", "torchaudio (>=0.10.0)", "torchvision (>=0.8)", "tqdm (>=4.41.0)", "transformers (>4.4.0)", "transformers (>=4.10.0)", "types-PyYAML", "types-emoji", "types-protobuf", "types-requests", "types-setuptools", "types-six", "types-tabulate"] +image = ["lpips (<=0.1.4)", "scipy (>1.0.0)", "torch-fidelity (<=0.4.0)", "torchvision (>=0.8)"] +multimodal = ["piq (<=0.8.0)", "transformers (>=4.10.0)"] +test = ["bert-score (==0.3.13)", "cloudpickle (>1.3)", "coverage (==7.3.1)", "dython (<=0.7.4)", "fairlearn", "fast-bss-eval (>=0.1.0)", "faster-coco-eval (>=1.3.3)", "fire (<=0.5.0)", "huggingface-hub (<0.18)", "jiwer (>=2.3.0)", "kornia (>=0.6.7)", "mir-eval (>=0.6)", "netcal (>1.0.0)", "numpy (<1.25.0)", "pandas (>1.0.0)", "pandas (>=1.4.0)", "phmdoctest (==1.4.0)", "psutil (<=5.9.5)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-doctestplus (==1.0.0)", "pytest-rerunfailures (==12.0)", "pytest-timeout (==2.1.0)", "pytorch-msssim (==1.0.0)", "requests (<=2.31.0)", "rouge-score (>0.1.0)", "sacrebleu (>=2.0.0)", "scikit-image (>=0.19.0)", "scikit-learn (>=1.1.1)", "scipy (>1.0.0)", "sewar (>=0.4.4)", "statsmodels (>0.13.5)", "torch-complex (<=0.4.3)"] +text = ["nltk (>=3.6)", "regex (>=2021.9.24)", "tqdm (>=4.41.0)", "transformers (>4.4.0)"] +typing = ["mypy (==1.5.1)", "types-PyYAML", "types-emoji", "types-protobuf", "types-requests", "types-setuptools", "types-six", "types-tabulate"] +visual = ["SciencePlots (>=2.0.0)", "matplotlib (>=3.2.0)"] [[package]] name = "tornado" -version = "6.2" +version = "6.3.3" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." category = "main" optional = false -python-versions = ">= 3.7" +python-versions = ">= 3.8" files = [ - {file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"}, - {file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"}, - {file = "tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"}, - {file = "tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"}, - {file = "tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"}, - {file = "tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"}, - {file = "tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"}, - {file = "tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"}, - {file = "tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"}, - {file = "tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"}, - {file = "tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"}, + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, + {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, + {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, + {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, ] [[package]] name = "tqdm" -version = "4.65.0" +version = "4.66.1" description = "Fast, Extensible Progress Meter" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"}, - {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"}, + {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, + {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["py-make (>=0.1.0)", "twine", "wheel"] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] [[package]] name = "traitlets" -version = "5.9.0" +version = "5.13.0" description = "Traitlets Python configuration system" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, - {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, + {file = "traitlets-5.13.0-py3-none-any.whl", hash = "sha256:baf991e61542da48fe8aef8b779a9ea0aa38d8a54166ee250d5af5ecf4486619"}, + {file = "traitlets-5.13.0.tar.gz", hash = "sha256:9b232b9430c8f57288c1024b34a8f0251ddcc47268927367a0dd3eeaca40deb5"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.6.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "types-python-dateutil" +version = "2.8.19.14" +description = "Typing stubs for python-dateutil" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "types-python-dateutil-2.8.19.14.tar.gz", hash = "sha256:1f4f10ac98bb8b16ade9dbee3518d9ace017821d94b057a425b069f834737f4b"}, + {file = "types_python_dateutil-2.8.19.14-py3-none-any.whl", hash = "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9"}, +] [[package]] name = "typing-extensions" @@ -5505,46 +5728,46 @@ files = [ [[package]] name = "uri-template" -version = "1.2.0" +version = "1.3.0" description = "RFC 6570 URI Template Processor" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "uri_template-1.2.0-py3-none-any.whl", hash = "sha256:f1699c77b73b925cf4937eae31ab282a86dc885c333f2e942513f08f691fc7db"}, - {file = "uri_template-1.2.0.tar.gz", hash = "sha256:934e4d09d108b70eb8a24410af8615294d09d279ce0e7cbcdaef1bd21f932b06"}, + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, ] [package.extras] -dev = ["flake8 (<4.0.0)", "flake8-annotations", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-noqa", "flake8-requirements", "flake8-type-annotations", "flake8-use-fstring", "mypy", "pep8-naming"] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] [[package]] name = "urllib3" -version = "1.26.15" +version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.8" files = [ - {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, - {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "wcwidth" -version = "0.2.6" +version = "0.2.12" description = "Measures the displayed width of unicode strings in a terminal" category = "main" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, - {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, + {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"}, + {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"}, ] [[package]] @@ -5577,64 +5800,64 @@ files = [ [[package]] name = "websocket-client" -version = "1.5.1" +version = "1.6.4" description = "WebSocket client for Python with low level API options" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "websocket-client-1.5.1.tar.gz", hash = "sha256:3f09e6d8230892547132177f575a4e3e73cfdf06526e20cc02aa1c3b47184d40"}, - {file = "websocket_client-1.5.1-py3-none-any.whl", hash = "sha256:cdf5877568b7e83aa7cf2244ab56a3213de587bbe0ce9d8b9600fc77b455d89e"}, + {file = "websocket-client-1.6.4.tar.gz", hash = "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df"}, + {file = "websocket_client-1.6.4-py3-none-any.whl", hash = "sha256:084072e0a7f5f347ef2ac3d8698a5e0b4ffbfcab607628cadabc650fc9a83a24"}, ] [package.extras] -docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] +docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] [[package]] name = "werkzeug" -version = "2.2.3" +version = "3.0.1" description = "The comprehensive WSGI web application library." category = "main" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Werkzeug-2.2.3-py3-none-any.whl", hash = "sha256:56433961bc1f12533306c624f3be5e744389ac61d722175d543e1751285da612"}, - {file = "Werkzeug-2.2.3.tar.gz", hash = "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe"}, + {file = "werkzeug-3.0.1-py3-none-any.whl", hash = "sha256:90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10"}, + {file = "werkzeug-3.0.1.tar.gz", hash = "sha256:507e811ecea72b18a404947aded4b3390e1db8f826b494d76550ef45bb3b1dcc"}, ] [package.dependencies] MarkupSafe = ">=2.1.1" [package.extras] -watchdog = ["watchdog"] +watchdog = ["watchdog (>=2.3)"] [[package]] name = "wheel" -version = "0.40.0" +version = "0.41.3" description = "A built-package format for Python" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"}, - {file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"}, + {file = "wheel-0.41.3-py3-none-any.whl", hash = "sha256:488609bc63a29322326e05560731bf7bfea8e48ad646e1f5e40d366607de0942"}, + {file = "wheel-0.41.3.tar.gz", hash = "sha256:4d4987ce51a49370ea65c0bfd2234e8ce80a12780820d9dc462597a6e60d0841"}, ] [package.extras] -test = ["pytest (>=6.0.0)"] +test = ["pytest (>=6.0.0)", "setuptools (>=65)"] [[package]] name = "widgetsnbextension" -version = "3.6.4" +version = "3.6.6" description = "IPython HTML widgets for Jupyter" category = "main" optional = false python-versions = "*" files = [ - {file = "widgetsnbextension-3.6.4-py2.py3-none-any.whl", hash = "sha256:3d2d4994aea8681eb438493e439f59f82ba81d91f388a12e55147ae137f4120e"}, - {file = "widgetsnbextension-3.6.4.tar.gz", hash = "sha256:ad1356c575d5add908afe886255deafb3f9b1589146a99279d1dcba5a05d16a5"}, + {file = "widgetsnbextension-3.6.6-py2.py3-none-any.whl", hash = "sha256:e7fb9999845affc9024ecfbe0a824dd8e633403d027b28ceadab398b633ad51c"}, + {file = "widgetsnbextension-3.6.6.tar.gz", hash = "sha256:46f4e3cb2d451bbd6141a13696d6ba17c9b5f50645dca9cfd26fe9644d5a00e1"}, ] [package.dependencies] @@ -5642,171 +5865,182 @@ notebook = ">=4.4.1" [[package]] name = "wrapt" -version = "1.15.0" +version = "1.16.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" +python-versions = ">=3.6" files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] [[package]] name = "yarl" -version = "1.8.2" +version = "1.9.3" description = "Yet another URL library" category = "main" optional = true python-versions = ">=3.7" files = [ - {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"}, - {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"}, - {file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"}, - {file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"}, - {file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"}, - {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"}, - {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"}, - {file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"}, - {file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"}, - {file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"}, - {file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"}, - {file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"}, - {file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"}, - {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"}, - {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"}, - {file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"}, - {file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"}, - {file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"}, - {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"}, - {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"}, - {file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"}, - {file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"}, - {file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"}, - {file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"}, + {file = "yarl-1.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32435d134414e01d937cd9d6cc56e8413a8d4741dea36af5840c7750f04d16ab"}, + {file = "yarl-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9a5211de242754b5e612557bca701f39f8b1a9408dff73c6db623f22d20f470e"}, + {file = "yarl-1.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:525cd69eff44833b01f8ef39aa33a9cc53a99ff7f9d76a6ef6a9fb758f54d0ff"}, + {file = "yarl-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc94441bcf9cb8c59f51f23193316afefbf3ff858460cb47b5758bf66a14d130"}, + {file = "yarl-1.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e36021db54b8a0475805acc1d6c4bca5d9f52c3825ad29ae2d398a9d530ddb88"}, + {file = "yarl-1.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0f17d1df951336a02afc8270c03c0c6e60d1f9996fcbd43a4ce6be81de0bd9d"}, + {file = "yarl-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5f3faeb8100a43adf3e7925d556801d14b5816a0ac9e75e22948e787feec642"}, + {file = "yarl-1.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aed37db837ecb5962469fad448aaae0f0ee94ffce2062cf2eb9aed13328b5196"}, + {file = "yarl-1.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:721ee3fc292f0d069a04016ef2c3a25595d48c5b8ddc6029be46f6158d129c92"}, + {file = "yarl-1.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b8bc5b87a65a4e64bc83385c05145ea901b613d0d3a434d434b55511b6ab0067"}, + {file = "yarl-1.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:dd952b9c64f3b21aedd09b8fe958e4931864dba69926d8a90c90d36ac4e28c9a"}, + {file = "yarl-1.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:c405d482c320a88ab53dcbd98d6d6f32ada074f2d965d6e9bf2d823158fa97de"}, + {file = "yarl-1.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9df9a0d4c5624790a0dea2e02e3b1b3c69aed14bcb8650e19606d9df3719e87d"}, + {file = "yarl-1.9.3-cp310-cp310-win32.whl", hash = "sha256:d34c4f80956227f2686ddea5b3585e109c2733e2d4ef12eb1b8b4e84f09a2ab6"}, + {file = "yarl-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:cf7a4e8de7f1092829caef66fd90eaf3710bc5efd322a816d5677b7664893c93"}, + {file = "yarl-1.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d61a0ca95503867d4d627517bcfdc28a8468c3f1b0b06c626f30dd759d3999fd"}, + {file = "yarl-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73cc83f918b69110813a7d95024266072d987b903a623ecae673d1e71579d566"}, + {file = "yarl-1.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d81657b23e0edb84b37167e98aefb04ae16cbc5352770057893bd222cdc6e45f"}, + {file = "yarl-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a1a8443091c7fbc17b84a0d9f38de34b8423b459fb853e6c8cdfab0eacf613"}, + {file = "yarl-1.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe34befb8c765b8ce562f0200afda3578f8abb159c76de3ab354c80b72244c41"}, + {file = "yarl-1.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c757f64afe53a422e45e3e399e1e3cf82b7a2f244796ce80d8ca53e16a49b9f"}, + {file = "yarl-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a57b41a0920b9a220125081c1e191b88a4cdec13bf9d0649e382a822705c65"}, + {file = "yarl-1.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:632c7aeb99df718765adf58eacb9acb9cbc555e075da849c1378ef4d18bf536a"}, + {file = "yarl-1.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b0b8c06afcf2bac5a50b37f64efbde978b7f9dc88842ce9729c020dc71fae4ce"}, + {file = "yarl-1.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1d93461e2cf76c4796355494f15ffcb50a3c198cc2d601ad8d6a96219a10c363"}, + {file = "yarl-1.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4003f380dac50328c85e85416aca6985536812c082387255c35292cb4b41707e"}, + {file = "yarl-1.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4d6d74a97e898c1c2df80339aa423234ad9ea2052f66366cef1e80448798c13d"}, + {file = "yarl-1.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b61e64b06c3640feab73fa4ff9cb64bd8182de52e5dc13038e01cfe674ebc321"}, + {file = "yarl-1.9.3-cp311-cp311-win32.whl", hash = "sha256:29beac86f33d6c7ab1d79bd0213aa7aed2d2f555386856bb3056d5fdd9dab279"}, + {file = "yarl-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:f7271d6bd8838c49ba8ae647fc06469137e1c161a7ef97d778b72904d9b68696"}, + {file = "yarl-1.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:dd318e6b75ca80bff0b22b302f83a8ee41c62b8ac662ddb49f67ec97e799885d"}, + {file = "yarl-1.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4b1efb11a8acd13246ffb0bee888dd0e8eb057f8bf30112e3e21e421eb82d4a"}, + {file = "yarl-1.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c6f034386e5550b5dc8ded90b5e2ff7db21f0f5c7de37b6efc5dac046eb19c10"}, + {file = "yarl-1.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd49a908cb6d387fc26acee8b7d9fcc9bbf8e1aca890c0b2fdfd706057546080"}, + {file = "yarl-1.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa4643635f26052401750bd54db911b6342eb1a9ac3e74f0f8b58a25d61dfe41"}, + {file = "yarl-1.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e741bd48e6a417bdfbae02e088f60018286d6c141639359fb8df017a3b69415a"}, + {file = "yarl-1.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c86d0d0919952d05df880a1889a4f0aeb6868e98961c090e335671dea5c0361"}, + {file = "yarl-1.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d5434b34100b504aabae75f0622ebb85defffe7b64ad8f52b8b30ec6ef6e4b9"}, + {file = "yarl-1.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79e1df60f7c2b148722fb6cafebffe1acd95fd8b5fd77795f56247edaf326752"}, + {file = "yarl-1.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:44e91a669c43f03964f672c5a234ae0d7a4d49c9b85d1baa93dec28afa28ffbd"}, + {file = "yarl-1.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3cfa4dbe17b2e6fca1414e9c3bcc216f6930cb18ea7646e7d0d52792ac196808"}, + {file = "yarl-1.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:88d2c3cc4b2f46d1ba73d81c51ec0e486f59cc51165ea4f789677f91a303a9a7"}, + {file = "yarl-1.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cccdc02e46d2bd7cb5f38f8cc3d9db0d24951abd082b2f242c9e9f59c0ab2af3"}, + {file = "yarl-1.9.3-cp312-cp312-win32.whl", hash = "sha256:96758e56dceb8a70f8a5cff1e452daaeff07d1cc9f11e9b0c951330f0a2396a7"}, + {file = "yarl-1.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:c4472fe53ebf541113e533971bd8c32728debc4c6d8cc177f2bff31d011ec17e"}, + {file = "yarl-1.9.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:126638ab961633f0940a06e1c9d59919003ef212a15869708dcb7305f91a6732"}, + {file = "yarl-1.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c99ddaddb2fbe04953b84d1651149a0d85214780e4d0ee824e610ab549d98d92"}, + {file = "yarl-1.9.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dab30b21bd6fb17c3f4684868c7e6a9e8468078db00f599fb1c14e324b10fca"}, + {file = "yarl-1.9.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:828235a2a169160ee73a2fcfb8a000709edf09d7511fccf203465c3d5acc59e4"}, + {file = "yarl-1.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc391e3941045fd0987c77484b2799adffd08e4b6735c4ee5f054366a2e1551d"}, + {file = "yarl-1.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51382c72dd5377861b573bd55dcf680df54cea84147c8648b15ac507fbef984d"}, + {file = "yarl-1.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:28a108cb92ce6cf867690a962372996ca332d8cda0210c5ad487fe996e76b8bb"}, + {file = "yarl-1.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8f18a7832ff85dfcd77871fe677b169b1bc60c021978c90c3bb14f727596e0ae"}, + {file = "yarl-1.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:7eaf13af79950142ab2bbb8362f8d8d935be9aaf8df1df89c86c3231e4ff238a"}, + {file = "yarl-1.9.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:66a6dbf6ca7d2db03cc61cafe1ee6be838ce0fbc97781881a22a58a7c5efef42"}, + {file = "yarl-1.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a0a4f3aaa18580038cfa52a7183c8ffbbe7d727fe581300817efc1e96d1b0e9"}, + {file = "yarl-1.9.3-cp37-cp37m-win32.whl", hash = "sha256:946db4511b2d815979d733ac6a961f47e20a29c297be0d55b6d4b77ee4b298f6"}, + {file = "yarl-1.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2dad8166d41ebd1f76ce107cf6a31e39801aee3844a54a90af23278b072f1ccf"}, + {file = "yarl-1.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bb72d2a94481e7dc7a0c522673db288f31849800d6ce2435317376a345728225"}, + {file = "yarl-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9a172c3d5447b7da1680a1a2d6ecdf6f87a319d21d52729f45ec938a7006d5d8"}, + {file = "yarl-1.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2dc72e891672343b99db6d497024bf8b985537ad6c393359dc5227ef653b2f17"}, + {file = "yarl-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8d51817cf4b8d545963ec65ff06c1b92e5765aa98831678d0e2240b6e9fd281"}, + {file = "yarl-1.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53ec65f7eee8655bebb1f6f1607760d123c3c115a324b443df4f916383482a67"}, + {file = "yarl-1.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cfd77e8e5cafba3fb584e0f4b935a59216f352b73d4987be3af51f43a862c403"}, + {file = "yarl-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e73db54c967eb75037c178a54445c5a4e7461b5203b27c45ef656a81787c0c1b"}, + {file = "yarl-1.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09c19e5f4404574fcfb736efecf75844ffe8610606f3fccc35a1515b8b6712c4"}, + {file = "yarl-1.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6280353940f7e5e2efaaabd686193e61351e966cc02f401761c4d87f48c89ea4"}, + {file = "yarl-1.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c25ec06e4241e162f5d1f57c370f4078797ade95c9208bd0c60f484834f09c96"}, + {file = "yarl-1.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7217234b10c64b52cc39a8d82550342ae2e45be34f5bff02b890b8c452eb48d7"}, + {file = "yarl-1.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4ce77d289f8d40905c054b63f29851ecbfd026ef4ba5c371a158cfe6f623663e"}, + {file = "yarl-1.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5f74b015c99a5eac5ae589de27a1201418a5d9d460e89ccb3366015c6153e60a"}, + {file = "yarl-1.9.3-cp38-cp38-win32.whl", hash = "sha256:8a2538806be846ea25e90c28786136932ec385c7ff3bc1148e45125984783dc6"}, + {file = "yarl-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:6465d36381af057d0fab4e0f24ef0e80ba61f03fe43e6eeccbe0056e74aadc70"}, + {file = "yarl-1.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2f3c8822bc8fb4a347a192dd6a28a25d7f0ea3262e826d7d4ef9cc99cd06d07e"}, + {file = "yarl-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7831566595fe88ba17ea80e4b61c0eb599f84c85acaa14bf04dd90319a45b90"}, + {file = "yarl-1.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ff34cb09a332832d1cf38acd0f604c068665192c6107a439a92abfd8acf90fe2"}, + {file = "yarl-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe8080b4f25dfc44a86bedd14bc4f9d469dfc6456e6f3c5d9077e81a5fedfba7"}, + {file = "yarl-1.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8535e111a064f3bdd94c0ed443105934d6f005adad68dd13ce50a488a0ad1bf3"}, + {file = "yarl-1.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d155a092bf0ebf4a9f6f3b7a650dc5d9a5bbb585ef83a52ed36ba46f55cc39d"}, + {file = "yarl-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:778df71c8d0c8c9f1b378624b26431ca80041660d7be7c3f724b2c7a6e65d0d6"}, + {file = "yarl-1.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9f9cafaf031c34d95c1528c16b2fa07b710e6056b3c4e2e34e9317072da5d1a"}, + {file = "yarl-1.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ca6b66f69e30f6e180d52f14d91ac854b8119553b524e0e28d5291a724f0f423"}, + {file = "yarl-1.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0e7e83f31e23c5d00ff618045ddc5e916f9e613d33c5a5823bc0b0a0feb522f"}, + {file = "yarl-1.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:af52725c7c39b0ee655befbbab5b9a1b209e01bb39128dce0db226a10014aacc"}, + {file = "yarl-1.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0ab5baaea8450f4a3e241ef17e3d129b2143e38a685036b075976b9c415ea3eb"}, + {file = "yarl-1.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d350388ba1129bc867c6af1cd17da2b197dff0d2801036d2d7d83c2d771a682"}, + {file = "yarl-1.9.3-cp39-cp39-win32.whl", hash = "sha256:e2a16ef5fa2382af83bef4a18c1b3bcb4284c4732906aa69422cf09df9c59f1f"}, + {file = "yarl-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:d92d897cb4b4bf915fbeb5e604c7911021a8456f0964f3b8ebbe7f9188b9eabb"}, + {file = "yarl-1.9.3-py3-none-any.whl", hash = "sha256:271d63396460b6607b588555ea27a1a02b717ca2e3f2cf53bdde4013d7790929"}, + {file = "yarl-1.9.3.tar.gz", hash = "sha256:4a14907b597ec55740f63e52d7fee0e9ee09d5b9d57a4f399a7423268e457b57"}, ] [package.dependencies] @@ -5815,25 +6049,25 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.15.0" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] -all = ["matplotlib", "pymongo", "route-distances", "scipy", "timeout-decorator"] +all = ["matplotlib", "molbloom", "pymongo", "route-distances", "scipy", "timeout-decorator"] tf = ["grpcio", "tensorflow", "tensorflow-serving-api"] [metadata] lock-version = "2.0" -python-versions = ">=3.8,<3.10" -content-hash = "146ff35eb2bee42ed25157c48f8bf72cda862e236e4745975efe686d5388b212" +python-versions = ">=3.9,<3.11" +content-hash = "9e4e8ce4cb94d50978a131fc3f0f0c1dd1acb41d22f6a91d272fc6b8e801279f" diff --git a/pyproject.toml b/pyproject.toml index 66e7a65..f76ca3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aizynthfinder" -version = "3.7.0" +version = "4.0.0" description = "Retrosynthetic route finding using neural network guided Monte-Carlo tree search" authors = ["Molecular AI group "] license = "MIT" diff --git a/tests/chem/test_mol.py b/tests/chem/test_mol.py index 344bdfd..503f0c7 100644 --- a/tests/chem/test_mol.py +++ b/tests/chem/test_mol.py @@ -88,3 +88,13 @@ def test_remove_atom_mapping(): mol.remove_atom_mapping() assert not mol.has_atom_mapping() + + +def test_chiral_fingerprint(): + mol1 = Molecule(smiles="C[C@@H](C(=O)O)N") + mol2 = Molecule(smiles="C[C@@H](C(=O)O)N") + + fp1 = mol1.fingerprint(radius=2, chiral=False) + fp2 = mol2.fingerprint(radius=2, chiral=True) + + assert fp1.tolist() != fp2.tolist() diff --git a/tests/chem/test_reaction.py b/tests/chem/test_reaction.py index 38048a9..cce1396 100644 --- a/tests/chem/test_reaction.py +++ b/tests/chem/test_reaction.py @@ -1,34 +1,11 @@ from aizynthfinder.chem import ( - Molecule, - UniqueMolecule, - TreeMolecule, - Reaction, - TemplatedRetroReaction, FixedRetroReaction, SmilesBasedRetroReaction, + TemplatedRetroReaction, + TreeMolecule, + UniqueMolecule, hash_reactions, - MoleculeException, ) -from aizynthfinder.reactiontree import ReactionTree - - -def test_fwd_reaction(): - mol1 = Molecule(smiles="CC(=O)O", sanitize=True) - mol2 = Molecule(smiles="NC", sanitize=True) - reaction = Reaction( - mols=[mol1, mol2], smarts="[C:1](=[O:2])-[OD1].[N!H0:3]>>[C:1](=[O:2])[N:3]" - ) - - products = reaction.apply() - - assert len(products) == 1 - assert len(products[0]) == 1 - assert products[0][0].smiles == "CNC(C)=O" - assert reaction.reaction_smiles() == "CC(=O)O.CN>>CNC(C)=O" - assert ( - reaction.hash_key() - == "48430f9760af903f4b846a5f13f0b41ede99be0df93b0b58b581ad4b" - ) def test_retro_reaction(get_action): @@ -83,13 +60,12 @@ def test_retro_reaction_with_rdkit(get_action): def test_retro_reaction_fingerprint(get_action): reaction = get_action() - fp = reaction.fingerprint(2, 10) + fingerprint = reaction.fingerprint(2, 10) - assert list(fp) == [0, -1, 0, -1, -1, 0, -1, -1, 0, 0] + assert list(fingerprint) == [0, -1, 0, -1, -1, 0, -1, -1, 0, 0] def test_retro_reaction_copy(get_action): - mol = TreeMolecule(parent=None, smiles="CCCCOc1ccc(CC(=O)N(C)O)cc1") reaction = get_action() _ = reaction.reactants @@ -157,9 +133,50 @@ def test_set_reactants_list_of_list(): assert rxn.reactants == ((reactant1, reactant2),) +def test_fixed_retroreaction_to_smiles_based_retroreaction(): + smiles = ( + "[CH3:4][NH:3][C:2]([CH3:5])=[O:1]>>[CH3:6][NH2:5].[CH3:4][C:2]([OH:1])=[O:3]" + ) + mol = UniqueMolecule(smiles="CNC(C)=O") + reactant1 = UniqueMolecule(smiles="CN") + reactant2 = UniqueMolecule(smiles="CC(=O)O") + + rxn = FixedRetroReaction(mol, metadata={"mapped_reaction_smiles": smiles}) + rxn.reactants = ((reactant1, reactant2),) + smiles_based_retroreaction = rxn.to_smiles_based_retroreaction() + + assert isinstance(smiles_based_retroreaction, SmilesBasedRetroReaction) + assert smiles_based_retroreaction.mol.smiles == "[CH3:4][NH:3][C:2]([CH3:5])=[O:1]" + assert smiles_based_retroreaction.reactants[0][0].smiles == "CN" + assert smiles_based_retroreaction.reactants[0][1].smiles == "CC(=O)O" + assert ( + smiles_based_retroreaction.mapped_reaction_smiles() + == "[O:1]=[C:2]([NH:3][CH3:4])[CH3:5]>>[NH2:5][CH3:6].[OH:1][C:2](=[O:3])[CH3:4]" + ) + + +def test_fixed_retroreaction_to_smiles_based_retroreaction_no_metadata(): + mol = UniqueMolecule(smiles="CNC(C)=O") + reactant1 = UniqueMolecule(smiles="CN") + reactant2 = UniqueMolecule(smiles="CC(=O)O") + + rxn = FixedRetroReaction(mol) + rxn.reactants = ((reactant1, reactant2),) + smiles_based_retroreaction = rxn.to_smiles_based_retroreaction() + + assert isinstance(smiles_based_retroreaction, SmilesBasedRetroReaction) + assert smiles_based_retroreaction.mol.smiles == "CNC(C)=O" + assert smiles_based_retroreaction.reactants[0][0].smiles == "CN" + assert smiles_based_retroreaction.reactants[0][1].smiles == "CC(=O)O" + assert ( + smiles_based_retroreaction.mapped_reaction_smiles() + == "[CH3:1][NH:2][C:3]([CH3:4])=[O:5]>>[CH3:6][NH2:7].[CH3:8][C:9](=[O:10])[OH:11]" + ) + + def test_reaction_hash(setup_linear_reaction_tree): - rt = setup_linear_reaction_tree() - reactions = list(rt.reactions())[:4] + reaction_tree = setup_linear_reaction_tree() + reactions = list(reaction_tree.reactions())[:4] hash_ = hash_reactions(reactions) @@ -170,44 +187,56 @@ def test_reaction_hash(setup_linear_reaction_tree): assert hash_ == "567c23da4673b8b2519aeafda9b26ae949ad3e24f570968ee5f80878" -def test_create_atom_tracking(): - mol = TreeMolecule(smiles="[C:1][N:2]C(C)=O", parent=None) - - assert mol.tracked_atom_indices == {1: 0, 2: 1} - - -def test_inherit_atom_tracking(): - mol = TreeMolecule(smiles="[C:1][N:2]C(C)=O", parent=None, sanitize=True) - reaction = SmilesBasedRetroReaction(mol, reactants_str="[C:1]C(=O)O.C[N:2]") +def test_mapped_atom_bonds(): + mol = TreeMolecule(smiles="[CH3:1][NH:2][C:3](C)=[O:4]", parent=None) + reaction = SmilesBasedRetroReaction( + mol, + mapped_prod_smiles="[CH3:1][NH:2][C:3](C)=[O:4]", + reactants_str="C[C:3](=[O:4])O.[CH3:1][NH:2]", + ) - assert reaction.reactants[0][0].tracked_atom_indices == {1: 0, 2: None} - assert reaction.reactants[0][1].tracked_atom_indices == {1: None, 2: 1} + assert reaction.reactants[0][0].mapped_atom_bonds == [(6, 3), (3, 4), (3, 7)] + assert reaction.reactants[0][1].mapped_atom_bonds == [(1, 2)] -def test_inherit_atom_tracking_rdchiral(): - smi = "CCCCOc1ccc(C[C:1](=O)[N:2](C)O)cc1" +def test_mapped_atom_bonds_rdchiral(): + smi = "CC(C)C[C:1](=O)[N:2](C)O" mol = TreeMolecule(smiles=smi, parent=None) smarts = ( "([#8:4]-[N;H0;D3;+0:5](-[C;D1;H3:6])-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3])" ">>(Cl-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3]).([#8:4]-[NH;D2;+0:5]-[C;D1;H3:6])" ) - rxn = TemplatedRetroReaction(mol, smarts=smarts) + reaction = TemplatedRetroReaction(mol, smarts=smarts) - assert rxn.reactants[0][0].tracked_atom_indices == {1: 10, 2: None} - assert rxn.reactants[0][1].tracked_atom_indices == {1: None, 2: 0} + assert reaction.reactants[0][0].mapped_atom_bonds == [ + (1, 6), + (6, 4), + (4, 3), + (4, 5), + (1, 7), + (1, 10), + ] + assert reaction.reactants[0][1].mapped_atom_bonds == [(2, 8), (2, 9)] -def test_inherit_atom_tracking_rdkit(): - smi = "CCCCOc1ccc(C[C:1](=O)[N:2](C)O)cc1" +def test_mapped_atom_bonds_rdkit(): + smi = "CC(C)C[C:1](=O)[N:2](C)O" mol = TreeMolecule(smiles=smi, parent=None) smarts = ( "([#8:4]-[N;H0;D3;+0:5](-[C;D1;H3:6])-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3])" ">>(Cl-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3]).([#8:4]-[NH;D2;+0:5]-[C;D1;H3:6])" ) - rxn = TemplatedRetroReaction(mol, smarts=smarts, use_rdchiral=False) - - assert rxn.reactants[0][0].tracked_atom_indices == {1: 1, 2: None} - assert rxn.reactants[0][1].tracked_atom_indices == {1: None, 2: 1} + reaction = TemplatedRetroReaction(mol, smarts=smarts, use_rdchiral=False) + + assert reaction.reactants[0][0].mapped_atom_bonds == [ + (10, 1), + (1, 6), + (1, 7), + (4, 6), + (3, 4), + (4, 5), + ] + assert reaction.reactants[0][1].mapped_atom_bonds == [(9, 2), (2, 8)] def test_inherit_atom_tracking_rdchiral_growing(): diff --git a/tests/chem/test_serialization.py b/tests/chem/test_serialization.py index 6b807fa..cee497d 100644 --- a/tests/chem/test_serialization.py +++ b/tests/chem/test_serialization.py @@ -33,14 +33,12 @@ def test_add_tree_mol(): "class": "TreeMolecule", "parent": id(mol1), "transform": 2, - "tracked_atom_indices": {}, }, id(mol1): { "smiles": "CCC", "class": "TreeMolecule", "parent": None, "transform": 1, - "tracked_atom_indices": {}, }, } diff --git a/tests/conftest.py b/tests/conftest.py index 41407b3..2d896c0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,6 +22,7 @@ from aizynthfinder.chem.serialization import MoleculeDeserializer from aizynthfinder.context.config import Configuration from aizynthfinder.context.policy import ExpansionStrategy, FilterStrategy +from aizynthfinder.context.stock import InMemoryInchiKeyQuery from aizynthfinder.search.andor_trees import ( AndOrSearchTreeBase, SplitAndOrTree, @@ -96,6 +97,7 @@ def create_dummy_stock1(tmpdir): "name": ["benzene", "toluene"], "CAS ID": ["71-43-2", "108-88-3"], "inchi_key": ["UHOVQNZJYSORNB-UHFFFAOYSA-N", "YXFVVABEGXRONW-UHFFFAOYSA-N"], + "price": [5.0, 10.0], } ) @@ -105,7 +107,7 @@ def wrapper(format_): data.to_hdf(filename, "table") elif format_ == "csv": filename = str(tmpdir / "stock1.csv") - data["inchi_key"].to_csv(filename, index=False) + data.to_csv(filename, index=False) else: filename = str(tmpdir / "stock1.txt") with open(filename, "w") as fileobj: @@ -186,15 +188,20 @@ def get_branched_expansion(): @pytest.fixture -def get_expansion_strategy(default_config): +def get_expansion_strategy(default_config): # noqa + # McCabe identifies this as too complex, we will ignore it class LookupExpansionStrategy(ExpansionStrategy): _required_kwargs = ["lookup"] def __init__(self, key, config, **kwargs): super().__init__(key, config, **kwargs) self.lookup = kwargs["lookup"] + self.cache = set() - def get_actions(self, molecules): + def get_actions(self, molecules, cache_molecules=None): + cache_molecules = cache_molecules or [] + for mol in molecules + cache_molecules: + self.cache.add(mol.inchi_key) possible_actions = [] priors = [] for mol in molecules: @@ -203,11 +210,20 @@ def get_actions(self, molecules): expansion_options = self.lookup[mol.smiles] if isinstance(expansion_options, dict): expansion_options = [expansion_options] - possible_actions.extend( - SmilesBasedRetroReaction(mol, reactants_str=item["smiles"]) - for item in expansion_options - ) - priors.extend(item["prior"] for item in expansion_options) + for item in expansion_options: + if "smiles" in item: + possible_actions.append( + SmilesBasedRetroReaction( + mol, + reactants_str=item["smiles"], + metadata={"policy_name": "simple_expansion"}, + ) + ) + if "smarts" in item: + possible_actions.append( + TemplatedRetroReaction(mol, smarts=item["smarts"]) + ) + priors.append(item["prior"]) return possible_actions, priors def wrapper(lookup, config=None): @@ -224,19 +240,20 @@ class LookupFilterStrategy(FilterStrategy): def __init__(self, key, config, **kwargs): super().__init__(key, config, **kwargs) self.lookup = kwargs["lookup"] + self.filter_cutoff: float = kwargs.get("filter_cutoff", 0.05) def apply(self, reaction): prob = self.lookup.get(reaction.smiles) if prob is None: return - if prob < self._config.filter_cutoff: + if prob < self.filter_cutoff: raise RejectionException(f"Reject {reaction} with prob {prob}") def feasibility(self, reaction): prob = self.lookup.get(reaction.smiles) if prob is None: return False, 0.0 - return prob < self._config.filter_cutoff, prob + return prob < self.filter_cutoff, prob def wrapper(lookup, config=None): return LookupFilterStrategy("dummy", config or default_config, lookup=lookup) @@ -332,8 +349,8 @@ def run( @pytest.fixture def setup_aizynthfinder(setup_policies, setup_stock): - def wrapper(expansions, stock): - finder = AiZynthFinder() + def wrapper(expansions, stock, config_dict=None): + finder = AiZynthFinder(configdict=config_dict) root_smi = list(expansions.keys())[0] setup_policies(expansions, config=finder.config) setup_stock(finder.config, *stock) @@ -493,6 +510,16 @@ def wrapper(exclude_from_stock=None): return wrapper +@pytest.fixture +def setup_mocked_model(mocker: pytest_mock.MockerFixture): + biases = [np.zeros(10), np.zeros(1)] + weights = [np.ones([10, 10]), np.ones([10, 1])] + + mocker.patch("builtins.open") + mocked_pickle_load = mocker.patch("aizynthfinder.search.retrostar.cost.pickle.load") + mocked_pickle_load.return_value = weights, biases + + @pytest.fixture def setup_policies(default_config, get_filter_strategy, get_expansion_strategy): def wrapper(expansions, filters=None, config=None): @@ -511,7 +538,7 @@ def wrapper(expansions, filters=None, config=None): @pytest.fixture -def setup_stock(default_config, tmpdir): +def setup_stock(default_config, setup_stock_with_query, tmpdir): """ Fixture for setting up stock of inchi keys in a textfile. Will return a function that should be called with any number of Molecule objects as arguments @@ -525,12 +552,24 @@ def wrapper(config=None, *molecules): filename = str(tmpdir / "stock.txt") with open(filename, "w") as fileobj: fileobj.write("\n".join([mol.inchi_key for mol in molecules])) - config.stock.load(filename, "stock") + config.stock.load(setup_stock_with_query(filename), "stock") config.stock.select("stock") return wrapper +@pytest.fixture +def setup_stock_with_query(default_config, create_dummy_stock1): + stock = default_config.stock + + def wrapper(query=None): + query = query if query is not None else create_dummy_stock1("hdf5") + stock_query = InMemoryInchiKeyQuery(query) + return stock_query + + return wrapper + + @pytest.fixture def write_yaml(tmpdir): filename = str(tmpdir / "test.yaml") diff --git a/tests/context/conftest.py b/tests/context/conftest.py index 9c4502a..b71d375 100644 --- a/tests/context/conftest.py +++ b/tests/context/conftest.py @@ -75,22 +75,9 @@ def wrapper(key="policy1", templates=None): templates_filename = create_templates_file(templates) strategy = TemplateBasedExpansionStrategy( - key, default_config, source="dummy.onnx", templatefile=templates_filename + key, default_config, model="dummy.onnx", template=templates_filename ) return strategy, mock_onnx_model return wrapper - - -@pytest.fixture -def setup_stock_with_query(default_config, create_dummy_stock1): - stock = default_config.stock - - def wrapper(query=None): - query = query if query is not None else create_dummy_stock1("hdf5") - stock.load(query, "stock1") - stock.select(["stock1"]) - return stock - - return wrapper diff --git a/tests/context/data/linear_route_w_metadata.json b/tests/context/data/linear_route_w_metadata.json new file mode 100644 index 0000000..8135f52 --- /dev/null +++ b/tests/context/data/linear_route_w_metadata.json @@ -0,0 +1,65 @@ +{ + "type": "mol", + "route_metadata": { + "created_at_iteration": 1, + "is_solved": true + }, + "hide": false, + "smiles": "OOc1ccc(-c2ccc(NC3CCCC(C4C=CC=C4)C3)cc2)cc1", + "is_chemical": true, + "in_stock": false, + "children": [ + { + "type": "reaction", + "hide": false, + "smiles": "OOc1ccc(-c2ccc(NC3CCCC(C4C=CC=C4)C3)cc2)cc1>>OOc1ccc(-c2ccccc2)cc1.NC1CCCC(C2C=CC=C2)C1", + "is_reaction": true, + "metadata": { + "classification": "abc" + }, + "children": [ + { + "type": "mol", + "hide": false, + "smiles": "NC1CCCC(C2C=CC=C2)C1", + "is_chemical": true, + "in_stock": true + }, + { + "type": "mol", + "hide": false, + "smiles": "OOc1ccc(-c2ccccc2)cc1", + "is_chemical": true, + "in_stock": false, + "children": [ + { + "type": "reaction", + "hide": false, + "smiles": "OOc1ccc(-c2ccccc2)cc1>>c1ccccc1.OOc1ccccc1", + "is_reaction": true, + "metadata": { + "classification": "xyz" + }, + "children": [ + { + "type": "mol", + "hide": false, + "smiles": "c1ccccc1", + "is_chemical": true, + "in_stock": true + }, + { + "type": "mol", + "hide": false, + "smiles": "OOc1ccccc1", + "is_chemical": true, + "in_stock": true + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/context/data/simple_filter.bloom b/tests/context/data/simple_filter.bloom new file mode 100644 index 0000000000000000000000000000000000000000..2337c59450e630da034b811125ad3c0a198f3e1a GIT binary patch literal 10258 zcmeI0K@P$&3m zC!WK^`}Q?qT3)X0f;+#WDk2o{*iS|!OJ>lcqGc??jEPT@5vI}ysDU!r6nJ_Oe=@(K ztzr?arYRU(md}MqGQxcBEKUqD6`7vfJXrv}WVj*_v?7P~Mk95S^n@v|0FIQwrohvS z_>=h+T@|a_O{VF}@`Vm*EMdN|{?#MA9RW&AhARR=E23_<)yywO8e2>N?V=po;-k8}g z=&O(<6VLEM2G-YNNRdE3wF(Li4ZVgLXD literal 0 HcmV?d00001 diff --git a/tests/context/data/test_reactions_template.csv b/tests/context/data/test_reactions_template.csv new file mode 100644 index 0000000..3cd710b --- /dev/null +++ b/tests/context/data/test_reactions_template.csv @@ -0,0 +1,4 @@ +ReactionSmilesClean mapped_rxn confidence RetroTemplate TemplateHash TemplateError +CN1CCC(Cl)CC1.N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F.O>>CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1 Cl[CH:5]1[CH2:4][CH2:3][N:2]([CH3:1])[CH2:26][CH2:25]1.N#[C:6][c:8]1[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]2[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]2)[c:23]1[F:24].[OH2:7]>>[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1 0.9424734380772164 [C:2]-[CH;D3;+0:1](-[C:3])-[C;H0;D3;+0:4](=[O;H0;D1;+0:6])-[c:5]>>Cl-[CH;D3;+0:1](-[C:2])-[C:3].N#[C;H0;D2;+0:4]-[c:5].[OH2;D0;+0:6] 23f00a3c507eef75b22252e8eea99b2ce8eab9a573ff2fbd8227d93f49960a27 +N#Cc1cccc(N)c1F.O=C(Cl)c1ccc(F)cc1>>N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F Cl[C:9](=[O:10])[c:11]1[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]1.[N:1]#[C:2][c:3]1[cH:4][cH:5][cH:6][c:7]([NH2:8])[c:18]1[F:19]>>[N:1]#[C:2][c:3]1[cH:4][cH:5][cH:6][c:7]([NH:8][C:9](=[O:10])[c:11]2[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]2)[c:18]1[F:19] 0.9855040989023992 [O;D1;H0:2]=[C;H0;D3;+0:1](-[c:3])-[NH;D2;+0:4]-[c:5]>>Cl-[C;H0;D3;+0:1](=[O;D1;H0:2])-[c:3].[NH2;D1;+0:4]-[c:5] dadfa1075f086a1e76ed69f4d1c5cc44999708352c462aac5817785131169c41 +NC(=O)c1ccc(F)cc1.Fc1c(Cl)cccc1C#N>>N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F Cl[c:7]1[cH:6][cH:5][cH:4][c:3]([C:2]#[N:1])[c:18]1[F:19].[NH2:8][C:9](=[O:10])[c:11]1[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]1>>[N:1]#[C:2][c:3]1[cH:4][cH:5][cH:6][c:7]([NH:8][C:9](=[O:10])[c:11]2[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]2)[c:18]1[F:19] 0.9707971018098916 [O;D1;H0:6]=[C:5](-[NH;D2;+0:4]-[c;H0;D3;+0:1](:[c:2]):[c:3])-[c:7]1:[c:8]:[c:9]:[c:10]:[c:11]:[c:12]:1>>Cl-[c;H0;D3;+0:1](:[c:2]):[c:3].[NH2;D1;+0:4]-[C:5](=[O;D1;H0:6])-[c:7]1:[c:8]:[c:9]:[c:10]:[c:11]:[c:12]:1 01ba54afaa6c16613833b643d8f2503d9222eec7a3834f1cdd002faeb50ef239 diff --git a/tests/context/test_expansion_strategies.py b/tests/context/test_expansion_strategies.py new file mode 100644 index 0000000..11d1657 --- /dev/null +++ b/tests/context/test_expansion_strategies.py @@ -0,0 +1,115 @@ +import pytest + +from aizynthfinder.chem import TreeMolecule +from aizynthfinder.context.policy import ( + MultiExpansionStrategy, + TemplateBasedExpansionStrategy, +) +from aizynthfinder.utils.exceptions import PolicyException + + +def test_multi_expansion_strategy_incorrect_keys( + default_config, setup_template_expansion_policy +): + expansion_policy = default_config.expansion_policy + strategy1, _ = setup_template_expansion_policy("policy1") + expansion_policy.load(strategy1) + + with pytest.raises(ValueError, match="expansion strategy keys must exist"): + multi_expansion_strategy = MultiExpansionStrategy( + "multi_expansion_strategy", + default_config, + expansion_strategies=["policy1", "policy2"], + ) + mols = [TreeMolecule(smiles="CCO", parent=None)] + multi_expansion_strategy.get_actions(mols) + + +def test_multi_expansion_strategy(default_config, setup_template_expansion_policy): + expansion_policy = default_config.expansion_policy + strategy1, _ = setup_template_expansion_policy("policy1") + expansion_policy.load(strategy1) + strategy2, _ = setup_template_expansion_policy("policy2") + expansion_policy.load(strategy2) + strategy3, _ = setup_template_expansion_policy("policy3") + expansion_policy.load(strategy3) + + multi_expansion_strategy = MultiExpansionStrategy( + "multi_expansion_strategy", + default_config, + expansion_strategies=["policy1", "policy2"], + ) + multi_expansion_strategy.additive_expansion = True + + mols = [TreeMolecule(smiles="CCO", parent=None)] + _, priors = multi_expansion_strategy.get_actions(mols) + + assert priors == [0.7, 0.2, 0.7, 0.2] + + +def test_multi_expansion_strategy_wo_additive_expansion( + default_config, setup_template_expansion_policy +): + expansion_policy = default_config.expansion_policy + strategy1, _ = setup_template_expansion_policy("policy1") + expansion_policy.load(strategy1) + strategy2, _ = setup_template_expansion_policy("policy2") + expansion_policy.load(strategy2) + + multi_expansion_strategy = MultiExpansionStrategy( + "multi_expansion_strategy", + default_config, + expansion_strategies=["policy1", "policy2"], + ) + + mols = [TreeMolecule(smiles="CCO", parent=None)] + _, priors = multi_expansion_strategy.get_actions(mols) + + assert priors == [0.7, 0.2] + + +def test_create_templated_expansion_strategy_wo_kwargs(): + with pytest.raises( + PolicyException, match=" class needs to be initiated with keyword arguments" + ): + _ = TemplateBasedExpansionStrategy("dummy", None) + + +def test_load_templated_expansion_strategy( + default_config, setup_template_expansion_policy +): + strategy, mocked_onnx_model = setup_template_expansion_policy() + mocked_onnx_model.assert_called_once() + assert len(strategy.templates) == 3 + + +def test_load_invalid_templated_expansion_strategy( + default_config, create_dummy_templates, mock_onnx_model +): + templates_filename = create_dummy_templates(4) + with pytest.raises(PolicyException): + TemplateBasedExpansionStrategy( + "policy1", + default_config, + model="dummy.onnx", + template=templates_filename, + ) + + +def test_load_templated_expansion_strategy_from_csv( + default_config, mock_onnx_model, tmpdir +): + templates_filename = str(tmpdir / "temp.csv") + + with open(templates_filename, "w") as fileobj: + fileobj.write("template_index\ttemplate\tmetadata\n") + fileobj.write("0\tAAA\tmetadata1\n") + fileobj.write("1\tBBB\tmetadata2\n") + fileobj.write("2\tCCC\tmetadata3\n") + + strategy = TemplateBasedExpansionStrategy( + "default", default_config, model="dummy.onnx", template=templates_filename + ) + + assert len(strategy.templates) == 3 + assert list(strategy.templates.columns) == ["template", "metadata"] diff --git a/tests/context/test_mcts_config.py b/tests/context/test_mcts_config.py index 9e52e16..9bf5274 100644 --- a/tests/context/test_mcts_config.py +++ b/tests/context/test_mcts_config.py @@ -5,6 +5,7 @@ from aizynthfinder.aizynthfinder import AiZynthFinder from aizynthfinder.context.config import Configuration +from aizynthfinder.context.stock import StockException def test_load_empty_dict(default_config): @@ -24,78 +25,81 @@ def test_load_empty_file(default_config, write_yaml): def test_load_from_file(write_yaml): filename = write_yaml( { - "properties": { - "cutoff_number": 300, - "post_processing": {"all_routes": True}, + "search": { + "algorithm": "mcts", + "algorithm_config": { + "C": 1.9, + "default_prior": 0.9, + "use_prior": False, + }, + "max_transforms": 6, + "time_limit": 200, + "break_bonds_operator": "OR", }, - "policy": {"properties": {"C": 1.9, "time_limit": 200}}, - "finder": {"properties": {"time_limit": 300}}, } ) config = Configuration.from_file(filename) - assert config.cutoff_number == 300 - assert config.C == 1.9 - assert config.time_limit == 200 - assert config.post_processing.all_routes + assert config.search.algorithm == "mcts" + assert config.search.time_limit == 200 + + assert config.search.algorithm_config == { + "C": 1.9, + "default_prior": 0.9, + "use_prior": False, + "prune_cycles_in_search": True, + "search_reward": "state score", + "immediate_instantiation": (), + "mcts_grouping": None, + } def test_load_from_dict_invalid_property(write_yaml): dict_ = { - "properties": {"dummy": 300}, - "policy": {"properties": {"C": 1.9}}, - "finder": {"properties": {"time_limit": 300}}, + "search": {"dummy": 300, "algorithm": "mcts"}, } - with pytest.raises(AttributeError): + with pytest.raises(AttributeError, match="Could not find attribute to set: dummy"): Configuration.from_dict(dict_) -def test_get_properties(default_config): +def test_update_search(default_config): config = default_config - props = config.properties - - # Just check a few properties - assert props["C"] == 1.4 - assert props["time_limit"] == 120 - assert props["max_transforms"] == 6 - assert "post_processing" not in props - - -def test_update_properties(default_config): - config = default_config - - assert config.C != 2.0 - assert config.time_limit != 300 - assert config.max_transforms == 6 - - config.properties = {"C": 2.0, "time_limit": 300, "max_transforms": None} + assert config.search.algorithm_config["C"] != 2.0 + assert config.search.time_limit != 300 + assert config.search.max_transforms == 6 - assert config.C == 2.0 - assert config.time_limit == 300 - assert config.max_transforms == 6 - - with pytest.raises(AttributeError): - config.properties = { - "C": 2.0, - "time_limit": 300, - "max_transforms": None, - "dummy": 2, + config = config.from_dict( + { + "search": { + "algorithm_config": {"C": 2.0}, + "time_limit": 300, + "max_transforms": None, + } } + ) + assert config.search.algorithm_config["C"] == 2.0 + assert config.search.time_limit == 300 + assert config.search.max_transforms == 6 - with pytest.raises(ValueError): - config.properties = { - "C": 2.0, - "time_limit": 300, - "max_transforms": None, - "post_processing": {"all_routes": True}, - } + with pytest.raises(AttributeError): + config = config.from_dict( + { + "search": { + "time_limit": 300, + "max_transforms": None, + "dummy": 2, + } + } + ) def test_load_stock(write_yaml, create_dummy_stock1): stock_filename = create_dummy_stock1("hdf5") - filename = write_yaml({"stock": {"files": {"test": stock_filename}}}) + filename = write_yaml( + {"stock": {"buyables": {"type": "inchiset", "path": stock_filename}}} + ) config = Configuration.from_file(filename) @@ -105,20 +109,57 @@ def test_load_stock(write_yaml, create_dummy_stock1): def test_load_policy(write_yaml, create_dummy_templates, mock_onnx_model): templates_filename = create_dummy_templates(3) filename = write_yaml( - {"policy": {"files": {"test": ["dummy.onnx", templates_filename]}}} + { + "expansion": { + "uspto": { + "type": "template-based", + "model": "dummy.onnx", + "template": templates_filename, + "cutoff_number": 75, + }, + "full": ["dummy.onnx", templates_filename], + } + } ) config = Configuration.from_file(filename) - assert config.expansion_policy.items == ["test"] + assert config.expansion_policy.items == ["full", "uspto"] def test_load_filter_policy(write_yaml, mock_onnx_model): - filename = write_yaml({"filter": {"files": {"test": "dummy.onnx"}}}) + filename = write_yaml( + { + "filter": { + "uspto": { + "type": "quick-filter", + "model": "dummy.onnx", + "exclude_from_policy": ["rc"], + }, + "full": "dummy.onnx", + } + } + ) + + config = Configuration.from_file(filename) + + assert config.filter_policy.items == ["full", "uspto"] + + +def test_load_stock(write_yaml, create_dummy_stock1): + stock_filename = create_dummy_stock1("hdf5") + filename = write_yaml( + { + "stock": { + "buyables": {"type": "inchiset", "path": stock_filename}, + "emolecules": stock_filename, + } + } + ) config = Configuration.from_file(filename) - assert config.filter_policy.items == ["test"] + assert config.stock.items == ["buyables", "emolecules"] def test_load_stop_criteria(write_yaml): @@ -136,7 +177,7 @@ def test_load_stop_criteria(write_yaml): def test_load_default_mongodb(write_yaml, mocker): mocked_client = mocker.patch("aizynthfinder.context.stock.queries.get_mongo_client") - filename = write_yaml({"stock": {"mongodb": {}}}) + filename = write_yaml({"stock": {"mongodb_stock": {"type": "mongodb"}}}) config = Configuration.from_file(filename) @@ -149,7 +190,8 @@ def test_load_specific_mongodb(write_yaml, mocker): filename = write_yaml( { "stock": { - "mongodb": { + "mongodb_stock": { + "type": "mongodb", "host": "myhost", "database": "mydatabase", "collection": "mycollection", @@ -173,8 +215,9 @@ def test_load_external_stock(write_yaml, create_dummy_stock1): filename = write_yaml( { "stock": { - "aizynthfinder.context.stock.stock.InMemoryInchiKeyQuery": { - "filename": stock_filename + "inchi": { + "type": "aizynthfinder.context.stock.stock.InMemoryInchiKeyQuery", + "path": stock_filename, } } } @@ -182,7 +225,7 @@ def test_load_external_stock(write_yaml, create_dummy_stock1): config = Configuration.from_file(filename) - assert config.stock.items == ["InMemoryInchiKeyQuery"] + assert config.stock.items == ["inchi"] def test_load_external_stock_incorrect_module(write_yaml, create_dummy_stock1): @@ -190,16 +233,16 @@ def test_load_external_stock_incorrect_module(write_yaml, create_dummy_stock1): filename = write_yaml( { "stock": { - "aizynthfinder.context.stocks.stock.InMemoryInchiKeyQuery": { - "filename": stock_filename + "inchi": { + "type": "aizynthfinder.context.stocks.stock.InMemoryInchiKeyQuery", + "path": stock_filename, } } } ) - config = Configuration.from_file(filename) - - assert config.stock.items == [] + with pytest.raises(StockException): + config = Configuration.from_file(filename) def test_load_external_stock_incorrect_class(write_yaml, create_dummy_stock1): @@ -207,16 +250,16 @@ def test_load_external_stock_incorrect_class(write_yaml, create_dummy_stock1): filename = write_yaml( { "stock": { - "aizynthfinder.context.stock.InnMemoryInchiKeyQuery": { - "filename": stock_filename + "inchi": { + "type": "aizynthfinder.context.stock.InnMemoryInchiKeyQuery", + "path": stock_filename, } } } ) - config = Configuration.from_file(filename) - - assert config.stock.items == [] + with pytest.raises(StockException): + config = Configuration.from_file(filename) def test_load_scorer_from_context_module(write_yaml): @@ -239,81 +282,137 @@ def test_load_scorer_from_module_spec(write_yaml): @mock.patch.dict( os.environ, - {"CUTOFF_NUMBER": "300", "C": "1.9"}, + {"ITERATION_LIMIT": "300", "C": "1.9"}, ) def test_load_yaml_with_environ(write_yaml): filename = write_yaml( { - "properties": { - "cutoff_number": "${CUTOFF_NUMBER}", - "post_processing": {"all_routes": True}, + "search": { + "algorithm_config": {"C": "${C}"}, + "iteration_limit": "${ITERATION_LIMIT}", }, - "policy": {"properties": {"C": "${C}"}}, - "finder": {"properties": {"cutoff_number": "${CUTOFF_NUMBER}"}}, } ) config = Configuration.from_file(filename) - assert config.cutoff_number == 300 - assert config.C == 1.9 + assert config.search.iteration_limit == 300 + assert config.search.algorithm_config["C"] == 1.9 -@mock.patch.dict(os.environ, {"CUTOFF_NUMBER": "300"}) +@mock.patch.dict(os.environ, {"ITERATION_LIMIT": "300"}) def test_load_yaml_with_environ_raises_error(write_yaml): filename = write_yaml( { - "properties": {"cutoff_number": "${CUTOFF}"}, - "policy": {"properties": {"C": 1.9}}, - "finder": {"properties": {"time_limit": 300}}, + "search": { + "algorithm_config": {"C": 1.9}, + "iteration_limit": "${ITERATION}", + }, } ) - with pytest.raises(ValueError, match="'CUTOFF' not in environment variables"): + with pytest.raises(ValueError, match="'ITERATION' not in environment variables"): Configuration.from_file(filename) -def test_init_search_yaml(write_yaml): +def test_load_algorithm_config(write_yaml): + filename = write_yaml({"search": {"algorithm_config": {"C": 1.9}}}) + + config = Configuration.from_file(filename) + + expected_keys = [ + "C", + "default_prior", + "use_prior", + "prune_cycles_in_search", + "search_reward", + "immediate_instantiation", + "mcts_grouping", + ] + for key in expected_keys: + assert key in config.search.algorithm_config, f"{key} not in config" + assert config.search.algorithm_config["C"] == 1.9 + + +def test_load_algorithm_config_failure(write_yaml): + filename = write_yaml({"search": {"algorithm_config": 5.5}}) + + with pytest.raises(ValueError, match="algorithm_config"): + Configuration.from_file(filename) + + +def test_init_search_yaml(write_yaml, create_dummy_templates, mock_onnx_model): + templates_filename = create_dummy_templates(3) filename = write_yaml( { - "properties": {"cutoff_number": 300}, - "policy": {"properties": {"C": 1.9}}, - "finder": {"properties": {"time_limit": 300}}, + "expansion": { + "policy1": { + "type": "template-based", + "model": "dummy.onnx", + "template": templates_filename, + "cutoff_number": 300, + } + }, + "search": {"time_limit": 300}, } ) finder = AiZynthFinder(filename) - assert finder.config.cutoff_number == 300 - assert finder.config.C == 1.9 - assert finder.config.time_limit == 300 + assert finder.config.expansion_policy["policy1"].cutoff_number == 300 + assert finder.config.search.time_limit == 300 -def test_init_search_dict(): +def test_init_search_dict(create_dummy_templates, mock_onnx_model): + templates_filename = create_dummy_templates(3) dict_ = { - "properties": {"cutoff_number": 300}, - "policy": {"properties": {"C": 1.9}}, - "finder": {"properties": {"time_limit": 300}}, + "expansion": { + "policy1": { + "type": "template-based", + "model": "dummy.onnx", + "template": templates_filename, + "cutoff_number": 300, + } + }, + "search": {"time_limit": 300}, } finder = AiZynthFinder(configdict=dict_) - assert finder.config.cutoff_number == 300 - assert finder.config.C == 1.9 - assert finder.config.time_limit == 300 + assert finder.config.expansion_policy["policy1"].cutoff_number == 300 + assert finder.config.search.time_limit == 300 -def test_init_search_yaml_dict(write_yaml): - filename = write_yaml({"properties": {"cutoff_number": 300}}) +def test_init_search_yaml_dict(write_yaml, create_dummy_templates, mock_onnx_model): + templates_filename = create_dummy_templates(3) + filename = write_yaml( + { + "expansion": { + "policy1": { + "type": "template-based", + "model": "dummy.onnx", + "template": templates_filename, + "cutoff_number": 300, + } + }, + "search": {"time_limit": 300}, + } + ) dict_ = { - "properties": {"cutoff_number": 100}, + "expansion": { + "policy1": { + "type": "template-based", + "model": "dummy.onnx", + "template": templates_filename, + "cutoff_number": 100, + } + }, } finder = AiZynthFinder(filename, configdict=dict_) - assert finder.config.cutoff_number == 300 + assert finder.config.expansion_policy["policy1"].cutoff_number == 300 def test_init_search_none(default_config): - finder = AiZynthFinder() assert finder.config == default_config diff --git a/tests/context/test_mol_cost.py b/tests/context/test_mol_cost.py deleted file mode 100644 index 22d9878..0000000 --- a/tests/context/test_mol_cost.py +++ /dev/null @@ -1,41 +0,0 @@ -from aizynthfinder.context.cost import ( - ZeroMoleculeCost, - MoleculeCost, -) -from aizynthfinder.chem import Molecule - - -def test_zero_cost(): - assert ZeroMoleculeCost()(None) == 0.0 - - -def test_create_mol_cost(): - mol = Molecule(smiles="CCCC") - - assert MoleculeCost()(mol) == 0.0 - - -def test_mol_cost_cache(mocker): - mol = Molecule(smiles="CCCC") - mocker.patch("aizynthfinder.context.cost.ZeroMoleculeCost.__call__") - cost = MoleculeCost() - cost[cost.selection].__call__.return_value = 5.0 - - assert cost(mol) == 5.0 - assert cost(mol) == 5.0 - cost[cost.selection].__call__.assert_called_once() - - -def test_load_cost(): - cost = MoleculeCost() - - cost.load(ZeroMoleculeCost()) - assert len(cost) == 1 - - -def test_load_cost_from_config(): - cost = MoleculeCost() - - cost.load_from_config(zero={}) - - assert len(cost) == 1 diff --git a/tests/context/test_policy.py b/tests/context/test_policy.py index c40f4a5..3dcbca4 100644 --- a/tests/context/test_policy.py +++ b/tests/context/test_policy.py @@ -9,39 +9,10 @@ from aizynthfinder.context.policy import ( QuickKerasFilter, ReactantsCountFilter, - TemplateBasedExpansionStrategy, ) from aizynthfinder.utils.exceptions import PolicyException, RejectionException -def test_create_templated_expansion_strategy_wo_kwargs(): - with pytest.raises( - PolicyException, match=" class needs to be initiated with keyword arguments" - ): - _ = TemplateBasedExpansionStrategy("dummy", None) - - -def test_load_templated_expansion_policy( - default_config, setup_template_expansion_policy -): - strategy, mocked_onnx_model = setup_template_expansion_policy() - mocked_onnx_model.assert_called_once() - assert len(strategy.templates) == 3 - - -def test_load_invalid_templated_expansion_policy( - default_config, create_dummy_templates, mock_onnx_model -): - templates_filename = create_dummy_templates(4) - with pytest.raises(PolicyException): - TemplateBasedExpansionStrategy( - "policy1", - default_config, - source="dummy.onnx", - templatefile=templates_filename, - ) - - def test_load_expansion_policy(default_config, setup_template_expansion_policy): strategy, _ = setup_template_expansion_policy() expansion_policy = default_config.expansion_policy @@ -51,25 +22,6 @@ def test_load_expansion_policy(default_config, setup_template_expansion_policy): expansion_policy.load(5) -def test_load_expansion_policy_templates_from_csv( - default_config, mock_onnx_model, tmpdir -): - templates_filename = str(tmpdir / "temp.csv") - - with open(templates_filename, "w") as fileobj: - fileobj.write("template_index\ttemplate\tmetadata\n") - fileobj.write("0\tAAA\tmetadata1\n") - fileobj.write("1\tBBB\tmetadata2\n") - fileobj.write("2\tCCC\tmetadata3\n") - - strategy = TemplateBasedExpansionStrategy( - "default", default_config, source="dummy.onnx", templatefile=templates_filename - ) - - assert len(strategy.templates) == 3 - assert list(strategy.templates.columns) == ["template", "metadata"] - - def test_load_expansion_policy_from_config_files( default_config, mock_onnx_model, create_dummy_templates ): @@ -77,10 +29,16 @@ def test_load_expansion_policy_from_config_files( expansion_policy = default_config.expansion_policy expansion_policy.load_from_config( **{ - "files": { - "policy1": ["dummy1.onnx", template_filename], - "policy2": ["dummy1.onnx", template_filename], - } + "policy1": { + "type": "template-based", + "model": "dummy1.onnx", + "template": template_filename, + }, + "policy2": { + "type": "template-based", + "model": "dummy1.onnx", + "template": template_filename, + }, } ) assert "policy1" in expansion_policy.items @@ -96,11 +54,22 @@ def test_load_expansion_policy_from_config_custom( expansion_policy = default_config.expansion_policy expansion_policy.load_from_config( **{ - "TemplateBasedExpansionStrategy": { - "policy1": {"source": "dummy1.onnx", "templatefile": template_filename} + "policy1": { + "type": "TemplateBasedExpansionStrategy", + "model": "dummy1.onnx", + "template": template_filename, + "cutoff_number": 75, }, - "aizynthfinder.context.policy.TemplateBasedExpansionStrategy": { - "policy2": {"source": "dummy1.onnx", "templatefile": template_filename} + "policy2": { + "type": "aizynthfinder.context.policy.TemplateBasedExpansionStrategy", + "model": "dummy1.onnx", + "template": template_filename, + "cutoff_number": 25, + }, + "policy3": { + "type": "aizynthfinder.context.policy.TemplateBasedExpansionStrategy", + "model": "dummy1.onnx", + "template": template_filename, }, } ) @@ -108,6 +77,11 @@ def test_load_expansion_policy_from_config_custom( assert len(expansion_policy["policy1"].templates) == 3 assert "policy2" in expansion_policy.items assert len(expansion_policy["policy2"].templates) == 3 + assert "policy3" in expansion_policy.items + assert len(expansion_policy["policy3"].templates) == 3 + assert expansion_policy["policy1"].cutoff_number == 75 + assert expansion_policy["policy2"].cutoff_number == 25 + assert expansion_policy["policy3"].cutoff_number == 50 def test_get_actions(default_config, setup_template_expansion_policy): @@ -127,16 +101,24 @@ def test_get_actions(default_config, setup_template_expansion_policy): policy_names = [action.metadata["policy_name"] for action in actions] assert policy_names == ["policy1", "policy1"] - expansion_policy._config.cutoff_cumulative = 1.0 + default_config.expansion_policy["policy1"].cutoff_cumulative = 1.0 + expansion_policy.reset_cache() actions, priors = expansion_policy.get_actions(mols) assert priors == [0.7, 0.2, 0.1] - expansion_policy._config.cutoff_number = 1 + default_config.expansion_policy["policy1"].cutoff_number = 1 + expansion_policy.reset_cache() actions, priors = expansion_policy.get_actions(mols) assert priors == [0.7] + default_config.expansion_policy["policy1"].cutoff_number = 2 + default_config.expansion_policy["policy1"].rescale_prior = True + expansion_policy.reset_cache() + actions, priors = expansion_policy.get_actions(mols) + assert [round(prior, 1) for prior in priors] == [0.6, 0.4] + def test_get_actions_two_policies(default_config, setup_template_expansion_policy): expansion_policy = default_config.expansion_policy @@ -144,7 +126,6 @@ def test_get_actions_two_policies(default_config, setup_template_expansion_polic expansion_policy.load(strategy1) strategy2, _ = setup_template_expansion_policy("policy2") expansion_policy.load(strategy2) - default_config.additive_expansion = True expansion_policy.select(["policy1", "policy2"]) mols = [TreeMolecule(smiles="CCO", parent=None)] @@ -155,25 +136,20 @@ def test_get_actions_two_policies(default_config, setup_template_expansion_polic assert policy_names == ["policy1"] * 2 + ["policy2"] * 2 assert priors == [0.7, 0.2, 0.7, 0.2] - expansion_policy._config.cutoff_cumulative = 1.0 + expansion_policy["policy1"].cutoff_cumulative = 1.0 + expansion_policy["policy2"].cutoff_cumulative = 1.0 + expansion_policy.reset_cache() actions, priors = expansion_policy.get_actions(mols) assert priors == [0.7, 0.2, 0.1, 0.7, 0.2, 0.1] - expansion_policy._config.cutoff_number = 1 + expansion_policy["policy1"].cutoff_number = 1 + expansion_policy["policy2"].cutoff_number = 1 + expansion_policy.reset_cache() actions, priors = expansion_policy.get_actions(mols) assert priors == [0.7, 0.7] - default_config.additive_expansion = False - default_config.cutoff_number = 2 - - actions, priors = expansion_policy.get_actions(mols) - - policy_names = [action.metadata["policy_name"] for action in actions] - assert policy_names == ["policy1", "policy1"] - assert priors == [0.7, 0.2] - def test_get_actions_using_rdkit( default_config, setup_template_expansion_policy, mocker @@ -197,7 +173,7 @@ def test_get_actions_using_rdkit( assert actions[0] is not None # Now switch to RDKit - default_config.use_rdchiral = False + default_config.expansion_policy["policy1"].use_rdchiral = False actions, _ = expansion_policy.get_actions(mols) # This is a kind of convulted way to check that the RDKit application route will be called @@ -206,6 +182,26 @@ def test_get_actions_using_rdkit( _ = actions[0].reactants +def test_template_based_expansion_caching( + default_config, mock_onnx_model, create_dummy_templates +): + template_filename = create_dummy_templates(3) + expansion_policy = default_config.expansion_policy + expansion_policy.load_from_config( + **{"policy1": {"model": "dummy1.onnx", "template": template_filename}}, + ) + policy = expansion_policy["policy1"] + mols = [TreeMolecule(smiles="CCO", parent=None)] + caching_mols = [TreeMolecule(smiles="CCCCO", parent=None)] + + actions1, priors1 = policy(mols, caching_mols) + actions2, priors2 = policy(mols) + + mock_onnx_model.assert_called_once() + assert priors1 == priors2 + assert actions1[0].smarts == actions2[0].smarts + + def test_create_quick_filter_strategy_wo_kwargs(): with pytest.raises( PolicyException, match=" class needs to be initiated with keyword arguments" @@ -214,7 +210,7 @@ def test_create_quick_filter_strategy_wo_kwargs(): def test_load_filter_policy(default_config, mock_onnx_model): - strategy = QuickKerasFilter("policy1", default_config, source="dummy.onnx") + strategy = QuickKerasFilter("policy1", default_config, model="dummy.onnx") default_config.filter_policy.load(strategy) mock_onnx_model.assert_called_once() @@ -227,22 +223,22 @@ def test_load_filter_policy_from_config_files(default_config, mock_onnx_model): filter_policy = default_config.filter_policy filter_policy.load_from_config( **{ - "files": { - "policy1": "dummy1.onnx", - "policy2": "dummy1.onnx", - } + "policy1": {"type": "quick-filter", "model": "dummy1.onnx"}, + "policy2": {"type": "quick-filter", "model": "dummy1.onnx"}, + "policy3": "dummy1.onnx", } ) assert "policy1" in filter_policy.items assert "policy2" in filter_policy.items + assert "policy3" in filter_policy.items def test_load_filter_policy_from_config_custom(default_config, mock_onnx_model): filter_policy = default_config.filter_policy filter_policy.load_from_config( **{ - "QuickKerasFilter": {"policy1": {"source": "dummy1.onnx"}}, - "feasibility": {"policy2": {"source": "dummy1.onnx"}}, + "policy1": {"type": "QuickKerasFilter", "model": "dummy1.onnx"}, + "policy2": {"type": "feasibility", "model": "dummy1.onnx"}, } ) assert "policy1" in filter_policy.items @@ -251,7 +247,9 @@ def test_load_filter_policy_from_config_custom(default_config, mock_onnx_model): def test_filter_rejection(default_config, mock_onnx_model): filter_policy = default_config.filter_policy - filter_policy.load_from_config(**{"files": {"policy1": "dummy1.onnx"}}) + filter_policy.load_from_config( + **{"policy1": {"type": "quick-filter", "model": "dummy1.onnx"}} + ) mol = TreeMolecule( parent=None, smiles="CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" ) @@ -263,11 +261,11 @@ def test_filter_rejection(default_config, mock_onnx_model): filter_policy(reaction) filter_policy.select("policy1") - filter_policy._config.filter_cutoff = 0.9 + filter_policy._config.filter_policy["policy1"].filter_cutoff = 0.9 with pytest.raises(RejectionException): filter_policy(reaction) - filter_policy._config.filter_cutoff = 0.15 + filter_policy._config.filter_policy["policy1"].filter_cutoff = 0.15 filter_policy(reaction) @@ -275,11 +273,10 @@ def test_skip_filter_rejection(default_config, mock_onnx_model): filter_policy = default_config.filter_policy filter_policy.load_from_config( **{ - "QuickKerasFilter": { - "policy1": { - "source": "dummy1.onnx", - "exclude_from_policy": ["dummy.onnx"], - } + "policy1": { + "type": "quick-filter", + "model": "dummy1.onnx", + "exclude_from_policy": ["dummy.onnx"], }, } ) @@ -287,7 +284,7 @@ def test_skip_filter_rejection(default_config, mock_onnx_model): parent=None, smiles="CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" ) filter_policy.select("policy1") - filter_policy._config.filter_cutoff = 0.9 + filter_policy._config.filter_policy["policy1"].filter_cutoff = 0.9 reaction = SmilesBasedRetroReaction( mol, reactants_str="CN1CCC(Cl)CC1.N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F.O" diff --git a/tests/context/test_score.py b/tests/context/test_score.py index 387c436..11f3fa8 100644 --- a/tests/context/test_score.py +++ b/tests/context/test_score.py @@ -1,20 +1,24 @@ -import pytest import numpy as np - +import pytest +from aizynthfinder.chem import Molecule, UniqueMolecule from aizynthfinder.context.scoring import ( - StateScorer, - NumberOfReactionsScorer, AverageTemplateOccurrenceScorer, - NumberOfPrecursorsScorer, + CombinedScorer, + FractionInStockScorer, + MaxTransformScorerer, NumberOfPrecursorsInStockScorer, + NumberOfPrecursorsScorer, + NumberOfReactionsScorer, PriceSumScorer, + ReactionClassMembershipScorer, RouteCostScorer, ScorerCollection, ScorerException, + StockAvailabilityScorer, + StateScorer, ) -from aizynthfinder.chem import Molecule, UniqueMolecule -from aizynthfinder.search.mcts import MctsSearchTree from aizynthfinder.reactiontree import ReactionTree +from aizynthfinder.search.mcts import MctsSearchTree def test_state_scorer_node(default_config, setup_linear_mcts): @@ -65,37 +69,61 @@ def test_sort(default_config, setup_linear_mcts, setup_branched_mcts): assert sorted_nodes == [node1, node2] -def test_template_occurrence_scorer_no_metadata(setup_linear_mcts): +def test_template_occurrence_scorer_no_metadata(setup_linear_mcts, default_config): _, node1 = setup_linear_mcts() - scorer = AverageTemplateOccurrenceScorer() + scorer = AverageTemplateOccurrenceScorer(config=default_config) assert scorer(node1) == 0 -def test_template_occurrence_scorer(setup_linear_mcts): +def test_template_occurrence_scorer(setup_linear_mcts, default_config): search_tree, _ = setup_linear_mcts() nodes = list(search_tree.graph()) nodes[0][nodes[1]]["action"].metadata["library_occurrence"] = 5 nodes[1][nodes[2]]["action"].metadata["library_occurence"] = 10 - scorer = AverageTemplateOccurrenceScorer() + scorer = AverageTemplateOccurrenceScorer(default_config) assert scorer(nodes[0]) == 0 assert scorer(nodes[1]) == 5 assert scorer(nodes[2]) == 7.5 -def test_template_occurrence_scorer_tree(setup_linear_reaction_tree): +def test_template_occurrence_scorer_minmax_scaled(setup_linear_mcts, default_config): + search_tree, _ = setup_linear_mcts() + nodes = list(search_tree.graph()) + nodes[0][nodes[1]]["action"].metadata["library_occurrence"] = 5 + nodes[1][nodes[2]]["action"].metadata["library_occurence"] = 10 + + scaling_params = {"name": "min_max", "min_val": 1, "max_val": 10, "reverse": False} + scorer = AverageTemplateOccurrenceScorer(default_config, scaling_params) + scores = scorer(nodes[:3]) + assert [round(score, 1) for score in scores] == [0, 0.4, 0.7] + + +def test_template_occurrence_scorer_squash_scaled(setup_linear_mcts, default_config): + search_tree, _ = setup_linear_mcts() + nodes = list(search_tree.graph()) + nodes[0][nodes[1]]["action"].metadata["library_occurrence"] = 5 + nodes[1][nodes[2]]["action"].metadata["library_occurence"] = 10 + + scaling_params = {"name": "squash", "slope": 1, "xoffset": 1, "yoffset": 0} + scorer = AverageTemplateOccurrenceScorer(default_config, scaling_params) + scores = scorer(nodes[:3]) + assert [round(score, 4) for score in scores] == [0.2689, 0.9820, 0.9985] + + +def test_template_occurrence_scorer_tree(setup_linear_reaction_tree, default_config): tree = setup_linear_reaction_tree() - scorer = AverageTemplateOccurrenceScorer() + scorer = AverageTemplateOccurrenceScorer(default_config) assert scorer(tree) == 0 -def test_template_occurrence_scorer_tree_one_node(): +def test_template_occurrence_scorer_tree_one_node(default_config): rt = ReactionTree() rt.root = Molecule(smiles="CCCCOc1ccc(CC(=O)N(C)O)cc1") rt.graph.add_node(rt.root) - scorer = AverageTemplateOccurrenceScorer() + scorer = AverageTemplateOccurrenceScorer(default_config) assert scorer(rt) == 0.0 @@ -105,6 +133,8 @@ def test_scorers_one_mcts_node(default_config): node = tree.root assert pytest.approx(StateScorer(default_config)(node), abs=1e-3) == 0.0497 + assert FractionInStockScorer(default_config)(node) == 0 + assert MaxTransformScorerer(default_config)(node) == 0 assert NumberOfReactionsScorer(default_config)(node) == 0 assert NumberOfPrecursorsScorer(default_config)(node) == 1 assert NumberOfPrecursorsInStockScorer(default_config)(node) == 0 @@ -116,6 +146,8 @@ def test_scoring_branched_mcts_tree(default_config, setup_branched_mcts): _, node = setup_branched_mcts() assert pytest.approx(StateScorer(default_config)(node), abs=1e-4) == 0.9866 + assert FractionInStockScorer(default_config)(node) == 1 + assert MaxTransformScorerer(default_config)(node) == 3 assert NumberOfReactionsScorer()(node) == 4 assert NumberOfPrecursorsScorer(default_config)(node) == 5 assert NumberOfPrecursorsInStockScorer(default_config)(node) == 5 @@ -128,6 +160,8 @@ def test_scoring_branched_mcts_tree_not_in_stock(default_config, setup_branched_ _, node = setup_branched_mcts("O") assert pytest.approx(StateScorer(default_config)(node), abs=1e-4) == 0.7966 + assert FractionInStockScorer(default_config)(node) == 4 / 5 + assert MaxTransformScorerer(default_config)(node) == 3 assert NumberOfReactionsScorer()(node) == 4 assert NumberOfPrecursorsScorer(default_config)(node) == 5 assert NumberOfPrecursorsInStockScorer(default_config)(node) == 4 @@ -142,6 +176,8 @@ def test_scorers_tree_one_node_route(default_config): tree.graph.add_node(tree.root) assert pytest.approx(StateScorer(default_config)(tree), abs=1e-3) == 0.0497 + assert FractionInStockScorer(default_config)(tree) == 0 + assert MaxTransformScorerer(default_config)(tree) == -1 assert NumberOfReactionsScorer(default_config)(tree) == 0 assert NumberOfPrecursorsScorer(default_config)(tree) == 1 assert NumberOfPrecursorsInStockScorer(default_config)(tree) == 0 @@ -153,6 +189,8 @@ def test_scoring_branched_route(default_config, setup_branched_reaction_tree): tree = setup_branched_reaction_tree() assert pytest.approx(StateScorer(default_config)(tree), abs=1e-4) == 0.9866 + assert FractionInStockScorer(default_config)(tree) == 1 + assert MaxTransformScorerer(default_config)(tree) == 3 assert NumberOfReactionsScorer()(tree) == 4 assert NumberOfPrecursorsScorer(default_config)(tree) == 5 assert NumberOfPrecursorsInStockScorer(default_config)(tree) == 5 @@ -167,6 +205,8 @@ def test_scoring_branched_route_not_in_stock( tree = setup_branched_reaction_tree("O") assert pytest.approx(StateScorer(default_config)(tree), abs=1e-4) == 0.7966 + assert FractionInStockScorer(default_config)(tree) == 4 / 5 + assert MaxTransformScorerer(default_config)(tree) == 3 assert NumberOfReactionsScorer()(tree) == 4 assert NumberOfPrecursorsScorer(default_config)(tree) == 5 assert NumberOfPrecursorsInStockScorer(default_config)(tree) == 4 @@ -175,8 +215,32 @@ def test_scoring_branched_route_not_in_stock( assert pytest.approx(cost_score, abs=1e-4) == 31.2344 +def test_reaction_class_scorer_tree(default_config, load_reaction_tree): + tree = ReactionTree.from_dict(load_reaction_tree("linear_route_w_metadata.json")) + scorer = ReactionClassMembershipScorer(default_config, reaction_class_set=["abc"]) + + # one within the set, one outside the set + assert scorer(tree) == 0.1 + + +def test_stock_availability_scorer_tree( + default_config, load_reaction_tree, setup_stock +): + setup_stock( + default_config, + "NC1CCCC(C2C=CC=C2)C1", + "c1ccccc1", + ) + tree = ReactionTree.from_dict(load_reaction_tree("linear_route_w_metadata.json")) + scorer = StockAvailabilityScorer(default_config, source_score={"stock": 0.5}) + + # 0.5*0.5*0.1 two in stock, one not in stock + assert scorer(tree) == 0.025 + + def test_create_scorer_collection(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() assert len(collection) == 5 @@ -191,6 +255,7 @@ def test_create_scorer_collection(default_config): def test_delete_scorer_to_collection(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() del collection["state score"] @@ -199,6 +264,7 @@ def test_delete_scorer_to_collection(default_config): def test_add_scorer_to_collection(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() del collection["state score"] collection.load(StateScorer(default_config)) @@ -208,6 +274,7 @@ def test_add_scorer_to_collection(default_config): def test_add_scorer_to_collection_no_scorer(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() with pytest.raises(ScorerException): collection.load(Molecule(smiles="CCC")) @@ -215,6 +282,7 @@ def test_add_scorer_to_collection_no_scorer(default_config): def test_load_scorer_to_collection_only_class(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() del collection["state score"] collection.load_from_config(**{"StateScorer": {}}) @@ -224,6 +292,7 @@ def test_load_scorer_to_collection_only_class(default_config): def test_load_scorer_to_collection_full_package(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() del collection["state score"] collection.load_from_config(**{"aizynthfinder.context.scoring.StateScorer": {}}) @@ -233,9 +302,108 @@ def test_load_scorer_to_collection_full_package(default_config): def test_load_scorer_to_collection_failures(default_config): collection = ScorerCollection(default_config) + collection.create_default_scorers() with pytest.raises(ScorerException, match=".*load module.*"): collection.load_from_config(**{"mypackage.scoring.StateScorer": {}}) with pytest.raises(ScorerException, match=".*class.*"): collection.load_from_config(**{"aizynthfinder.context.scoring.NoScorer": {}}) + + +def test_subset_scorer_collection(default_config): + collection = ScorerCollection(default_config) + names = ["state score", "number of pre-cursors"] + new_collection = collection.make_subset(names) + + assert len(new_collection) == 2 + assert new_collection.names() == names + + +def test_subset_scorer_collection_not_exists(default_config): + collection = ScorerCollection(default_config) + names = ["state score", "dummy"] + + with pytest.raises(ScorerException, match="dummy"): + collection.make_subset(names) + + +def test_score_vector(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + collection = ScorerCollection(default_config) + collection.select_all() + + scores = collection.score_vector(node) + assert pytest.approx(scores, abs=1e-3) == [0.9866, 4, 5, 5, 0] + + +def test_score_vector_no_selection(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + collection = ScorerCollection(default_config) + + scores = collection.score_vector(node) + assert scores == [] + + +def test_weighted_sum_score(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + collection = ScorerCollection(default_config) + collection.select_all() + + score = collection.weighted_score(node, weights=[0.0, 0.5, 1.0, 1.0, 0.0]) + assert score == 12 + + with pytest.raises(ScorerException): + collection.weighted_score(node, weights=[]) + + with pytest.raises(ScorerException): + collection.weighted_score(node, weights=[1.0]) + + +def test_weighted_sum_score_no_selection(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + collection = ScorerCollection(default_config) + + with pytest.raises(ScorerException): + collection.weighted_score(node, weights=[0.0, 0.5, 1.0, 1.0, 0.0]) + + +def test_combined_scorer_node_default_weights(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + + combined_scorer = CombinedScorer( + default_config, ["state score", "number of reactions"] + ) + score = combined_scorer(node) + + assert repr(combined_scorer) == "state score + number of reactions" + assert round(score, 4) == 2.4933 + + +def test_combined_scorer_node(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + + combined_scorer = CombinedScorer( + default_config, + ["state score", "number of reactions"], + [0.75, 0.25], + ) + score = combined_scorer(node) + + assert repr(combined_scorer) == "state score + number of reactions" + assert round(score, 4) == 1.7399 + + +def test_combined_scorer_reaction_tree(default_config, setup_branched_mcts): + _, node = setup_branched_mcts() + reaction_tree = node.to_reaction_tree() + + combined_scorer = CombinedScorer( + default_config, + ["state score", "number of reactions"], + [0.75, 0.25], + ) + score = combined_scorer(reaction_tree) + + assert repr(combined_scorer) == "state score + number of reactions" + assert round(score, 4) == 1.7399 diff --git a/tests/context/test_stock.py b/tests/context/test_stock.py index e037e81..0c74bad 100644 --- a/tests/context/test_stock.py +++ b/tests/context/test_stock.py @@ -1,46 +1,85 @@ import pytest import sys +import pandas as pd + from aizynthfinder.chem import Molecule from aizynthfinder.context.stock import ( StockException, ) +from aizynthfinder.context.stock.queries import HAS_MOLBLOOM from aizynthfinder.tools.make_stock import ( extract_plain_smiles, extract_smiles_from_module, make_hdf5_stock, make_mongo_stock, + make_molbloom, + make_molbloom_inchi, ) -def test_load_stock(default_config, create_dummy_stock1): - filename = create_dummy_stock1("hdf5") +def test_load_stock(default_config, setup_stock_with_query): + stock_query = setup_stock_with_query() - default_config.stock.load(filename, "stock1") + default_config.stock.load(stock_query, "stock1") - assert len(default_config.stock["stock1"]) == 2 + assert "stock1" in default_config.stock.items + + with pytest.raises(StockException): + default_config.stock.load("stock", "stock1") -def test_load_csv_stock(default_config, create_dummy_stock1): - filename = create_dummy_stock1("csv") +def test_load_csv_stock(default_config, create_dummy_stock1, setup_stock_with_query): + stock_query = setup_stock_with_query(create_dummy_stock1("csv")) - default_config.stock.load(filename, "stock1") + default_config.stock.load(stock_query, "stock1") assert len(default_config.stock["stock1"]) == 2 -def test_load_txt_stock(default_config, create_dummy_stock1): - filename = create_dummy_stock1("txt") +def test_load_txt_stock(default_config, create_dummy_stock1, setup_stock_with_query): + stock_query = setup_stock_with_query(create_dummy_stock1("txt")) - default_config.stock.load(filename, "stock1") + default_config.stock.load(stock_query, "stock1") assert len(default_config.stock["stock1"]) == 2 -def test_availability_string(default_config, create_dummy_stock1, create_dummy_stock2): +def test_load_from_config(default_config, create_dummy_stock1): + filename = create_dummy_stock1("csv") stock = default_config.stock - stock.load(create_dummy_stock1("hdf5"), "stock1") - stock.load(create_dummy_stock2, "stock2") + + stock.load_from_config( + **{ + "stock1": { + "type": "InMemoryInchiKeyQuery", + "path": filename, + "price_col": "price", + }, + "stock2": filename, + "stock3": { + "type": "aizynthfinder.context.stock.queries.InMemoryInchiKeyQuery", + "path": filename, + }, + "stock4": { + "type": "inchiset", + "path": filename, + }, + } + ) + + assert "stock1" in stock.items + assert "stock2" in stock.items + assert "stock3" in stock.items + assert "stock4" in stock.items + + +def test_availability_string( + default_config, setup_stock_with_query, create_dummy_stock1, create_dummy_stock2 +): + stock = default_config.stock + stock.load(setup_stock_with_query(create_dummy_stock1("hdf5")), "stock1") + stock.load(setup_stock_with_query(create_dummy_stock2), "stock2") stock.select(["stock1", "stock2"]) @@ -67,8 +106,98 @@ def test_mol_in_stock(setup_stock_with_query): assert toluene in stock -def test_exclude(setup_stock_with_query): - stock = setup_stock_with_query() +def test_load_csv_stock_with_price(default_config, create_dummy_stock1): + filename = create_dummy_stock1("csv") + + default_config.stock.load_from_config( + **{ + "stock1": { + "type": "InMemoryInchiKeyQuery", + "path": filename, + "price_col": "price", + } + } + ) + default_config.stock.select_all() + + assert len(default_config.stock) == 2 + + benzene = Molecule(smiles="c1ccccc1") + assert default_config.stock.price(benzene) == 5.0 + + toluene = Molecule(smiles="Cc1ccccc1") + assert default_config.stock.price(toluene) == 10.0 + + +def test_load_csv_stock_with_price_duplicates(tmpdir, default_config): + filename = str(tmpdir / "stock1.hdf5") + pd.DataFrame( + { + "inchi_key": ["UHOVQNZJYSORNB-UHFFFAOYSA-N", "UHOVQNZJYSORNB-UHFFFAOYSA-N"], + "price": [5.0, 10.0], + } + ).to_hdf(filename, "table") + + with pytest.raises(StockException, match="unique"): + default_config.stock.load_from_config( + **{ + "stock1": { + "type": "InMemoryInchiKeyQuery", + "path": filename, + "price_col": "price", + } + } + ) + + +def test_load_csv_stock_with_null_price(tmpdir, default_config): + filename = str(tmpdir / "stock1.hdf5") + pd.DataFrame( + { + "inchi_key": ["UHOVQNZJYSORNB-UHFFFAOYSA-N", "YXFVVABEGXRONW-UHFFFAOYSA-N"], + "price": [5.0, None], + } + ).to_hdf(filename, "table") + + with pytest.raises(StockException, match="impute"): + default_config.stock.load_from_config( + **{ + "stock1": { + "type": "InMemoryInchiKeyQuery", + "path": filename, + "price_col": "price", + } + } + ) + + +def test_load_csv_stock_with_negative_price(tmpdir, default_config): + filename = str(tmpdir / "stock1.hdf5") + pd.DataFrame( + { + "inchi_key": ["UHOVQNZJYSORNB-UHFFFAOYSA-N", "YXFVVABEGXRONW-UHFFFAOYSA-N"], + "price": [5.0, -1], + } + ).to_hdf(filename, "table") + + with pytest.raises(StockException, match="non-negative"): + default_config.stock.load_from_config( + **{ + "stock1": { + "type": "InMemoryInchiKeyQuery", + "path": filename, + "price_col": "price", + } + } + ) + + +def test_exclude(default_config, setup_stock_with_query): + stock_query = setup_stock_with_query() + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) benzene = Molecule(smiles="c1ccccc1") assert benzene in stock @@ -77,8 +206,12 @@ def test_exclude(setup_stock_with_query): assert benzene not in stock -def test_exclude_many(setup_stock_with_query): - stock = setup_stock_with_query() +def test_exclude_many(default_config, setup_stock_with_query): + stock_query = setup_stock_with_query() + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) benzene = Molecule(smiles="c1ccccc1") assert benzene in stock @@ -99,56 +232,84 @@ def test_exclude_many(setup_stock_with_query): assert toluene not in stock -def test_price_no_price(setup_stock_with_query): - stock = setup_stock_with_query() +def test_price_no_price(default_config, setup_stock_with_query): + stock_query = setup_stock_with_query() + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) with pytest.raises(StockException): stock.price(Molecule(smiles="c1ccccc1")) -def test_price_with_price(setup_stock_with_query, make_stock_query): +def test_price_with_price(default_config, make_stock_query): mol = Molecule(smiles="c1ccccc1") price = {mol: 14} - stock = setup_stock_with_query(make_stock_query([mol], price=price)) + stock_query = make_stock_query([mol], price=price) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) assert stock.price(mol) == 14 -def test_price_with_price_raises(setup_stock_with_query, make_stock_query): +def test_price_with_price_raises(default_config, make_stock_query): mol = Molecule(smiles="c1ccccc1") - stock = setup_stock_with_query(make_stock_query([mol])) + stock_query = make_stock_query([mol]) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) with pytest.raises(StockException): stock.price(Molecule(smiles="c1ccccc1")) -def test_amount_no_amount(setup_stock_with_query): - stock = setup_stock_with_query() +def test_amount_no_amount(default_config, setup_stock_with_query): + stock_query = setup_stock_with_query() + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) with pytest.raises(StockException): stock.amount(Molecule(smiles="c1ccccc1")) -def test_amount_with_amount(setup_stock_with_query, make_stock_query): +def test_amount_with_amount(default_config, make_stock_query): mol = Molecule(smiles="c1ccccc1") amount = {mol: 14} - stock = setup_stock_with_query(make_stock_query([mol], amount=amount)) + stock_query = make_stock_query([mol], amount=amount) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) assert stock.amount(mol) == 14 -def test_amount_with_amount_raises(setup_stock_with_query, make_stock_query): +def test_amount_with_amount_raises(default_config, make_stock_query): mol = Molecule(smiles="c1ccccc1") - stock = setup_stock_with_query(make_stock_query([mol])) + stock_query = make_stock_query([mol]) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) with pytest.raises(StockException): stock.amount(Molecule(smiles="c1ccccc1")) -def test_counts_filter(setup_stock_with_query, make_stock_query): +def test_counts_filter(default_config, make_stock_query): mol1 = Molecule(smiles="c1ccccc1") mol2 = Molecule(smiles="CC(=O)CO") - stock = setup_stock_with_query(make_stock_query([mol1, mol2])) + stock_query = make_stock_query([mol1, mol2]) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) stock.set_stop_criteria({"size": {"C": 2}}) @@ -164,19 +325,26 @@ def test_counts_filter(setup_stock_with_query, make_stock_query): assert mol2 not in stock -def test_no_entries_filter(setup_stock_with_query, make_stock_query): - stock = setup_stock_with_query(make_stock_query([])) +def test_no_entries_filter(default_config, make_stock_query): + stock_query = make_stock_query([]) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) stock.set_stop_criteria({"size": {"C": 10, "O": 0}}) assert Molecule(smiles="c1ccccc1") not in stock -def test_amounts_filter(setup_stock_with_query, make_stock_query): +def test_amounts_filter(default_config, make_stock_query): mol1 = Molecule(smiles="c1ccccc1") mol2 = Molecule(smiles="CC(=O)CO") mol3 = Molecule(smiles="CCC") - query = make_stock_query([mol1, mol2, mol3], amount={mol1: 10, mol2: 5}) - stock = setup_stock_with_query(query) + stock_query = make_stock_query([mol1, mol2, mol3], amount={mol1: 10, mol2: 5}) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) stock.set_stop_criteria({"amount": 10}) @@ -185,12 +353,15 @@ def test_amounts_filter(setup_stock_with_query, make_stock_query): assert mol3 in stock -def test_price_filter(setup_stock_with_query, make_stock_query): +def test_price_filter(default_config, make_stock_query): mol1 = Molecule(smiles="c1ccccc1") mol2 = Molecule(smiles="CC(=O)CO") mol3 = Molecule(smiles="CCC") - query = make_stock_query([mol1, mol2, mol3], price={mol1: 10, mol2: 5}) - stock = setup_stock_with_query(query) + stock_query = make_stock_query([mol1, mol2, mol3], price={mol1: 10, mol2: 5}) + stock = default_config.stock + + stock.load(stock_query, "stock1") + stock.select(["stock1"]) stock.set_stop_criteria({"price": 5}) @@ -246,10 +417,13 @@ def test_mongodb_availability(mocked_mongo_db_query): assert query.availability_string(benzene) == "source1,source2" -def test_mongodb_integration(setup_stock_with_query, mocked_mongo_db_query): +def test_mongodb_integration(default_config, mocked_mongo_db_query): _, query = mocked_mongo_db_query() query.molecules.count_documents.return_value = 1 - stock = setup_stock_with_query(query) + stock = default_config.stock + + stock.load(query, "stock1") + stock.select(["stock1"]) ethanol = Molecule(smiles="CCO") assert ethanol in stock @@ -286,7 +460,14 @@ def test_make_hdf5_stock(default_config, tmpdir): make_hdf5_stock(inchi_keys, filename) stock = default_config.stock - stock.load(filename, "stock1") + stock.load_from_config( + **{ + "stock1": { + "type": "inchiset", + "path": filename, + } + } + ) stock.select(["stock1"]) assert len(stock) == 2 @@ -301,3 +482,39 @@ def test_make_mongodb_stock(mocked_mongo_db_query): query.molecules.insert_many.assert_called_once() # [0][0] is to get the first ordered argument, i.e. the generator of items to be inserted assert len(list(query.molecules.insert_many.call_args[0][0])) == 2 + + +@pytest.mark.xfail(condition=not HAS_MOLBLOOM, reason="molbloom package not installed") +def test_load_bloom_filter(default_config, shared_datadir): + stock = default_config.stock + filename = str(shared_datadir / "simple_filter.bloom") + + stock.load_from_config(**{"bloom": filename}) + + assert Molecule(smiles="c1ccccc1") in stock["bloom"] + + +@pytest.mark.xfail(condition=not HAS_MOLBLOOM, reason="molbloom package not installed") +def test_make_bloom_filter(default_config, tmpdir): + stock = default_config.stock + filename = str(tmpdir / "temp.bloom") + smiles = ("CC", "CCO") + + make_molbloom(smiles, filename, 10, 3) + + stock.load_from_config(molbloom=filename) + + assert Molecule(smiles="CC") in stock["molbloom"] + + +@pytest.mark.xfail(condition=not HAS_MOLBLOOM, reason="molbloom package not installed") +def test_make_bloom_inchi_filter(default_config, tmpdir): + stock = default_config.stock + filename = str(tmpdir / "temp2.bloom") + inchi_keys = ("label1", "label2") + + make_molbloom_inchi(inchi_keys, filename, 10, 3) + + stock.load_from_config(molbloom=filename) + + assert "molbloom" in stock.items diff --git a/tests/data/and_or_tree.json b/tests/data/and_or_tree.json index a337d21..8ef7b7f 100644 --- a/tests/data/and_or_tree.json +++ b/tests/data/and_or_tree.json @@ -2242,869 +2242,745 @@ "smiles": "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1", "class": "TreeMolecule", "parent": null, - "transform": 0, - "tracked_atom_indices": {} + "transform": 0 }, "139643166203664": { "smiles": "[C:14](=[O:15])([c:16]1[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]1)[Cl:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643171528960": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201504": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643162454288": { "smiles": "[CH3:1][I:900]=[N+:13]([c:12]1[cH:11][cH:10][cH:9][c:8]([C:6]([CH:5]2[CH2:4][CH2:3][NH:2][CH2:26][CH2:25]2)=[O:7])[c:23]1[F:24])[O-:901]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162454624": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455056": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1)([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162454144": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162454048": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1)(=[O:900])[O:901][CH2:902][c:903]1[cH:904][cH:905][cH:906][cH:907][cH:908]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455488": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455728": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455968": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166201120": { "smiles": "[CH3:1][NH:2][CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]1[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]1[F:24])[CH2:25][CH2:26][Cl:900]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166202416": { "smiles": "[CH3:1][NH:2][CH2:26][CH2:25][CH:5]([CH2:4][CH2:3][Cl:900])[C:6](=[O:7])[c:8]1[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643173163552": { "smiles": "[CH2:1]=[O:900]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173165280": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643162452464": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166163824": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164870880": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:902]([O:901][CH3:900])[CH3:903])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164872128": { "smiles": "[cH:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171738528": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]=[C:900]([c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:907]3[cH:908][cH:909][cH:910][cH:911][cH:912]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164872464": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171738432": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739248": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739344": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739536": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739632": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171738048": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901]([CH3:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740112": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([F:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740688": { "smiles": "[NH3:13]", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740400": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901](=[O:900])[O:902][CH2:903][c:904]3[cH:905][cH:906][cH:907][cH:908][cH:909]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171741456": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171741024": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]([CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[CH2:907][c:908]3[cH:909][cH:910][cH:911][cH:912][cH:913]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740928": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([C:901]([OH:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740640": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740880": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740016": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Cl:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164869104": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([N+:13](=[O:901])[O-:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164869056": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([N+:13](=[O:901])[O-:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643173070016": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[c:11]([Cl:901])[c:12]([N+:13](=[O:902])[O-:903])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739392": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164870496": { "smiles": "[NH4+:13]", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643162692720": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162692240": { "smiles": "[N:2]1([CH2:900][c:901]2[cH:902][cH:903][cH:904][cH:905][cH:906]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162690464": { "smiles": "[N:2]1([C:901](=[O:900])[O:902][CH2:903][c:904]2[cH:905][cH:906][cH:907][cH:908][cH:909]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164991936": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162692624": { "smiles": "[N:2]1([C:901]([CH3:900])=[O:902])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164991840": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901]([CH3:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164991984": { "smiles": "[N:2]1([C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993136": { "smiles": "[N:2]1([C:903]([O:902][CH2:901][CH3:900])=[O:904])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992800": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992944": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH:901]=[O:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993280": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:912]([O:911][C:908]([CH3:907])([CH3:909])[CH3:910])=[O:913])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992848": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994720": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994864": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992512": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992080": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([C:901]([OH:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164995392": { "smiles": "[NH3:13]", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164995248": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([F:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643155805712": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901](=[O:900])[O:902][CH2:903][c:904]3[cH:905][cH:906][cH:907][cH:908][cH:909]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164856432": { "smiles": "[N:2]1([C:905]([O:904][CH2:903][CH2:902][CH2:901][CH3:900])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164857152": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][cH:12][c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164856960": { "smiles": "[N:2]1([C:901](=[O:900])[O-:902])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164857104": { "smiles": "[N:2]1([C:901](=[O:900])[c:902]2[cH:903][cH:904][cH:905][cH:906][cH:907]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993712": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993664": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]=[C:900]([c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:907]3[cH:908][cH:909][cH:910][cH:911][cH:912]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994192": { "smiles": "[n:2]1[cH:3][cH:4][c:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[cH:25][cH:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166164976": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[cH:23]2)[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643171531312": { "smiles": "[N:2]1([CH2:901][CH3:900])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994768": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Cl:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166164112": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:902]([O:901][CH3:900])[CH3:903])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166166464": { "smiles": "[cH:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166164448": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166163392": { "smiles": "[N:2]1([c:909]2[n:908][c:907]([NH:906][CH2:905][c:904]3[cH:903][cH:902][c:901]([F:900])[cH:923][c:921]3[F:922])[c:912](-[c:913]3[cH:914][cH:915][c:916]([F:917])[cH:918][c:919]3[F:920])[cH:911][n:910]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643173069200": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901]([CH3:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069008": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069440": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173166960": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]=[C:900]([c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:907]3[cH:908][cH:909][cH:910][cH:911][cH:912]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069680": { "smiles": "[CH3:1][I:900]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069968": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070400": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070880": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070832": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173068960": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070448": { "smiles": "[C:6]([c:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24])#[N:901]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070736": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([Cl:900])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069632": { "smiles": "[OH2:7]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071264": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1)([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071600": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Cl:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072032": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901](=[O:900])[O:902][CH2:903][c:904]3[cH:905][cH:906][cH:907][cH:908][cH:909]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070592": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070544": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:902]([O:901][CH3:900])[CH3:903])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070064": { "smiles": "[cH:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072272": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072320": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([C:901]([OH:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995808": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([F:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995136": { "smiles": "[NH3:13]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072224": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995568": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH:901]=[O:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071648": { "smiles": "[CH3:1][OH:900]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071360": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995856": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995472": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][cH:12][c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173164800": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[Cl:900])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173164224": { "smiles": "[c:8]1([I:901])[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173163312": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[c:11]([Cl:901])[c:12]([N+:13](=[O:902])[O-:903])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173164848": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]([CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[CH2:907][c:908]3[cH:909][cH:910][cH:911][cH:912][cH:913]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643157042560": { "smiles": "[C:14](=[O:15])([c:16]1[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]1)[OH:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643157043712": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200256": { "smiles": "[CH2:1]=[O:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201936": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202032": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1)([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200736": { "smiles": "[CH3:1][I:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166203376": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200976": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200112": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1)(=[O:900])[O:901][CH2:902][c:903]1[cH:904][cH:905][cH:906][cH:907][cH:908]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200352": { "smiles": "[C:6]([c:8]1[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]2[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]2)[c:23]1[F:24])#[N:901]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202848": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([Cl:900])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202608": { "smiles": "[OH2:7]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201024": { "smiles": "[C:14](=[O:15])([c:16]1[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]1)[O:901][CH3:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201744": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202176": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:903]([O:902][CH3:901])[CH3:904])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201600": { "smiles": "[c:8]1([Br:900])[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]2[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]2)[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 } } } \ No newline at end of file diff --git a/tests/data/full_search_tree.json.gz b/tests/data/full_search_tree.json.gz index edf449ba9203011dc2b5d6a34025c60fd7cacd4c..ee2342cabdcb51beace28acd084799e7fec0cc8d 100644 GIT binary patch literal 179671 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 J-DBHO765y67uf&+ literal 218545 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ℜ7)*RX=d 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%0D6k#Dbt2LetnGKD~*R#vrAtg^_bzZnGE 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 M{|(8{ayPFb04K_GdH?_b diff --git a/tests/data/make_false2_template_library.csv b/tests/data/make_false2_template_library.csv deleted file mode 100644 index 88ba6e3..0000000 --- a/tests/data/make_false2_template_library.csv +++ /dev/null @@ -1,4 +0,0 @@ -PseudoHash RSMI retro_template template_hash template_code -039c3d4c9304218d50b06ed252b67c1ed287ea5331fa2755fdd984e6 O=C1CCC(=O)N1[Br:1].[F:2][c:3]1[cH:4][cH:5][c:6]2[c:7]([cH:8]1)[N:9]([CH3:10])[C:11](=[O:12])[CH2:13][CH2:14]2.CCOC(C)=O.CN(C)C=O.O>>[Br:1][c:4]1[c:3]([F:2])[cH:8][c:7]2[c:6]([cH:5]1)[CH2:14][CH2:13][C:11](=[O:12])[N:9]2[CH3:10] ([Br;H0;D1;+0:1]-[c;H0;D3;+0:3](:[c:2]):[c:4])>>(O=C1-C-C-C(=O)-N-1-[Br;H0;D1;+0:1]).([c:2]:[cH;D2;+0:3]:[c:4]) 04aac57316494f5621172b80523cd496e017f4d0104703ad33b2fa4b 0 -17774f52ad0f5f143d46c931fd76d0019b368a6127051cd9630916da [C:1]([C:2]#[CH:3])(=[O:4])[O:5][CH2:6][CH3:7].[N:8](=[N+:9]=[N-:10])[CH2:11][CH2:12][CH2:13][CH2:14][n:15]1[c:16](=[O:17])[cH:18][c:19]([NH:20][C:21]([CH2:22][c:23]2[cH:24][cH:25][cH:26][cH:27][cH:28]2)=[O:29])[cH:30][cH:31]1.CC(=O)O.CCN(C(C)C)C(C)C.ClCCl.[Cu]I>>[C:1]([c:2]1[cH:3][n:8]([CH2:11][CH2:12][CH2:13][CH2:14][n:15]2[c:16](=[O:17])[cH:18][c:19]([NH:20][C:21]([CH2:22][c:23]3[cH:24][cH:25][cH:26][cH:27][cH:28]3)=[O:29])[cH:30][cH:31]2)[n:9][n:10]1)(=[O:4])[O:5][CH2:6][CH3:7] ([C:8]-[n;H0;D3;+0:9]1:[cH;D2;+0:7]:[c;H0;D3;+0:6](-[C:4](=[O;D1;H0:5])-[#8:3]-[C:2]-[C;D1;H3:1]):[n;H0;D2;+0:11]:[n;H0;D2;+0:10]:1)>>([C;D1;H3:1]-[C:2]-[#8:3]-[C:4](=[O;D1;H0:5])-[C;H0;D2;+0:6]#[CH;D1;+0:7]).([C:8]-[N;H0;D2;+0:9]=[N+;H0;D2:10]=[N-;H0;D1:11]) 9af1e46e34a295ad5081f37e7127e808912f4d1725b636f26cc50a4b 1 -6fde2b6d9c02503241835575c60690f5530e5207ed95efe44724f1d2 CC[O:1][C:2]([C:3]([CH2:4][c:5]1[cH:6][cH:7][cH:8][cH:9][cH:10]1)([CH3:11])[S:12](=[O:13])(=[O:14])[CH2:15][c:16]1[cH:17][cH:18][c:19]([O:20][CH3:21])[cH:22][cH:23]1)=[O:24].CO.[Na+].[OH-]>>[OH:1][C:2]([C:3]([CH2:4][c:5]1[cH:6][cH:7][cH:8][cH:9][cH:10]1)([CH3:11])[S:12](=[O:13])(=[O:14])[CH2:15][c:16]1[cH:17][cH:18][c:19]([O:20][CH3:21])[cH:22][cH:23]1)=[O:24] ([C:3]-[C:2](=[O;D1;H0:4])-[OH;D1;+0:1])>>(C-C-[O;H0;D2;+0:1]-[C:2](-[C:3])=[O;D1;H0:4]) 9a4c5ceadb3b4a753bb8f03491f138cd875a84f1d327e818237f90df 2 diff --git a/tests/data/make_false_template_library.csv b/tests/data/make_false_template_library.csv deleted file mode 100644 index e160e96..0000000 --- a/tests/data/make_false_template_library.csv +++ /dev/null @@ -1,3 +0,0 @@ -0,039c3d4c9304218d50b06ed252b67c1ed287ea5331fa2755fdd984e6,O=C1CCC(=O)N1[Br:1].[F:2][c:3]1[cH:4][cH:5][c:6]2[c:7]([cH:8]1)[N:9]([CH3:10])[C:11](=[O:12])[CH2:13][CH2:14]2.CCOC(C)=O.CN(C)C=O.O,[Br:1][c:4]1[c:3]([F:2])[cH:8][c:7]2[c:6]([cH:5]1)[CH2:14][CH2:13][C:11](=[O:12])[N:9]2[CH3:10],([Br;H0;D1;+0:1]-[c;H0;D3;+0:3](:[c:2]):[c:4])>>(O=C1-C-C-C(=O)-N-1-[Br;H0;D1;+0:1]).([c:2]:[cH;D2;+0:3]:[c:4]),04aac57316494f5621172b80523cd496e017f4d0104703ad33b2fa4b,0 -0,17774f52ad0f5f143d46c931fd76d0019b368a6127051cd9630916da,[C:1]([C:2]#[CH:3])(=[O:4])[O:5][CH2:6][CH3:7].[N:8](=[N+:9]=[N-:10])[CH2:11][CH2:12][CH2:13][CH2:14][n:15]1[c:16](=[O:17])[cH:18][c:19]([NH:20][C:21]([CH2:22][c:23]2[cH:24][cH:25][cH:26][cH:27][cH:28]2)=[O:29])[cH:30][cH:31]1.CC(=O)O.CCN(C(C)C)C(C)C.ClCCl.[Cu]I,[C:1]([c:2]1[cH:3][n:8]([CH2:11][CH2:12][CH2:13][CH2:14][n:15]2[c:16](=[O:17])[cH:18][c:19]([NH:20][C:21]([CH2:22][c:23]3[cH:24][cH:25][cH:26][cH:27][cH:28]3)=[O:29])[cH:30][cH:31]2)[n:9][n:10]1)(=[O:4])[O:5][CH2:6][CH3:7],([C:8]-[n;H0;D3;+0:9]1:[cH;D2;+0:7]:[c;H0;D3;+0:6](-[C:4](=[O;D1;H0:5])-[#8:3]-[C:2]-[C;D1;H3:1]):[n;H0;D2;+0:11]:[n;H0;D2;+0:10]:1)>>([C;D1;H3:1]-[C:2]-[#8:3]-[C:4](=[O;D1;H0:5])-[C;H0;D2;+0:6]#[CH;D1;+0:7]).([C:8]-[N;H0;D2;+0:9]=[N+;H0;D2:10]=[N-;H0;D1:11]),9af1e46e34a295ad5081f37e7127e808912f4d1725b636f26cc50a4b,1 -0,6fde2b6d9c02503241835575c60690f5530e5207ed95efe44724f1d2,CC[O:1][C:2]([C:3]([CH2:4][c:5]1[cH:6][cH:7][cH:8][cH:9][cH:10]1)([CH3:11])[S:12](=[O:13])(=[O:14])[CH2:15][c:16]1[cH:17][cH:18][c:19]([O:20][CH3:21])[cH:22][cH:23]1)=[O:24].CO.[Na+].[OH-],[OH:1][C:2]([C:3]([CH2:4][c:5]1[cH:6][cH:7][cH:8][cH:9][cH:10]1)([CH3:11])[S:12](=[O:13])(=[O:14])[CH2:15][c:16]1[cH:17][cH:18][c:19]([O:20][CH3:21])[cH:22][cH:23]1)=[O:24],([C:3]-[C:2](=[O;D1;H0:4])-[OH;D1;+0:1])>>(C-C-[O;H0;D2;+0:1]-[C:2](-[C:3])=[O;D1;H0:4]),9a4c5ceadb3b4a753bb8f03491f138cd875a84f1d327e818237f90df,2 diff --git a/tests/data/test_reactions_template.csv b/tests/data/test_reactions_template.csv new file mode 100644 index 0000000..933ae98 --- /dev/null +++ b/tests/data/test_reactions_template.csv @@ -0,0 +1,4 @@ +ReactionSmilesClean mapped_rxn confidence RetroTemplate TemplateHash TemplateError +CN1CCC(Cl)CC1.N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F.O>>CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1 Cl[CH:5]1[CH2:4][CH2:3][N:2]([CH3:1])[CH2:26][CH2:25]1.N#[C:6][c:8]1[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]2[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]2)[c:23]1[F:24].[OH2:7]>>[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1 0.9424734380772164 [C:2]-[CH;D3;+0:1](-[C:3])-[C;H0;D3;+0:4](=[O;H0;D1;+0:6])-[c:5]>>Cl-[CH;D3;+0:1](-[C:2])-[C:3].N#[C;H0;D2;+0:4]-[c:5].[OH2;D0;+0:6] 23f00a3c507eef75b22252e8eea99b2ce8eab9a573ff2fbd8227d93f49960a27 +N#Cc1cccc(N)c1F.O=C(Cl)c1ccc(F)cc1>>N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F Cl[C:9](=[O:10])[c:11]1[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]1.[N:1]#[C:2][c:3]1[cH:4][cH:5][cH:6][c:7]([NH2:8])[c:18]1[F:19]>>[N:1]#[C:2][c:3]1[cH:4][cH:5][cH:6][c:7]([NH:8][C:9](=[O:10])[c:11]2[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]2)[c:18]1[F:19] 0.9855040989023992 [O;D1;H0:2]=[C;H0;D3;+0:1](-[c:3])-[NH;D2;+0:4]-[c:5]>>Cl-[C;H0;D3;+0:1](=[O;D1;H0:2])-[c:3].[NH2;D1;+0:4]-[c:5] dadfa1075f086a1e76ed69f4d1c5cc44999708352c462aac5817785131169c41 +NC(=O)c1ccc(F)cc1.Fc1c(Cl)cccc1C#N>>N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F Cl[c:7]1[cH:6][cH:5][cH:4][c:3]([C:2]#[N:1])[c:18]1[F:19].[NH2:8][C:9](=[O:10])[c:11]1[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]1>>[N:1]#[C:2][c:3]1[cH:4][cH:5][cH:6][c:7]([NH:8][C:9](=[O:10])[c:11]2[cH:12][cH:13][c:14]([F:15])[cH:16][cH:17]2)[c:18]1[F:19] 0.9707971018098916 [O;D1;H0:6]=[C:5](-[NH;D2;+0:4]-[c;H0;D3;+0:1](:[c:2]):[c:3])-[c:7]1:[c:8]:[c:9]:[c:10]:[c:11]:[c:12]:1>>Cl-[c;H0;D3;+0:1](:[c:2]):[c:3].[NH2;D1;+0:4]-[C:5](=[O;D1;H0:6])-[c:7]1:[c:8]:[c:9]:[c:10]:[c:11]:[c:12]:1 01ba54afaa6c16613833b643d8f2503d9222eec7a3834f1cdd002faeb50ef239 \ No newline at end of file diff --git a/tests/data/tree_for_clustering.json b/tests/data/tree_for_clustering.json index 8bb51ef..fb291a7 100644 --- a/tests/data/tree_for_clustering.json +++ b/tests/data/tree_for_clustering.json @@ -162,92 +162,79 @@ "smiles": "Cc1ccc2nc3ccccc3c(Nc3ccc(NC(=S)Nc4ccccc4)cc3)c2c1", "class": "TreeMolecule", "parent": null, - "transform": 0, - "tracked_atom_indices": {} + "transform": 0 }, "140579263366672": { "smiles": "[CH3:1][c:2]1[cH:3][cH:4][c:5]2[n:6][c:7]3[cH:8][cH:9][cH:10][cH:11][c:12]3[c:13]([Cl:900])[c:31]2[cH:32]1", "class": "TreeMolecule", "parent": 140579172428000, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "140579263368016": { "smiles": "[NH2:14][c:15]1[cH:16][cH:17][c:18]([NH:19][C:20](=[S:21])[NH:22][c:23]2[cH:24][cH:25][cH:26][cH:27][cH:28]2)[cH:29][cH:30]1", "class": "TreeMolecule", "parent": 140579172428000, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "140577500646512": { "smiles": "[C:20](=[S:21])=[N:22][c:23]1[cH:24][cH:25][cH:26][cH:27][cH:28]1", "class": "TreeMolecule", "parent": 140579172428000, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "140577500646080": { "smiles": "[CH3:1][c:2]1[cH:3][cH:4][c:5]2[n:6][c:7]3[cH:8][cH:9][cH:10][cH:11][c:12]3[c:13]([NH:14][c:15]3[cH:16][cH:17][c:18]([NH2:19])[cH:29][cH:30]3)[c:31]2[cH:32]1", "class": "TreeMolecule", "parent": 140579172428000, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "140577500644928": { "smiles": "[CH3:1][c:2]1[cH:3][cH:4][c:5]2[n:6][c:7]3[cH:8][cH:9][cH:10][cH:11][c:12]3[c:13]([NH:14][c:15]3[cH:16][cH:17][c:18]([N:19]=[C:20]=[S:21])[cH:29][cH:30]3)[c:31]2[cH:32]1", "class": "TreeMolecule", "parent": 140579172428000, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "140577500646944": { "smiles": "[NH2:22][c:23]1[cH:24][cH:25][cH:26][cH:27][cH:28]1", "class": "TreeMolecule", "parent": 140579172428000, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "140581032331392": { "smiles": "[CH3:1][c:2]1[cH:3][cH:4][c:5]2[n:6][c:7]3[cH:8][cH:9][cH:10][cH:11][c:12]3[c:13]([Cl:900])[c:31]2[cH:32]1", "class": "TreeMolecule", "parent": 140577500644928, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "140579263264128": { "smiles": "[NH2:14][c:15]1[cH:16][cH:17][c:18]([N:19]=[C:20]=[S:21])[cH:29][cH:30]1", "class": "TreeMolecule", "parent": 140577500644928, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "140577571413008": { "smiles": "[CH3:1][c:2]1[cH:3][cH:4][c:5]2[n:6][c:7]3[cH:8][cH:9][cH:10][cH:11][c:12]3[c:13]([Br:900])[c:31]2[cH:32]1", "class": "TreeMolecule", "parent": 140577500644928, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "140577571410704": { "smiles": "[NH2:14][c:15]1[cH:16][cH:17][c:18]([N:19]=[C:20]=[S:21])[cH:29][cH:30]1", "class": "TreeMolecule", "parent": 140577500644928, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "140579263368160": { "smiles": "[CH3:1][c:2]1[cH:3][cH:4][c:5]2[n:6][c:7]3[cH:8][cH:9][cH:10][cH:11][c:12]3[c:13]([NH2:14])[c:31]2[cH:32]1", "class": "TreeMolecule", "parent": 140577500644928, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "140579263366576": { "smiles": "[c:15]1([Br:900])[cH:16][cH:17][c:18]([N:19]=[C:20]=[S:21])[cH:29][cH:30]1", "class": "TreeMolecule", "parent": 140577500644928, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 } } } \ No newline at end of file diff --git a/tests/mcts/conftest.py b/tests/mcts/conftest.py index fd227b7..5cc9e71 100644 --- a/tests/mcts/conftest.py +++ b/tests/mcts/conftest.py @@ -18,13 +18,13 @@ def fresh_tree(default_config): @pytest.fixture def set_default_prior(default_config): - default_config.use_prior = False + default_config.search.algorithm_config["use_prior"] = False def wrapper(prior): - default_config.default_prior = prior + default_config.search.algorithm_config["default_prior"] = prior yield wrapper - default_config.use_prior = True + default_config.search.algorithm_config["use_prior"] = True @pytest.fixture diff --git a/tests/mcts/test_node.py b/tests/mcts/test_node.py index 4688fdb..1786e62 100644 --- a/tests/mcts/test_node.py +++ b/tests/mcts/test_node.py @@ -2,7 +2,10 @@ def test_root_state_properties(generate_root): root = generate_root("CCCCOc1ccc(CC(=O)N(C)O)cc1") root2 = generate_root("CCCCOc1ccc(CC(=O)N(C)O)cc1") - assert round(root.state.score, 4) == 0.0491 + search_reward = root._config.search.algorithm_config["search_reward"] + scorer = root._config.scorers[search_reward] + + assert round(scorer(root), 4) == 0.0491 assert root.state.stock_availability == ["Not in stock"] assert hash(root.state) == hash(root2.state) assert root.created_at_iteration is None @@ -35,6 +38,24 @@ def test_expand_root_with_default_priors(setup_mcts_search, set_default_prior): assert view["objects"] == [None, None, None] +def test_expand_root_immediate_instantiation(setup_mcts_search, default_config): + root, _, _ = setup_mcts_search + default_config.search.algorithm_config["immediate_instantiation"] = [ + "simple_expansion" + ] + + root.expand() + + view = root.children_view() + assert len(view["actions"]) == 3 + assert view["priors"] == [0.7, 0.5, 0.3] + assert view["values"] == [0.7, 0.5, -1e6] + assert view["visitations"] == [1, 1, 1] + assert view["objects"][0] is not None + assert view["objects"][1] is not None + assert view["objects"][2] is None + + def test_expand_when_solved(setup_mcts_search, setup_stock): root, _, _ = setup_mcts_search root.expand() diff --git a/tests/mcts/test_reward.py b/tests/mcts/test_reward.py new file mode 100644 index 0000000..f3f8404 --- /dev/null +++ b/tests/mcts/test_reward.py @@ -0,0 +1,106 @@ +from aizynthfinder.analysis import TreeAnalysis +from aizynthfinder.context.scoring import StateScorer, NumberOfReactionsScorer + + +def test_reward_node(default_config, generate_root): + config = default_config + search_reward_scorer = repr(StateScorer(config)) + post_process_reward_scorer = repr(NumberOfReactionsScorer()) + + config.search.algorithm_config["search_reward"] = search_reward_scorer + config.post_processing.route_scorer = post_process_reward_scorer + + node = generate_root("CCCCOc1ccc(CC(=O)N(C)O)cc1", config) + + search_scorer = config.scorers[config.search.algorithm_config["search_reward"]] + route_scorer = config.scorers[config.post_processing.route_scorer] + + assert round(search_scorer(node), 4) == 0.0491 + assert route_scorer(node) == 0 + + +def test_default_postprocessing_reward(setup_aizynthfinder): + """Test using default postprocessing.route_score""" + root_smi = "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" + child1_smi = ["CN1CCC(Cl)CC1", "N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F", "O"] + lookup = {root_smi: {"smiles": ".".join(child1_smi), "prior": 1.0}} + finder = setup_aizynthfinder(lookup, child1_smi) + + config = finder.config + config.search.return_first = True + + search_reward_scorer = repr(NumberOfReactionsScorer()) + default_reward_scorer = repr(StateScorer(config)) + + config.search.algorithm_config["search_reward"] = search_reward_scorer + finder.config = config + + assert finder.config.post_processing.route_scorer == default_reward_scorer + + finder.tree_search() + tree_analysis_search = TreeAnalysis( + finder.tree, scorer=config.scorers[search_reward_scorer] + ) + tree_analysis_pp = TreeAnalysis( + finder.tree, scorer=config.scorers[default_reward_scorer] + ) + + finder.build_routes() + + assert finder.config.post_processing.route_scorer == default_reward_scorer + assert finder.tree.reward_scorer_name == search_reward_scorer + + top_score_tree_analysis = tree_analysis_search.tree_statistics()["top_score"] + top_score_finder = finder.tree.reward_scorer(tree_analysis_search.best()) + + assert top_score_finder == top_score_tree_analysis + + top_score_tree_analysis = tree_analysis_pp.tree_statistics()["top_score"] + top_score_finder = finder.analysis.tree_statistics()["top_score"] + + assert top_score_finder == top_score_tree_analysis + + +def test_custom_reward(setup_aizynthfinder): + """Test using different custom reward functions for MCTS and route building.""" + + root_smi = "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" + child1_smi = ["CN1CCC(Cl)CC1", "N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F", "O"] + lookup = {root_smi: {"smiles": ".".join(child1_smi), "prior": 1.0}} + finder = setup_aizynthfinder(lookup, child1_smi) + + # Test first with return_first and multiple route scores + config = finder.config + config.search.return_first = True + + search_reward_scorer = repr(StateScorer(config)) + post_process_reward_scorer = repr(NumberOfReactionsScorer()) + + config.search.algorithm_config["search_reward"] = search_reward_scorer + config.post_processing.route_scorer = post_process_reward_scorer + finder.config = config + + assert finder.config.post_processing.route_scorer == post_process_reward_scorer + + finder.tree_search() + tree_analysis_search = TreeAnalysis( + finder.tree, scorer=config.scorers[search_reward_scorer] + ) + tree_analysis_pp = TreeAnalysis( + finder.tree, scorer=config.scorers[post_process_reward_scorer] + ) + + finder.build_routes() + + assert finder.config.post_processing.route_scorer == post_process_reward_scorer + assert finder.tree.reward_scorer_name == search_reward_scorer + + top_score_tree_analysis = tree_analysis_search.tree_statistics()["top_score"] + top_score_finder = finder.tree.reward_scorer(tree_analysis_search.best()) + + assert top_score_finder == top_score_tree_analysis + + top_score_tree_analysis = tree_analysis_pp.tree_statistics()["top_score"] + top_score_finder = finder.analysis.tree_statistics()["top_score"] + + assert top_score_finder == top_score_tree_analysis diff --git a/tests/mcts/test_serialization.py b/tests/mcts/test_serialization.py index b71aa9b..c21123a 100644 --- a/tests/mcts/test_serialization.py +++ b/tests/mcts/test_serialization.py @@ -8,6 +8,8 @@ def test_serialize_deserialize_state(default_config): mol = TreeMolecule(parent=None, smiles="CCC", transform=1) state0 = MctsState([mol], default_config) + node0 = MctsNode(state=state0, owner=None, config=default_config) + serializer = MoleculeSerializer() state_serialized = state0.serialize(serializer) @@ -17,11 +19,15 @@ def test_serialize_deserialize_state(default_config): deserializer = MoleculeDeserializer(serializer.store) state1 = MctsState.from_dict(state_serialized, default_config, deserializer) + node1 = MctsNode(state=state1, owner=None, config=default_config) + + search_reward = default_config.search.algorithm_config["search_reward"] + scorer = default_config.scorers[search_reward] assert len(state1.mols) == 1 assert state1.mols[0] == state0.mols[0] assert state1.in_stock_list == state0.in_stock_list - assert state1.score == state0.score + assert scorer(node1) == scorer(node0) def test_serialize_node(setup_mcts_search): diff --git a/tests/retrostar/conftest.py b/tests/retrostar/conftest.py index 7ddb20d..f1d5062 100644 --- a/tests/retrostar/conftest.py +++ b/tests/retrostar/conftest.py @@ -3,6 +3,7 @@ from aizynthfinder.search.retrostar.search_tree import SearchTree +from aizynthfinder.search.retrostar.cost import MoleculeCost from aizynthfinder.search.retrostar.nodes import MoleculeNode from aizynthfinder.aizynthfinder import AiZynthFinder @@ -15,7 +16,7 @@ def wrapper(expansions, stock): setup_policies(expansions, config=finder.config) setup_stock(finder.config, *stock) finder.target_smiles = root_smi - finder.config.search_algorithm = ( + finder.config.search.algorithm = ( "aizynthfinder.search.retrostar.search_tree.SearchTree" ) return finder @@ -23,16 +24,6 @@ def wrapper(expansions, stock): return wrapper -@pytest.fixture -def setup_mocked_model(mocker): - biases = [np.zeros(10), np.zeros(1)] - weights = [np.ones([10, 10]), np.ones([10, 1])] - - mocker.patch("builtins.open") - mocked_pickle_load = mocker.patch("aizynthfinder.search.retrostar.cost.pickle.load") - mocked_pickle_load.return_value = weights, biases - - @pytest.fixture def setup_search_tree(default_config, setup_policies, setup_stock): root_smiles = "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" @@ -54,6 +45,8 @@ def setup_search_tree(default_config, setup_policies, setup_stock): @pytest.fixture def setup_star_root(default_config): def wrapper(smiles): - return MoleculeNode.create_root(smiles, config=default_config) + return MoleculeNode.create_root( + smiles, config=default_config, molecule_cost=MoleculeCost(default_config) + ) return wrapper diff --git a/tests/retrostar/data/andor_tree_for_clustering.json b/tests/retrostar/data/andor_tree_for_clustering.json index 69f2162..a26380a 100644 --- a/tests/retrostar/data/andor_tree_for_clustering.json +++ b/tests/retrostar/data/andor_tree_for_clustering.json @@ -2920,869 +2920,745 @@ "smiles": "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1", "class": "TreeMolecule", "parent": null, - "transform": 0, - "tracked_atom_indices": {} + "transform": 0 }, "139643166203664": { "smiles": "[C:14](=[O:15])([c:16]1[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]1)[Cl:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643171528960": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201504": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643162454288": { "smiles": "[CH3:1][I:900]=[N+:13]([c:12]1[cH:11][cH:10][cH:9][c:8]([C:6]([CH:5]2[CH2:4][CH2:3][NH:2][CH2:26][CH2:25]2)=[O:7])[c:23]1[F:24])[O-:901]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162454624": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455056": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1)([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162454144": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162454048": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1)(=[O:900])[O:901][CH2:902][c:903]1[cH:904][cH:905][cH:906][cH:907][cH:908]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455488": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455728": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162455968": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166201120": { "smiles": "[CH3:1][NH:2][CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]1[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]1[F:24])[CH2:25][CH2:26][Cl:900]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166202416": { "smiles": "[CH3:1][NH:2][CH2:26][CH2:25][CH:5]([CH2:4][CH2:3][Cl:900])[C:6](=[O:7])[c:8]1[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643166201504, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643173163552": { "smiles": "[CH2:1]=[O:900]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173165280": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643162452464": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166163824": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164870880": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:902]([O:901][CH3:900])[CH3:903])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164872128": { "smiles": "[cH:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171738528": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]=[C:900]([c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:907]3[cH:908][cH:909][cH:910][cH:911][cH:912]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164872464": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171738432": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739248": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739344": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739536": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739632": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171738048": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901]([CH3:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740112": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([F:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740688": { "smiles": "[NH3:13]", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740400": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901](=[O:900])[O:902][CH2:903][c:904]3[cH:905][cH:906][cH:907][cH:908][cH:909]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171741456": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171741024": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]([CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[CH2:907][c:908]3[cH:909][cH:910][cH:911][cH:912][cH:913]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740928": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([C:901]([OH:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740640": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740880": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171740016": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Cl:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164869104": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([N+:13](=[O:901])[O-:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164869056": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([N+:13](=[O:901])[O-:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643173070016": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[c:11]([Cl:901])[c:12]([N+:13](=[O:902])[O-:903])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643171739392": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643164870496": { "smiles": "[NH4+:13]", "class": "TreeMolecule", "parent": 139643162452464, - "transform": 4, - "tracked_atom_indices": {} + "transform": 4 }, "139643162692720": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N+:13](=[O:900])[O-:901])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162692240": { "smiles": "[N:2]1([CH2:900][c:901]2[cH:902][cH:903][cH:904][cH:905][cH:906]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162690464": { "smiles": "[N:2]1([C:901](=[O:900])[O:902][CH2:903][c:904]2[cH:905][cH:906][cH:907][cH:908][cH:909]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164991936": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643162692624": { "smiles": "[N:2]1([C:901]([CH3:900])=[O:902])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164991840": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901]([CH3:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164991984": { "smiles": "[N:2]1([C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993136": { "smiles": "[N:2]1([C:903]([O:902][CH2:901][CH3:900])=[O:904])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992800": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992944": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH:901]=[O:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993280": { "smiles": "[N:2]1([C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:912]([O:911][C:908]([CH3:907])([CH3:909])[CH3:910])=[O:913])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992848": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994720": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994864": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992512": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164992080": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([C:901]([OH:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164995392": { "smiles": "[NH3:13]", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164995248": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([F:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643155805712": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901](=[O:900])[O:902][CH2:903][c:904]3[cH:905][cH:906][cH:907][cH:908][cH:909]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164856432": { "smiles": "[N:2]1([C:905]([O:904][CH2:903][CH2:902][CH2:901][CH3:900])=[O:906])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164857152": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][cH:12][c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164856960": { "smiles": "[N:2]1([C:901](=[O:900])[O-:902])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164857104": { "smiles": "[N:2]1([C:901](=[O:900])[c:902]2[cH:903][cH:904][cH:905][cH:906][cH:907]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993712": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164993664": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]=[C:900]([c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:907]3[cH:908][cH:909][cH:910][cH:911][cH:912]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994192": { "smiles": "[n:2]1[cH:3][cH:4][c:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[cH:25][cH:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166164976": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[cH:23]2)[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643171531312": { "smiles": "[N:2]1([CH2:901][CH3:900])[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643164994768": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Cl:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166164112": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:902]([O:901][CH3:900])[CH3:903])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166166464": { "smiles": "[cH:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166164448": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643166163392": { "smiles": "[N:2]1([c:909]2[n:908][c:907]([NH:906][CH2:905][c:904]3[cH:903][cH:902][c:901]([F:900])[cH:923][c:921]3[F:922])[c:912](-[c:913]3[cH:914][cH:915][c:916]([F:917])[cH:918][c:919]3[F:920])[cH:911][n:910]2)[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643173165280, - "transform": 3, - "tracked_atom_indices": {} + "transform": 3 }, "139643173069200": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901]([CH3:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069008": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:905]([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:906])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069440": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([F:900])([F:902])[F:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173166960": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]=[C:900]([c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:907]3[cH:908][cH:909][cH:910][cH:911][cH:912]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069680": { "smiles": "[CH3:1][I:900]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069968": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070400": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:904]([C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070880": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[c:9]([Cl:900])[cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070832": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][c:11]([Cl:900])[c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173068960": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070448": { "smiles": "[C:6]([c:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24])#[N:901]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070736": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([Cl:900])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173069632": { "smiles": "[OH2:7]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071264": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1)([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071600": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Cl:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072032": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:901](=[O:900])[O:902][CH2:903][c:904]3[cH:905][cH:906][cH:907][cH:908][cH:909]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070592": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([Br:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070544": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:902]([O:901][CH3:900])[CH3:903])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173070064": { "smiles": "[cH:8]1[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072272": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072320": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([C:901]([OH:900])=[O:902])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995808": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([F:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995136": { "smiles": "[NH3:13]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173072224": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995568": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][CH:901]=[O:900])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071648": { "smiles": "[CH3:1][OH:900]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173071360": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995856": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643172995472": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][cH:12][c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173164800": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[Cl:900])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173164224": { "smiles": "[c:8]1([I:901])[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173163312": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][c:10]([Cl:900])[c:11]([Cl:901])[c:12]([N+:13](=[O:902])[O-:903])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643173164848": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([N:13]([CH2:900][c:901]3[cH:902][cH:903][cH:904][cH:905][cH:906]3)[CH2:907][c:908]3[cH:909][cH:910][cH:911][cH:912][cH:913]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643171528960, - "transform": 2, - "tracked_atom_indices": {} + "transform": 2 }, "139643157042560": { "smiles": "[C:14](=[O:15])([c:16]1[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]1)[OH:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643157043712": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200256": { "smiles": "[CH2:1]=[O:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201936": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202032": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1)([O:904][C:901]([CH3:900])([CH3:902])[CH3:903])=[O:905]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200736": { "smiles": "[CH3:1][I:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166203376": { "smiles": "[NH:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200976": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([CH:6]([OH:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200112": { "smiles": "[C:1]([N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]3[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]3)[c:23]2[F:24])[CH2:25][CH2:26]1)(=[O:900])[O:901][CH2:902][c:903]1[cH:904][cH:905][cH:906][cH:907][cH:908]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166200352": { "smiles": "[C:6]([c:8]1[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]2[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]2)[c:23]1[F:24])#[N:901]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202848": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([Cl:900])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202608": { "smiles": "[OH2:7]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201024": { "smiles": "[C:14](=[O:15])([c:16]1[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]1)[O:901][CH3:900]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201744": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[c:8]2[cH:9][cH:10][cH:11][c:12]([NH2:13])[c:23]2[F:24])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166202176": { "smiles": "[CH3:1][N:2]1[CH2:3][CH2:4][CH:5]([C:6](=[O:7])[N:903]([O:902][CH3:901])[CH3:904])[CH2:25][CH2:26]1", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 }, "139643166201600": { "smiles": "[c:8]1([Br:900])[cH:9][cH:10][cH:11][c:12]([NH:13][C:14](=[O:15])[c:16]2[cH:17][cH:18][c:19]([F:20])[cH:21][cH:22]2)[c:23]1[F:24]", "class": "TreeMolecule", "parent": 139643154371392, - "transform": 1, - "tracked_atom_indices": {} + "transform": 1 } } } \ No newline at end of file diff --git a/tests/retrostar/test_retrostar.py b/tests/retrostar/test_retrostar.py index a986173..75132cd 100644 --- a/tests/retrostar/test_retrostar.py +++ b/tests/retrostar/test_retrostar.py @@ -44,7 +44,7 @@ def test_one_expansion_with_finder(setup_aizynthfinder): finder = setup_aizynthfinder(lookup, child1_smi) # Test first with return_first - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() nodes = finder.tree.mol_nodes @@ -55,8 +55,8 @@ def test_one_expansion_with_finder(setup_aizynthfinder): assert finder.search_stats["returned_first"] # then test with iteration limit - finder.config.return_first = False - finder.config.iteration_limit = 45 + finder.config.search.return_first = False + finder.config.search.iteration_limit = 45 finder.prepare_tree() finder.tree_search() diff --git a/tests/retrostar/test_retrostar_cost.py b/tests/retrostar/test_retrostar_cost.py index 43a6d73..f1e8ec1 100644 --- a/tests/retrostar/test_retrostar_cost.py +++ b/tests/retrostar/test_retrostar_cost.py @@ -1,25 +1,45 @@ -import numpy as np - import pytest -from aizynthfinder.context.cost import MoleculeCost -from aizynthfinder.search.retrostar.cost import RetroStarCost from aizynthfinder.chem import Molecule +from aizynthfinder.search.retrostar.cost import ( + MoleculeCost, + RetroStarCost, + ZeroMoleculeCost, +) def test_retrostar_cost(setup_mocked_model): mol = Molecule(smiles="CCCC") cost = RetroStarCost(model_path="dummy", fingerprint_length=10, dropout_rate=0.0) - assert pytest.approx(cost(mol), abs=0.001) == 30 + assert pytest.approx(cost.calculate(mol), abs=0.001) == 30 + + +def test_zero_molecule_cost(): + mol = Molecule(smiles="CCCC") + + cost = ZeroMoleculeCost().calculate(mol) + assert cost == 0.0 -def test_load_cost_from_config(setup_mocked_model): - cost = MoleculeCost() +def test_molecule_cost_zero(default_config): + default_config.search.algorithm_config["molecule_cost"] = { + "cost": "ZeroMoleculeCost" + } + mol = Molecule(smiles="CCCC") + + molecule_cost = MoleculeCost(default_config)(mol) + assert molecule_cost == 0.0 - dict_ = { - "aizynthfinder.search.retrostar.cost.RetroStarCost": {"model_path": "dummy"} + +def test_molecule_cost_retrostar(default_config, setup_mocked_model): + default_config.search.algorithm_config["molecule_cost"] = { + "cost": "aizynthfinder.search.retrostar.cost.RetroStarCost", + "model_path": "dummy", + "fingerprint_length": 10, + "dropout_rate": 0.0, } - cost.load_from_config(**dict_) + mol = Molecule(smiles="CCCC") - assert len(cost) == 2 + molecule_cost = MoleculeCost(default_config)(mol) + assert pytest.approx(molecule_cost, abs=0.001) == 30 diff --git a/tests/retrostar/test_retrostar_nodes.py b/tests/retrostar/test_retrostar_nodes.py index a784fce..9ba260e 100644 --- a/tests/retrostar/test_retrostar_nodes.py +++ b/tests/retrostar/test_retrostar_nodes.py @@ -96,7 +96,9 @@ def test_serialization_deserialization( dict_ = root.serialize(molecule_serializer) molecule_deserializer = MoleculeDeserializer(molecule_serializer.store) - node = MoleculeNode.from_dict(dict_, default_config, molecule_deserializer) + node = MoleculeNode.from_dict( + dict_, default_config, molecule_deserializer, root.molecule_cost + ) assert node.mol == root.mol assert node.value == root.value @@ -113,7 +115,7 @@ def test_serialization_deserialization( assert grandchild1.mol == grandchild2.mol -def test_converstion_to_reaction_tree( +def test_conversion_to_reaction_tree( setup_star_root, get_action, default_config, setup_stock ): root_smiles = "CCCCOc1ccc(CC(=O)N(C)O)cc1" diff --git a/tests/test_cli.py b/tests/test_cli.py index af1c427..9f36ea7 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -359,7 +359,11 @@ def test_cli_smiles_argument_incorrect( def test_make_stock_from_plain_file( - create_dummy_smiles_source, tmpdir, add_cli_arguments, default_config + create_dummy_smiles_source, + tmpdir, + add_cli_arguments, + default_config, + setup_stock_with_query, ): output_name = str(tmpdir / "temp.hdf5") filename = create_dummy_smiles_source("txt") @@ -367,7 +371,7 @@ def test_make_stock_from_plain_file( make_stock_main() - default_config.stock.load(filename, "stock1") + default_config.stock.load(setup_stock_with_query(filename), "stock1") default_config.stock.select(["stock1"]) assert len(default_config.stock) == 3 @@ -414,8 +418,8 @@ def test_download_public_data(tmpdir, mocker, add_cli_arguments): assert os.path.exists(tmpdir / "config.yml") with open(tmpdir / "config.yml", "r") as fileobj: config = yaml.load(fileobj.read(), Loader=yaml.SafeLoader) - policies = config.get("policy", {}).get("files", {}) + policies = config.get("expansion", {}) assert "uspto" in policies assert len(policies["uspto"]) == 2 - stocks = config.get("stock", {}).get("files", {}) + stocks = config.get("stock", {}) assert "zinc" in stocks diff --git a/tests/test_finder.py b/tests/test_finder.py index 8be1ce5..9089c9a 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -1,5 +1,7 @@ import logging +import pandas as pd +import pytest from aizynthfinder.aizynthfinder import AiZynthFinder @@ -51,7 +53,7 @@ def test_one_expansion(setup_aizynthfinder): finder = setup_aizynthfinder(lookup, child1_smi) # Test first with return_first - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() nodes = list(finder.tree.graph()) @@ -64,8 +66,8 @@ def test_one_expansion(setup_aizynthfinder): assert finder.search_stats["returned_first"] # then test with iteration limit - finder.config.return_first = False - finder.config.iteration_limit = 45 + finder.config.search.return_first = False + finder.config.search.iteration_limit = 45 finder.prepare_tree() finder.tree_search() @@ -91,7 +93,7 @@ def test_two_expansions(setup_aizynthfinder): child1_smi[1]: {"smiles": ".".join(child2_smi), "prior": 1.0}, } finder = setup_aizynthfinder(lookup, [child1_smi[0], child1_smi[2]] + child2_smi) - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() @@ -147,6 +149,21 @@ def test_two_expansions_two_children(setup_aizynthfinder): assert state_smiles(nodes[4].state) == [child2_smi[0]] + grandchild_smi assert finder.search_stats["iterations"] == 100 + # then test with immediate expansion + finder.config.search.algorithm_config["immediate_instantiation"] = [ + "simple_expansion" + ] + finder.prepare_tree() + finder.tree_search() + + nodes = list(finder.tree.graph()) + assert len(nodes) == 5 + assert nodes[0].created_at_iteration == 0 + assert nodes[1].created_at_iteration == 1 + assert nodes[2].created_at_iteration == 1 + assert nodes[3].created_at_iteration == 1 + assert nodes[4].created_at_iteration == 2 + def test_three_expansions(setup_aizynthfinder): """ @@ -172,7 +189,7 @@ def test_three_expansions(setup_aizynthfinder): finder = setup_aizynthfinder( lookup, [child1_smi[0], child1_smi[2], child2_smi[0]] + child3_smi ) - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() @@ -209,9 +226,9 @@ def test_three_expansions_not_solved(setup_aizynthfinder): child2_smi[1]: {"smiles": child3_smi[0], "prior": 1.0}, } finder = setup_aizynthfinder(lookup, [child1_smi[0], child1_smi[2], child2_smi[0]]) - finder.config.return_first = True - finder.config.max_transforms = 2 - finder.config.iteration_limit = 15 + finder.config.search.return_first = True + finder.config.search.max_transforms = 2 + finder.config.search.iteration_limit = 15 finder.tree_search() @@ -253,8 +270,8 @@ def test_two_expansions_no_expandable_root(setup_aizynthfinder): }, } finder = setup_aizynthfinder(lookup, [child1_smi[0], child1_smi[2]]) - finder.config.return_first = True - finder.config.iteration_limit = 10 + finder.config.search.return_first = True + finder.config.search.iteration_limit = 10 finder.tree_search() @@ -303,7 +320,7 @@ def test_two_expansions_no_reactants_first_child(setup_aizynthfinder): finder = setup_aizynthfinder( lookup, [child1_smi[0], child1_smi[2]] + grandchild1_smi ) - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() @@ -362,7 +379,7 @@ def test_three_expansions_no_reactants_first_child(setup_aizynthfinder): finder = setup_aizynthfinder( lookup, [child1_smi[0], child1_smi[2], grandchild1_smi[0]] + grandchild2_smi ) - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() @@ -421,7 +438,7 @@ def test_three_expansions_no_reactants_second_level(setup_aizynthfinder): finder = setup_aizynthfinder( lookup, [child1_smi[0], child1_smi[2], grandchild1_smi[0]] + grandchild2_smi ) - finder.config.return_first = True + finder.config.search.return_first = True finder.tree_search() @@ -479,7 +496,7 @@ def test_two_expansions_no_reactants_second_child(setup_aizynthfinder): finder = setup_aizynthfinder( lookup, [child1_smi[0], child1_smi[2]] + grandchild1_smi ) - finder.config.iteration_limit = 10 + finder.config.search.iteration_limit = 10 finder.tree_search() @@ -514,7 +531,7 @@ def test_two_expansions_cyclic(setup_aizynthfinder): }, } finder = setup_aizynthfinder(lookup, []) - finder.config.iteration_limit = 1 + finder.config.search.iteration_limit = 1 finder.tree_search() @@ -546,8 +563,8 @@ def test_two_expansions_prune_cyclic(setup_aizynthfinder): }, } finder = setup_aizynthfinder(lookup, []) - finder.config.iteration_limit = 1 - finder.config.prune_cycles_in_search = False + finder.config.search.iteration_limit = 1 + finder.config.search.algorithm_config["prune_cycles_in_search"] = False finder.tree_search() @@ -587,7 +604,7 @@ def test_two_expansions_two_children_one_filtered(setup_aizynthfinder, caplog): finder.filter_policy[finder.filter_policy.selection[0]].lookup = { f"{root_smi}>>{'.'.join(child2_smi)}": 0.2 } - finder.config.iteration_limit = 10 + finder.config.search.iteration_limit = 10 with caplog.at_level(logging.DEBUG): finder.tree_search() @@ -607,7 +624,7 @@ def test_two_expansions_two_children_one_filtered(setup_aizynthfinder, caplog): assert finder.search_stats["iterations"] == 10 # Now raise the filter threshold to remove child 2, grandchild 2 - finder.config.filter_cutoff = 0.5 + finder.config.filter_policy["dummy"].filter_cutoff = 0.5 finder.target_smiles = finder.target_smiles # Trigger re-set with caplog.at_level(logging.DEBUG): @@ -634,6 +651,7 @@ def test_stock_info(setup_aizynthfinder): # Test first with return_first finder.config.return_first = True + finder.config.scorers.create_default_scorers() finder.tree_search() assert finder.stock_info() == {} @@ -643,3 +661,103 @@ def test_stock_info(setup_aizynthfinder): expected = {smi: ["stock"] for smi in child1_smi} expected[root_smi] = [] assert finder.stock_info() == expected + + +def test_two_expansions_two_children_full_redundant_expansion(setup_aizynthfinder): + """ + Test the building of this tree: + root + / \ + child 1 (child 2) + | | + grandchild 1 (grandchild 2) + """ + root_smi = "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" + child_smi = ["CN1CCC(Cl)CC1", "N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F", "O"] + grandchild_smi = ["N#Cc1cccc(N)c1F", "O=C(Cl)c1ccc(F)cc1"] + lookup = { + root_smi: [ + {"smiles": ".".join(child_smi), "prior": 0.7}, + {"smiles": ".".join(child_smi), "prior": 0.3}, + ], + child_smi[1]: {"smiles": ".".join(grandchild_smi), "prior": 0.7}, + child_smi[1]: {"smiles": ".".join(grandchild_smi), "prior": 0.7}, + } + finder = setup_aizynthfinder(lookup, [child_smi[0], child_smi[2]] + grandchild_smi) + + finder.config.search.algorithm_config["mcts_grouping"] = "full" + finder.tree_search() + + nodes = list(finder.tree.graph()) + assert len(nodes) == 3 + + assert state_smiles(nodes[0].state) == [root_smi] + assert state_smiles(nodes[1].state) == child_smi + assert state_smiles(nodes[2].state) == [child_smi[0], child_smi[2]] + grandchild_smi + assert "additional_actions" in nodes[0].children_view()["actions"][0].metadata + additional_expansions = ( + nodes[0].children_view()["actions"][0].metadata["additional_actions"] + ) + assert len(additional_expansions) == 1 + assert additional_expansions[0] == {"policy_name": "simple_expansion"} + assert finder.search_stats["iterations"] == 100 + + # Switch to partial degeneracy grouping + + finder.config.mcts_grouping = "partial" + finder.tree_search() + + nodes = list(finder.tree.graph()) + assert len(nodes) == 3 + + +def test_two_expansions_two_children_partial_redundant_expansion(setup_aizynthfinder): + """ + Test the building of this tree: + root + / \ + child 1 (child 2) + | | + grandchild 1 (grandchild 2) + """ + root_smi = "CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1" + child_smi = ["CN1CCC(Cl)CC1", "N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F", "O"] + child2_smi = ["CN1CCC(Cl)CC1", "N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F"] + grandchild_smi = ["N#Cc1cccc(N)c1F", "O=C(Cl)c1ccc(F)cc1"] + lookup = { + root_smi: [ + {"smiles": ".".join(child_smi), "prior": 0.7}, + {"smiles": ".".join(child2_smi), "prior": 0.3}, + ], + child_smi[1]: {"smiles": ".".join(grandchild_smi), "prior": 0.7}, + child_smi[1]: {"smiles": ".".join(grandchild_smi), "prior": 0.7}, + } + finder = setup_aizynthfinder(lookup, [child_smi[0], child_smi[2]] + grandchild_smi) + + # First run with full degeneracy grouping + + finder.config.search.algorithm_config["mcts_grouping"] = "full" + finder.tree_search() + + nodes = list(finder.tree.graph()) + assert len(nodes) == 5 + + # Then turn to partial + + finder.config.search.algorithm_config["mcts_grouping"] = "Partial" + finder.target_smiles = finder.target_smiles # Trigger re-set + finder.tree_search() + + nodes = list(finder.tree.graph()) + assert len(nodes) == 3 + + assert state_smiles(nodes[0].state) == [root_smi] + assert state_smiles(nodes[1].state) == child_smi + assert state_smiles(nodes[2].state) == [child_smi[0], child_smi[2]] + grandchild_smi + assert "additional_actions" in nodes[0].children_view()["actions"][0].metadata + additional_expansions = ( + nodes[0].children_view()["actions"][0].metadata["additional_actions"] + ) + assert len(additional_expansions) == 1 + assert additional_expansions[0] == {"policy_name": "simple_expansion"} + assert finder.search_stats["iterations"] == 100 diff --git a/tests/test_training.py b/tests/test_training.py deleted file mode 100644 index db888ad..0000000 --- a/tests/test_training.py +++ /dev/null @@ -1,411 +0,0 @@ -import os - -import pytest -import pandas as pd -import numpy as np - -from aizynthfinder.chem import Molecule - -try: - from scipy import sparse - - from aizynthfinder.training.utils import ( - Config, - create_reactants_molecules, - reverse_template, - reaction_hash, - split_and_save_data, - smiles_to_fingerprint, - is_sanitizable, - reaction_to_fingerprints, - ) - from aizynthfinder.training.keras_models import ( - ExpansionModelSequence, - FilterModelSequence, - ) - from aizynthfinder.training.make_false_products import ( - strict_application, - random_application, - recommender_application, - ) -except ImportError: - SUPPORT_TRAINING = False -else: - SUPPORT_TRAINING = True - - -@pytest.fixture -def default_config(): - return Config() - - -@pytest.fixture -def filter_model_sequence(mocker, default_config): - mocked_load_npz = mocker.patch( - "aizynthfinder.training.keras_models.sparse.load_npz" - ) - input_array = sparse.csr_matrix(np.zeros([9000, 10])) - input_array2 = sparse.csr_matrix(np.zeros([9000, 10])) - mocked_load_npz.side_effect = [input_array, ValueError(), input_array2] - - label_array = np.zeros([9000, 100]) - mocked_np_load = mocker.patch("aizynthfinder.training.keras_models.np.load") - mocked_np_load.return_value = {"arr_0": label_array} - - return FilterModelSequence(default_config, "training") - - -@pytest.fixture -def expansion_model_sequence(mocker, default_config): - mocked_load_npz = mocker.patch( - "aizynthfinder.training.keras_models.sparse.load_npz" - ) - input_array = sparse.csr_matrix(np.zeros([9000, 10])) - label_array = sparse.csr_matrix(np.zeros([9000, 100])) - mocked_load_npz.side_effect = [input_array, label_array] - - return ExpansionModelSequence(default_config, "training") - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_empty_config(default_config, write_yaml): - filename = write_yaml({}) - - config = Config(filename) - - assert config._config == default_config._config - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_update_single_setting(default_config, write_yaml): - filename = write_yaml({"fingerprint_len": 10}) - - config = Config(filename) - - assert config["fingerprint_len"] == 10 - assert config["template_occurrence"] == default_config["template_occurrence"] - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_update_nested_setting(default_config, write_yaml): - filename = write_yaml( - {"split_size": {"training": 0.8, "testing": 0.1, "validation": 0.1}} - ) - - config = Config(filename) - - assert config["template_occurrence"] == default_config["template_occurrence"] - assert config["split_size"]["training"] == 0.8 - assert config["split_size"]["testing"] == 0.1 - assert config["split_size"]["validation"] == 0.1 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_update_invalid_setting(default_config, write_yaml): - filename = write_yaml( - {"fingerprint_len": {"training": 0.8, "testing": 0.1, "validation": 0.1}} - ) - - config = Config(filename) - - assert config["fingerprint_len"] == default_config["fingerprint_len"] - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_config_filename(default_config): - - filename = default_config.filename("raw_library") - assert filename.startswith(default_config["output_path"]) - assert filename.endswith(default_config["file_postfix"]["raw_library"]) - - filename = default_config.filename("something") - assert filename.startswith(default_config["output_path"]) - assert filename.endswith("something") - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_split_and_save_data_frame(tmpdir, default_config): - default_config["output_path"] = str(tmpdir) - default_config["file_prefix"] = "dummy" - filename_train = str( - tmpdir / "dummy" + default_config["file_postfix"]["training_library"] - ) - filename_valid = str( - tmpdir / "dummy" + default_config["file_postfix"]["validation_library"] - ) - filename_test = str( - tmpdir / "dummy" + default_config["file_postfix"]["testing_library"] - ) - data = pd.DataFrame.from_dict({"one": np.zeros(100), "two": np.ones(100)}) - - split_and_save_data(data, "library", default_config) - - assert os.path.exists(filename_train) - assert os.path.exists(filename_valid) - assert os.path.exists(filename_test) - - data_read = pd.read_csv(filename_train, header=None, names=["one", "two"]) - assert len(data_read) == 90 - - data_read = pd.read_csv(filename_valid, header=None, names=["one", "two"]) - assert len(data_read) == 5 - - data_read = pd.read_csv(filename_test, header=None, names=["one", "two"]) - assert len(data_read) == 5 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_split_and_save_data_ndarray(tmpdir, default_config): - default_config["output_path"] = str(tmpdir) - default_config["file_prefix"] = "dummy" - filename_train = str( - tmpdir / "dummy" + default_config["file_postfix"]["training_inputs"] - ) - filename_valid = str( - tmpdir / "dummy" + default_config["file_postfix"]["validation_inputs"] - ) - filename_test = str( - tmpdir / "dummy" + default_config["file_postfix"]["testing_inputs"] - ) - data = np.ones([100, 2]) - - split_and_save_data(data, "inputs", default_config) - - assert os.path.exists(filename_train) - assert os.path.exists(filename_valid) - assert os.path.exists(filename_test) - - data_read = np.load(filename_train)["arr_0"] - assert len(data_read) == 90 - - data_read = np.load(filename_valid)["arr_0"] - assert len(data_read) == 5 - - data_read = np.load(filename_test)["arr_0"] - assert len(data_read) == 5 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_split_and_save_data_sparse(default_config, tmpdir): - default_config["output_path"] = str(tmpdir) - default_config["file_prefix"] = "dummy" - filename_train = str( - tmpdir / "dummy" + default_config["file_postfix"]["training_inputs"] - ) - filename_valid = str( - tmpdir / "dummy" + default_config["file_postfix"]["validation_inputs"] - ) - filename_test = str( - tmpdir / "dummy" + default_config["file_postfix"]["testing_inputs"] - ) - data = sparse.csr_matrix(np.ones([100, 2])) - - split_and_save_data(data, "inputs", default_config) - - assert os.path.exists(filename_train) - assert os.path.exists(filename_valid) - assert os.path.exists(filename_test) - - data_read = sparse.load_npz(str(filename_train)) - assert data_read.shape[0] == 90 - - data_read = sparse.load_npz(str(filename_valid)) - assert data_read.shape[0] == 5 - - data_read = sparse.load_npz(str(filename_test)) - assert data_read.shape[0] == 5 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_smiles_to_fingerprint(default_config): - default_config["fingerprint_len"] = 10 - - fingerprint = smiles_to_fingerprint(["O"], default_config) - - assert sum(fingerprint) == 1 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_is_sanitizable(): - - flag = is_sanitizable(("O")) - assert flag - - flag = is_sanitizable(("c1ccccc1(C)(C)")) - assert not flag - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_reaction_to_fingerprint(default_config): - default_config["fingerprint_len"] = 10 - product_smiles = "[Cl:1][c:2]1[c:3]([C:4](=[O:5])[C:12]([F:11])([F:13])[F:14])[cH:6][c:7]([F:10])[cH:8][cH:9]1" # noqa - reactants_smiles = "C[O:5][C:4](=O)[c:3]1[c:2]([Cl:1])[cH:9][cH:8][c:7]([F:10])[cH:6]1.C[Si](C)(C)[C:12]([F:11])([F:13])[F:14].COCCOC.Cl.[Cs+].[F-].[Na+].[OH-]" # noqa - - fingerprint = reaction_to_fingerprints( - [product_smiles, reactants_smiles], default_config - ) - - assert list(fingerprint) == [-1, -1, -1, 0, -1, 0, 0, -1, 0, -1] - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_expansion_model_sequence_loading(expansion_model_sequence): - - assert expansion_model_sequence.input_dim == 10 - assert expansion_model_sequence.output_dim == 100 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_expansion_model_sequence_slicing(expansion_model_sequence, default_config): - seq = expansion_model_sequence - - xbatch, ybatch = seq[1] - - assert xbatch.shape[0] == default_config["batch_size"] - assert ybatch.shape[0] == default_config["batch_size"] - assert xbatch.shape[1] == expansion_model_sequence.input_dim - assert ybatch.shape[1] == expansion_model_sequence.output_dim - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_filter_model_sequence_loading(filter_model_sequence): - - assert filter_model_sequence.input_dim == 10 - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_filter_model_sequence_slicing(filter_model_sequence, default_config): - seq = filter_model_sequence - - xbatch, ybatch = seq[1] - - assert xbatch[0].shape[0] == default_config["batch_size"] - assert xbatch[1].shape[0] == default_config["batch_size"] - assert ybatch.shape[0] == default_config["batch_size"] - assert xbatch[0].shape[1] == filter_model_sequence.input_dim - assert xbatch[1].shape[1] == filter_model_sequence.input_dim - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_reactants_molecules(): - reactants_str = "C[O:5][C:4](=O)[c:3]1[c:2]([Cl:1])[cH:9][cH:8][c:7]([F:10])[cH:6]1.C[Si](C)(C)[C:12]([F:11])([F:13])[F:14].COCCOC.Cl.[Cs+].[F-]" # noqa - - mols = create_reactants_molecules(reactants_str) - - assert len(mols) == 2 - expected_smiles = ( - "C[O:5][C:4](=O)[c:3]1[c:2]([Cl:1])[cH:9][cH:8][c:7]([F:10])[cH:6]1" - ) - assert mols[0].smiles == expected_smiles - assert mols[1].smiles == "C[Si](C)(C)[C:12]([F:11])([F:13])[F:14]" - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_reverse_template(): - retro_template = "([C:2]-[C:3](=[O;D1;H0:4])-[N;H0;D3;+0:5](-[CH3;D1;+0:1])-[c:6])>>(I-[CH3;D1;+0:1]).([C:2]-[C:3](=[O;D1;H0:4])-[NH;D2;+0:5]-[c:6])" # noqa - expected = "(I-[CH3;D1;+0:1]).([C:2]-[C:3](=[O;D1;H0:4])-[NH;D2;+0:5]-[c:6])>>([C:2]-[C:3](=[O;D1;H0:4])-[N;H0;D3;+0:5](-[CH3;D1;+0:1])-[c:6])" # noqa - - assert reverse_template(retro_template) == expected - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_reaction_hash(): - reactants_str = "C[O:5][C:4](=O)[c:3]1[c:2]([Cl:1])[cH:9][cH:8][c:7]([F:10])[cH:6]1.C[Si](C)(C)[C:12]([F:11])([F:13])[F:14].COCCOC.Cl.[Cs+].[F-].[Na+].[OH-]" # noqa - product = Molecule( - smiles="[Cl:1][c:2]1[c:3]([C:4](=[O:5])[C:12]([F:11])([F:13])[F:14])[cH:6][c:7]([F:10])[cH:8][cH:9]1" - ) - expected = "c92d362cc28df004939d1af699cc8038a2f82ddcdf37eacf3c7366db" - - assert reaction_hash(reactants_str, product) == expected - - -@pytest.fixture -def library_data(shared_datadir, default_config): - default_config["library_headers"] = [ - "index", - "reaction_hash", - "reactants", - "products", - "retro_template", - "template_hash", - "template_code", - ] - default_config["negative_data"]["random_trials"] = 10 - filename = str(shared_datadir / "make_false_template_library.csv") - library = pd.read_csv( - filename, - index_col=False, - header=None, - names=default_config["library_headers"], - ) - return library, default_config - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_strict_application(library_data): - library, config = library_data - errors = [] - - gen = strict_application(library, config, errors) - new_df = next(gen) - - assert len(new_df) == 2 - assert not errors - hashes = sorted(list(new_df.reaction_hash.values)) - assert hashes[0] == "a885c1d5fb93760b042b03a81d400d316908ce892f83a2de49e06042" - assert hashes[1] == "fe2192395a637b200d94c29fddc4db38033456eacca0b8112052239c" - - assert next(gen) is None - assert next(gen) is None - - with pytest.raises(StopIteration): - next(gen) - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_random_application(library_data): - library, config = library_data - errors = [] - - gen = random_application(library, config, errors) - - assert next(gen) is None - - new_df = next(gen) - - assert len(new_df) == 1 - assert not errors - hash_ = new_df.reaction_hash.values[0] - assert hash_ == "acefe9ee01e5e4b6c84d4ed550f4819d791051f095d66abd60a80b25" - - assert next(gen) is None - - with pytest.raises(StopIteration): - next(gen) - - -@pytest.mark.xfail(condition=not SUPPORT_TRAINING, reason="Dependencies not installed") -def test_recommender_application(library_data, mocker): - mocked_load_model = mocker.patch( - "aizynthfinder.training.make_false_products.load_keras_model" - ) - mocked_model = mocked_load_model.return_value - mocked_model.predict.return_value = np.asarray([0.5, 0.3, 0.2]) - library, config = library_data - errors = [] - - gen = recommender_application(library, config, errors) - - assert next(gen) is None - - new_df = next(gen) - - assert len(new_df) == 1 - assert not errors - hash_ = new_df.reaction_hash.values[0] - assert hash_ == "acefe9ee01e5e4b6c84d4ed550f4819d791051f095d66abd60a80b25" - - assert next(gen) is None - - with pytest.raises(StopIteration): - next(gen) diff --git a/tests/utils/test_image.py b/tests/utils/test_image.py index 0245dab..2cd82b8 100644 --- a/tests/utils/test_image.py +++ b/tests/utils/test_image.py @@ -20,7 +20,7 @@ def new_image(): @pytest.fixture -def setup_graphviz_graph(): +def setup_graph(): mol1 = TreeMolecule(smiles="CCCO", parent=None) reaction = TemplatedRetroReaction(mol=mol1, smarts="") @@ -64,53 +64,11 @@ def test_save_molecule_images(): assert len(os.listdir(image.IMAGE_FOLDER)) == nfiles + 2 -@pytest.mark.xfail( - condition=shutil.which("dot") is None, reason="graphviz is not installed" -) -def test_graphviz_usage(mocker, tmpdir, setup_graphviz_graph): - mkstemp_patch = mocker.patch("aizynthfinder.utils.image.tempfile.mkstemp") - files = [ - (None, str(tmpdir / "graph1.dot")), - (None, str(tmpdir / "img2.png")), - ] - mkstemp_patch.side_effect = files - molecules, reactions, edges, frame_colors = setup_graphviz_graph - - img = image.make_graphviz_image(molecules, reactions, edges, frame_colors) - - assert img.height > 0 - assert img.width > 0 - for _, filename in files: - assert os.path.exists(filename) - - -@pytest.mark.xfail( - condition=shutil.which("dot") is None, reason="graphviz is not installed" -) -def test_graphviz_usage_exception_dot(mocker, tmpdir, setup_graphviz_graph): - exists_patch = mocker.patch("aizynthfinder.utils.image.os.path.exists") - exists_patch.side_effect = [False, True] - molecules, reactions, edges, frame_colors = setup_graphviz_graph - - img = image.make_graphviz_image(molecules, reactions, edges, frame_colors) - assert img.height > 0 - assert img.width > 0 - - -def test_graphviz_usage_exception_dot_both(mocker, tmpdir, setup_graphviz_graph): - exists_patch = mocker.patch("aizynthfinder.utils.image.os.path.exists") - exists_patch.return_value = False - molecules, reactions, edges, frame_colors = setup_graphviz_graph - - with pytest.raises(FileNotFoundError, match=".*'dot'.*"): - image.make_graphviz_image(molecules, reactions, edges, frame_colors) - - -def test_visjs_page(mocker, tmpdir, setup_graphviz_graph): +def test_visjs_page(mocker, tmpdir, setup_graph): mkdtemp_patch = mocker.patch("aizynthfinder.utils.image.tempfile.mkdtemp") mkdtemp_patch.return_value = str(tmpdir / "tmp") os.mkdir(tmpdir / "tmp") - molecules, reactions, edges, frame_colors = setup_graphviz_graph + molecules, reactions, edges, frame_colors = setup_graph filename = str(tmpdir / "arch.tar") image.make_visjs_page(filename, molecules, reactions, edges, frame_colors) From 78efc8be32c02342deed6ba82bbbad99453496bd Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 05:26:38 +0000 Subject: [PATCH 03/10] Replace CHANGELOG content --- CHANGELOG.md | 170 ++++++++++----------------------------------------- 1 file changed, 31 insertions(+), 139 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26675a7..2ad9c75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ - Fixing an issue when concatenating JSON data files. -## Version 3.6.0 2022-11-25 +## Version 3.6.0 2022-11-28 (2022-11-25) ### Features @@ -72,35 +72,20 @@ - Graphviz dependency for route drawing is removed, pure python implementation is used instead - Dependencies reworked so that a minimal package can be installed - Extra dependencies are related to route distances, clustering, training, MongoDB and external models -- (AZ) support for template lookup is removed +- Downloaded files are now the latest USPTO and Ringbreaker models ### Trivial changes - RDKit and route-distances package now installed from pypi - Documentation updated and extended -## Version 3.5.2 2022-07-27 - -### Trivial changes - -- Fix dependency for route-distances -- Update Seldon environment - -## Version 3.5.1 2022-07-22 - -### Bug-fixes - -- Fix atom-mapping inheritence for atoms only in reactants - -## Version 3.5.0 2022-07-21 +## Version 3.5.0 2022-11-28 (2022-07-21) ### Features -- All Seldon models now uses version 0.5.0 of aizynthfinder_models (Reaction connect models july 2022) - Atom-mapping is tracked from product to reactant - Support loading of template library from (gzipped) CSV file - Support of saving aizynthcli output to (gzipped) JSON file -- DeepRetrosynthesis model now returns a field called "mapped_reaction_smiles" - AiZynthExpander now tracks non-applicable templates ### Bug-fixes @@ -109,12 +94,10 @@ ### Trival changes - Silent progress bar when utilizing local Keras model - ## Version 3.4.0 2022-04-28 ### Features -- Deep retrosynthesis Seldon model - Gracefully fail predictions with aizynthcli if target is unsanitizable (Github issue 66) ### Trivial changes @@ -122,25 +105,26 @@ - Remove usage of depracted Pandas function append (Github issue 63) - Correct documentation of aizynthcli (Github issue 67) -## Version 3.3.0 2022-02-14 +## Version 3.3.1 2022-03-09 + +### Trivial changes + +- Updated pinned versions of route_distances, jinja2 and tensorflow + +## Version 3.3.0 2022-02-24 ### Features +- Support for Retro* tree search - Support for breadth-first exhaustive tree search - Support for depth-first proof-number tree search - Possible to save concatenated reaction trees to separate file -### Trivial changes - -- Retro* search algorithm moved to public package - -## Version 3.2.1 2022-01-17 - ### Bugfixes - RouteCostScorer fix for rare routes -## Version 3.2.0 2022-01-11 +## Version 3.2.0 2022-02-24 ### Features @@ -150,12 +134,10 @@ - Introduce short aliases for filter policies - Reaction shape support in GraphViz visualisation of routes -## Version 3.1.0 2021-11-09 +## Version 3.1.0 2021-12-21 ### Features -- Reaction connect API is updated for version 2.0 -- Filter to remove unreasonable expansions (when the template remove most of the molecule) - ReactantsCountFiler (Github issue 42) to filter reactions with incompatible number of reactants - ForwardRegenerationFiler to filter reactions where the forward reaction is incompatible - Possible to skip quick Keras filter for specific policies @@ -172,23 +154,13 @@ ### Trivial changes - Update type hints to be compatible with latest numpy release - -## Version 3.0.1 2021-08-31 - -### Trivial changes - -- REST and GRPC Tensorflow clients now using named input vectors when provided - -### Bugfixes - -- Correct input vectors provided to REST and GRPC tensorflow clients for filter policy +- Update route-distances dependency ## Version 3.0.0 2021-07-26 ### Features - Generalized expansion and filter policies - policies no longer need to be Keras models -- ReactionConnect-based expansion policy and stock query - Updated image generation for synthesis routes - Improved code to prune "regeneration reactions" in MCTS (Github issue 38) - Reactants are sorted in output from ReactionTree class @@ -205,6 +177,7 @@ - Removed MCTS-specific routines in the TreeAnalysis class - Removed code for identifying cycles in ReactionTree +- Remove JSON interface to AiZynthFinder class ### Bugfixes @@ -215,7 +188,7 @@ - Documentation updates - Extensive re-factoring of test cases -## Version 2.6.0 - 2021-05-03 +## Version 2.6.0 - 2021-06-11 (2021-05-03) ### Features @@ -224,17 +197,12 @@ - Route distance calculations with ML model is now supported - Reaction tree objects now has property `is_branched` -### Trivial changes - -- `scikit-learn` is now imported before `tensorflow`, according to Github issue 30 -## Version 2.5.0 - 2021-03-30 +## Version 2.5.0 - 2021-06-11 (2021-03-30) ### Features - Introduce an interface for search algorithm working on AND/OR trees -- Add a reference implementation of the Retro* algorithm in the az sub-package -- Improved AiZynthExpander model to group predictions with the same precursors - The progress bar is now removed upon completion of the tree search - Move `ReactionTree` class to a new module (this will not brake backwards compatibility) @@ -244,9 +212,10 @@ ### Trivial changes -- Use pylint as the code linter +- `scikit-learn` is now imported before `tensorflow`, according to Github issue 30 + +## Version 2.4.0 - 2021-02-22 (2021-02-22) -## Version 2.4.0 - 2021-02-22 ### Features @@ -259,29 +228,19 @@ - Update of black version causing some re-formatting - Small changes to documentation -## Version 2.3.0 - 2021-01-20 +## Version 2.3.0 - 2021-02-22 (2021-01-20) ### Features - Add option to timeout distance calculation of route collections -- Add option to perform clustering in Seldon AiZynthFinder model -- Add new Seldon model AiZynthExpander encapsulating expansion policies - -### Bugfixes - -- Jinja templates are now packaged with the python package - -## Version 2.2.1 - 2020-12-01 - -### Bug fixes -- Fix price and amount function in AiZynth MongoDB stock query +## Version 2.2.1 - 2020-12-18 -### Trivial changes +### Bugfixes -- Introduce caching of fingerprints in template info class +- Include templates for producing routes in package -## Version 2.2.0 - 2020-11-23 +## Version 2.2.0 - 2020-12-14 (2020-11-23) ### Features @@ -289,37 +248,25 @@ - Add new scorers for total price and route score - Add support for adding stop criteria to all stocks - Add stop criteria UI for Jupyter notebook -- Enable the applicability filtered-expansion model in Seldon model -- Improved memory management for template look-up ### Trivial changes - Refactor handling of MongoDB instances - Refactor code to connect with REST and gRPC servers -- Refactor AiZynth buyables query class - -## Version 2.1.1 - 2020-11-08 - -### Bugfixes -- Matching names of policies and scorers in Seldon model - -## Version 2.1.0 - 2020-11-03 +## Version 2.1.0 - 2020-12-07 (2020-11-03) ### Features - Possibility to extract a combined tree for all predicted routes - New classes to use Tensorflow servers as policies -- Add an internal stock query class to use on the AiZynth platform -- Enable use of the tool as a Seldon server ### Trivial changes -- Reduced memory consumption for average product similarity scorer - Improved code for route visualizaition -## Version 2.0.0 - 2020-09-29 +## Version 2.0.0 - 2020-11-24 (2020-09-29) ### Breaking changes @@ -341,27 +288,25 @@ - Catch exceptions from RDChiral more gracefully -## Version 1.2.0 - 2020-09-04 +## Version 1.2.0 - 2020-11-24 (2020-09-04) ### Features - Add score "number of pre-cursors" - Add score "number of pre-cursors in stock" -- Add a stock query to use the AiZynth Buyable API - Enable the loading of MCTS configuration from dict ### Bugfixes - Fix bug in State score for branched reaction trees - Fix bug in "Number of reaction" score for branched MCTS trees -- Fix bug in "Average template occurence" score for trees with no reactions - Fix bug in Jupyter GUI when selecting policies of several available ### Trivial changes - Update python requirement specifications -## Version 1.1.0 - 2020-06-30 +## Version 1.1.0 - 2020-11-24 (2020-06-30) ### Features @@ -369,7 +314,6 @@ - Flag repetetive patterns in routes so they can be hidden - Enable possibility to use more than one rollout policy - Add --nproc argument to aizynthcli to enable trivial multiprocessing -- Add tool to download publicly released data ### Bugfixes @@ -379,58 +323,6 @@ - Add consistency check between rollout neural network and template list -## Version 1.0.0 - 2020-06-01 - -### Breaking changes - -- The tree search algorithm now breaks down any target molecule in stock by default - -### Features - -- Add option to break down target molecules that are in stock -- Add a GUI extension and API to lookup reactions in Reaxys and Pistachio -- Metadata is added to reactions and to the output - -### Bugfixes - -- Fix issue with tree search when all children are rejected - -### Trivial changes - -- Improved documentation -- Improved test coverage -- Interface to graphviz is entirely within the package, not with third-party library - -## Version 0.3.0 - 2020-04-14 - -### Features - -- Add tools to train rollout policy model -- Add tools to create stock from SMILES -- Introduced the RouteCollection class for easy analysis of routes -- Introduced possibility to use external Keras model - -### Bugfixes - -- Fix recreation of reaction tree from dict for certain types of routes - - -## Version 0.2.0 - 2020-03-16 - -### Features - -- Moved internal tree search classes to aizynthfinder.mcts package -- Removed concept of runaway nodes, now exhaustively look through all actions -- Add auto-selecting of stocks and policy in aizynthcli tool -- Add support for custom stock class in aizynthcli tool -- Add support for MongoDB stock lookup - -### Bugfixes - -- Fix cut-off of predictions in Policy class based on threshold and minimum number - -## Version 0.1.0 - 2020-02-18 +## Version 1.0.0 - 2020-06-11 -- Re-factored codebase -- Provide route visualization in Jupyter Notebooks -- Provide command to run predictions in batch \ No newline at end of file +- First public version \ No newline at end of file From 4afa5be139ba590866c521e0ed952bedeb30c73e Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 05:37:23 +0000 Subject: [PATCH 04/10] Replace README content --- README.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 22e3b0f..59312ae 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,17 @@ -# aizynthfinder +# AiZynthFinder -aizynthfinder is a tool for retrosynthetic planning. The default algorithm is based on a Monte Carlo tree search that recursively breaks down a molecule to purchasable precursors. The tree search is guided by a policy that suggests possible precursors by utilizing a neural network trained on a library of known reaction templates. This setup is completely customizable as the tool +[![License](https://img.shields.io/github/license/MolecularAI/aizynthfinder)](https://github.com/MolecularAI/aizynthfinder/blob/master/LICENSE) +[![Tests](https://github.com/MolecularAI/aizynthfinder/workflows/tests/badge.svg)](https://github.com/MolecularAI/aizynthfinder/actions?workflow=tests) +[![codecov](https://codecov.io/gh/MolecularAI/aizynthfinder/branch/master/graph/badge.svg)](https://codecov.io/gh/MolecularAI/aizynthfinder) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black) +[![version](https://img.shields.io/github/v/release/MolecularAI/aizynthfinder)](https://github.com/MolecularAI/aizynthfinder/releases) +[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MolecularAI/aizynthfinder/blob/master/contrib/notebook.ipynb) + +AiZynthFinder is a tool for retrosynthetic planning. The default algorithm is based on a Monte Carlo tree search that recursively breaks down a molecule to purchasable precursors. The tree search is guided by a policy that suggests possible precursors by utilizing a neural network trained on a library of known reaction templates. This setup is completely customizable as the tool supports multiple search algorithms and expansion policies. +An introduction video can be found here: [https://youtu.be/r9Dsxm-mcgA](https://youtu.be/r9Dsxm-mcgA) + ## Prerequisites Before you begin, ensure you have met the following requirements: @@ -35,7 +44,7 @@ as interfaces to the algorithm: aizynthapp --config config_local.yml -Consult the documentation [here](https://pages.scp.astrazeneca.net/mai/aizynthfinder/doc/) +Consult the documentation [here](https://molecularai.github.io/aizynthfinder/) for more information. To use tool you need @@ -44,7 +53,14 @@ To use tool you need 2. A trained expansion policy network 3. A trained filter policy network (optional) -These files are available on SCP. +Such files can be downloaded from [figshare](https://figshare.com/articles/AiZynthFinder_a_fast_robust_and_flexible_open-source_software_for_retrosynthetic_planning/12334577) and [here](https://figshare.com/articles/dataset/A_quick_policy_to_filter_reactions_based_on_feasibility_in_AI-guided_retrosynthetic_planning/13280507) or they can be downloaded automatically using + +``` +download_public_data my_folder +``` + +where ``my_folder`` is the folder that you want download to. +This will create a ``config.yml`` file that you can use with either ``aizynthcli`` or ``aizynthapp``. ## Development @@ -56,7 +72,7 @@ Run the tests using: pytest -v -The full command run on Jenkins is available through an `invoke` command +The full command run on the CI server is available through an `invoke` command invoke full-tests @@ -88,11 +104,12 @@ Please use ``black`` package for formatting, and follow ``pep8`` style guide. ## Contributors -* Samuel Genheden -* Lakshidaa Saigiridharan +* [@SGenheden](https://www.github.com/SGenheden) +* [@lakshidaa](https://github.com/Lakshidaa) * Helen Lai -* Esben Bjerrum -* Amol Thakkar +* [@EBjerrum](https://www.github.com/EBjerrum) +* [@A-Thakkar](https://www.github.com/A-Thakkar) +* [@benteb](https://www.github.com/benteb) The contributors have limited time for support questions, but please do not hesitate to submit an issue (see above). From 9d3912e15912b2475b48b2ef5d0686b65e143123 Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 05:42:27 +0000 Subject: [PATCH 05/10] Fix typos in README --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59312ae..ce20067 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,9 @@ as interfaces to the algorithm: aizynthapp --config config_local.yml -Consult the documentation [here](https://molecularai.github.io/aizynthfinder/) -for more information. +Consult the documentation [here](https://molecularai.github.io/aizynthfinder/) for more information. -To use tool you need +To use the tool you need 1. A stock file 2. A trained expansion policy network From 951c1e4665163c1982ed59c53e5a9b6e71b429df Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 05:46:03 +0000 Subject: [PATCH 06/10] Update tests workflow poetry install --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a77f6c3..77909f6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh | bash -s -- --batch conda env create -f env-dev.yml - conda run --name aizynth-dev poetry install -E all -E tf + conda run --name aizynth-dev poetry install --all-extras conda run --name aizynth-dev inv full-tests - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 From 69510f413a67d191d6330e86e8f2938493aa9ffe Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 05:48:27 +0000 Subject: [PATCH 07/10] Update tests workflow poetry install --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 77909f6..a77f6c3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh | bash -s -- --batch conda env create -f env-dev.yml - conda run --name aizynth-dev poetry install --all-extras + conda run --name aizynth-dev poetry install -E all -E tf conda run --name aizynth-dev inv full-tests - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 From 4d012550e81eda056d07b2a040eceef037e9c188 Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 12:16:42 +0000 Subject: [PATCH 08/10] Fix Python version --- README.md | 19 +- aizynthfinder/plugins/README.md | 69 ++++++ aizynthfinder/plugins/expansion_strategies.py | 207 ++++++++++++++++++ env-users.yml | 2 +- pyproject.toml | 2 +- 5 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 aizynthfinder/plugins/README.md create mode 100644 aizynthfinder/plugins/expansion_strategies.py diff --git a/README.md b/README.md index ce20067..d539e08 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,23 @@ The tool has been developed on a Linux platform, but the software has been teste ## Installation +### For end-users + +First time, execute the following command in a console or an Anaconda prompt + + conda create "python>=3.8,<3.10" -n aizynth-env + +To install, activate the environment and install the package using pypi + + conda activate aizynth-env + python -m pip install aizynthfinder[all] + +for a smaller package, without all the functionality, you can also type + + python -m pip install aizynthfinder + +### For developers + First clone the repository using Git. Then execute the following commands in the root of the repository @@ -105,7 +122,7 @@ Please use ``black`` package for formatting, and follow ``pep8`` style guide. * [@SGenheden](https://www.github.com/SGenheden) * [@lakshidaa](https://github.com/Lakshidaa) -* Helen Lai +* [@helenlai](https://github.com/helenlai) * [@EBjerrum](https://www.github.com/EBjerrum) * [@A-Thakkar](https://www.github.com/A-Thakkar) * [@benteb](https://www.github.com/benteb) diff --git a/aizynthfinder/plugins/README.md b/aizynthfinder/plugins/README.md new file mode 100644 index 0000000..9fa1889 --- /dev/null +++ b/aizynthfinder/plugins/README.md @@ -0,0 +1,69 @@ +# Plugins + +This folder contains some features for `aizynthfinder` that +does not yet fit into the main codebase. It could be experimental +features, or features that require the user to install some +additional third-party dependencies. + +For the expansion models, you generally need to add the `plugins` folder to the `PYTHONPATH`, e.g. + + export PYTHONPATH=~/aizynthfinder/plugins/ + +where the `aizynthfinder` repository is in the home folder + +## Chemformer expansion model + +An expansion model using a REST API for the Chemformer model +is supplied in the `expansion_strategies` module. + +To use it, you first need to install the `chemformer` package +and launch the REST API service that comes with it. + +To use the expansion model in `aizynthfinder` you can use a config-file +containing these lines + + expansion: + chemformer: + type: expansion_strategies.ChemformerBasedExpansionStrategy + url: http://localhost:8000/chemformer-api/predict + search: + algorithm_config: + immediate_instantiation: [chemformer] + time_limit: 300 + +The `time_limit` is a recommandation for allowing the more expensive expansion model +to finish a sufficient number of retrosynthesis iterations. + +You would have to change `localhost:8000` to the name and port of the machine hosting the REST service. + +You can then use the config-file with either `aizynthcli` or the Jupyter notebook interface. + +## ModelZoo expansion model + +An expansion model using the ModelZoo feature is supplied in the `expansion_strategies` +module. This is an adoption of the code from this repo: `https://github.com/AlanHassen/modelsmatter` that were used in the publications [Models Matter: The Impact of Single-Step Models on Synthesis Prediction](https://arxiv.org/abs/2308.05522) and [Mind the Retrosynthesis Gap: Bridging the divide between Single-step and Multi-step Retrosynthesis Prediction](https://openreview.net/forum?id=LjdtY0hM7tf). + +To use it, you first need to install the `modelsmatter_modelzoo` package from +https://github.com/PTorrenPeraire/modelsmatter_modelzoo and set up the `ssbenchmark` +environment. + +Ensure that the `external_models` sub-package contains the models required. +If it does not, you will need to manually clone the required model repositories +within `external_models`. + +To use the expansion model in `aizynthfinder`, you can specify it in the config-file +under `expansion`. Here is an example setting to use the expansion model with `chemformer` +as the external model: + + expansion: + chemformer: + type: expansion_strategies.ModelZooExpansionStrategy: + module_path: /path_to_folder_containing_cloned_repository/modelsmatter_modelzoo/external_models/modelsmatter_chemformer_hpc/ + use_gpu: False + params: + module_path: /path_to_model_file/chemformer_backward.ckpt + vocab_path: /path_to_vocab_file/bart_vocab_downstream.txt + search: + algorithm_config: + immediate_instantiation: [chemformer] + time_limit: 300 \ No newline at end of file diff --git a/aizynthfinder/plugins/expansion_strategies.py b/aizynthfinder/plugins/expansion_strategies.py new file mode 100644 index 0000000..f5a0ef4 --- /dev/null +++ b/aizynthfinder/plugins/expansion_strategies.py @@ -0,0 +1,207 @@ +""" Module containing classes that implements different expansion policy strategies +""" +from __future__ import annotations + +from typing import TYPE_CHECKING + +import numpy as np +import requests +from requests.exceptions import ConnectionError # pylint: disable=redefined-builtin + +from aizynthfinder.chem import SmilesBasedRetroReaction +from aizynthfinder.context.policy import ExpansionStrategy +from aizynthfinder.utils.math import softmax + +if TYPE_CHECKING: + from aizynthfinder.chem import TreeMolecule + from aizynthfinder.chem.reaction import RetroReaction + from aizynthfinder.context.config import Configuration + from aizynthfinder.utils.type_utils import Dict, List, Sequence, Tuple + +try: + from ssbenchmark.model_zoo import ModelZoo +except ImportError: + HAS_MODELZOO = False +else: + HAS_MODELZOO = True + + +class ChemformerBasedExpansionStrategy(ExpansionStrategy): + """ + A template-free expansion strategy that will return `SmilesBasedRetroReaction` objects upon expansion. + It is based on calls to a REST API to the Chemformer model + + :param key: the key or label + :param config: the configuration of the tree search + :param url: the URL to the REST API + :param ntrials: how many time to try a REST request + """ + + _required_kwargs = ["url"] + + def __init__(self, key: str, config: Configuration, **kwargs: str) -> None: + super().__init__(key, config, **kwargs) + + self._url: str = kwargs["url"] + self._ntrials = kwargs.get("ntrials", 3) + self._cache: Dict[str, Tuple[Sequence[str], Sequence[float]]] = {} + + # pylint: disable=R0914 + def get_actions( + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, + ) -> Tuple[List[RetroReaction], List[float]]: + """ + Get all the probable actions of a set of molecules, using the selected policies and given cutoffs + + :param molecules: the molecules to consider + :param cache_molecules: additional molecules that are sent to + the expansion model but for which predictions are not returned + :return: the actions and the priors of those actions + """ + possible_actions = [] + priors = [] + + cache_molecules = cache_molecules or [] + self._update_cache(molecules + cache_molecules) + + for mol in molecules: + try: + output_smiles, probs = self._cache[mol.inchi_key] + except KeyError: + continue + + priors.extend(probs) + for idx, reactants_str in enumerate(output_smiles): + metadata = {} + metadata["policy_probability"] = float(probs[idx]) + metadata["policy_probability_rank"] = idx + metadata["policy_name"] = self.key + possible_actions.append( + SmilesBasedRetroReaction( + mol, metadata=metadata, reactants_str=reactants_str + ) + ) + return possible_actions, priors # type: ignore + + def reset_cache(self) -> None: + """Reset the prediction cache""" + self._cache = {} + + def _update_cache(self, molecules: Sequence[TreeMolecule]) -> None: + pred_inchis = [] + smiles_list = [] + for molecule in molecules: + if molecule.inchi_key in self._cache or molecule.inchi_key in pred_inchis: + continue + smiles_list.append(molecule.smiles) + pred_inchis.append(molecule.inchi_key) + + if not pred_inchis: + return + + for _ in range(self._ntrials): + try: + ret = requests.post(self._url, json=smiles_list) + except ConnectionError: + continue + if ret.status_code == requests.codes.ok: + break + + if ret.status_code != requests.codes.ok: + self._logger.debug( + f"Failed to retrieve results from Chemformer model: {ret.content}" + ) + return + + predictions = ret.json() + for prediction, inchi in zip(predictions, pred_inchis): + self._cache[inchi] = (prediction["output"], softmax(prediction["lhs"])) + + +class ModelZooExpansionStrategy(ExpansionStrategy): + """ + An expansion strategy that uses a single step model to operate on a Smiles-level + of abstraction + + :param key: the key or label of the single step model + :param config: the configuration of the tree search + :param module_path: the path to the external model + + :raises ImportError: if ssbenchmark has not been installed. + """ + + _required_kwargs = ["module_path"] + + def __init__(self, key: str, config: Configuration, **kwargs: str) -> None: + if not HAS_MODELZOO: + raise ImportError( + "Cannot use this expansion strategy as it seems like " + "ssbenchmark is not installed." + ) + + super().__init__(key, config, **kwargs) + module_path = kwargs["module_path"] + gpu_mode = kwargs.pop("use_gpu", False) + model_params = dict(kwargs.pop("params", {})) + + self.model_zoo = ModelZoo(key, module_path, gpu_mode, model_params) + self._cache: Dict[str, Tuple[Sequence[str], Sequence[float]]] = {} + + def get_actions( + self, + molecules: Sequence[TreeMolecule], + cache_molecules: Sequence[TreeMolecule] = None, + ) -> Tuple[List[RetroReaction], List[float]]: + """ + Get all the probable actions of a set of molecules, using the selected policies + and given cutoffs. + + :param molecules: the molecules to consider + :param cache_molecules: additional molecules that are sent to the expansion + model but for which predictions are not returned + + :return: the actions and the priors of those actions + """ + possible_actions = [] + priors = [] + cache_molecules = cache_molecules or [] + self._update_cache(molecules + cache_molecules) + + for mol in molecules: + output_smiles, probs = self._cache[mol.inchi_key] + priors.extend(probs) + + for idx, move in enumerate(output_smiles): + metadata = {} + metadata["reaction"] = move + metadata["policy_probability"] = float(probs[idx].round(4)) + metadata["policy_probability_rank"] = idx + metadata["policy_name"] = self.key + + possible_actions.append( + SmilesBasedRetroReaction(mol, reactants_str=move, metadata=metadata) + ) + + return possible_actions, priors + + def _update_cache(self, molecules: Sequence[TreeMolecule]) -> None: + pred_inchis = [] + smiles_list = [] + + for molecule in molecules: + if molecule.inchi_key in self._cache or molecule.inchi_key in pred_inchis: + continue + smiles_list.append(molecule.smiles) + pred_inchis.append(molecule.inchi_key) + + if not pred_inchis: + return + + pred_reactants, pred_priors = ( + np.array(item) for item in self.model_zoo.model_call(smiles_list) + ) + + for reactants, priors, inchi in zip(pred_reactants, pred_priors, pred_inchis): + self._cache[inchi] = (reactants, priors) diff --git a/env-users.yml b/env-users.yml index a69f86d..66cc98e 100644 --- a/env-users.yml +++ b/env-users.yml @@ -7,4 +7,4 @@ dependencies: - git - pip>=20.0 - pip: - - git+ssh://git@bitbucket.astrazeneca.net:7999/com/aizynthfinder.git \ No newline at end of file + - https://github.com/MolecularAI/aizynthfinder/archive/v3.7.0.tar.gz \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f76ca3f..fbc421d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ min-public-methods = 0 disable = "W3101, R0022, W1201, W1203, R0401, W0707, W0221, W0603, R0801, R1735, W1514, C0209, W0237, R1732, W0602, R0914, typecheck" [tool.poetry.dependencies] -python = ">=3.8,<3.10" +python = ">=3.9,<3.11" ipywidgets = "^7.5.1" jinja2 = "^3.0.0" jupyter = "^1.0.0" From 801c55d60a0d58a8d26252b675d14e1976a80a4f Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 14:35:37 +0000 Subject: [PATCH 09/10] Restructure plugins module --- {aizynthfinder/plugins => plugins}/README.md | 0 {aizynthfinder/plugins => plugins}/expansion_strategies.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {aizynthfinder/plugins => plugins}/README.md (100%) rename {aizynthfinder/plugins => plugins}/expansion_strategies.py (100%) diff --git a/aizynthfinder/plugins/README.md b/plugins/README.md similarity index 100% rename from aizynthfinder/plugins/README.md rename to plugins/README.md diff --git a/aizynthfinder/plugins/expansion_strategies.py b/plugins/expansion_strategies.py similarity index 100% rename from aizynthfinder/plugins/expansion_strategies.py rename to plugins/expansion_strategies.py From 6e9e809c99dfd08ffe2db6bc1db51f36b1a93456 Mon Sep 17 00:00:00 2001 From: "Saigiridharan, Lakshidaa" Date: Tue, 5 Dec 2023 14:58:37 +0000 Subject: [PATCH 10/10] Fix max_transforms in mcts --- aizynthfinder/search/mcts/state.py | 2 +- tests/test_finder.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aizynthfinder/search/mcts/state.py b/aizynthfinder/search/mcts/state.py index 162ec7e..89e8e34 100644 --- a/aizynthfinder/search/mcts/state.py +++ b/aizynthfinder/search/mcts/state.py @@ -51,7 +51,7 @@ def __init__(self, mols: Sequence[TreeMolecule], config: Configuration) -> None: self.is_solved = all(self.in_stock_list) self.max_transforms = max(mol.transform for mol in self.mols) self.is_terminal = ( - self.max_transforms > config.search.max_transforms + self.max_transforms >= config.search.max_transforms ) or self.is_solved inchis = [mol.inchi_key for mol in self.mols] diff --git a/tests/test_finder.py b/tests/test_finder.py index 9089c9a..f020f4f 100644 --- a/tests/test_finder.py +++ b/tests/test_finder.py @@ -227,7 +227,7 @@ def test_three_expansions_not_solved(setup_aizynthfinder): } finder = setup_aizynthfinder(lookup, [child1_smi[0], child1_smi[2], child2_smi[0]]) finder.config.search.return_first = True - finder.config.search.max_transforms = 2 + finder.config.search.max_transforms = 3 finder.config.search.iteration_limit = 15 finder.tree_search() @@ -569,7 +569,7 @@ def test_two_expansions_prune_cyclic(setup_aizynthfinder): finder.tree_search() nodes = list(finder.tree.graph()) - assert len(nodes) == 8 + assert len(nodes) == 7 assert state_smiles(nodes[0].state) == [root_smi] assert state_smiles(nodes[1].state) == child1_smi assert state_smiles(nodes[2].state) == [root_smi]