diff --git a/.cspell.json b/.cspell.json index a7915f0..f0eb92a 100644 --- a/.cspell.json +++ b/.cspell.json @@ -23,10 +23,12 @@ "Modelica", "MODELICAPATH", "mofile", + "mpignore", "nllong", "openstudio", "Optimica", "oversizing", + "pathspec", "pygments", "redeclarations", "Reparse", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50c3b21..2f1d93b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.9", "3.11"] + python-version: ["3.9", "3.12"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index da038c2..a461241 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ exclude: | repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: check-added-large-files diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9c032b5..ce96840 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,19 @@ Changelog ========= +Version 0.5.0 +============= + +## What's Changed +* Support py312 by @vtnate in https://github.com/urbanopt/modelica-builder/pull/73 +* Add method to scale loads in an MOS file by @nllong in https://github.com/urbanopt/modelica-builder/pull/74 +* Bump version of antlr runtime to 4.13.1 by @nllong in https://github.com/urbanopt/modelica-builder/pull/75 +* Add `.mpignore` to skip loading files in ModelicaProject by @nllong in https://github.com/urbanopt/modelica-builder/pull/77 +* Upgrade to MBLv10 by @vtnate in https://github.com/urbanopt/modelica-builder/pull/72 +* Update copyright dates by @nllong in https://github.com/urbanopt/modelica-builder/pull/80 + +**Full Changelog**: https://github.com/urbanopt/modelica-builder/compare/v0.4.0...v0.5.0 + Version 0.4.0 ============= diff --git a/LICENSE.txt b/LICENSE.txt index 19341d8..12c7f47 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,29 +1,26 @@ -Copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. +Copyright (c) 2020, 2024, Alliance for Sustainable Energy, LLC. All rights reserved. BSD 3-Clause License -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +(1) Redistributions of source code must retain the above copyright notice, this list of conditions +and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions +and the following disclaimer in the documentation and/or other materials provided with the +distribution. -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. +(3) Neither the name of the copyright holder nor the names of its contributors may be used to endorse +or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/conf.py b/docs/conf.py index a300db8..5ffd534 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -90,7 +90,7 @@ # General information about the project. project = u'modelica-builder' -copyright = u'2023, Nicholas Long' +copyright = u'2024, Alliance for Sustainable Energy, LLC' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/modelica_builder/builder.py b/modelica_builder/builder.py index 9daa752..f31d953 100644 --- a/modelica_builder/builder.py +++ b/modelica_builder/builder.py @@ -1,10 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" - +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md from modelica_builder import config from modelica_builder.edit import Edit diff --git a/modelica_builder/config.py b/modelica_builder/config.py index 10bc1bb..09a37ef 100644 --- a/modelica_builder/config.py +++ b/modelica_builder/config.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # global config variables # If true, then each inserted component/annotation argument will be indented on a new line diff --git a/modelica_builder/edit.py b/modelica_builder/edit.py index a63a5ff..7d2be1f 100644 --- a/modelica_builder/edit.py +++ b/modelica_builder/edit.py @@ -1,10 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" - +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md from modelica_builder import modelica_parser diff --git a/modelica_builder/model.py b/modelica_builder/model.py index eb4c663..236ca78 100644 --- a/modelica_builder/model.py +++ b/modelica_builder/model.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md import logging import os diff --git a/modelica_builder/modelica_mos_file.py b/modelica_builder/modelica_mos_file.py index e920d15..ade6288 100644 --- a/modelica_builder/modelica_mos_file.py +++ b/modelica_builder/modelica_mos_file.py @@ -1,27 +1,35 @@ # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +import copy +import logging import re from pathlib import Path from typing import Any, Union +logger = logging.getLogger(__name__) + class ModelicaMOS(object): - def __init__(self, filename: str, data: str = None): + def __init__(self, filename: str, header_data: str = None, data_definition: str = None): """Read in a .mos file if it exists into a data object The format is CSV with additional header info, so for - now read the data as a string. + now read the data as a string and then convert the timeseries + data as floats. Args: filename (str): Name of the file to import, typically a full path + header_data (str, optional): header information as a string. Defaults to None. + data_definition (str, optional): The type of data without the dimension, e.g., double tab1. Defaults to None. Raises: FileNotFoundError: File does not exist Exception: The file extension needs to be MOS """ - # allow reading in the data directly for testing purposes, for the + # allow reading in the header_data directly for testing purposes, for the # most part. - if not data: + self.data = [] + if not header_data: if Path(filename).exists(): self.filename = Path(filename) else: @@ -30,9 +38,27 @@ def __init__(self, filename: str, data: str = None): if self.filename.suffix.lower() != ".mos": raise Exception(f"{filename} is not a .mos file") - self.data = self.filename.read_text() + self.header_data = "" + self.data_definition = "" + # read the first n-rows until the data are not prepended with a # or is blank + for line in self.filename.open(): + if line.startswith('#') or line.strip() == '': + self.header_data += line + else: + # if the line has a ; then it is data + if ';' not in line: + # strip out the dimensions, because we will put + # those in based on the size of data later. + self.data_definition = line.rstrip().split('(')[0] + else: + self.data.append(line.rstrip().split(';')) + + # convert the data types to have first column be int and the remaining float + for row, column in enumerate(self.data): + self.data[row] = [int(column[0])] + [float(x) for x in column[1:]] else: - self.data = data + self.header_data = header_data + self.data_definition = "double tab1" def retrieve_header_variable_value(self, key: str, cast_type: type = str) -> Any: """Retrieve a value from a variable in the header @@ -46,7 +72,7 @@ def retrieve_header_variable_value(self, key: str, cast_type: type = str) -> Any """ # check if the peak water heating load is zero, otherwise just skip key_re = rf'#(\s?{key}\s?)=\s?(-?\b\d[\d,.]*\b)(.*\s)' - match = re.search(key_re, self.data) + match = re.search(key_re, self.header_data) if match: # the first group is the variable name, the second is the value value = match.group(2).strip() @@ -77,23 +103,97 @@ def replace_header_variable_value(self, key: str, new_value: Any) -> bool: key_re = rf'#(\s?{key}\s?)=\s?(-?\b\d[\d,.]*\b)(.*\s)' # verify that group3 exists, otherwise the key doesn't exist - match = re.search(key_re, self.data) + match = re.search(key_re, self.header_data) if match: if match.group(3): # if there are units, then put the unit back in - self.data = re.sub(key_re, '#' + r'\g<1>' + f"= {new_value}" + r'\g<3>', self.data) + self.header_data = re.sub(key_re, '#' + r'\g<1>' + f"= {new_value}" + r'\g<3>', self.header_data) else: # no g3, therefore, just replace the var and value. - self.data = re.sub(key_re, '#' + r'\g<1>' + f"= {new_value}", self.data) + self.header_data = re.sub(key_re, '#' + r'\g<1>' + f"= {new_value}", self.header_data) # replace the value, this requires recreating the variable and value - self.data = re.sub(key_re, '#' + r'\g<1>' + f"= {new_value}" + r'\g<3>', self.data) + self.header_data = re.sub(key_re, '#' + r'\g<1>' + f"= {new_value}" + r'\g<3>', self.header_data) + return True + + def scale_loads(self, scale_factors: list, load_type: Union[str, int, list[int]] = "all") -> bool: + """Scale the loads by a factor. The scale factors must look like the following: + [ + {'start_time': Timestamp('2021-01-01 00:00:00'), 'end_time': Timestamp('2021-01-04 23:59:59'), 'scaling_factor': 0.72}, + {'start_time': Timestamp('2021-05-01 00:00:00'), 'end_time': Timestamp('2021-01-10 23:59:59'), 'scaling_factor': 1.50}, + ... + ] + + This method can be used to scale the loads for a time period in an attempt to match + existing data from another source. For example, if we know the total loads per day, then + you can scale the loads to meet the total load. + + Args: + scale_factors (list): A list of dictionaries with start, end, and value to scale. + + load_type (str, optional): Type of load to scale. Defaults to "all", but can be "heating", + "cooling", "water_heating", or "all". + + Returns: + bool: Always True + """ + # skip if data is empty + if not self.data: + raise Exception("No data to scale") + + # if passing a string, then convert to the index in the same + # format as the load_type version. + if isinstance(load_type, str): + # column name mappers + column_mapper = { + "cooling": [1], + "heating": [2], + "water_heating": [3], + "all": [1, 2, 3] + } + elif isinstance(load_type, int): + column_mapper = { + "custom": [load_type], + } + load_type = 'custom' + elif isinstance(load_type, list): + column_mapper = { + "custom": load_type, + } + load_type = 'custom' + + # create a copy to operate on + scale_factor = copy.deepcopy(scale_factors) + # convert the start_time and end_time to seconds from the beginning of the year + first_time_stamp = scale_factor[0]["start_time"] + for scale_factor in scale_factors: + scale_factor["start_time_seconds"] = (scale_factor["start_time"] - first_time_stamp).total_seconds() + scale_factor["end_time_seconds"] = (scale_factor["end_time"] - first_time_stamp).total_seconds() + + logger.debug(scale_factors) + + # convert the scale_factor datetime to a seconds value + for column_index in column_mapper[load_type]: + # multiple each row's column by the scale factor + for row, column in enumerate(self.data): + # get the scaling factor based on the time (inclusive on both sides) + for scale_factor in scale_factors: + if scale_factor["start_time_seconds"] <= column[0] <= scale_factor["end_time_seconds"]: + column[column_index] = column[column_index] * scale_factor["scaling_factor"] + self.data[row] = column + return True def save(self): """Save the file back to disk""" - self.filename.write_text(self.data) + self.save_as(self.filename) def save_as(self, filename: Union[str, Path]): """Save the file to a new filename""" - Path(filename).write_text(self.data) + # reconstruct the file data + data_definition = self.data_definition + f"({len(self.data)},{len(self.data[0])})" + write_data = self.header_data + data_definition + '\n' + for row in self.data: + # join the row with a ; and convert each element to a string + write_data += ';'.join([str(x) for x in row]) + '\n' + Path(filename).write_text(write_data) diff --git a/modelica_builder/modelica_parser/README.rst b/modelica_builder/modelica_parser/README.rst index 111506c..f69ebfa 100644 --- a/modelica_builder/modelica_parser/README.rst +++ b/modelica_builder/modelica_parser/README.rst @@ -1 +1,4 @@ These files are automatically generated using Antlr. Do not manipulate directly. + +However, the modelica.g4 file has been updated to support functionality that is not yet supported by the community-provided Modelica grammar. Make sure to conduct substantial +testing if modifying the modelica.g4 file. diff --git a/modelica_builder/modelica_parser/utils.py b/modelica_builder/modelica_parser/utils.py index 9a11588..0a2505d 100644 --- a/modelica_builder/modelica_parser/utils.py +++ b/modelica_builder/modelica_parser/utils.py @@ -1,9 +1,6 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + import sys diff --git a/modelica_builder/modelica_project.py b/modelica_builder/modelica_project.py index 67a59fd..88f799e 100644 --- a/modelica_builder/modelica_project.py +++ b/modelica_builder/modelica_project.py @@ -1,11 +1,9 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + import logging import os +import pathspec import time from pathlib import Path from typing import Union @@ -86,9 +84,15 @@ def __init__(self, package_file): self.root_directory = Path(package_file).parent self.file_types = ['.mo', '.txt', '.mos', '.order', ] self.file_types_to_skip = ['.log', '.mat', ] + # skip some specific files that software may create that are not needed to be # sent around with the modelica project. - self.file_names_to_skip = ['analysis_variables.csv', 'analysis_name.txt', '.DS_Store', ] + self.file_names_to_skip = ['.DS_Store', '.mpignore'] + + # Keep track of the files that have been ignored. + self.mpignore_files = [] + + # object to store all the files in the package self.file_data = {} self._load_data() @@ -96,7 +100,25 @@ def __init__(self, package_file): def _load_data(self) -> None: """method to load all of the files into a data structure for processing""" # walk the tree and add in all the files + + # Try to find a .mpignore file in the directory with the package.mo. + # Eventually we should support searching up the tree. + project_ignore_file = self.root_directory / '.mpignore' + if project_ignore_file.exists(): + patterns = [] + with open(project_ignore_file) as f: + patterns = f.read().splitlines() + spec = pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, patterns) + else: + spec = None + for file_path in self.root_directory.rglob('*'): + # if there is a spec, check if the file is in the spec and ignore if matches + if spec: + if spec.match_file(str(file_path.relative_to(self.root_directory))): + self.mpignore_files.append(file_path) + continue + if file_path.suffix in self.file_types_to_skip and file_path.is_file(): # skip files that have the file_types_to_skip suffix continue @@ -113,16 +135,19 @@ def _load_data(self) -> None: # this is a directory, add in an empty ModelicaFileObject # to keep track of the directory. # - # however, we ignore if there is a tmp directory or the parent dir is - # tmp. Maybe we need to support more than 2 levels here. + # We ignore if there is a tmp directory and display only the + # first time the tmp shows up in the tree walking. if 'tmp' in file_path.parts: - _log.warning(f"Found a tmp directory, skipping {file_path}") + if file_path.parts[-1] == 'tmp': + _log.warning(f"Found a tmp directory, skipping {file_path}") + + # always continue continue rel_path = file_path.relative_to(self.root_directory) self.file_data[str(rel_path)] = ModelicaFileObject(file_path) else: - print(f"Unknown file {file_path}") + print(f"Unknown file {file_path}, these can be ignored by creating a .mpignore file in the project root") # now sort the file_data by the keys self.file_data = {key: self.file_data[key] for key in sorted(self.file_data)} diff --git a/modelica_builder/package_parser.py b/modelica_builder/package_parser.py index 6aa4e3c..ddf371d 100644 --- a/modelica_builder/package_parser.py +++ b/modelica_builder/package_parser.py @@ -77,26 +77,34 @@ def parse_within_statement(self) -> Optional[List[str]]: return self.within @classmethod - def new_from_template(cls, path: Union[str, Path], name: str, order: list[str], within: Union[str, None] = None) -> "PackageParser": - """Create new package data based on the package.mo template. If within is not specified, then it is + def new_from_template(cls, + path: Union[str, Path], + name: str, + order: list[str], + mbl_version: Union[str, None] = None, + within: Union[str, None] = None + ) -> "PackageParser": + """Create new package data based on the package.mo template. If 'within' is not specified, then it is assumed that this is a top level package and will load from the package_base template. Args: path (str): the path where the resulting package file and order will be saved to. name (str): the name of the model order (list[str]): ordered list of which models will be loaded (saved to package.order) - within (str, optional): name where this package is within.. Defaults to None. + mbl_version (str, optional): the version of the model buildings library (only used in package_base.mot) + within (str, optional): name where this package is within. Defaults to None. + Returns: PackageParser: object of the package parser """ klass = PackageParser(path) - if within: + if not mbl_version: template = klass.template_env.get_template("package.mot") else: template = klass.template_env.get_template("package_base.mot") - klass.package_data = template.render(within=within, name=name, order=order) + klass.package_data = template.render(within=within, name=name, order=order, mbl_version=mbl_version) klass.order_data = "\n".join(order) klass.package_name = name klass.parse_within_statement() diff --git a/modelica_builder/selector.py b/modelica_builder/selector.py index 948fa2c..bfce3f6 100644 --- a/modelica_builder/selector.py +++ b/modelica_builder/selector.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md import re diff --git a/modelica_builder/templates/package_base.mot b/modelica_builder/templates/package_base.mot index b967bfa..e0bf2b8 100644 --- a/modelica_builder/templates/package_base.mot +++ b/modelica_builder/templates/package_base.mot @@ -2,5 +2,5 @@ package {{name}} extends Modelica.Icons.Package; annotation (uses( - Modelica(version="4.0.0"), Buildings(version="9.1.0")), version="1"); + Modelica(version="4.0.0"), Buildings(version="{{mbl_version}}")), version="1"); end {{name}}; diff --git a/modelica_builder/transformation.py b/modelica_builder/transformation.py index 78fc743..8b65790 100644 --- a/modelica_builder/transformation.py +++ b/modelica_builder/transformation.py @@ -1,10 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" - +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md import logging from antlr4.xpath import XPath diff --git a/modelica_builder/transformer.py b/modelica_builder/transformer.py index 66e3c10..8f6a48e 100644 --- a/modelica_builder/transformer.py +++ b/modelica_builder/transformer.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md from modelica_builder.edit import Edit diff --git a/poetry.lock b/poetry.lock index 6412822..5fdad3b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -13,13 +13,13 @@ files = [ [[package]] name = "antlr4-python3-runtime" -version = "4.13.0" -description = "ANTLR 4.13.0 runtime for Python 3" +version = "4.13.1" +description = "ANTLR 4.13.1 runtime for Python 3" optional = false python-versions = "*" files = [ - {file = "antlr4-python3-runtime-4.13.0.tar.gz", hash = "sha256:0d5454928ae40c8a6b653caa35046cd8492c8743b5fbc22ff4009099d074c7ae"}, - {file = "antlr4_python3_runtime-4.13.0-py3-none-any.whl", hash = "sha256:53e6e208cf4a1ad53fb8b1b4467b756375a4f827331e290618aedcf481cb1d5c"}, + {file = "antlr4-python3-runtime-4.13.1.tar.gz", hash = "sha256:3cd282f5ea7cfb841537fe01f143350fdb1c0b1ce7981443a2fa8513fddb6d1a"}, + {file = "antlr4_python3_runtime-4.13.1-py3-none-any.whl", hash = "sha256:78ec57aad12c97ac039ca27403ad61cb98aaec8a3f9bb8144f889aa0fa28b943"}, ] [[package]] @@ -39,13 +39,13 @@ tomli = {version = "*", markers = "python_version < \"3.11\""} [[package]] name = "babel" -version = "2.13.0" +version = "2.14.0" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, - {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] [package.extras] @@ -53,13 +53,13 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] [[package]] @@ -75,101 +75,101 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, - {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, + {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]] @@ -269,13 +269,13 @@ yaml = ["PyYAML (>=3.10)"] [[package]] name = "distlib" -version = "0.3.7" +version = "0.3.8" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] [[package]] @@ -301,13 +301,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -315,29 +315,29 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.12.4" +version = "3.13.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.12.4-py3-none-any.whl", hash = "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4"}, - {file = "filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd"}, + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-timeout (>=2.1)"] -typing = ["typing-extensions (>=4.7.1)"] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] [[package]] name = "identify" -version = "2.5.30" +version = "2.5.33" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.30-py2.py3-none-any.whl", hash = "sha256:afe67f26ae29bab007ec21b03d4114f41316ab9dd15aa8736a167481e108da54"}, - {file = "identify-2.5.30.tar.gz", hash = "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d"}, + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, ] [package.extras] @@ -345,13 +345,13 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] @@ -367,20 +367,20 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.8.0" +version = "7.0.1" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] 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"] @@ -563,15 +563,26 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + [[package]] name = "platformdirs" -version = "3.11.0" +version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, - {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] [package.extras] @@ -624,38 +635,39 @@ files = [ [[package]] name = "pycodestyle" -version = "2.11.0" +version = "2.11.1" description = "Python style guide checker" optional = false python-versions = ">=3.8" files = [ - {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, - {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, + {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, + {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, ] [[package]] name = "pygments" -version = "2.16.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {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 = "pytest" -version = "7.4.2" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, - {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -779,17 +791,17 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "68.2.2" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, - {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +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"] @@ -1030,47 +1042,46 @@ files = [ [[package]] name = "typing-extensions" -version = "4.8.0" +version = "4.9.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, ] [[package]] name = "urllib3" -version = "2.0.6" +version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"}, - {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"}, + {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)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.24.5" +version = "20.25.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"}, - {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"}, + {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, + {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" +platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] @@ -1093,5 +1104,5 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" -python-versions = ">=3.9, <3.12" -content-hash = "92b504d9c474e747e0d9471a733f94af9b4ad9a30a4c86258403f334ffaf4088" +python-versions = ">=3.9, <3.13" +content-hash = "a7f3ad1e8596d6e75f349f86d5e6576977f84121f7f30941b2e8a44a5441b606" diff --git a/pyproject.toml b/pyproject.toml index ab79c12..a3a86dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [tool.poetry] name = "modelica-builder" -version = "0.4.0" +version = "0.5.0" description = "Modelica builder enables programmatic parsing and modification of Modelica files." -authors = ["Nicholas Long "] +authors = ["Nicholas Long ", "Nathan Moore "] license = "BSD-3-Clause" readme = "README.rst" @@ -22,13 +22,15 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] [tool.poetry.dependencies] # Urbanopt SDK requires Python 3.10 as of UOv0.9.0 -python = ">=3.9, <3.12" -antlr4-python3-runtime = "4.13" +python = ">=3.9, <3.13" +antlr4-python3-runtime = "4.13.1" jinja2 = "3.1.2" +pathspec = "^0.11.2" [tool.poetry.dev-dependencies] autopep8 = "~2.0" @@ -49,5 +51,9 @@ toml = "~0.10" requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" +[tool.pytest.ini_options] +log_cli = true +log_cli_level = "DEBUG" + [tool.isort] multi_line_output = 3 diff --git a/setup.py b/setup.py index 088a405..0c50453 100755 --- a/setup.py +++ b/setup.py @@ -1,91 +1,12 @@ +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # -*- coding: utf-8 -*- + """ Setup file for modelica_builder. Use setup.cfg to configure your project. """ -from pkg_resources import VersionConflict, require from setuptools import setup -import distutils.cmd -import distutils.log -import glob -import os -import re -import sys - -PYTHON_REGEX = re.compile(r'^""".\*{100}.*:copyright.*\*{100}."""$', re.MULTILINE | re.DOTALL) -PYTHON_LICENSE = '''""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -"""''' - -EXCLUDE_FILES = ["__init__.py", "modelicaLexer.py", "modelicaListener.py", "modelicaParser.py"] -PATHS = [ - {"glob": "modelica_builder/**/*.py", "license": PYTHON_LICENSE, "REGEX": PYTHON_REGEX, }, - {"glob": "tests/**/*.py", "license": PYTHON_LICENSE, "REGEX": PYTHON_REGEX}, - # single files - # { "glob": 'bin/resources/**/file.py', "license": PYTHON_LICENSE, "REGEX": PYTHON_REGEX }, -] - - -class UpdateLicenses(distutils.cmd.Command): - """Custom command for updating the license doc strings.""" - - description = "Update the license/copyright headers" - - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def check_and_update_license(self, filename): - """ - check if the license exists in the file, and if it does, then make sure it is up-to-date with - the license defined in this file. - - :param filename: str, path of the file to update - :return: None - """ - s = open(filename, "r").read() - if PYTHON_REGEX.search(s): - print("License already exists, updating") - content = re.sub(PYTHON_REGEX, PYTHON_LICENSE, s) - with open(filename, "w") as f: - f.write(content) - f.close() - else: - print("Adding license") - with open(filename, "r+") as f: - content = f.read() - f.seek(0, 0) - f.write(PYTHON_LICENSE.rstrip("\r\n") + "\n\n\n" + content) - f.close() - - def run(self): - for p in PATHS: - gl = glob.glob(p["glob"], recursive=True) - for g in gl: - print(os.path.basename(g)) - if os.path.basename(g) in EXCLUDE_FILES: - print(f"Skipping file {g}") - else: - print(f"Checking license in file {g}") - self.check_and_update_license(g) - - -try: - require('setuptools>=38.3') -except VersionConflict: - print("Error: version of setuptools is too old (<38.3)!") - sys.exit(1) - - if __name__ == "__main__": - setup( - cmdclass={"update_licenses": UpdateLicenses}, - ) + setup() diff --git a/tests/conftest.py b/tests/conftest.py index 9cbb5eb..a890b59 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # -*- coding: utf-8 -*- diff --git a/tests/data/B2_no_water_load.mos b/tests/data/B2_no_water_load.mos index 213648c..49d4413 100644 --- a/tests/data/B2_no_water_load.mos +++ b/tests/data/B2_no_water_load.mos @@ -15,11 +15,11 @@ #Peak space heating load = 38986.3 Watts #Peak water heating load = 0 Watts double tab1(8760,4) -3600;0;0;0.0 -7200;0;0;0.0 -10800;0;0;0.0 -14400;0;0;0.0 -18000;0;16240.4;0.0 -21600;0;13281.1;0.0 -25200;0;9459.4;0.0 -28800;-1793.3;0;0.0 +3600;-100;200;0.0 +7200;-100;200;0.0 +10800;-100;200;0.0 +14400;-100;200;0.0 +18000;-100;200;0.0 +21600;-100;200;0.0 +25200;-100;200;0.0 +28800;-100;200;0.0 diff --git a/tests/data/packages/teaser_single/Districts/unneeded.csv b/tests/data/packages/teaser_single/Districts/unneeded.csv new file mode 100644 index 0000000..9f54893 --- /dev/null +++ b/tests/data/packages/teaser_single/Districts/unneeded.csv @@ -0,0 +1 @@ +# another file to make sure gets filtered out diff --git a/tests/data/packages/teaser_single/package.mo b/tests/data/packages/teaser_single/package.mo index b994622..719cdfd 100644 --- a/tests/data/packages/teaser_single/package.mo +++ b/tests/data/packages/teaser_single/package.mo @@ -2,5 +2,5 @@ package teaser_single extends Modelica.Icons.Package; annotation (uses( - Modelica(version="4.0.0"), Buildings(version="9.1.0")), version="1"); + Modelica(version="4.0.0"), Buildings(version="10.0.0")), version="1"); end teaser_single; diff --git a/tests/data/packages/teaser_single/results.csv b/tests/data/packages/teaser_single/results.csv new file mode 100644 index 0000000..304f58f --- /dev/null +++ b/tests/data/packages/teaser_single/results.csv @@ -0,0 +1 @@ +# file to ensure pathspec filters this out diff --git a/tests/test_benchmarks.py b/tests/test_benchmarks.py index b755918..0bf7af2 100644 --- a/tests/test_benchmarks.py +++ b/tests/test_benchmarks.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # -*- coding: utf-8 -*- diff --git a/tests/test_builder.py b/tests/test_builder.py index 6d7c5c8..35ac202 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # -*- coding: utf-8 -*- diff --git a/tests/test_edit.py b/tests/test_edit.py index 6457fec..d573ccb 100644 --- a/tests/test_edit.py +++ b/tests/test_edit.py @@ -1,10 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" - +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # -*- coding: utf-8 -*- diff --git a/tests/test_model.py b/tests/test_model.py index 65f8c6c..61832bd 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,9 +1,6 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + import os import tempfile diff --git a/tests/test_modelica_mos.py b/tests/test_modelica_mos.py index f1e0a42..fcbdd90 100644 --- a/tests/test_modelica_mos.py +++ b/tests/test_modelica_mos.py @@ -1,10 +1,14 @@ # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +import logging import os import unittest +from datetime import datetime from pathlib import Path +_log = logging.getLogger(__name__) + from modelica_builder.modelica_mos_file import ModelicaMOS @@ -21,7 +25,7 @@ def test_variable_retrieval_basic(self): #Var2 = 1 Watts #Var3 = 2 """ - file = ModelicaMOS('not_a_real_file.mos', data=data) + file = ModelicaMOS('not_a_real_file.mos', header_data=data) self.assertEqual(file.retrieve_header_variable_value('Var1', cast_type=int), 0) self.assertEqual(file.retrieve_header_variable_value('Var2'), '1') self.assertEqual(file.retrieve_header_variable_value('Var3'), '2') @@ -34,7 +38,7 @@ def test_variable_retrieval_floats(self): # Var3 = 1,245 Watts with space # Var 4 = 1,245 Watts """ - file = ModelicaMOS('not_a_real_file.mos', data=data) + file = ModelicaMOS('not_a_real_file.mos', header_data=data) self.assertEqual(file.retrieve_header_variable_value('Var1', cast_type=float), 1245.25) self.assertEqual(file.retrieve_header_variable_value('Var2', cast_type=float), 1245) self.assertEqual(file.retrieve_header_variable_value('Var3', cast_type=float), 1245) @@ -45,14 +49,14 @@ def test_variable_retrieval_negatives(self): data = """ #Var1 = -1,245.25 Watts """ - file = ModelicaMOS('not_a_real_file.mos', data=data) + file = ModelicaMOS('not_a_real_file.mos', header_data=data) self.assertEqual(file.retrieve_header_variable_value('Var1', cast_type=float), -1245.25) def test_variable_retrieval_not_found(self): data = """ #Var1 = 1234 Watts """ - file = ModelicaMOS('not_a_real_file.mos', data=data) + file = ModelicaMOS('not_a_real_file.mos', header_data=data) self.assertEqual(file.retrieve_header_variable_value('Var2', cast_type=float), None) def test_replace_variable_value(self): @@ -62,7 +66,7 @@ def test_replace_variable_value(self): #Var3=2 #Var4 = -3 """ - file = ModelicaMOS('not_a_real_file.mos', data=data) + file = ModelicaMOS('not_a_real_file.mos', header_data=data) self.assertEqual(file.retrieve_header_variable_value('Var1', cast_type=float), 0) file.replace_header_variable_value('Var1', 1234) file.replace_header_variable_value('Var2', 2345) @@ -76,7 +80,6 @@ def test_replace_variable_value(self): self.assertEqual(file.retrieve_header_variable_value('Var4', cast_type=float), -1234) def test_read_write_with_replace(self): - file = ModelicaMOS(self.data_dir / 'B2_no_water_load.mos') self.assertEqual(file.retrieve_header_variable_value('Peak water heating load', cast_type=float), 0) file.replace_header_variable_value('Peak water heating load', 5124) @@ -92,3 +95,95 @@ def test_read_write_with_replace(self): # just call the save method for 'crash' check new_file.save() + + def test_scaling_loads(self): + scaling_factors = [ + # y m d h m s + {'start_time': datetime(2021, 1, 1, 0, 0, 0), 'end_time': datetime(2021, 1, 1, 3, 0, 0), 'scaling_factor': 0.25}, # noqa + {'start_time': datetime(2021, 1, 1, 4, 0, 0), 'end_time': datetime(2021, 12, 31, 23, 59, 59), 'scaling_factor': 1} + ] + file = ModelicaMOS(self.data_dir / 'B2_no_water_load.mos') + file.scale_loads(scaling_factors) + + # save to a new file to compare + file.save_as(self.output_dir / 'B2_no_water_load_scaled.mos') + # read in the new file and check the value + self.assertTrue((self.output_dir / 'B2_no_water_load_scaled.mos').exists()) + new_mos = ModelicaMOS(self.output_dir / 'B2_no_water_load_scaled.mos') + + # to find these values, you must manually look at the original file and then the scaling factor and make + # sure that the values match. + _log.debug(new_mos.data) + self.assertEqual(new_mos.data[0][0], 3600) + self.assertEqual(new_mos.data[0][1], -25) + self.assertEqual(new_mos.data[0][2], 50) + + # second >= 14400 should not be scaled, which is in row 3 (0-based) + self.assertEqual(new_mos.data[3][0], 14400) + self.assertEqual(new_mos.data[3][1], -100) + self.assertEqual(new_mos.data[3][2], 200) + + def test_scaling_loads_single_named_column(self): + scaling_factors = [ + # y m d h m s + {'start_time': datetime(2021, 1, 1, 0, 0, 0), 'end_time': datetime(2021, 1, 1, 3, 0, 0), 'scaling_factor': 0.25}, # noqa + {'start_time': datetime(2021, 1, 1, 4, 0, 0), 'end_time': datetime(2021, 12, 31, 23, 59, 59), 'scaling_factor': 1} + ] + file = ModelicaMOS(self.data_dir / 'B2_no_water_load.mos') + file.scale_loads(scaling_factors, 'heating') + + # save to a new file to compare + file.save_as(self.output_dir / 'B2_no_water_load_scaled_single_named_column.mos') + # read in the new file and check the value + self.assertTrue((self.output_dir / 'B2_no_water_load_scaled_single_named_column.mos').exists()) + new_mos = ModelicaMOS(self.output_dir / 'B2_no_water_load_scaled_single_named_column.mos') + + # to find these values, you must manually look at the original file and then the scaling factor and make + # sure that the values match. + _log.debug(new_mos.data) + self.assertEqual(new_mos.data[0][0], 3600) + self.assertEqual(new_mos.data[0][1], -100) + self.assertEqual(new_mos.data[0][2], 50) + + # second >= 14400 should not be scaled, which is in row 3 (0-based) + self.assertEqual(new_mos.data[3][0], 14400) + self.assertEqual(new_mos.data[3][1], -100) + self.assertEqual(new_mos.data[3][2], 200) + + def test_scaling_loads_column_index(self): + """Test scaling a load by a column index""" + scaling_factors = [ + # y m d h m s + {'start_time': datetime(2021, 1, 1, 0, 0, 0), 'end_time': datetime(2021, 1, 1, 3, 0, 0), 'scaling_factor': 0.25}, # noqa + {'start_time': datetime(2021, 1, 1, 4, 0, 0), 'end_time': datetime(2021, 12, 31, 23, 59, 59), 'scaling_factor': 1} + ] + file = ModelicaMOS(self.data_dir / 'B2_no_water_load.mos') + file.scale_loads(scaling_factors, 1) + + # save to a new file to compare + file.save_as(self.output_dir / 'B2_no_water_load_scaled_column_index.mos') + # read in the new file and check the value + self.assertTrue((self.output_dir / 'B2_no_water_load_scaled_column_index.mos').exists()) + new_mos = ModelicaMOS(self.output_dir / 'B2_no_water_load_scaled_column_index.mos') + + # to find these values, you must manually look at the original file and then the scaling factor and make + # sure that the values match. + _log.debug(new_mos.data) + self.assertEqual(new_mos.data[0][0], 3600) + self.assertEqual(new_mos.data[0][1], -25) + self.assertEqual(new_mos.data[0][2], 200) + + # second >= 14400 should not be scaled, which is in row 3 (0-based) + self.assertEqual(new_mos.data[3][0], 14400) + self.assertEqual(new_mos.data[3][1], -100) + self.assertEqual(new_mos.data[3][2], 200) + + def test_scaling_load_no_data_error(self): + # test with decimal separators + data = """ +#Var1 = -1,245.25 Watts +""" + file = ModelicaMOS('not_a_real_file.mos', header_data=data) + with self.assertRaises(Exception) as ctx: + file.scale_loads([]) + self.assertIn("No data to scale", str(ctx.exception)) diff --git a/tests/test_modelica_project.py b/tests/test_modelica_project.py index 57805ec..c8e9aac 100644 --- a/tests/test_modelica_project.py +++ b/tests/test_modelica_project.py @@ -1,9 +1,6 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + import os import shutil import unittest @@ -66,3 +63,24 @@ def test_project_save_as(self): # verify that the package.mo file was saved self.assertTrue((self.output_dir / 'test_package_1' / 'package.mo').exists()) + + def test_mpignore_file(self): + """Verify that the mpignore file is loaded correctly""" + package_file = self.data_dir / 'teaser_single' / 'package.mo' + + mpignore_file = package_file.parent / '.mpignore' + # delete the mpignore file if it exists + if mpignore_file.exists(): + mpignore_file.unlink() + # write an mpignore file into the 'teaser_single' directory + with open(mpignore_file, 'w') as f: + f.write('*.csv\n') + + project = ModelicaProject(package_file) + + # there should be two ignored files + # ignored = [f.file_path.name for f in project.mpignore_files] + self.assertEqual(len(project.mpignore_files), 2) + ignored = [project.root_directory / Path('results.csv'), + project.root_directory / Path('Districts/unneeded.csv')] + self.assertListEqual(project.mpignore_files, ignored) diff --git a/tests/test_package_parser.py b/tests/test_package_parser.py index 4a27602..92eb627 100644 --- a/tests/test_package_parser.py +++ b/tests/test_package_parser.py @@ -3,6 +3,7 @@ import os import unittest +from pathlib import Path from modelica_builder.package_parser import PackageParser @@ -16,7 +17,10 @@ def setUp(self): def test_new_from_template(self): package = PackageParser.new_from_template( - self.output_dir, 'new_model_name', ["model_a", "model_b"], within="SomeWithin" + self.output_dir, + 'new_model_name', + ["model_a", "model_b"], + within="SomeWithin", ) package.save() @@ -33,9 +37,29 @@ def test_new_from_template(self): with open(os.path.join(self.output_dir, 'package.order')) as f: self.assertTrue('model_a\nmodel_b' in f.read(), 'Incorrect package order') + def test_mbl_version(self): + package = PackageParser.new_from_template( + self.output_dir, + 'new_model_name', + ["model_a", "model_b"], + mbl_version="2.0.0" + ) + package.save() + + self.assertTrue((Path(self.output_dir) / 'package.mo').exists()) + self.assertTrue((Path(self.output_dir) / 'package.order').exists()) + + # check for strings in files + with open(Path(self.output_dir) / 'package.mo') as f: + file_data = f.read() + self.assertTrue('Buildings(version="2.0.0"' in file_data, 'Incorrect mbl_version') + def test_round_trip(self): package = PackageParser.new_from_template( - self.output_dir, 'another_model', ["model_x", "model_y"], within="DifferentWithin" + self.output_dir, + 'another_model', + ["model_x", "model_y"], + within="DifferentWithin", ) package.save() @@ -45,7 +69,10 @@ def test_round_trip(self): def test_rename_package_model(self): package = PackageParser.new_from_template( - self.output_dir, 'rename_model', ["model_1", "model_2"], within="RenameWithin" + self.output_dir, + 'rename_model', + ["model_1", "model_2"], + within="RenameWithin", ) package.save() @@ -56,7 +83,10 @@ def test_rename_package_model(self): def test_rename_model_in_order(self): package = PackageParser.new_from_template( - self.output_dir, 'rename_model', ["model_1", "model_2"], within="RenameWithin" + self.output_dir, + 'rename_model', + ["model_1", "model_2"], + within="RenameWithin", ) package.save() @@ -66,7 +96,10 @@ def test_rename_model_in_order(self): def test_add_model(self): package = PackageParser.new_from_template( - self.output_dir, 'so_many_models', ["model_beta", "model_gamma"], within="SoMany" + self.output_dir, + 'so_many_models', + ["model_beta", "model_gamma"], + within="SoMany", ) package.save() @@ -77,7 +110,10 @@ def test_add_model(self): def test_within_clause(self): package = PackageParser.new_from_template( - self.output_dir, 'within_clause', ["model_a", "model_b"], within="SomeWithin" + self.output_dir, + 'within_clause', + ["model_a", "model_b"], + within="SomeWithin", ) package.save() diff --git a/tests/test_selector.py b/tests/test_selector.py index 9a1a56f..3fd6664 100644 --- a/tests/test_selector.py +++ b/tests/test_selector.py @@ -1,10 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" - +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md # -*- coding: utf-8 -*- diff --git a/tests/tests.py b/tests/tests.py index dde4af4..ecbcfe2 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,9 +1,5 @@ -""" -**************************************************************************************************** -:copyright (c) 2020-2023, Alliance for Sustainable Energy, LLC. -All rights reserved. -**************************************************************************************************** -""" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md import difflib