Skip to content

Commit 2529b14

Browse files
Update Python versions (#13)
1 parent 99867c3 commit 2529b14

File tree

20 files changed

+94
-71
lines changed

20 files changed

+94
-71
lines changed

.github/workflows/build.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
strategy:
2222
fail-fast: false
2323
matrix:
24-
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
24+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
2525

2626
steps:
2727
- uses: actions/checkout@v1
@@ -58,27 +58,23 @@ jobs:
5858
path: junit/pytest-results-${{ matrix.python-version }}.xml
5959
if: always()
6060

61-
- name: Codecov
62-
run: |
63-
bash <(curl -s https://codecov.io/bash)
64-
6561
- name: Install distribution dependencies
6662
run: |
6763
rm -rf junit
6864
rm -rf deps
6965
pip install build
70-
if: matrix.python-version == 3.12
66+
if: matrix.python-version == 3.13
7167

7268
- name: Create distribution package
7369
run: python -m build
74-
if: matrix.python-version == 3.12
70+
if: matrix.python-version == 3.13
7571

7672
- name: Upload distribution package
7773
uses: actions/upload-artifact@v4
7874
with:
7975
name: dist
8076
path: dist
81-
if: matrix.python-version == 3.12
77+
if: matrix.python-version == 3.13
8278

8379
publish:
8480
runs-on: ubuntu-latest
@@ -91,10 +87,10 @@ jobs:
9187
name: dist
9288
path: dist
9389

94-
- name: Use Python 3.12
90+
- name: Use Python 3.13
9591
uses: actions/setup-python@v1
9692
with:
97-
python-version: '3.12'
93+
python-version: '3.13'
9894

9995
- name: Install dependencies
10096
run: |

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [2.0.5] - 2025-11-24
9+
10+
- Upgrade Python versions in workflow.
11+
- Remove support for Python <= 3.10.
12+
- Remove Codecov from README and workflow.
13+
- Upgrade type annotations.
14+
815
## [2.0.4] - 2023-12-28 :snowman_with_snow:
16+
917
- Improves the library to deep-merge dictionaries of values instead of replacing
1018
objects entirely (fix [#10](https://github.com/Neoteroi/essentials-configuration/issues/10)), by @StummeJ.
1119
- Adds Python 3.12 to the build matrix, upgrades dev dependencies and fix tests

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
![Build](https://github.com/Neoteroi/essentials-configuration/workflows/Build/badge.svg)
22
[![pypi](https://img.shields.io/pypi/v/essentials-configuration.svg)](https://pypi.python.org/pypi/essentials-configuration)
33
[![versions](https://img.shields.io/pypi/pyversions/essentials-configuration.svg)](https://github.com/Neoteroi/essentials-configuration)
4-
[![codecov](https://codecov.io/gh/Neoteroi/essentials-configuration/branch/main/graph/badge.svg?token=VzAnusWIZt)](https://codecov.io/gh/Neoteroi/essentials-configuration)
54
[![license](https://img.shields.io/github/license/Neoteroi/essentials-configuration.svg)](https://github.com/Neoteroi/essentials-configuration/blob/main/LICENSE)
65

76
# Python configuration utilities
7+
88
Implementation of key-value pair based configuration for Python applications.
99

1010
**Features:**
11+
1112
- support for most common sources of application settings
1213
- support for overriding settings in sequence
1314
- support for nested structures and lists, using attribute notation
@@ -31,6 +32,7 @@ enabling different scenarios like configuration by environment and system
3132
instance.
3233

3334
## Supported sources:
35+
3436
- **toml** files
3537
- **yaml** files
3638
- **json** files

config/common/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from abc import ABC, abstractmethod
22
from collections import abc
3-
from typing import Any, Dict, List, Mapping, Optional, Type, TypeVar
3+
from typing import Any, Mapping, Type, TypeVar
44

55
from deepmerge import Merger
66

@@ -97,7 +97,7 @@ def merge_values(destination: Mapping[str, Any], source: Mapping[str, Any]) -> N
9797

9898
class ConfigurationSource(ABC):
9999
@abstractmethod
100-
def get_values(self) -> Dict[str, Any]:
100+
def get_values(self) -> dict[str, Any]:
101101
"""Returns the values read from this source."""
102102

103103
def __repr__(self) -> str:
@@ -112,7 +112,7 @@ def __init__(self, values: Mapping[str, Any]) -> None:
112112
super().__init__()
113113
self._values = dict(values.items())
114114

115-
def get_values(self) -> Dict[str, Any]:
115+
def get_values(self) -> dict[str, Any]:
116116
return self._values
117117

118118

@@ -136,11 +136,11 @@ def __new__(cls, arg=None):
136136
return [cls(item) for item in arg]
137137
return arg
138138

139-
def __init__(self, mapping: Optional[Mapping[str, Any]] = None):
139+
def __init__(self, mapping: Mapping[str, Any] | None = None):
140140
"""
141141
Creates a new instance of Configuration object with the given values.
142142
"""
143-
self._data: Dict[str, Any] = dict(mapping.items()) if mapping else {}
143+
self._data: dict[str, Any] = dict(mapping.items()) if mapping else {}
144144

145145
def __contains__(self, item: str) -> bool:
146146
return item in self._data
@@ -166,7 +166,7 @@ def __repr__(self) -> str:
166166
return f"<Configuration {repr(hidden_values)}>"
167167

168168
@property
169-
def values(self) -> Dict[str, Any]:
169+
def values(self) -> dict[str, Any]:
170170
"""
171171
Returns a copy of the dictionary of current settings.
172172
"""
@@ -190,13 +190,13 @@ def __init__(self, *sources: ConfigurationSource) -> None:
190190
object from different sources. Sources are applied in the given order and can
191191
override each other's settings.
192192
"""
193-
self._sources: List[ConfigurationSource] = list(sources) if sources else []
193+
self._sources: list[ConfigurationSource] = list(sources) if sources else []
194194

195195
def __repr__(self) -> str:
196196
return f"<ConfigurationBuilder {self._sources}>"
197197

198198
@property
199-
def sources(self) -> List[ConfigurationSource]:
199+
def sources(self) -> list[ConfigurationSource]:
200200
return self._sources
201201

202202
def add_source(self, source: ConfigurationSource):

config/common/files.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from abc import abstractmethod
22
from pathlib import Path
3-
from typing import Any, Dict, Union
3+
from typing import Any
44

55
from config.common import ConfigurationSource
66
from config.errors import MissingConfigurationFileError
77

8-
PathType = Union[Path, str]
8+
PathType = Path | str
99

1010

1111
class FileConfigurationSource(ConfigurationSource):
@@ -15,13 +15,13 @@ def __init__(self, file_path: PathType, optional: bool = False) -> None:
1515
self.optional = optional
1616

1717
@abstractmethod
18-
def read_source(self) -> Dict[str, Any]:
18+
def read_source(self) -> dict[str, Any]:
1919
"""
2020
Reads values from the source file path. This method is not
2121
used if the file does not exist.
2222
"""
2323

24-
def get_values(self) -> Dict[str, Any]:
24+
def get_values(self) -> dict[str, Any]:
2525
if not self.file_path.exists():
2626
if self.optional:
2727
return {}

config/env/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from typing import Any, Dict, Optional
2+
from typing import Any
33

44
from dotenv import load_dotenv
55

@@ -10,16 +10,16 @@
1010
class EnvironmentVariables(ConfigurationSource):
1111
def __init__(
1212
self,
13-
prefix: Optional[str] = None,
13+
prefix: str | None = None,
1414
strip_prefix: bool = True,
15-
file: Optional[PathType] = None,
15+
file: PathType | None = None,
1616
) -> None:
1717
super().__init__()
1818
self.prefix = prefix
1919
self.strip_prefix = strip_prefix
2020
self._file = file
2121

22-
def get_values(self) -> Dict[str, Any]:
22+
def get_values(self) -> dict[str, Any]:
2323
if self._file:
2424
load_dotenv(self._file)
2525

config/ini/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import configparser
22
from collections import abc
3-
from typing import Any, Dict
3+
from typing import Any
44

55
from config.common.files import FileConfigurationSource
66

@@ -20,7 +20,7 @@ def _develop_configparser_values(parser):
2020

2121

2222
class INIFile(FileConfigurationSource):
23-
def read_source(self) -> Dict[str, Any]:
23+
def read_source(self) -> dict[str, Any]:
2424
parser = configparser.ConfigParser()
2525
parser.read(self.file_path, encoding="utf8")
2626
return _develop_configparser_values(parser)

config/json/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import json
2-
from typing import Any, Dict
2+
from typing import Any
33

44
from config.common.files import FileConfigurationSource
55

66

77
class JSONFile(FileConfigurationSource):
8-
def read_source(self) -> Dict[str, Any]:
8+
def read_source(self) -> dict[str, Any]:
99
with open(self.file_path, "rt", encoding="utf-8") as source:
1010
return json.load(source)

config/toml/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Callable, Dict
1+
from typing import Any, Callable
22

33
from config.common.files import FileConfigurationSource, PathType
44

@@ -20,6 +20,6 @@ def __init__(
2020
super().__init__(file_path, optional)
2121
self.parse_float = parse_float
2222

23-
def read_source(self) -> Dict[str, Any]:
23+
def read_source(self) -> dict[str, Any]:
2424
with open(self.file_path, "rb") as source:
2525
return tomllib.load(source, parse_float=self.parse_float)

config/user/__init__.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
This module provides support for user settings stored locally, for development, or for
33
CLIs.
44
"""
5+
56
from pathlib import Path
6-
from typing import Any, Dict, Optional
7+
from typing import Any
78
from uuid import uuid4
89

910
from config.common import ConfigurationSource
@@ -36,9 +37,7 @@ class UserSettings(ConfigurationSource):
3637
This class reads settings stored in a file inside the user's folder.
3738
"""
3839

39-
def __init__(
40-
self, project_name: Optional[str] = None, optional: bool = True
41-
) -> None:
40+
def __init__(self, project_name: str | None = None, optional: bool = True) -> None:
4241
"""
4342
Configures an instance of UserSettings that obtains values from a project file
4443
stored in the user's folder. If a project name is not provided, it is
@@ -60,6 +59,6 @@ def get_base_folder(self) -> Path:
6059
def settings_file_path(self) -> Path:
6160
return self._settings_file_path
6261

63-
def get_values(self) -> Dict[str, Any]:
62+
def get_values(self) -> dict[str, Any]:
6463
"""Returns the values read from this source."""
6564
return self._source.get_values()

0 commit comments

Comments
 (0)