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.
Files changed (61) hide show
  1. {sysnet_pyutils-1.7.11/sysnet_pyutils.egg-info → sysnet_pyutils-1.8.0}/PKG-INFO +113 -20
  2. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/README.md +112 -19
  3. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/pyproject.toml +1 -1
  4. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/__init__.py +2 -0
  5. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/utils.py +564 -13
  6. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0/sysnet_pyutils.egg-info}/PKG-INFO +113 -20
  7. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/SOURCES.txt +2 -0
  8. sysnet_pyutils-1.8.0/tests/test_config_secrets.py +282 -0
  9. sysnet_pyutils-1.8.0/tests/test_config_store.py +834 -0
  10. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils_missing_branches.py +3 -3
  11. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/LICENSE +0 -0
  12. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/setup.cfg +0 -0
  13. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/barcode.py +0 -0
  14. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/constants.py +0 -0
  15. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/cron_utils/__init__.py +0 -0
  16. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/cron_utils/validation.py +0 -0
  17. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/data_utils.py +0 -0
  18. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/domino.py +0 -0
  19. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/geo.py +0 -0
  20. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/__init__.py +0 -0
  21. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/global_model.py +0 -0
  22. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/models.py +0 -0
  23. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/globalmodel/timeutils.py +0 -0
  24. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/ident.py +0 -0
  25. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/log.py +0 -0
  26. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/models/__init__.py +0 -0
  27. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/models/general.py +0 -0
  28. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/ses.py +0 -0
  29. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/syslog/__init__.py +0 -0
  30. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/syslog/factory.py +0 -0
  31. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils/tools.py +0 -0
  32. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/dependency_links.txt +0 -0
  33. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/not-zip-safe +0 -0
  34. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/requires.txt +0 -0
  35. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/sysnet_pyutils.egg-info/top_level.txt +0 -0
  36. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_cron_utils.py +0 -0
  37. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_cron_validation_edge.py +0 -0
  38. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils.py +0 -0
  39. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils_datetime.py +0 -0
  40. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils_edge.py +0 -0
  41. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_data_utils_missing_branches.py +0 -0
  42. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_domino.py +0 -0
  43. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_domino_edge.py +0 -0
  44. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_geo.py +0 -0
  45. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_global_model_recursive.py +0 -0
  46. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_global_model_timezone.py +0 -0
  47. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_ident_barcode.py +0 -0
  48. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_log_importerror_branch.py +0 -0
  49. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_log_mongo.py +0 -0
  50. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_models_contact.py +0 -0
  51. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_models_general.py +0 -0
  52. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_models_general_edge.py +0 -0
  53. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_package_init_version.py +0 -0
  54. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_recursive_update.py +0 -0
  55. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_ses.py +0 -0
  56. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_ses_importerror_branch.py +0 -0
  57. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_syslog_factory.py +0 -0
  58. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_tools.py +0 -0
  59. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils.py +0 -0
  60. {sysnet_pyutils-1.7.11 → sysnet_pyutils-1.8.0}/tests/test_utils_edge.py +0 -0
  61. {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.7.11
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
  [![Python](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
731
731
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
732
- [![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](tests/)
732
+ [![Verze](https://img.shields.io/badge/version-1.8.0-blue.svg)](https://pypi.org/project/sysnet-pyutils/1.8.0/)
733
+ [![Tests](https://github.com/SYSNET-CZ/pyutils/actions/workflows/ci.yml/badge.svg)](https://github.com/SYSNET-CZ/pyutils/actions/workflows/ci.yml)
733
734
  [![Coverage](https://img.shields.io/badge/coverage-90%25-brightgreen.svg)](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.models.general import InfoType, InfoComponentType, InfoStatusEnum
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
- code="mongo",
1234
+ name="mongo",
1213
1235
  status=InfoStatusEnum.GREEN,
1214
- info="Connected to localhost:27017"
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
- code="storage",
1241
+ name="storage",
1220
1242
  status=InfoStatusEnum.RED,
1221
- info="Disk space low"
1243
+ message="Disk space low"
1222
1244
  ))
1223
1245
 
1224
1246
  # Automatický výpočet celkového statusu (RED > YELLOW > GREEN)
1225
- info.update_status()
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 D:\development\git\pyutils
1275
+ cd ~/projects/pyutils
1254
1276
 
1255
1277
  # Všechny testy
1256
- venv\Scripts\python.exe -m pytest tests/
1278
+ .venv/bin/python -m pytest tests/
1257
1279
 
1258
1280
  # S podrobným výstupem
1259
- venv\Scripts\python.exe -m pytest tests/ -v
1281
+ .venv/bin/python -m pytest tests/ -v
1260
1282
 
1261
1283
  # S pokrytím kódu
1262
- venv\Scripts\python.exe -m pytest tests/ --cov=sysnet_pyutils --cov-report=html
1284
+ .venv/bin/python -m pytest tests/ --cov=sysnet_pyutils --cov-report=html
1263
1285
 
1264
1286
  # Konkrétní modul
1265
- venv\Scripts\python.exe -m pytest tests/test_utils.py -v
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
- ├── upload.ps1 # Skript pro publikaci na PyPI
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: `venv\Scripts\python.exe -m pytest tests/`
1330
- 5. Aktualizujte `README.md` a `REVIZE_PROJEKTU.md`
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
- -*Verze: 1.7.6*
1466
- +*Verze: 1.7.6*
1467
- *Datum: 2026-06-19*
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
  [![Python](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
8
8
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
9
- [![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](tests/)
9
+ [![Verze](https://img.shields.io/badge/version-1.8.0-blue.svg)](https://pypi.org/project/sysnet-pyutils/1.8.0/)
10
+ [![Tests](https://github.com/SYSNET-CZ/pyutils/actions/workflows/ci.yml/badge.svg)](https://github.com/SYSNET-CZ/pyutils/actions/workflows/ci.yml)
10
11
  [![Coverage](https://img.shields.io/badge/coverage-90%25-brightgreen.svg)](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.models.general import InfoType, InfoComponentType, InfoStatusEnum
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
- code="mongo",
511
+ name="mongo",
490
512
  status=InfoStatusEnum.GREEN,
491
- info="Connected to localhost:27017"
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
- code="storage",
518
+ name="storage",
497
519
  status=InfoStatusEnum.RED,
498
- info="Disk space low"
520
+ message="Disk space low"
499
521
  ))
500
522
 
501
523
  # Automatický výpočet celkového statusu (RED > YELLOW > GREEN)
502
- info.update_status()
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 D:\development\git\pyutils
552
+ cd ~/projects/pyutils
531
553
 
532
554
  # Všechny testy
533
- venv\Scripts\python.exe -m pytest tests/
555
+ .venv/bin/python -m pytest tests/
534
556
 
535
557
  # S podrobným výstupem
536
- venv\Scripts\python.exe -m pytest tests/ -v
558
+ .venv/bin/python -m pytest tests/ -v
537
559
 
538
560
  # S pokrytím kódu
539
- venv\Scripts\python.exe -m pytest tests/ --cov=sysnet_pyutils --cov-report=html
561
+ .venv/bin/python -m pytest tests/ --cov=sysnet_pyutils --cov-report=html
540
562
 
541
563
  # Konkrétní modul
542
- venv\Scripts\python.exe -m pytest tests/test_utils.py -v
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
- ├── upload.ps1 # Skript pro publikaci na PyPI
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: `venv\Scripts\python.exe -m pytest tests/`
607
- 5. Aktualizujte `README.md` a `REVIZE_PROJEKTU.md`
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
- -*Verze: 1.7.6*
743
- +*Verze: 1.7.6*
744
- *Datum: 2026-06-19*
835
+ *Verze: 1.8.0*
836
+
837
+ *Datum: 2026-10-27*
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sysnet-pyutils"
7
- version = "1.7.11"
7
+ version = "1.8.0"
8
8
  description = "SYSNET Python Utilities - kompletní sada nástrojů pro Python aplikace"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -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,