From 8807d19fc37c610eb1c725dfb79966c46ec2f357 Mon Sep 17 00:00:00 2001 From: Roberto Prevato Date: Thu, 28 Dec 2023 11:31:58 +0100 Subject: [PATCH] Prepare for v2.0.4 --- .flake8 | 2 +- .github/workflows/build.yml | 15 ++------------- CHANGELOG.md | 6 ++++++ Makefile | 2 +- config/common/__init__.py | 6 +++--- pyproject.toml | 9 +++++++-- requirements.txt | 15 +++++++-------- tests/test_configuration.py | 18 +++++++++++++----- 8 files changed, 40 insertions(+), 33 deletions(-) diff --git a/.flake8 b/.flake8 index 0f6f5a8..359f948 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -exclude = __pycache__,built,build,venv +exclude = __pycache__,built,build,venv,venv312,dist ignore = E203, E266, W503 max-line-length = 88 max-complexity = 18 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a4572e6..01e2b38 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9, "3.10", "3.11"] + python-version: [3.8, 3.9, "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v1 @@ -33,20 +33,9 @@ jobs: with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@v1 - id: depcache - with: - path: deps - key: requirements-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }} - - - name: Download dependencies - if: steps.depcache.outputs.cache-hit != 'true' - run: | - pip download --dest=deps -r requirements.txt - - name: Install dependencies run: | - pip install -U --no-index --find-links=deps deps/* + pip install -r requirements.txt - name: Run tests run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index ce9ae42..41cf064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.4] - 2023-12-28 :snowman_with_snow: +- Improves the library to deep-merge dictionaries of values instead of replacing + objects entirely (fix [#10](https://github.com/Neoteroi/essentials-configuration/issues/10)), by @StummeJ. +- Adds Python 3.12 to the build matrix, upgrades dev dependencies and fix tests + to support Python 3.12. + ## [2.0.3] - 2023-04-15 :crown: - Adopts `Rich`, through `rich-click` for the project CLI. - Renames the recently added `secrets` feature to `settings`. diff --git a/Makefile b/Makefile index 74be263..f3510fe 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ check-flake8: check-isort: @echo "$(BOLD)Checking isort$(RESET)" - @isort --check-only . 2>&1 + @isort --check-only config 2>&1 check-black: diff --git a/config/common/__init__.py b/config/common/__init__.py index a71fca5..7ce3bb3 100644 --- a/config/common/__init__.py +++ b/config/common/__init__.py @@ -49,7 +49,7 @@ def apply_key_value(obj: Mapping[str, Any], key: str, value: Any) -> Mapping[str sub_property, abc.MutableSequence ): raise ConfigurationOverrideError( - f"The key `{key}` cannot be used " + f"The key '{key}' cannot be used " f"because it overrides another " f"variable with shorter key! ({part}, {sub_property})" ) @@ -67,7 +67,7 @@ def apply_key_value(obj: Mapping[str, Any], key: str, value: Any) -> Mapping[str sub_property[index] = merger.merge(sub_property[index], value) except IndexError: raise ConfigurationOverrideError( - f"Invalid override for mutable sequence {key}; " + f"Invalid override for mutable sequence {key}, " f"assignment index out of range" ) else: @@ -81,7 +81,7 @@ def apply_key_value(obj: Mapping[str, Any], key: str, value: Any) -> Mapping[str sub_property[last_part] = value except TypeError as type_error: raise ConfigurationOverrideError( - f"Invalid assignment {key} -> {value}; {str(type_error)}" + f"Invalid assignment {key} -> {value}, {str(type_error)}" ) return obj diff --git a/pyproject.toml b/pyproject.toml index a2ca48c..aee7601 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "essentials-configuration" -version = "2.0.3" +version = "2.0.4" authors = [{ name = "Roberto Prevato", email = "roberto.prevato@gmail.com" }] description = "Implementation of key-value pair based configuration for Python applications." readme = "README.md" @@ -17,11 +17,16 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Operating System :: OS Independent", ] keywords = ["configuration", "root", "management", "strategy", "settings"] -dependencies = ["deepmerge~=1.1.0", "tomli; python_version < '3.11'", "python-dotenv~=1.0.0"] +dependencies = [ + "deepmerge~=1.1.0", + "tomli; python_version < '3.11'", + "python-dotenv~=1.0.0", +] [project.optional-dependencies] yaml = ["PyYAML"] diff --git a/requirements.txt b/requirements.txt index efe10ba..61e3c46 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ appdirs==1.4.4 attrs==22.1.0 -black==22.10.0 +black==22.12.0 build==0.10.0 -click==8.1.3 -coverage==6.5.0 +click==8.1.7 +coverage==7.4.0 deepmerge==1.1.0 flake8==5.0.4 iniconfig==1.1.1 @@ -24,14 +24,13 @@ pyflakes==2.5.0 Pygments==2.15.0 pyparsing==3.0.9 pyproject_hooks==1.0.0 -pytest==7.2.0 -pytest-cov==4.0.0 +pytest==7.4.3 +pytest-cov==4.1.0 python-dotenv==1.0.0 -PyYAML==6.0 +PyYAML==6.0.1 regex==2022.10.31 rich==13.3.4 rich-click==1.6.1 toml==0.10.2 tomli==2.0.1 -typed-ast==1.5.4 -typing_extensions==4.5.0 +typing_extensions==4.9.0 diff --git a/tests/test_configuration.py b/tests/test_configuration.py index cb0a8f4..d604d41 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -2,7 +2,6 @@ from typing import Any, Dict from uuid import uuid4 -import pkg_resources import pytest from config.common import ( @@ -18,16 +17,25 @@ from config.toml import TOMLFile from config.yaml import YAMLFile +try: + from importlib.resources import files + + def _get_file_path(file_name: str) -> str: + return str(files("tests") / file_name) + +except ImportError: + # Python 3.8 + import pkg_resources + + def _get_file_path(file_name: str) -> str: + return pkg_resources.resource_filename(__name__, f"./{file_name}") + class FooSource(ConfigurationSource): def get_values(self) -> Dict[str, Any]: return {} -def _get_file_path(file_name: str) -> str: - return pkg_resources.resource_filename(__name__, f"./{file_name}") - - def test_builder(): builder = ConfigurationBuilder()