Skip to content

Commit

Permalink
Add missing annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
inean committed Sep 14, 2024
1 parent 4c7420d commit 3077758
Show file tree
Hide file tree
Showing 24 changed files with 978 additions and 951 deletions.
11 changes: 6 additions & 5 deletions .github/actions/setup-python-with-uv/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,15 @@ runs:
python-version: ${{ inputs.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v2
run: curl -LsSf https://astral.sh/uv/install.sh | sh
shell: bash

- name: Pin Python Version
run: |
export PYTHONUNBUFFERED=True
uv python pin ${{ steps.extract-python-version.outputs.python-version }}
shell: bash

- name: Install dependencies
run: uv sync ${{ inputs.uv-sync-options}}
shell: bash

- name: Normalize UV Sync Options
id: normalize-uv-sync-options
run: |
Expand All @@ -50,3 +47,7 @@ runs:
with:
path: ~/.cache/uv
key: ${{ runner.os }}-python-${{ steps.extract-python-version.outputs.python-version }}-uv-sync-${{ env.normalized-uv-sync-options }}

- name: Install dependencies
run: uv sync ${{ inputs.uv-sync-options}}
shell: bash
7 changes: 6 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ repos:
pass_filenames: false
stages: [commit]
files: ^pyproject\.toml$
additional_dependencies: [toml]

- id: mypy
name: mypy
language: system
types: [python]
entry: uv run mypy --strict

- id: pyupgrade
name: Pyupgrade
Expand Down
43 changes: 41 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ dns-synchub = "dns_synchub:main"

[tool.uv]
dev-dependencies = [
# lint
"mypy>=1.11.2",
"pre-commit>=3.7.1",
"pyupgrade>=3.16.0",
"ruff>=0.5.4",
Expand Down Expand Up @@ -69,7 +71,9 @@ filterwarnings = [

[tool.coverage.run]
branch = true
source = 'dns_synchub'
source = [
'dns_synchub',
]
context = '${CONTEXT}'

[tool.coverage.report]
Expand All @@ -83,7 +87,9 @@ exclude_lines = [
]

[tool.coverage.paths]
source = 'src/dns_synchub/'
source = [
'src/dns_synchub/',
]

[tool.ruff]
# set max-line-length to 100
Expand Down Expand Up @@ -150,3 +156,36 @@ keep-runtime-typing = true
[tool.deptry]
root = 'src/dns_synchub'

[tool.mypy]
mypy_path = "types"
files = [
"src/",
"tests/",
]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
namespace_packages = true
no_implicit_reexport = true
python_version = '3.11'
show_error_codes = true
strict_optional = true
warn_redundant_casts = true
warn_unused_configs = true
warn_unused_ignores = true

# for strict mypy: (this is the tricky one :-))
disallow_untyped_defs = true

# remaining arguments from `mypy --strict` which cause errors
# no_implicit_optional = true
# warn_return_any = true

[[tool.mypy.overrides]]
module = [
'dotenv.*',
]
ignore_missing_imports = true
35 changes: 17 additions & 18 deletions scripts/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import argparse
import os
import sys
import tomllib

import toml
TOML_FILE = 'pyproject.toml'
DATA_FILE = 'src/dns_synchub/__about__.py'

TOML_FILE = "pyproject.toml"
DATA_FILE = "src/dns_synchub/__about__.py"


def update_version(toml_file: str | None = None, data_file: str | None = None):
def update_version(toml_file: str | None = None, data_file: str | None = None) -> None:
# Get the current working directory
current_dir = os.getcwd()

Expand All @@ -23,39 +22,39 @@ def update_version(toml_file: str | None = None, data_file: str | None = None):
sys.stderr.write(f"Source file '{toml_file}' not found\n")
sys.exit(1)
if not os.path.exists(data_file):
sys.stderr.write(f"Destination File {data_file} not found\n")
sys.stderr.write(f'Destination File {data_file} not found\n')
sys.exit(1)

# Read the version from pyproject.toml
with open(toml_file, "r") as f:
pyproject_data = toml.load(f)
with open(toml_file, 'rb') as f:
pyproject_data = tomllib.load(f)
# Read the current contents of __about__.py
with open(data_file, "r") as f:
with open(data_file) as f:
lines = f.readlines()

# Update the version in __about__.py
with open(data_file, "w") as f:
version = pyproject_data["project"]["version"]
with open(data_file, 'w') as f:
version = pyproject_data['project']['version']
for line in lines:
line = f'__version__ = "{version}"\n' if line.startswith("__version__") else line
line = f"__version__ = '{version}'\n" if line.startswith('__version__') else line
f.write(line)


if __name__ == "__main__":
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Update version in destination file from source file.",
description='Update version in destination file from source file.',
)
parser.add_argument(
"--source",
'--source',
type=str,
default=TOML_FILE,
help=f"PyProject file to read version from ({TOML_FILE})",
help=f'PyProject file to read version from ({TOML_FILE})',
)
parser.add_argument(
"--target",
'--target',
type=str,
default=DATA_FILE,
help=f"Python Destination file to update version in ({DATA_FILE})",
help=f'Python Destination file to update version in ({DATA_FILE})',
)
args = parser.parse_args()

Expand Down
2 changes: 1 addition & 1 deletion src/dns_synchub/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.0"
__version__ = '0.1.0'
64 changes: 26 additions & 38 deletions src/dns_synchub/__init__.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,26 @@
from __future__ import annotations

import asyncio
import sys

from pydantic import ValidationError

import dns_synchub.cli as cli
import dns_synchub.logger as logger
import dns_synchub.settings as settings


def main():
try:
# Load environment variables from the specified env file
cli.parse_args()

# Load settings
options = settings.Settings()

# Check for uppercase docker secrets or env variables
assert options.cf_token
assert options.target_domain
assert len(options.domains) > 0

except ValidationError as e:
print(f"Unable to load settings: {e}", file=sys.stderr)
sys.exit(1)

# Set up logging and dump runtime settings
log = logger.report_current_status_and_settings(logger.get_logger(options), options)
try:
asyncio.run(cli.main(log, settings=options))
except KeyboardInterrupt:
# asyncio.run will cancel any task pending when the main function exits
log.info("Cancel by user.")
log.info("Exiting...")
sys.exit(1)
# src/dns_synchub/__init__.py

from .__about__ import __version__ as VERSION
from .logger import get_logger, initialize_logger
from .mappers import CloudFlareMapper
from .pollers import DockerPoller, TraefikPoller
from .settings import Settings

__version__ = VERSION

__all__ = [
# logger subpackage
'get_logger',
'initialize_logger',
# settings subpackage
'Settings',
# pollers subpackage
'DockerPoller',
'TraefikPoller',
# mappers subpackage
'CloudFlareMapper',
]


def __dir__() -> 'list[str]':
return list(__all__)
73 changes: 69 additions & 4 deletions src/dns_synchub/__main__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,81 @@
#!/usr/bin/env python3

import asyncio
from logging import Logger
import pathlib
import re
import sys

import dns_synchub
from pydantic import ValidationError

if __name__ == "__main__":
import dns_synchub.cli as cli
import dns_synchub.logger as logger
import dns_synchub.settings as settings


def report_state(settings: settings.Settings) -> Logger:
log = logger.initialize_logger(settings=settings)

settings.dry_run and log.info(f'Dry Run: {settings.dry_run}') # type: ignore
log.debug(f'Default TTL: {settings.default_ttl}')
log.debug(f'Refresh Entries: {settings.refresh_entries}')

log.debug(f"Traefik Polling Mode: {'On' if settings.enable_traefik_poll else 'Off'}")
if settings.enable_traefik_poll:
if settings.traefik_poll_url and re.match(r'^\w+://[^/?#]+', settings.traefik_poll_url):
log.debug(f'Traefik Poll Url: {settings.traefik_poll_url}')
log.debug(f'Traefik Poll Seconds: {settings.traefik_poll_seconds}')
else:
settings.enable_traefik_poll = False
log.error(f'Traefik polling disabled: Bad url: {settings.traefik_poll_url}')

log.debug(f"Docker Polling Mode: {'On' if settings.enable_docker_poll else 'Off'}")
log.debug(f'Docker Poll Seconds: {settings.docker_timeout_seconds}')

for dom in settings.domains:
log.debug(f'Domain Configuration: {dom.name}')
log.debug(f' Target Domain: {dom.target_domain}')
log.debug(f' TTL: {dom.ttl}')
log.debug(f' Record Type: {dom.rc_type}')
log.debug(f' Proxied: {dom.proxied}')
log.debug(f' Excluded Subdomains: {dom.excluded_sub_domains}')

return log


def main() -> int:
try:
# Load environment variables from the specified env file
cli.parse_args()
# Load settings
options = settings.Settings()
# Check for uppercase docker secrets or env variables
assert options.cf_token
assert options.target_domain
assert len(options.domains) > 0
except ValidationError as e:
print(f'Unable to load settings: {e}', file=sys.stderr)
return 1

# Set up logging and dump runtime settings
log = report_state(options)
try:
asyncio.run(cli.main(log, settings=options))
except KeyboardInterrupt:
# asyncio.run will cancel any task pending when the main function exits
log.info('Cancel by user.')
log.info('Exiting...')

# Exit grqacefully
return 0


if __name__ == '__main__':
# If the script is run as a module, use the directory name as the script name
script_name = pathlib.Path(sys.argv[0]).stem
if sys.argv[0] == __file__:
script_path = pathlib.Path(sys.argv[0])
script_name = script_path.parent.name.replace("_", "-")
script_name = script_path.parent.name.replace('_', '-')
# Set the script name to the first argument and invoke the main function
sys.argv[0] = script_name
sys.exit(dns_synchub.main())
sys.exit(main())
Loading

0 comments on commit 3077758

Please sign in to comment.