Skip to content

merge feature/2/create-first-version #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Mar 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f9939c6
[#2]: initialize python project; done with:
dd-ssc Mar 10, 2025
df1a257
[#2]: align python project conf with corporate convention, extend:
dd-ssc Mar 10, 2025
6747326
[#2]: get `uv sync` to work; add uv.lock; done with:
dd-ssc Mar 10, 2025
597989a
[#2]: $ (cd code/python && uv add keyring)
dd-ssc Mar 10, 2025
f033368
[#2]: $ (cd code/python && uv add --group dev ruff)
dd-ssc Mar 10, 2025
7384d79
[#2]: implement the very first version of the backend; add py.typed
dd-ssc Mar 11, 2025
fd144d6
[#2]: make keyring load backend: conf project entry points; doc issues
dd-ssc Mar 11, 2025
02e8d82
[#2]: $ (cd code/python && uv add platformdirs pydantic PyYAML rich)
dd-ssc Mar 11, 2025
ddd60fe
[#2]: add conf file model; process conf, set up logging; add conf file
dd-ssc Mar 11, 2025
1806b19
[#2]: add data file; add to conf file model/conf; use it; add func docs
dd-ssc Mar 13, 2025
ac5da62
[#2]: ruff doesn't show any live issues in VS Code; remove:
dd-ssc Mar 18, 2025
f1e01d4
[#2]: enable live issues in VS Code: add VS Code conf file
dd-ssc Mar 18, 2025
9cf6a91
[#2]: suppress pyright issue; doc keyring issue; add doc and TODO
dd-ssc Mar 18, 2025
3b2219b
[#2]: doc issues with rich logging ./. two backends; work around
dd-ssc Mar 18, 2025
a5bc498
[#2]: add a pydantic model for python logging configuration, many TODOs;
dd-ssc Mar 21, 2025
6c7391a
[#2]: add pydantic model for rich logging conf extending logging conf
dd-ssc Mar 21, 2025
cee34a2
[#2]: add conf for console and reference to it in handler conf
dd-ssc Mar 21, 2025
294d5b5
[#2]: move sample log output to match flow and simplify coming changes
dd-ssc Mar 21, 2025
9cdf830
[#2]: adapt to reviewed conf data model: prep log root wherever needed
dd-ssc Mar 21, 2025
f61895e
[#2]: refactor to using reviewed conf data model: process console confs,
dd-ssc Mar 21, 2025
b111e67
[#2]: review approach to methods: do not return values, but set members;
dd-ssc Mar 21, 2025
6ab2ec5
[#2]: gitlab.com project deploy tokens were rotated: update local copies
dd-ssc Mar 22, 2025
1ad9466
[#2]: add first GitHub Action / CI/CD conf: do setup, run `uv sync`
dd-ssc Mar 23, 2025
e7b17d6
[#2]: add second GitHub Action / CI/CD conf: do setup, run `uv build`;
dd-ssc Mar 23, 2025
389a002
[#2]: add third GitHub Action / CI/CD conf: do setup, run `uv publish`;
dd-ssc Mar 23, 2025
f897d0d
[#2]: add link to medium.com article, update Publish GitHub Action
dd-ssc Mar 23, 2025
52763a6
[#2]: manually increase project version number: 0.0.0 -> 0.0.1
dd-ssc Mar 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
# build.yaml
#
# GitHub Action Build Workflow CI/CD configuration.
#
# author : stefan schablowski
# contact : stefan.schablowski@desmodyne.com
# created : 2025-03-23


# uv > Using uv in GitHub Actions:
# https://docs.astral.sh/uv/guides/integration/github


name: Build
on: [push]

jobs:
build:
name: build
runs-on: ubuntu-latest

steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5
with:
version: 0.6.9

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: code/python/pyproject.toml

- name: Run `uv build`
run: uv build --directory code/python
49 changes: 49 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
# publish.yaml
#
# GitHub Action Publish Workflow CI/CD configuration.
#
# author : stefan schablowski
# contact : stefan.schablowski@desmodyne.com
# created : 2025-03-23


# taken from "Step 3" at
# https://medium.com/@blackary/ ...
# ... publishing-a-python-package-from-github-to-pypi-in-2024-a6fb8635d45d


name: Publish
on:
release:
types: [created]

jobs:
publish:
environment:
name: pypi
url: https://pypi.org/p/keyring-insecure-backend
name: publish
permissions:
id-token: write
runs-on: ubuntu-latest

steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5
with:
version: 0.6.9

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: code/python/pyproject.toml

- name: Run `uv build`
run: uv build --directory code/python

- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
37 changes: 37 additions & 0 deletions .github/workflows/sync.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
# sync.yaml
#
# GitHub Action Sync Workflow CI/CD configuration.
#
# author : stefan schablowski
# contact : stefan.schablowski@desmodyne.com
# created : 2025-03-23


# see ./build.yaml


name: Sync
on: [push]

jobs:
sync:
name: sync
runs-on: ubuntu-latest

steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5
with:
version: 0.6.9

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: code/python/pyproject.toml

- name: Run `uv sync`
run: uv sync --directory code/python
51 changes: 51 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// settings.json
//
// Visual Studio Code workspace settings
//
// author : stefan schablowski
// contact : stefan.schablowski@desmodyne.com
// created : 2021-09-25


// NOTE: file suffix says .json, but actual file format is some proprietary
// Microsoft mess: mostly a json file, but with JavaScript-style (?) comments;
// can't be read/modified or even displayed properly by regular json tools :-/

// NOTE: VS Code user ./. workspace settings:
// + user settings are stored in
// $HOME/Library/Application Support/Code/User/settings.json
// + workspace settings are stored in
// .../.vscode/settings.json
// + workspace settings take precedence over user settings:
// https://code.visualstudio.com/docs/getstarted/settings#_settings-precedence
//
// TODO: review VS Code settings, move from user to workspace settings
// TODO: review VS Code analysis / linting / etc. settings:
// https://code.visualstudio.com/docs/python/settings-reference


{
// make auto indentation less dumb
"editor.autoIndent": "advanced",
// display a vertical line at 80 characters
"editor.rulers": [ 80 ],

// remove trailing whitespace upon saving files
"files.trimTrailingWhitespace": true,

// pylance > pyright settings
"python.analysis.diagnosticMode": "workspace",
"python.analysis.exclude": [
"attic",
"code/python/.venv",
"doc/python/.venv",
"tmp"
],
"python.analysis.typeCheckingMode": "strict",

// NOTE: one single argument is probably not worth creating a shell frontend
"shellcheck.customArgs": [
"--enable=all",
"-x"
]
}
33 changes: 33 additions & 0 deletions code/python/keyring_insecure_backend/ConfFileModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python
# encoding: utf-8

"""
ConfFileModel.py

Insecure Keyring Backend configuration file data model.

author : stefan schablowski
contact : stefan.schablowski@desmodyne.com
created : 2025-03-11
"""


from pathlib import Path

# https://pypi.org/project/pydantic
from pydantic import BaseModel, ConfigDict

from .ConfRichLoggingModel import ConfRichLoggingModel


# -----------------------------------------------------------------------------
# public types

class ConfFileModel(BaseModel):
"""
Pydantic model that defines configuration file attributes.
"""

model_config = ConfigDict(extra='forbid')
logging: ConfRichLoggingModel
path_to_data_file: Path
149 changes: 149 additions & 0 deletions code/python/keyring_insecure_backend/ConfLoggingModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env python
# encoding: utf-8

"""
ConfLoggingModel.py

Python logging configuration data model.

author : stefan schablowski
contact : stefan.schablowski@desmodyne.com
created : 2025-03-18
"""


# python > logging > configuration:
# https://docs.python.org/3/library/logging.config.html
# python > logging > configuration > data model:
# https://docs.python.org/3/library/logging.config.html#dictionary-schema-details


# TODO: add validators to ensure logging objects reference valid other objects
# TODO: support user-defined objects ?
# https://docs.python.org/3/library/logging.config.html#user-defined-objects


from typing import Any, Dict, List, Literal, Optional

# https://pypi.org/project/pydantic
from pydantic import BaseModel, ConfigDict, Field


# -----------------------------------------------------------------------------
# supporting types

class ConfLoggingFilterModel(BaseModel):
"""
Pydantic helper model that defines logging filter conf attrbutes.
"""

# https://docs.python.org/3/library/logging.html#logging.Filter

model_config = ConfigDict(extra='forbid')
name: Optional[str] = None


class ConfLoggingFormatterModel(BaseModel):
"""
Pydantic helper model that defines logging formatter conf attrbutes.
"""

# https://docs.python.org/3/library/logging.html#logging.Formatter

model_config = ConfigDict(extra='forbid')
# NOTE: 'class' obviously is a python keyword; use alias to work around:
# https://stackoverflow.com/a/70584815
# https://docs.pydantic.dev/latest/concepts/fields/#field-aliases
# TODO: restrict to dot notation / valid class names ?
class_: Optional[str] = Field(alias = 'class', default = None)
# TODO: verify this is a valid date format ?
datefmt: Optional[str] = None
defaults: Optional[Dict[str, Any]] = None
# TODO: verify this is a valid log message format ?
format: Optional[str] = None
# TODO: restrict to '%', '{' or '$'
style: Optional[str] = None
# NOTE: 'validate' is a BaseModel method; see class_ above
validate_: Optional[bool] = Field(alias = 'validate', default = None)


class ConfLoggingHandlerModel(BaseModel):
"""
Pydantic helper model that defines logging handler conf attrbutes.
"""

# https://docs.python.org/3/library/logging.html#logging.Handler
# however, most useful info is in the handlers section at
# https://docs.python.org/3/library/logging.config.html ...
# ... #dictionary-schema-details

# from above page:
# > All other keys are passed through as keyword
# > arguments to the handler’s constructor.
# --> do not forbid extra attributes as usual
model_config = ConfigDict(extra='allow')
class_: Optional[str] = Field(alias = 'class', default = None)
filters: Optional[List[str]] = None
formatter: Optional[str] = None
# TODO: restrict to python log levels (?) in upper case (?)
level: Optional[str] = None


class ConfLoggingLoggerModel(BaseModel):
"""
Pydantic helper model that defines logging logger conf attrbutes.
"""

# https://docs.python.org/3/library/logging.html#logging.Logger
# however, most useful info is in the loggers section at
# https://docs.python.org/3/library/logging.config.html ...
# ... #dictionary-schema-details and at
# https://docs.python.org/3/library/logging.config.html ...
# ... #object-connections

model_config = ConfigDict(extra='forbid')
filters: Optional[List[str]] = None
handlers: Optional[List[str]] = None
level: Optional[str] = None
propagate: Optional[bool] = None


# -----------------------------------------------------------------------------
# public types

class ConfLoggingModel(BaseModel):
"""
Pydantic model that defines python logging configuration attributes.
"""

# TODO: python's interpretation of 'optional' seems inconsistent:
# + python logging configuration docs say attributes are optional:
# https://docs.python.org/3/library/logging.config.html ...
# ... #dictionary-schema-details > 'All other keys are optional'
# + from python typing docs at
# https://docs.python.org/3/library/typing.html#typing.Optional:
# > Optional[X] is equivalent to X | None (or Union[X, None]).
# however, using `Optional[...] = None` below as in e.g.
# formatters: Optional[Dict[str, ConfLoggingFormatterModel]] = None
# fails because python code seems to expect empty dictionaries:
# File ".../lib/python3.13/logging/config.py", line 581, in configure
# for name in formatters:
# ^^^^^^^^^^
# TypeError: 'NoneType' object is not iterable
# workaround: use {} as default value instead of None

model_config = ConfigDict(extra='forbid')
# NOTE: attribute order not alphabetical, but follows documentation at
# https://docs.python.org/3/library/logging.config.html ...
# ... #dictionary-schema-details
version: Literal[1]
formatters: Optional[Dict[str, ConfLoggingFormatterModel]] = {}
filters: Optional[Dict[str, ConfLoggingFilterModel]] = {}
handlers: Optional[Dict[str, ConfLoggingHandlerModel]] = {}
loggers: Optional[Dict[str, ConfLoggingLoggerModel]] = {}
# TODO: from https://docs.python.org/3/library/logging.config.html:
# > configuration will be as for any logger,
# > except that the propagate setting will not be applicable
root: Optional[ConfLoggingLoggerModel] = None
incremental: Optional[bool] = None
disable_existing_loggers: Optional[bool] = None
Loading