From 253bddeb1e9d1f14f5c024a73ec6a34bd3f50112 Mon Sep 17 00:00:00 2001 From: Lukas Riedel <34276446+peanutfun@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:12:13 +0200 Subject: [PATCH 1/2] Allow downgrading of Python and update links in contribution guide (#900) * Allow downgrading of Python bugfix version Adjust install guide accordingly. * Fix links in CONTRIBUTING.md * Update CHANGELOG.md --- CHANGELOG.md | 2 ++ CONTRIBUTING.md | 13 +++++++------ doc/guide/install.rst | 7 ++++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 232be705d7..203f7230d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ CLIMADA tutorials. [#872](https://github.com/CLIMADA-project/climada_python/pull ### Fixed - Avoid an issue where a Hazard subselection would have a fraction matrix with only zeros as entries by throwing an error [#866](https://github.com/CLIMADA-project/climada_python/pull/866) +- Allow downgrading the Python bugfix version to improve environment compatibility [#900](https://github.com/CLIMADA-project/climada_python/pull/900) +- Fix broken links in `CONTRIBUTING.md` [#900](https://github.com/CLIMADA-project/climada_python/pull/900) ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9d465d7e5e..f21b73e951 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,7 @@ Please contact the [lead developers](https://wcr.ethz.ch/research/climada.html) ## Minimal Steps to Contribute -Before you start, please have a look at our [Developer Guide][devguide]. +Before you start, please have a look at our Developer Guide section in the [CLIMADA Docs][docs]. To contribute follow these steps: @@ -65,21 +65,22 @@ To contribute follow these steps: ## Resources -The CLIMADA documentation provides a [Developer Guide][devguide]. +The [CLIMADA documentation][docs] provides several Developer Guides. Here's a selection of the commonly required information: * How to use Git and GitHub for CLIMADA development: [Development and Git and CLIMADA](https://climada-python.readthedocs.io/en/latest/guide/Guide_Git_Development.html) -* Coding instructions for CLIMADA: [Python Dos and Don'ts](https://climada-python.readthedocs.io/en/latest/guide/Guide_PythonDos-n-Donts.html), [Performance Tips](https://climada-python.readthedocs.io/en/latest/guide/Guide_Py_Performance.html), [CLIMADA Conventions](https://climada-python.readthedocs.io/en/latest/guide/Guide_Miscellaneous.html) -* How to execute tests in CLIMADA: [Testing and Continuous Integration][testing] +* Coding instructions for CLIMADA: [Python Dos and Don'ts](https://climada-python.readthedocs.io/en/latest/guide/Guide_PythonDos-n-Donts.html), [Performance Tips](https://climada-python.readthedocs.io/en/latest/guide/Guide_Py_Performance.html), [CLIMADA Conventions](https://climada-python.readthedocs.io/en/latest/guide/Guide_CLIMADA_conventions.html) +* How to execute tests in CLIMADA: [Testing][testing] and [Continuous Integration](https://climada-python.readthedocs.io/en/latest/guide/Guide_continuous_integration_GitHub_actions.html) ## Pull Requests After developing a new feature, fixing a bug, or updating the tutorials, you can create a [pull request](https://docs.github.com/en/pull-requests) to have your changes reviewed and then merged into the CLIMADA code base. To ensure that your pull request can be reviewed quickly and easily, please have a look at the _Resources_ above before opening a pull request. -In particular, please check out the [Pull Request instructions](https://climada-python.readthedocs.io/en/latest/guide/Guide_Git_Development.html#Pull-requests). +In particular, please check out the [Pull Request instructions](https://climada-python.readthedocs.io/en/latest/guide/Guide_Git_Development.html#pull-requests). We provide a description template for pull requests that helps you provide the essential information for reviewers. It also contains a checklist for both pull request authors and reviewers to guide the review process. +[docs]: https://climada-python.readthedocs.io/en/latest/ [devguide]: https://climada-python.readthedocs.io/en/latest/#developer-guide -[testing]: https://climada-python.readthedocs.io/en/latest/guide/Guide_Continuous_Integration_and_Testing.html +[testing]: https://climada-python.readthedocs.io/en/latest/guide/Guide_Testing.html diff --git a/doc/guide/install.rst b/doc/guide/install.rst index 43a977372a..c30fefd055 100644 --- a/doc/guide/install.rst +++ b/doc/guide/install.rst @@ -161,7 +161,12 @@ For advanced Python users or developers of CLIMADA, we recommed cloning the CLIM .. code-block:: shell - mamba create -n climada_env python=3.9 + mamba create -n climada_env "python=3.9.*" + + .. hint:: + + Use the wildcard ``.*`` at the end to allow a downgrade of the bugfix version of Python. + This increases compatibility when installing the requirements in the next step. .. note:: From 926d1142590cf3562ae0983d3fb080a7a73928bb Mon Sep 17 00:00:00 2001 From: emanuel-schmid Date: Fri, 28 Jun 2024 10:11:01 +0200 Subject: [PATCH 2/2] typo and docstring cosmetics --- climada/hazard/base.py | 2 +- climada/util/checker.py | 116 +++++++++++++++++------------- climada/util/test/test_checker.py | 10 +-- 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/climada/hazard/base.py b/climada/hazard/base.py index 108ba65b4a..ecd68ebd17 100644 --- a/climada/hazard/base.py +++ b/climada/hazard/base.py @@ -628,7 +628,7 @@ def _check_events(self): if np.unique(self.event_id).size != num_ev: raise ValueError("There are events with the same identifier.") - u_check.check_oligatories(self.__dict__, self.vars_oblig, 'Hazard.', + u_check.check_obligatories(self.__dict__, self.vars_oblig, 'Hazard.', num_ev, num_ev, num_cen) u_check.check_optionals(self.__dict__, self.vars_opt, 'Hazard.', num_ev) self.event_name = u_check.array_default(num_ev, self.event_name, diff --git a/climada/util/checker.py b/climada/util/checker.py index 2bcbbef057..c48ea3be9c 100644 --- a/climada/util/checker.py +++ b/climada/util/checker.py @@ -32,16 +32,24 @@ LOGGER = logging.getLogger(__name__) -def check_oligatories(var_dict, var_obl, name_prefix, n_size, n_row, n_col): + +def check_obligatories(var_dict, var_obl, name_prefix, n_size, n_row, n_col): """Check size of obligatory variables. - Paraemters: - var_dict (dict): __dict__ class attribute - var_obl (set): name of the obligatory variables - name_prefix (str): name to add in the error log, e.g. the class name - n_size (int): size expected from arrays and lists - n_row (int): number of rows expected in 2D arrays - n_col (int): number of columns expected in 2D arrays + Parameters + ---------- + var_dict : dict + __dict__ class attribute + var_obl : set + name of the obligatory variables + name_prefix : str + name to add in the error log, e.g. the class name + n_size : int + size expected from arrays and lists + n_row : int + number of rows expected in 2D arrays + n_col : int + number of columns expected in 2D arrays Raises ------ @@ -57,14 +65,20 @@ def check_oligatories(var_dict, var_obl, name_prefix, n_size, n_row, n_col): elif isinstance(var_val, (np.ndarray, sparse.csr_matrix)) and var_val.ndim == 2: shape(n_row, n_col, var_val, name_prefix + var_name) + def check_optionals(var_dict, var_opt, name_prefix, n_size): """Check size of obligatory variables. - Paraemters: - var_dict (dict): __dict__ class attribute - var_opt (set): name of the ooptional variables - name_prefix (str): name to add in the error log, e.g. the class name - n_size (int): size expected from arrays and lists + Parameters + ---------- + var_dict : dict + __dict__ class attribute + var_opt : set + name of the ooptional variables + name_prefix : str + name to add in the error log, e.g. the class name + n_size : int + size expected from arrays and lists Raises ------ @@ -75,17 +89,19 @@ def check_optionals(var_dict, var_opt, name_prefix, n_size): if isinstance(var_val, (np.ndarray, list)): array_optional(n_size, var_val, name_prefix + var_name) + def empty_optional(var, var_name): """Check if a data structure is empty.""" if not var: LOGGER.debug("%s not set. ", var_name) + def size(exp_len, var, var_name): """Check if the length of a variable is the expected one. - Raises - ------ - ValueError + Raises + ------ + ValueError """ try: if isinstance(exp_len, int): @@ -96,12 +112,13 @@ def size(exp_len, var, var_name): except TypeError as err: raise ValueError(f"{var_name} has wrong size.") from err + def shape(exp_row, exp_col, var, var_name): """Check if the length of a variable is the expected one. - Raises - ------ - ValueError + Raises + ------ + ValueError """ try: if exp_row != var.shape[0]: @@ -115,45 +132,46 @@ def shape(exp_row, exp_col, var, var_name): def array_optional(exp_len, var, var_name): """Check if array has right size. Warn if array empty. Call check_size. - Parameters - ---------- - exp_len : str - expected array size - var : np.array - numpy array to check - var_name : str - name of the variable. Used in error/warning msg - - Raises - ------ - ValueError + Parameters + ---------- + exp_len : str + expected array size + var : np.array + numpy array to check + var_name : str + name of the variable. Used in error/warning msg + + Raises + ------ + ValueError """ if len(var) == 0 and exp_len > 0: LOGGER.debug("%s not set. ", var_name) else: size(exp_len, var, var_name) + def array_default(exp_len, var, var_name, def_val): """Check array has right size. Set default value if empty. Call check_size. - Parameters - ---------- - exp_len : str - expected array size - var : np.array - numpy array to check - var_name : str - name of the variable. Used in error/warning msg - def_val : np.array - nump array used as default value - - Raises - ------ - ValueError - - Returns - ------- - Filled array + Parameters + ---------- + exp_len : str + expected array size + var : np.array + numpy array to check + var_name : str + name of the variable. Used in error/warning msg + def_val : np.array + nump array used as default value + + Raises + ------ + ValueError + + Returns + ------- + Filled array """ res = var if len(var) == 0 and exp_len > 0: diff --git a/climada/util/test/test_checker.py b/climada/util/test/test_checker.py index c645b2a51f..f75a8d78c5 100644 --- a/climada/util/test/test_checker.py +++ b/climada/util/test/test_checker.py @@ -41,25 +41,25 @@ def __init__(self): class TestChecks(unittest.TestCase): """Test loading funcions from the Hazard class""" - def test_check_oligatories_pass(self): + def test_check_obligatories_pass(self): """Correct DummyClass definition""" dummy = DummyClass() - u_check.check_oligatories(dummy.__dict__, dummy.vars_oblig, "DummyClass.", + u_check.check_obligatories(dummy.__dict__, dummy.vars_oblig, "DummyClass.", dummy.id.size, dummy.id.size, 2) - def test_check_oligatories_fail(self): + def test_check_obligatories_fail(self): """Wrong DummyClass definition""" dummy = DummyClass() dummy.array = np.arange(3) with self.assertRaises(ValueError) as cm: - u_check.check_oligatories(dummy.__dict__, dummy.vars_oblig, "DummyClass.", + u_check.check_obligatories(dummy.__dict__, dummy.vars_oblig, "DummyClass.", dummy.id.size, dummy.id.size, 2) self.assertIn('Invalid DummyClass.array size: 25 != 3.', str(cm.exception)) dummy = DummyClass() dummy.sparse_arr = sparse.csr_matrix(np.zeros((25, 1))) with self.assertRaises(ValueError) as cm: - u_check.check_oligatories(dummy.__dict__, dummy.vars_oblig, "DummyClass.", + u_check.check_obligatories(dummy.__dict__, dummy.vars_oblig, "DummyClass.", dummy.id.size, dummy.id.size, 2) self.assertIn('Invalid DummyClass.sparse_arr column size: 2 != 1.', str(cm.exception))