sysnet-pyutils 1.7.11__tar.gz → 1.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sysnet_pyutils-1.7.11/sysnet_pyutils.egg-info → sysnet_pyutils-1.8.0}/PKG-INFO +113 -20
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/README.md +112 -19
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/pyproject.toml +1 -1
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/__init__.py +2 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/utils.py +564 -13
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0/sysnet_pyutils.egg-info}/PKG-INFO +113 -20
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/SOURCES.txt +2 -0
- sysnet_pyutils-1.8.0/tests/test_config_secrets.py +282 -0
- sysnet_pyutils-1.8.0/tests/test_config_store.py +834 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils_missing_branches.py +3 -3
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/LICENSE +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/setup.cfg +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/barcode.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/constants.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/cron_utils/__init__.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/cron_utils/validation.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/data_utils.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/domino.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/geo.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/__init__.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/global_model.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/models.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/timeutils.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/ident.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/log.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/models/__init__.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/models/general.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/ses.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/syslog/__init__.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/syslog/factory.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/tools.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/dependency_links.txt +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/not-zip-safe +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/requires.txt +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/top_level.txt +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_cron_utils.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_cron_validation_edge.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils_datetime.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils_edge.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils_missing_branches.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_domino.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_domino_edge.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_geo.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_global_model_recursive.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_global_model_timezone.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_ident_barcode.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_log_importerror_branch.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_log_mongo.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_models_contact.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_models_general.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_models_general_edge.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_package_init_version.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_recursive_update.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_ses.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_ses_importerror_branch.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_syslog_factory.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_tools.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils_edge.py +0 -0
- {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils_log_base64.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sysnet-pyutils
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: SYSNET Python Utilities - kompletní sada nástrojů pro Python aplikace
|
|
5
5
|
Author-email: Data Developer <info@sysnet.cz>
|
|
6
6
|
Maintainer-email: SYSNET Development Team <info@sysnet.cz>
|
|
@@ -729,7 +729,8 @@ Knihovna obsahuje základní, v aplikacích hojně používané, utility pro Pyt
|
|
|
729
729
|
|
|
730
730
|
[](https://www.python.org/downloads/)
|
|
731
731
|
[](LICENSE)
|
|
732
|
-
[](https://pypi.org/project/sysnet-pyutils/1.8.0/)
|
|
733
|
+
[](https://github.com/SYSNET-CZ/pyutils/actions/workflows/ci.yml)
|
|
733
734
|
[](tests/)
|
|
734
735
|
|
|
735
736
|
---
|
|
@@ -753,6 +754,7 @@ Knihovna obsahuje základní, v aplikacích hojně používané, utility pro Pyt
|
|
|
753
754
|
- [Volitelné závislosti](#volitelné-závislosti)
|
|
754
755
|
- [Testování](#testování)
|
|
755
756
|
- [Vývoj](#vývoj)
|
|
757
|
+
- [CI/CD](#cicd)
|
|
756
758
|
- [Systémové proměnné](#systémové-proměnné)
|
|
757
759
|
- [Changelog](#changelog)
|
|
758
760
|
- [Podpora](#podpora)
|
|
@@ -864,6 +866,26 @@ if config.loaded:
|
|
|
864
866
|
db_url = config.config['database']
|
|
865
867
|
```
|
|
866
868
|
|
|
869
|
+
Chování `Config`:
|
|
870
|
+
|
|
871
|
+
- **Soubor:** ukládá se atomicky (dočasný soubor + přejmenování), čitelně (diakritika bez `\u` escape) a v pořadí klíčů z paměti. Nový soubor má práva 600 a chybějící adresáře
|
|
872
|
+
se vytvoří s právy 700; práva existujícího souboru se nemění a volnější než 600 se při načtení zalogují jako varování.
|
|
873
|
+
- **Výchozí cesta:** nezadáte-li `config_path`, použije se proměnná prostředí `PYUTILS_CONFIG_PATH`. Bez ní platí dosavadní
|
|
874
|
+
umístění `conf/config.yml` vedle modulu (s varováním); není-li zapisovatelné, vyhodí se `ConfigError` s radou.
|
|
875
|
+
- **Chyby:** poškozený YAML vyhodí `ConfigParseError` (podtřída `ConfigError` i `yaml.YAMLError`) s cestou, popisem a
|
|
876
|
+
řádkem, nikdy s obsahem souboru; soubor zůstane nepřepsaný.
|
|
877
|
+
- **Nové výchozí hodnoty:** s existujícím souborem se `config_dict` ignoruje. Chcete-li po upgradu aplikace doplnit chybějící
|
|
878
|
+
klíče, použijte `Config(config_path=..., config_dict=..., merge_defaults=True)`: doplní se jen to, co v souboru chybí
|
|
879
|
+
(vnořené slovníky do hloubky, seznamy ne) a hodnoty ze souboru se nikdy nepřepíšou.
|
|
880
|
+
- **Secrets:** hodnotu v YAML lze zadat odkazem `${env:NAZEV}` nebo `${file:/absolutni/cesta}` (i uvnitř textu, např.
|
|
881
|
+
`mongodb://u:${env:MONGO_PASSWORD}@h`); rozliší se při načtení na `Secret` (podtřída `str`, `repr` a log maskované,
|
|
882
|
+
`reveal()` vrací čistý `str`). Chybějící zdroj je `ConfigError`, nikdy tichý prázdný řetězec. `store()` zapisuje
|
|
883
|
+
zpět odkaz, nikdy hodnotu. `config.redacted()` vrací kopii pro health a debug, `config.audit()` cesty k heslům
|
|
884
|
+
v otevřené podobě. Doslovné `${` zapište jako `$${`. Viz `docs/adr/0001-config-secrets.md`.
|
|
885
|
+
- **Vstup:** `config_dict` se při inicializaci zkopíruje; pozdější změny `config` neovlivní slovník volajícího a naopak.
|
|
886
|
+
- **Opakované volání:** `Config(...)` vrací stále tutéž instanci; odlišná cesta nebo `config_dict` se ignoruje a zaloguje
|
|
887
|
+
se varování.
|
|
888
|
+
|
|
867
889
|
#### Context a autentizace
|
|
868
890
|
|
|
869
891
|
```python
|
|
@@ -1203,26 +1225,26 @@ print(str(log_item)) # "2023-05-15 10:00:00 [SYSTEM] Dokument autorizován"
|
|
|
1203
1225
|
Sjednocený formát pro sledování zdraví služby (health check).
|
|
1204
1226
|
|
|
1205
1227
|
```python
|
|
1206
|
-
from sysnet_pyutils
|
|
1228
|
+
from sysnet_pyutils import InfoType, InfoComponentType, InfoStatusEnum, calculate_status
|
|
1207
1229
|
|
|
1208
1230
|
info = InfoType(name="My Service", version="1.0.0")
|
|
1209
1231
|
|
|
1210
1232
|
# Přidání komponenty (např. MongoDB)
|
|
1211
1233
|
info.components.append(InfoComponentType(
|
|
1212
|
-
|
|
1234
|
+
name="mongo",
|
|
1213
1235
|
status=InfoStatusEnum.GREEN,
|
|
1214
|
-
|
|
1236
|
+
message="Connected to localhost:27017"
|
|
1215
1237
|
))
|
|
1216
1238
|
|
|
1217
1239
|
# Přidání další komponenty s chybou
|
|
1218
1240
|
info.components.append(InfoComponentType(
|
|
1219
|
-
|
|
1241
|
+
name="storage",
|
|
1220
1242
|
status=InfoStatusEnum.RED,
|
|
1221
|
-
|
|
1243
|
+
message="Disk space low"
|
|
1222
1244
|
))
|
|
1223
1245
|
|
|
1224
1246
|
# Automatický výpočet celkového statusu (RED > YELLOW > GREEN)
|
|
1225
|
-
info.
|
|
1247
|
+
info.status = calculate_status([component.status for component in info.components])
|
|
1226
1248
|
print(info.status) # RED
|
|
1227
1249
|
```
|
|
1228
1250
|
|
|
@@ -1250,19 +1272,19 @@ Knihovna obsahuje komplexní sadu testů s >90% pokrytím kódu.
|
|
|
1250
1272
|
|
|
1251
1273
|
```bash
|
|
1252
1274
|
# Z kořenového adresáře projektu
|
|
1253
|
-
cd
|
|
1275
|
+
cd ~/projects/pyutils
|
|
1254
1276
|
|
|
1255
1277
|
# Všechny testy
|
|
1256
|
-
venv
|
|
1278
|
+
.venv/bin/python -m pytest tests/
|
|
1257
1279
|
|
|
1258
1280
|
# S podrobným výstupem
|
|
1259
|
-
venv
|
|
1281
|
+
.venv/bin/python -m pytest tests/ -v
|
|
1260
1282
|
|
|
1261
1283
|
# S pokrytím kódu
|
|
1262
|
-
venv
|
|
1284
|
+
.venv/bin/python -m pytest tests/ --cov=sysnet_pyutils --cov-report=html
|
|
1263
1285
|
|
|
1264
1286
|
# Konkrétní modul
|
|
1265
|
-
venv
|
|
1287
|
+
.venv/bin/python -m pytest tests/test_utils.py -v
|
|
1266
1288
|
```
|
|
1267
1289
|
|
|
1268
1290
|
### Testovací soubory
|
|
@@ -1287,6 +1309,9 @@ venv\Scripts\python.exe -m pytest tests/test_utils.py -v
|
|
|
1287
1309
|
|
|
1288
1310
|
```
|
|
1289
1311
|
pyutils/
|
|
1312
|
+
├── .github/workflows/ # GitHub Actions CI/CD
|
|
1313
|
+
│ ├── ci.yml # Syntax check, pytest, ruff
|
|
1314
|
+
│ └── release.yml # Ověření verze, testy, build a publikace na PyPI
|
|
1290
1315
|
├── sysnet_pyutils/ # Hlavní balíček
|
|
1291
1316
|
│ ├── __init__.py # Veřejné API
|
|
1292
1317
|
│ ├── utils.py # Hlavní utility modul
|
|
@@ -1316,8 +1341,7 @@ pyutils/
|
|
|
1316
1341
|
├── logs/ # Adresář pro logy
|
|
1317
1342
|
├── pyproject.toml # Build a nástroje
|
|
1318
1343
|
├── requirements.txt # Závislosti (legacy)
|
|
1319
|
-
├──
|
|
1320
|
-
├── upload.cmd # Skript pro publikaci (cmd)
|
|
1344
|
+
├── CHANGELOG.md # Přehled změn a vydání
|
|
1321
1345
|
└── LICENSE
|
|
1322
1346
|
```
|
|
1323
1347
|
|
|
@@ -1326,8 +1350,45 @@ pyutils/
|
|
|
1326
1350
|
1. Implementujte funkci v příslušném modulu
|
|
1327
1351
|
2. Exportujte ji v `sysnet_pyutils/__init__.py`
|
|
1328
1352
|
3. Napište testy v `tests/test_<modul>.py`
|
|
1329
|
-
4. Spusťte testy:
|
|
1330
|
-
5. Aktualizujte `README.md` a `
|
|
1353
|
+
4. Spusťte testy: `.venv/bin/python -m pytest tests/`
|
|
1354
|
+
5. Aktualizujte `README.md` a `CHANGELOG.md`
|
|
1355
|
+
|
|
1356
|
+
### CI/CD
|
|
1357
|
+
|
|
1358
|
+
Automatizaci zajišťují GitHub Actions na self-hosted runneru s Pythonem 3.11:
|
|
1359
|
+
|
|
1360
|
+
| Workflow | Spuštění | Kroky |
|
|
1361
|
+
|----------|----------|-------|
|
|
1362
|
+
| [`.github/workflows/ci.yml`](.github/workflows/ci.yml) | Každý push na `main` a pull request do `main` | Kontrola syntaxe (`compileall`), testy (`pytest`) a lint (`ruff`) |
|
|
1363
|
+
| [`.github/workflows/release.yml`](.github/workflows/release.yml) | Push tagu `v*` | Ověření verze, kontrola syntaxe a testy, build balíčku a publikace na PyPI |
|
|
1364
|
+
|
|
1365
|
+
Obě workflow používají čistý checkout, před instalací mažou pip cache a pro testy
|
|
1366
|
+
instalují `.[dev,cron,mongodb]`, včetně potřebných volitelných závislostí.
|
|
1367
|
+
Ruff je v CI zatím **informativní** (`ruff check sysnet_pyutils/ || true`);
|
|
1368
|
+
chyby syntaxe a testů naopak workflow zastaví.
|
|
1369
|
+
|
|
1370
|
+
Release workflow porovnává tag bez prefixu `v` s verzí v `pyproject.toml`.
|
|
1371
|
+
Při nesouladu nebo selhání testů se nepublikuje. Po úspěšných kontrolách
|
|
1372
|
+
vytvoří distribuční balíčky pomocí `python -m build` a nahraje je přes `twine`.
|
|
1373
|
+
GitHub secret **`PYPI_API_TOKEN` je nastaven v repozitáři** a poskytuje token pro PyPI;
|
|
1374
|
+
token nepatří do zdrojového kódu.
|
|
1375
|
+
|
|
1376
|
+
#### Vydání nové verze
|
|
1377
|
+
|
|
1378
|
+
1. Změňte `version` v `pyproject.toml` (například na `1.8.0`) a aktualizujte dokumentaci včetně changelogu a badge.
|
|
1379
|
+
2. Commitněte změny a dostaňte je na `main`; před vytvořením tagu ověřte úspěšné CI a správný release commit.
|
|
1380
|
+
3. Na tomto commitu vytvořte a odešlete odpovídající tag:
|
|
1381
|
+
|
|
1382
|
+
```bash
|
|
1383
|
+
git tag v1.8.0 && git push origin v1.8.0
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
4. GitHub Actions automaticky provedou kontroly, build a publikaci.
|
|
1387
|
+
Výsledek sledujte v [Release workflow](https://github.com/SYSNET-CZ/pyutils/actions/workflows/release.yml).
|
|
1388
|
+
|
|
1389
|
+
Původní ruční postup (`python -m build` a `twine upload`, dříve i Windows skripty
|
|
1390
|
+
`upload.ps1` a `upload.cmd`, odstraněné ve verzi 1.7.12) je nahrazen touto pipeline;
|
|
1391
|
+
při běžném vydání již lokálně nic nenahrávejte na PyPI.
|
|
1331
1392
|
|
|
1332
1393
|
---
|
|
1333
1394
|
|
|
@@ -1346,6 +1407,38 @@ pyutils/
|
|
|
1346
1407
|
|
|
1347
1408
|
## 📚 Changelog
|
|
1348
1409
|
|
|
1410
|
+
Podrobnosti nových změn jsou v [CHANGELOG.md](CHANGELOG.md).
|
|
1411
|
+
|
|
1412
|
+
### Verze 1.8.0 (2026-10-27)
|
|
1413
|
+
|
|
1414
|
+
- 🔐 `Config`: ochrana secrets. Hodnotu v YAML lze zadat odkazem `${env:NAZEV}` nebo `${file:/absolutni/cesta}`; rozlišuje se při načtení na nový typ `Secret` (maskovaný `repr`, `str` a log), `store()` zapisuje zpět odkaz, nikdy hodnotu. Nově `Config.redacted()` a `Config.audit()`. Viz `docs/adr/0001-config-secrets.md`.
|
|
1415
|
+
- 💾 `Config.store()` a `replace()` zapisují atomicky (dočasný soubor + přejmenování); nový soubor má práva 600, chybějící adresáře se vytvoří s právy 700.
|
|
1416
|
+
- ⚠️ `Config` bez `config_dict` má `config == {}` místo `None` a nezapisuje `null`; `config_dict` se při inicializaci kopíruje; YAML se ukládá čitelně (diakritika) a v pořadí klíčů z paměti. První `store()` po upgradu přepíše soubor v novém formátu.
|
|
1417
|
+
- ✅ `ConfigParseError` pro poškozený YAML (i `yaml.YAMLError`), výchozí cesta z `PYUTILS_CONFIG_PATH`, opt-in `merge_defaults=True`, varování při ignorovaných parametrech opakovaného `Config(...)`.
|
|
1418
|
+
|
|
1419
|
+
Podrobnosti a dopady na stávající aplikace jsou v [CHANGELOG.md](CHANGELOG.md).
|
|
1420
|
+
|
|
1421
|
+
### Verze 1.7.12 (2026-10-27)
|
|
1422
|
+
|
|
1423
|
+
- ✅ GitHub Actions CI/CD: kontrola syntaxe, pytest a ruff při push/PR na `main`; ověření verze, testy, build a publikace na PyPI při tagu `v*`.
|
|
1424
|
+
- ✅ Opraveny starší chyby v `tests/test_models_general.py`: `InfoComponentType(code=...)` → `name=...`, neexistující `update_status()` → funkce `calculate_status()`.
|
|
1425
|
+
- ✅ Doplněny veřejné exporty `InfoComponentType`, `InfoStatusEnum`, `InfoType` a `calculate_status` v `sysnet_pyutils/__init__.py`.
|
|
1426
|
+
- ✅ Ukázka Info/Health výše odpovídá aktuálnímu API (`name`, `message`, `calculate_status`).
|
|
1427
|
+
|
|
1428
|
+
- 🧹 Odstraněny sledované pomocné soubory (`mypy_*.txt`, `upload.cmd`, `upload.ps1`, `run_pytest.py`, `REVIZE_PROJEKTU.md`); Windows cesty v README a `CLAUDE.md` nahrazeny linuxovými.
|
|
1429
|
+
|
|
1430
|
+
### Verze 1.7.11 (2026-09-25)
|
|
1431
|
+
|
|
1432
|
+
- ✅ `MetadataEssentialType.creator: str | None` — sjednocení s `MetadataTypeBase`, výchozí hodnota `None` (#10229).
|
|
1433
|
+
|
|
1434
|
+
### Verze 1.7.10 (2026-09-25)
|
|
1435
|
+
|
|
1436
|
+
- ✅ `MetadataEssentialType.creator_organization: LinkedType | None` — organizace tvůrce i v základních metadatech, výchozí hodnota `None` (#10229).
|
|
1437
|
+
|
|
1438
|
+
### Verze 1.7.9 (2026-09-25)
|
|
1439
|
+
|
|
1440
|
+
- ✅ `MetadataTypeBase.creator_organization: LinkedType | None` — organizace tvůrce dokumentu, výchozí hodnota `None` (#10229).
|
|
1441
|
+
|
|
1349
1442
|
### Verze 1.7.6 (2026-06-19)
|
|
1350
1443
|
|
|
1351
1444
|
**Nové funkce:**
|
|
@@ -1462,6 +1555,6 @@ Tento projekt je licencován pod MIT licencí — viz [LICENSE](LICENSE) soubor.
|
|
|
1462
1555
|
|
|
1463
1556
|
**Vytvořeno s ❤️ týmem SYSNET**
|
|
1464
1557
|
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1558
|
+
*Verze: 1.8.0*
|
|
1559
|
+
|
|
1560
|
+
*Datum: 2026-10-27*
|
|
@@ -6,7 +6,8 @@ Knihovna obsahuje základní, v aplikacích hojně používané, utility pro Pyt
|
|
|
6
6
|
|
|
7
7
|
[](https://www.python.org/downloads/)
|
|
8
8
|
[](LICENSE)
|
|
9
|
-
[](https://pypi.org/project/sysnet-pyutils/1.8.0/)
|
|
10
|
+
[](https://github.com/SYSNET-CZ/pyutils/actions/workflows/ci.yml)
|
|
10
11
|
[](tests/)
|
|
11
12
|
|
|
12
13
|
---
|
|
@@ -30,6 +31,7 @@ Knihovna obsahuje základní, v aplikacích hojně používané, utility pro Pyt
|
|
|
30
31
|
- [Volitelné závislosti](#volitelné-závislosti)
|
|
31
32
|
- [Testování](#testování)
|
|
32
33
|
- [Vývoj](#vývoj)
|
|
34
|
+
- [CI/CD](#cicd)
|
|
33
35
|
- [Systémové proměnné](#systémové-proměnné)
|
|
34
36
|
- [Changelog](#changelog)
|
|
35
37
|
- [Podpora](#podpora)
|
|
@@ -141,6 +143,26 @@ if config.loaded:
|
|
|
141
143
|
db_url = config.config['database']
|
|
142
144
|
```
|
|
143
145
|
|
|
146
|
+
Chování `Config`:
|
|
147
|
+
|
|
148
|
+
- **Soubor:** ukládá se atomicky (dočasný soubor + přejmenování), čitelně (diakritika bez `\u` escape) a v pořadí klíčů z paměti. Nový soubor má práva 600 a chybějící adresáře
|
|
149
|
+
se vytvoří s právy 700; práva existujícího souboru se nemění a volnější než 600 se při načtení zalogují jako varování.
|
|
150
|
+
- **Výchozí cesta:** nezadáte-li `config_path`, použije se proměnná prostředí `PYUTILS_CONFIG_PATH`. Bez ní platí dosavadní
|
|
151
|
+
umístění `conf/config.yml` vedle modulu (s varováním); není-li zapisovatelné, vyhodí se `ConfigError` s radou.
|
|
152
|
+
- **Chyby:** poškozený YAML vyhodí `ConfigParseError` (podtřída `ConfigError` i `yaml.YAMLError`) s cestou, popisem a
|
|
153
|
+
řádkem, nikdy s obsahem souboru; soubor zůstane nepřepsaný.
|
|
154
|
+
- **Nové výchozí hodnoty:** s existujícím souborem se `config_dict` ignoruje. Chcete-li po upgradu aplikace doplnit chybějící
|
|
155
|
+
klíče, použijte `Config(config_path=..., config_dict=..., merge_defaults=True)`: doplní se jen to, co v souboru chybí
|
|
156
|
+
(vnořené slovníky do hloubky, seznamy ne) a hodnoty ze souboru se nikdy nepřepíšou.
|
|
157
|
+
- **Secrets:** hodnotu v YAML lze zadat odkazem `${env:NAZEV}` nebo `${file:/absolutni/cesta}` (i uvnitř textu, např.
|
|
158
|
+
`mongodb://u:${env:MONGO_PASSWORD}@h`); rozliší se při načtení na `Secret` (podtřída `str`, `repr` a log maskované,
|
|
159
|
+
`reveal()` vrací čistý `str`). Chybějící zdroj je `ConfigError`, nikdy tichý prázdný řetězec. `store()` zapisuje
|
|
160
|
+
zpět odkaz, nikdy hodnotu. `config.redacted()` vrací kopii pro health a debug, `config.audit()` cesty k heslům
|
|
161
|
+
v otevřené podobě. Doslovné `${` zapište jako `$${`. Viz `docs/adr/0001-config-secrets.md`.
|
|
162
|
+
- **Vstup:** `config_dict` se při inicializaci zkopíruje; pozdější změny `config` neovlivní slovník volajícího a naopak.
|
|
163
|
+
- **Opakované volání:** `Config(...)` vrací stále tutéž instanci; odlišná cesta nebo `config_dict` se ignoruje a zaloguje
|
|
164
|
+
se varování.
|
|
165
|
+
|
|
144
166
|
#### Context a autentizace
|
|
145
167
|
|
|
146
168
|
```python
|
|
@@ -480,26 +502,26 @@ print(str(log_item)) # "2023-05-15 10:00:00 [SYSTEM] Dokument autorizován"
|
|
|
480
502
|
Sjednocený formát pro sledování zdraví služby (health check).
|
|
481
503
|
|
|
482
504
|
```python
|
|
483
|
-
from sysnet_pyutils
|
|
505
|
+
from sysnet_pyutils import InfoType, InfoComponentType, InfoStatusEnum, calculate_status
|
|
484
506
|
|
|
485
507
|
info = InfoType(name="My Service", version="1.0.0")
|
|
486
508
|
|
|
487
509
|
# Přidání komponenty (např. MongoDB)
|
|
488
510
|
info.components.append(InfoComponentType(
|
|
489
|
-
|
|
511
|
+
name="mongo",
|
|
490
512
|
status=InfoStatusEnum.GREEN,
|
|
491
|
-
|
|
513
|
+
message="Connected to localhost:27017"
|
|
492
514
|
))
|
|
493
515
|
|
|
494
516
|
# Přidání další komponenty s chybou
|
|
495
517
|
info.components.append(InfoComponentType(
|
|
496
|
-
|
|
518
|
+
name="storage",
|
|
497
519
|
status=InfoStatusEnum.RED,
|
|
498
|
-
|
|
520
|
+
message="Disk space low"
|
|
499
521
|
))
|
|
500
522
|
|
|
501
523
|
# Automatický výpočet celkového statusu (RED > YELLOW > GREEN)
|
|
502
|
-
info.
|
|
524
|
+
info.status = calculate_status([component.status for component in info.components])
|
|
503
525
|
print(info.status) # RED
|
|
504
526
|
```
|
|
505
527
|
|
|
@@ -527,19 +549,19 @@ Knihovna obsahuje komplexní sadu testů s >90% pokrytím kódu.
|
|
|
527
549
|
|
|
528
550
|
```bash
|
|
529
551
|
# Z kořenového adresáře projektu
|
|
530
|
-
cd
|
|
552
|
+
cd ~/projects/pyutils
|
|
531
553
|
|
|
532
554
|
# Všechny testy
|
|
533
|
-
venv
|
|
555
|
+
.venv/bin/python -m pytest tests/
|
|
534
556
|
|
|
535
557
|
# S podrobným výstupem
|
|
536
|
-
venv
|
|
558
|
+
.venv/bin/python -m pytest tests/ -v
|
|
537
559
|
|
|
538
560
|
# S pokrytím kódu
|
|
539
|
-
venv
|
|
561
|
+
.venv/bin/python -m pytest tests/ --cov=sysnet_pyutils --cov-report=html
|
|
540
562
|
|
|
541
563
|
# Konkrétní modul
|
|
542
|
-
venv
|
|
564
|
+
.venv/bin/python -m pytest tests/test_utils.py -v
|
|
543
565
|
```
|
|
544
566
|
|
|
545
567
|
### Testovací soubory
|
|
@@ -564,6 +586,9 @@ venv\Scripts\python.exe -m pytest tests/test_utils.py -v
|
|
|
564
586
|
|
|
565
587
|
```
|
|
566
588
|
pyutils/
|
|
589
|
+
├── .github/workflows/ # GitHub Actions CI/CD
|
|
590
|
+
│ ├── ci.yml # Syntax check, pytest, ruff
|
|
591
|
+
│ └── release.yml # Ověření verze, testy, build a publikace na PyPI
|
|
567
592
|
├── sysnet_pyutils/ # Hlavní balíček
|
|
568
593
|
│ ├── __init__.py # Veřejné API
|
|
569
594
|
│ ├── utils.py # Hlavní utility modul
|
|
@@ -593,8 +618,7 @@ pyutils/
|
|
|
593
618
|
├── logs/ # Adresář pro logy
|
|
594
619
|
├── pyproject.toml # Build a nástroje
|
|
595
620
|
├── requirements.txt # Závislosti (legacy)
|
|
596
|
-
├──
|
|
597
|
-
├── upload.cmd # Skript pro publikaci (cmd)
|
|
621
|
+
├── CHANGELOG.md # Přehled změn a vydání
|
|
598
622
|
└── LICENSE
|
|
599
623
|
```
|
|
600
624
|
|
|
@@ -603,8 +627,45 @@ pyutils/
|
|
|
603
627
|
1. Implementujte funkci v příslušném modulu
|
|
604
628
|
2. Exportujte ji v `sysnet_pyutils/__init__.py`
|
|
605
629
|
3. Napište testy v `tests/test_<modul>.py`
|
|
606
|
-
4. Spusťte testy:
|
|
607
|
-
5. Aktualizujte `README.md` a `
|
|
630
|
+
4. Spusťte testy: `.venv/bin/python -m pytest tests/`
|
|
631
|
+
5. Aktualizujte `README.md` a `CHANGELOG.md`
|
|
632
|
+
|
|
633
|
+
### CI/CD
|
|
634
|
+
|
|
635
|
+
Automatizaci zajišťují GitHub Actions na self-hosted runneru s Pythonem 3.11:
|
|
636
|
+
|
|
637
|
+
| Workflow | Spuštění | Kroky |
|
|
638
|
+
|----------|----------|-------|
|
|
639
|
+
| [`.github/workflows/ci.yml`](.github/workflows/ci.yml) | Každý push na `main` a pull request do `main` | Kontrola syntaxe (`compileall`), testy (`pytest`) a lint (`ruff`) |
|
|
640
|
+
| [`.github/workflows/release.yml`](.github/workflows/release.yml) | Push tagu `v*` | Ověření verze, kontrola syntaxe a testy, build balíčku a publikace na PyPI |
|
|
641
|
+
|
|
642
|
+
Obě workflow používají čistý checkout, před instalací mažou pip cache a pro testy
|
|
643
|
+
instalují `.[dev,cron,mongodb]`, včetně potřebných volitelných závislostí.
|
|
644
|
+
Ruff je v CI zatím **informativní** (`ruff check sysnet_pyutils/ || true`);
|
|
645
|
+
chyby syntaxe a testů naopak workflow zastaví.
|
|
646
|
+
|
|
647
|
+
Release workflow porovnává tag bez prefixu `v` s verzí v `pyproject.toml`.
|
|
648
|
+
Při nesouladu nebo selhání testů se nepublikuje. Po úspěšných kontrolách
|
|
649
|
+
vytvoří distribuční balíčky pomocí `python -m build` a nahraje je přes `twine`.
|
|
650
|
+
GitHub secret **`PYPI_API_TOKEN` je nastaven v repozitáři** a poskytuje token pro PyPI;
|
|
651
|
+
token nepatří do zdrojového kódu.
|
|
652
|
+
|
|
653
|
+
#### Vydání nové verze
|
|
654
|
+
|
|
655
|
+
1. Změňte `version` v `pyproject.toml` (například na `1.8.0`) a aktualizujte dokumentaci včetně changelogu a badge.
|
|
656
|
+
2. Commitněte změny a dostaňte je na `main`; před vytvořením tagu ověřte úspěšné CI a správný release commit.
|
|
657
|
+
3. Na tomto commitu vytvořte a odešlete odpovídající tag:
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
git tag v1.8.0 && git push origin v1.8.0
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
4. GitHub Actions automaticky provedou kontroly, build a publikaci.
|
|
664
|
+
Výsledek sledujte v [Release workflow](https://github.com/SYSNET-CZ/pyutils/actions/workflows/release.yml).
|
|
665
|
+
|
|
666
|
+
Původní ruční postup (`python -m build` a `twine upload`, dříve i Windows skripty
|
|
667
|
+
`upload.ps1` a `upload.cmd`, odstraněné ve verzi 1.7.12) je nahrazen touto pipeline;
|
|
668
|
+
při běžném vydání již lokálně nic nenahrávejte na PyPI.
|
|
608
669
|
|
|
609
670
|
---
|
|
610
671
|
|
|
@@ -623,6 +684,38 @@ pyutils/
|
|
|
623
684
|
|
|
624
685
|
## 📚 Changelog
|
|
625
686
|
|
|
687
|
+
Podrobnosti nových změn jsou v [CHANGELOG.md](CHANGELOG.md).
|
|
688
|
+
|
|
689
|
+
### Verze 1.8.0 (2026-10-27)
|
|
690
|
+
|
|
691
|
+
- 🔐 `Config`: ochrana secrets. Hodnotu v YAML lze zadat odkazem `${env:NAZEV}` nebo `${file:/absolutni/cesta}`; rozlišuje se při načtení na nový typ `Secret` (maskovaný `repr`, `str` a log), `store()` zapisuje zpět odkaz, nikdy hodnotu. Nově `Config.redacted()` a `Config.audit()`. Viz `docs/adr/0001-config-secrets.md`.
|
|
692
|
+
- 💾 `Config.store()` a `replace()` zapisují atomicky (dočasný soubor + přejmenování); nový soubor má práva 600, chybějící adresáře se vytvoří s právy 700.
|
|
693
|
+
- ⚠️ `Config` bez `config_dict` má `config == {}` místo `None` a nezapisuje `null`; `config_dict` se při inicializaci kopíruje; YAML se ukládá čitelně (diakritika) a v pořadí klíčů z paměti. První `store()` po upgradu přepíše soubor v novém formátu.
|
|
694
|
+
- ✅ `ConfigParseError` pro poškozený YAML (i `yaml.YAMLError`), výchozí cesta z `PYUTILS_CONFIG_PATH`, opt-in `merge_defaults=True`, varování při ignorovaných parametrech opakovaného `Config(...)`.
|
|
695
|
+
|
|
696
|
+
Podrobnosti a dopady na stávající aplikace jsou v [CHANGELOG.md](CHANGELOG.md).
|
|
697
|
+
|
|
698
|
+
### Verze 1.7.12 (2026-10-27)
|
|
699
|
+
|
|
700
|
+
- ✅ GitHub Actions CI/CD: kontrola syntaxe, pytest a ruff při push/PR na `main`; ověření verze, testy, build a publikace na PyPI při tagu `v*`.
|
|
701
|
+
- ✅ Opraveny starší chyby v `tests/test_models_general.py`: `InfoComponentType(code=...)` → `name=...`, neexistující `update_status()` → funkce `calculate_status()`.
|
|
702
|
+
- ✅ Doplněny veřejné exporty `InfoComponentType`, `InfoStatusEnum`, `InfoType` a `calculate_status` v `sysnet_pyutils/__init__.py`.
|
|
703
|
+
- ✅ Ukázka Info/Health výše odpovídá aktuálnímu API (`name`, `message`, `calculate_status`).
|
|
704
|
+
|
|
705
|
+
- 🧹 Odstraněny sledované pomocné soubory (`mypy_*.txt`, `upload.cmd`, `upload.ps1`, `run_pytest.py`, `REVIZE_PROJEKTU.md`); Windows cesty v README a `CLAUDE.md` nahrazeny linuxovými.
|
|
706
|
+
|
|
707
|
+
### Verze 1.7.11 (2026-09-25)
|
|
708
|
+
|
|
709
|
+
- ✅ `MetadataEssentialType.creator: str | None` — sjednocení s `MetadataTypeBase`, výchozí hodnota `None` (#10229).
|
|
710
|
+
|
|
711
|
+
### Verze 1.7.10 (2026-09-25)
|
|
712
|
+
|
|
713
|
+
- ✅ `MetadataEssentialType.creator_organization: LinkedType | None` — organizace tvůrce i v základních metadatech, výchozí hodnota `None` (#10229).
|
|
714
|
+
|
|
715
|
+
### Verze 1.7.9 (2026-09-25)
|
|
716
|
+
|
|
717
|
+
- ✅ `MetadataTypeBase.creator_organization: LinkedType | None` — organizace tvůrce dokumentu, výchozí hodnota `None` (#10229).
|
|
718
|
+
|
|
626
719
|
### Verze 1.7.6 (2026-06-19)
|
|
627
720
|
|
|
628
721
|
**Nové funkce:**
|
|
@@ -739,6 +832,6 @@ Tento projekt je licencován pod MIT licencí — viz [LICENSE](LICENSE) soubor.
|
|
|
739
832
|
|
|
740
833
|
**Vytvořeno s ❤️ týmem SYSNET**
|
|
741
834
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
835
|
+
*Verze: 1.8.0*
|
|
836
|
+
|
|
837
|
+
*Datum: 2026-10-27*
|
|
@@ -123,9 +123,11 @@ from sysnet_pyutils.utils import ( # API klíče; Konverze; Hashe; Base64; Vali
|
|
|
123
123
|
Config,
|
|
124
124
|
ConfigError,
|
|
125
125
|
ConfigFlag,
|
|
126
|
+
ConfigParseError,
|
|
126
127
|
Context,
|
|
127
128
|
Log,
|
|
128
129
|
LoggedObject,
|
|
130
|
+
Secret,
|
|
129
131
|
Singleton,
|
|
130
132
|
api_key_generate,
|
|
131
133
|
api_key_next,
|