haiway 0.10.14__tar.gz → 0.10.16__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 (99) hide show
  1. haiway-0.10.16/.github/workflows/ci.yml +38 -0
  2. haiway-0.10.16/.github/workflows/publish.yml +33 -0
  3. haiway-0.10.16/Makefile +89 -0
  4. {haiway-0.10.14 → haiway-0.10.16}/PKG-INFO +1 -1
  5. haiway-0.10.16/config/pre-push +57 -0
  6. haiway-0.10.16/examples/fastAPI/.dockerignore +5 -0
  7. haiway-0.10.16/examples/fastAPI/Dockerfile +37 -0
  8. haiway-0.10.16/examples/fastAPI/Makefile +86 -0
  9. haiway-0.10.16/examples/fastAPI/README.md +1 -0
  10. haiway-0.10.16/examples/fastAPI/config/.env.example +11 -0
  11. haiway-0.10.16/examples/fastAPI/config/unit.json +50 -0
  12. haiway-0.10.16/examples/fastAPI/docker-compose.yml +44 -0
  13. haiway-0.10.16/examples/fastAPI/pyproject.toml +65 -0
  14. haiway-0.10.16/examples/fastAPI/src/features/todos/__init__.py +5 -0
  15. haiway-0.10.16/examples/fastAPI/src/features/todos/calls.py +16 -0
  16. haiway-0.10.16/examples/fastAPI/src/features/todos/config.py +1 -0
  17. haiway-0.10.16/examples/fastAPI/src/features/todos/state.py +12 -0
  18. haiway-0.10.16/examples/fastAPI/src/features/todos/types.py +15 -0
  19. haiway-0.10.16/examples/fastAPI/src/features/todos/user_tasks.py +17 -0
  20. haiway-0.10.16/examples/fastAPI/src/integrations/__init__.py +0 -0
  21. haiway-0.10.16/examples/fastAPI/src/integrations/postgres/__init__.py +12 -0
  22. haiway-0.10.16/examples/fastAPI/src/integrations/postgres/client.py +146 -0
  23. haiway-0.10.16/examples/fastAPI/src/integrations/postgres/config.py +19 -0
  24. haiway-0.10.16/examples/fastAPI/src/integrations/postgres/state.py +64 -0
  25. haiway-0.10.16/examples/fastAPI/src/integrations/postgres/types.py +27 -0
  26. haiway-0.10.16/examples/fastAPI/src/server/__init__.py +10 -0
  27. haiway-0.10.16/examples/fastAPI/src/server/__main__.py +10 -0
  28. haiway-0.10.16/examples/fastAPI/src/server/application.py +54 -0
  29. haiway-0.10.16/examples/fastAPI/src/server/config.py +11 -0
  30. haiway-0.10.16/examples/fastAPI/src/server/middlewares/__init__.py +5 -0
  31. haiway-0.10.16/examples/fastAPI/src/server/middlewares/context.py +133 -0
  32. haiway-0.10.16/examples/fastAPI/src/server/routes/__init__.py +7 -0
  33. haiway-0.10.16/examples/fastAPI/src/server/routes/technical.py +21 -0
  34. haiway-0.10.16/examples/fastAPI/src/server/routes/todos.py +26 -0
  35. haiway-0.10.16/examples/fastAPI/src/solutions/__init__.py +0 -0
  36. haiway-0.10.16/examples/fastAPI/src/solutions/user_tasks/__init__.py +12 -0
  37. haiway-0.10.16/examples/fastAPI/src/solutions/user_tasks/calls.py +54 -0
  38. haiway-0.10.16/examples/fastAPI/src/solutions/user_tasks/config.py +1 -0
  39. haiway-0.10.16/examples/fastAPI/src/solutions/user_tasks/postgres.py +106 -0
  40. haiway-0.10.16/examples/fastAPI/src/solutions/user_tasks/state.py +25 -0
  41. haiway-0.10.16/examples/fastAPI/src/solutions/user_tasks/types.py +70 -0
  42. haiway-0.10.16/examples/fastAPI/uv.lock +435 -0
  43. haiway-0.10.16/guidelines/functionalities.md +252 -0
  44. haiway-0.10.16/guidelines/packages.md +321 -0
  45. haiway-0.10.16/junit/test-results.xml +1 -0
  46. {haiway-0.10.14 → haiway-0.10.16}/pyproject.toml +1 -28
  47. haiway-0.10.16/src/haiway/py.typed +0 -0
  48. haiway-0.10.16/tests/__init__.py +0 -0
  49. haiway-0.10.16/tests/test_async_queue.py +111 -0
  50. haiway-0.10.16/tests/test_attribute_path.py +250 -0
  51. haiway-0.10.16/tests/test_auto_retry.py +297 -0
  52. haiway-0.10.16/tests/test_cache.py +192 -0
  53. haiway-0.10.16/tests/test_context.py +63 -0
  54. haiway-0.10.16/tests/test_state.py +242 -0
  55. haiway-0.10.16/tests/test_streaming.py +125 -0
  56. haiway-0.10.16/tests/test_timeout.py +53 -0
  57. haiway-0.10.16/uv.lock +318 -0
  58. haiway-0.10.14/hatch_version.py +0 -20
  59. {haiway-0.10.14 → haiway-0.10.16}/.gitignore +0 -0
  60. {haiway-0.10.14 → haiway-0.10.16}/LICENSE +0 -0
  61. {haiway-0.10.14 → haiway-0.10.16}/README.md +0 -0
  62. /haiway-0.10.14/haiway/py.typed → /haiway-0.10.16/examples/fastAPI/src/features/__int__.py +0 -0
  63. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/__init__.py +0 -0
  64. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/__init__.py +0 -0
  65. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/access.py +0 -0
  66. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/disposables.py +0 -0
  67. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/identifier.py +0 -0
  68. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/logging.py +0 -0
  69. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/metrics.py +0 -0
  70. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/state.py +0 -0
  71. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/tasks.py +0 -0
  72. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/context/types.py +0 -0
  73. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/__init__.py +0 -0
  74. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/asynchrony.py +0 -0
  75. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/caching.py +0 -0
  76. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/metrics.py +0 -0
  77. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/retries.py +0 -0
  78. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/throttling.py +0 -0
  79. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/timeouted.py +0 -0
  80. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/helpers/tracing.py +0 -0
  81. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/state/__init__.py +0 -0
  82. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/state/attributes.py +0 -0
  83. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/state/path.py +0 -0
  84. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/state/requirement.py +0 -0
  85. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/state/structure.py +0 -0
  86. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/state/validation.py +0 -0
  87. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/types/__init__.py +0 -0
  88. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/types/default.py +0 -0
  89. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/types/frozen.py +0 -0
  90. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/types/missing.py +0 -0
  91. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/__init__.py +0 -0
  92. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/always.py +0 -0
  93. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/collections.py +0 -0
  94. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/env.py +0 -0
  95. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/freezing.py +0 -0
  96. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/logs.py +0 -0
  97. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/mimic.py +0 -0
  98. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/noop.py +0 -0
  99. {haiway-0.10.14 → haiway-0.10.16/src}/haiway/utils/queue.py +0 -0
@@ -0,0 +1,38 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ pull_request:
9
+ branches:
10
+ - "*"
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ matrix:
17
+ os: [ubuntu-latest, macos-latest, windows-latest]
18
+ python-version: ["3.12", "3.13"]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Install uv and set the python version
24
+ uses: astral-sh/setup-uv@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+
28
+ - name: Install
29
+ run: uv sync --all-groups --all-extras --frozen --no-python-downloads
30
+
31
+ - name: Lint
32
+ run: uv run ruff check --output-format=github ./src ./tests && uv run pyright --project ./
33
+
34
+ - name: Test
35
+ run: uv run pytest --rootdir= ./tests --doctest-modules --junitxml=junit/test-results.xml
36
+
37
+ - name: Build
38
+ run: uv build
@@ -0,0 +1,33 @@
1
+ name: publish
2
+
3
+ on:
4
+ release:
5
+ types:
6
+ - released
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ id-token: write
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with:
16
+ ref: ${{ github.event.release.tag_name }}
17
+
18
+ - name: Install uv and set the python version
19
+ uses: astral-sh/setup-uv@v5
20
+ with:
21
+ python-version: 3.12
22
+
23
+ - name: Install
24
+ run: uv sync --all-groups --all-extras --frozen --no-python-downloads
25
+
26
+ - name: Lint
27
+ run: uv run ruff check --output-format=github ./src ./tests && uv run pyright --project ./
28
+
29
+ - name: Test
30
+ run: uv run pytest --rootdir= ./tests --doctest-modules --junitxml=junit/test-results.xml
31
+
32
+ - name: Publish
33
+ run: uv build && uv publish
@@ -0,0 +1,89 @@
1
+ SHELL := sh
2
+ .ONESHELL:
3
+ .SHELLFLAGS := -eu -c
4
+ .DELETE_ON_ERROR:
5
+
6
+ SOURCES_PATH := src
7
+ TESTS_PATH := tests
8
+
9
+ # load environment config from .env if able
10
+ -include .env
11
+
12
+ ifndef UV_VERSION
13
+ UV_VERSION := 0.6.4
14
+ endif
15
+
16
+ .PHONY: uv_check venv sync update format lint test release
17
+
18
+ # Check installed UV version and install if needed
19
+ uv_check:
20
+ @echo 'Checking uv version...'
21
+
22
+ # Install if not present
23
+ @if ! command -v uv > /dev/null; then \
24
+ echo '...installing uv...'; \
25
+ curl -LsSf https://github.com/astral-sh/uv/releases/download/$(UV_VERSION)/uv-installer.sh | sh; \
26
+ if [ $$? -ne 0 ]; then \
27
+ echo "...installing uv failed!"; \
28
+ exit 1; \
29
+ fi; \
30
+ fi
31
+
32
+ # Check version and update if needed
33
+ @if command -v uv > /dev/null; then \
34
+ CURRENT_VERSION=$$(uv --version | head -n1 | cut -d" " -f2); \
35
+ if [ "$$(printf "%s\n%s" "$(UV_VERSION)" "$$CURRENT_VERSION" | sort -V | head -n1)" != "$(UV_VERSION)" ]; then \
36
+ echo '...updating uv...'; \
37
+ curl -LsSf https://github.com/astral-sh/uv/releases/download/$(UV_VERSION)/uv-installer.sh | sh; \
38
+ if [ $$? -ne 0 ]; then \
39
+ echo "...updating uv failed!"; \
40
+ exit 1; \
41
+ fi; \
42
+ else \
43
+ echo '...uv version is up-to-date!'; \
44
+ fi; \
45
+ fi
46
+
47
+ # Setup virtual environment for local development.
48
+ venv: uv_check
49
+ @echo '# Preparing development environment...'
50
+ @echo '...cloning .env...'
51
+ @cp -n ./config/.env.example ./.env || :
52
+ @echo '...preparing git hooks...'
53
+ @cp -n ./config/pre-push ./.git/hooks/pre-push || :
54
+ @echo '...preparing venv...'
55
+ @uv sync --all-groups --all-extras --frozen --reinstall
56
+ @echo '...development environment ready! Activate venv using `. ./.venv/bin/activate`.'
57
+
58
+ # Sync environment with uv based on constraints
59
+ sync: uv_check
60
+ @echo '# Synchronizing dependencies...'
61
+ @uv sync --all-groups --all-extras --frozen
62
+ @echo '...finished!'
63
+
64
+ # Update and lock dependencies from pyproject.toml
65
+ update:
66
+ @echo '# Updating dependencies...'
67
+ @uv sync --all-groups --all-extras --upgrade
68
+ @echo '...finished!'
69
+
70
+ # Run formatter.
71
+ format:
72
+ @ruff check --quiet --fix $(SOURCES_PATH) $(TESTS_PATH)
73
+ @ruff format --quiet $(SOURCES_PATH) $(TESTS_PATH)
74
+
75
+ # Run linters and code checks.
76
+ lint:
77
+ @bandit -r $(SOURCES_PATH)
78
+ @ruff check $(SOURCES_PATH) $(TESTS_PATH)
79
+ @pyright --project ./
80
+
81
+ # Run tests suite.
82
+ test:
83
+ @python -B -m pytest -v --cov=$(SOURCES_PATH) --rootdir=$(TESTS_PATH)
84
+
85
+ release: lint test
86
+ @echo '# Preparing release...'
87
+ @uv build
88
+ @uv publish
89
+ @echo '...finished!'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haiway
3
- Version: 0.10.14
3
+ Version: 0.10.16
4
4
  Summary: Framework for dependency injection and state management within structured concurrency model.
5
5
  Project-URL: Homepage, https://miquido.com
6
6
  Project-URL: Repository, https://github.com/miquido/haiway.git
@@ -0,0 +1,57 @@
1
+ #!/bin/sh
2
+
3
+ if git rev-parse --verify HEAD >/dev/null 2>&1
4
+ then
5
+ against=HEAD
6
+ else
7
+ against=$(git hash-object -t tree /dev/null)
8
+ fi
9
+
10
+ remote="$1"
11
+ url="$2"
12
+
13
+ zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
14
+
15
+ while read local_ref local_oid remote_ref remote_oid
16
+ do
17
+ if test "$local_oid" = "$zero"
18
+ then
19
+ # Handle delete
20
+ :
21
+ else
22
+ if test "$remote_oid" = "$zero"
23
+ then
24
+ # New branch, examine all commits
25
+ range="$local_oid"
26
+ else
27
+ # Update to existing branch, examine new commits
28
+ range="$remote_oid..$local_oid"
29
+ fi
30
+
31
+ # Check for WIP commit
32
+ commit=$(git rev-list -n 1 --grep '^WIP' "$range")
33
+ if test -n "$commit"
34
+ then
35
+ echo >&2 "Found WIP commit in $local_ref, not pushing"
36
+ exit 1
37
+ fi
38
+ fi
39
+ done
40
+
41
+ . ./.venv/bin/activate
42
+
43
+ make lint
44
+
45
+ if test $? != 0
46
+ then
47
+ cat <<\EOF
48
+
49
+ Error: Linting failed.
50
+
51
+ Ensure project quality and make all linting rules pass!
52
+
53
+ EOF
54
+ exit 1
55
+ fi
56
+
57
+ exec git diff-index --check --cached $against --
@@ -0,0 +1,5 @@
1
+ *
2
+ !./pyproject.toml
3
+ !./config/unit.json
4
+ !./src
5
+ !./uv.lock
@@ -0,0 +1,37 @@
1
+ ARG PYTHON_TAG=3.12
2
+ ARG UNIT_TAG=1.32.1-python${PYTHON_TAG}
3
+
4
+ # SERVER #
5
+
6
+ FROM unit:${UNIT_TAG} AS server_builder
7
+
8
+ # copy only the parts needed for production
9
+ COPY ./src/integrations ./src/integrations
10
+ COPY ./src/solutions ./src/solutions
11
+ COPY ./src/features ./src/features
12
+ COPY ./src/server ./src/server
13
+
14
+ # install dependencies and packages
15
+ COPY --from=ghcr.io/astral-sh/uv:0.5.14 /uv /uvx /bin/
16
+
17
+ ENV UV_PROJECT_ENVIRONMENT="/usr/local/"
18
+
19
+ RUN --mount=type=bind,source=./uv.lock,target=./uv.lock --mount=type=bind,source=./pyproject.toml,target=./pyproject.toml uv sync --python python${PYTHON_TAG} --locked --no-editable --no-python-downloads --link-mode copy --compile-bytecode --only-group server
20
+
21
+ FROM server_builder AS server
22
+
23
+ # allow access to home directory for asyncpg library
24
+ RUN chgrp -R unit ${HOME} && chmod -R 050 ${HOME}
25
+
26
+ RUN apt-get update \
27
+ && apt-get upgrade -y \
28
+ && apt-get -y autoremove \
29
+ && apt-get clean \
30
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
31
+
32
+ # copy configuration
33
+ COPY ./config/unit.json /docker-entrypoint.d/config.json
34
+
35
+ CMD ["unitd", "--no-daemon", "--log", "/dev/stdout"]
36
+
37
+ # port 80 is already exposed by nginx unit image, can't change it...
@@ -0,0 +1,86 @@
1
+ SHELL := sh
2
+ .ONESHELL:
3
+ .SHELLFLAGS := -eu -c
4
+ .DELETE_ON_ERROR:
5
+
6
+ SOURCES_PATH := src
7
+
8
+ # load environment config from .env if able
9
+ -include .env
10
+
11
+ ifndef UV_VERSION
12
+ UV_VERSION := 0.5.14
13
+ endif
14
+
15
+ .PHONY: uv_check venv sync update format lint run docker_run
16
+
17
+ # Check installed UV version and install if needed
18
+ uv_check:
19
+ @echo 'Checking uv version...'
20
+
21
+ # Install if not present
22
+ @if ! command -v uv > /dev/null; then \
23
+ echo '...installing uv...'; \
24
+ curl -LsSf https://github.com/astral-sh/uv/releases/download/$(UV_VERSION)/uv-installer.sh | sh; \
25
+ if [ $$? -ne 0 ]; then \
26
+ echo "...installing uv failed!"; \
27
+ exit 1; \
28
+ fi; \
29
+ fi
30
+
31
+ # Check version and update if needed
32
+ @if command -v uv > /dev/null; then \
33
+ CURRENT_VERSION=$$(uv --version | head -n1 | cut -d" " -f2); \
34
+ if [ "$$(printf "%s\n%s" "$(UV_VERSION)" "$$CURRENT_VERSION" | sort -V | head -n1)" != "$(UV_VERSION)" ]; then \
35
+ echo '...updating uv...'; \
36
+ curl -LsSf https://github.com/astral-sh/uv/releases/download/$(UV_VERSION)/uv-installer.sh | sh; \
37
+ if [ $$? -ne 0 ]; then \
38
+ echo "...updating uv failed!"; \
39
+ exit 1; \
40
+ fi; \
41
+ else \
42
+ echo '...uv version is up-to-date!'; \
43
+ fi; \
44
+ fi
45
+
46
+ # Setup virtual environment for local development.
47
+ venv: uv_check
48
+ @echo '# Preparing development environment...'
49
+ @echo '...cloning .env...'
50
+ @cp -n ./config/.env.example ./.env || :
51
+ @echo '...preparing git hooks...'
52
+ @cp -n ./config/pre-push ./.git/hooks/pre-push || :
53
+ @echo '...preparing venv...'
54
+ @uv sync --all-groups --all-extras --frozen --reinstall
55
+ @echo '...development environment ready! Activate venv using `. ./.venv/bin/activate`.'
56
+
57
+ # Sync environment with uv based on constraints
58
+ sync: uv_check
59
+ @echo '# Synchronizing dependencies...'
60
+ @uv sync --all-groups --all-extras --frozen
61
+ @echo '...finished!'
62
+
63
+ # Update and lock dependencies from pyproject.toml
64
+ update:
65
+ @echo '# Updating dependencies...'
66
+ @uv sync --all-groups --all-extras --upgrade
67
+ @echo '...finished!'
68
+
69
+ # Run formatter.
70
+ format:
71
+ @ruff check --quiet --fix $(SOURCES_PATH)
72
+ @ruff format --quiet $(SOURCES_PATH)
73
+
74
+ # Run linters and code checks.
75
+ lint:
76
+ @bandit -r $(SOURCES_PATH)
77
+ @ruff check $(SOURCES_PATH)
78
+ @pyright --project ./
79
+
80
+ # Run the server
81
+ run:
82
+ @python -m server
83
+
84
+ # Run all services locally using docker-compose.
85
+ docker_run:
86
+ @docker compose up --force-recreate --build server
@@ -0,0 +1 @@
1
+ ## Haiway FastAPI Example
@@ -0,0 +1,11 @@
1
+ PYTHONOPTIMIZE=0
2
+ DEBUG_LOGGING=1
3
+ # Server
4
+ SERVER_PORT=8080
5
+ # Postgres
6
+ POSTGRES_DATABASE=postgres
7
+ POSTGRES_HOST=localhost
8
+ POSTGRES_PORT=5432
9
+ POSTGRES_USER=postgres
10
+ POSTGRES_PASSWORD=postgres
11
+ POSTGRES_SSLMODE=disable
@@ -0,0 +1,50 @@
1
+ {
2
+ "listeners": {
3
+ "*:80": {
4
+ "pass": "routes/api"
5
+ }
6
+ },
7
+ "routes": {
8
+ "api": [
9
+ {
10
+ "match": {
11
+ "uri": "/health"
12
+ },
13
+ "action": {
14
+ "return": 204
15
+ }
16
+ },
17
+ {
18
+ "match": {
19
+ "uri": "/*"
20
+ },
21
+ "action": {
22
+ "pass": "applications/server"
23
+ }
24
+ }
25
+ ]
26
+ },
27
+ "applications": {
28
+ "server": {
29
+ "type": "python",
30
+ "protocol": "asgi",
31
+ "path": "/",
32
+ "module": "server",
33
+ "callable": "app",
34
+ "processes": 1,
35
+ "environment": {
36
+ "PYTHONOPTIMIZE": "2",
37
+ "HOME": "."
38
+ }
39
+ }
40
+ },
41
+ "access_log": {
42
+ "path": "/dev/stdout",
43
+ "format": "$time_local [ACCESS] $request_line -> $status"
44
+ },
45
+ "settings": {
46
+ "http": {
47
+ "server_version": false
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,44 @@
1
+ services:
2
+ server:
3
+ depends_on:
4
+ postgres:
5
+ condition: service_healthy
6
+ links:
7
+ - postgres
8
+ build:
9
+ context: .
10
+ dockerfile: Dockerfile
11
+ target: server
12
+ ports:
13
+ - ${SERVER_PORT:-8080}:80
14
+ restart: no
15
+ environment:
16
+ PYTHONOPTIMIZE: ${PYTHONOPTIMIZE:-2}
17
+ DEBUG_LOGGING: ${DEBUG_LOGGING}
18
+ POSTGRES_DATABASE: ${POSTGRES_DATABASE}
19
+ POSTGRES_HOST: postgres
20
+ POSTGRES_PORT: 5432
21
+ POSTGRES_USER: ${POSTGRES_USER}
22
+ POSTGRES_SSLMODE: ${POSTGRES_SSLMODE:-prefer}
23
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
24
+
25
+ postgres:
26
+ image: postgres:16.3-alpine3.20
27
+ restart: always
28
+ environment:
29
+ POSTGRES_USER: ${POSTGRES_USER}
30
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
31
+ POSTGRES_DB: ${POSTGRES_DATABASE}
32
+ volumes:
33
+ - postgres_data:/var/lib/postgresql/data
34
+ ports:
35
+ - ${POSTGRES_PORT}:5432
36
+ healthcheck:
37
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DATABASE}"]
38
+ interval: 10s
39
+ start_period: 10s
40
+ timeout: 10s
41
+ retries: 3
42
+
43
+ volumes:
44
+ postgres_data:
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "haiway_fastapi"
7
+ description = "Example of haiway usage with fastapi."
8
+ version = "0.1.0"
9
+ readme = "README.md"
10
+ maintainers = [
11
+ { name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
12
+ ]
13
+ requires-python = ">=3.12"
14
+ dependencies = [
15
+ "haiway @ git+https://github.com/miquido/haiway@main",
16
+ "asyncpg~=0.30",
17
+ "httpx~=0.28.0",
18
+ ]
19
+
20
+ [project.urls]
21
+ Homepage = "https://miquido.com"
22
+
23
+ [dependency-groups]
24
+ server = [
25
+ "haiway_fastapi",
26
+ "fastapi-slim~=0.115",
27
+ ]
28
+ dev = [
29
+ "haiway_fastapi",
30
+ "uvicorn~=0.30",
31
+ "ruff~=0.8.0",
32
+ "pyright~=1.1",
33
+ "bandit~=1.7",
34
+ ]
35
+
36
+ [tool.ruff]
37
+ target-version = "py312"
38
+ line-length = 100
39
+ extend-exclude = [".venv", ".git", ".cache"]
40
+ lint.select = ["E", "F", "A", "I", "B", "PL", "W", "C", "RUF", "UP"]
41
+ lint.ignore = []
42
+
43
+ [tool.ruff.lint.per-file-ignores]
44
+ "__init__.py" = ["F401", "E402"]
45
+ "./tests/*.py" = ["PLR2004"]
46
+
47
+ [tool.pyright]
48
+ pythonVersion = "3.12"
49
+ venvPath = "."
50
+ venv = ".venv"
51
+ include = ["./src"]
52
+ exclude = ["**/node_modules", "**/__pycache__"]
53
+ ignore = []
54
+ stubPath = "./stubs"
55
+ reportMissingImports = true
56
+ reportMissingTypeStubs = true
57
+ typeCheckingMode = "strict"
58
+ userFileIndexingLimit = -1
59
+ useLibraryCodeForTypes = true
60
+
61
+ [tool.setuptools]
62
+ include-package-data = true
63
+
64
+ [tool.setuptools.packages.find]
65
+ where = ["src"]
@@ -0,0 +1,5 @@
1
+ from features.todos.calls import complete_todo
2
+
3
+ __all__ = [
4
+ "complete_todo",
5
+ ]
@@ -0,0 +1,16 @@
1
+ from uuid import UUID
2
+
3
+ from haiway import ctx
4
+
5
+ from features.todos.state import Todos
6
+
7
+ __all__ = [
8
+ "complete_todo",
9
+ ]
10
+
11
+
12
+ async def complete_todo(
13
+ *,
14
+ identifier: UUID,
15
+ ) -> None:
16
+ await ctx.state(Todos).complete(identifier=identifier)
@@ -0,0 +1,12 @@
1
+ from haiway import State
2
+
3
+ from features.todos.types import TodoCompletion
4
+ from features.todos.user_tasks import complete_todo_task
5
+
6
+ __all__ = [
7
+ "Todos",
8
+ ]
9
+
10
+
11
+ class Todos(State):
12
+ complete: TodoCompletion = complete_todo_task
@@ -0,0 +1,15 @@
1
+ from typing import Protocol, runtime_checkable
2
+ from uuid import UUID
3
+
4
+ __all__ = [
5
+ "TodoCompletion",
6
+ ]
7
+
8
+
9
+ @runtime_checkable
10
+ class TodoCompletion(Protocol):
11
+ async def __call__(
12
+ self,
13
+ *,
14
+ identifier: UUID,
15
+ ) -> None: ...
@@ -0,0 +1,17 @@
1
+ from uuid import UUID
2
+
3
+ from haiway import ctx
4
+
5
+ from solutions.user_tasks import UserTask, UserTasks
6
+
7
+ __all__ = [
8
+ "complete_todo_task",
9
+ ]
10
+
11
+
12
+ async def complete_todo_task(
13
+ *,
14
+ identifier: UUID,
15
+ ) -> None:
16
+ task: UserTask = await ctx.state(UserTasks).fetch(identifier=identifier)
17
+ await ctx.state(UserTasks).update(task=task.updated(completed=True))
@@ -0,0 +1,12 @@
1
+ from integrations.postgres.client import PostgresClient
2
+ from integrations.postgres.state import Postgres, PostgresConnection
3
+ from integrations.postgres.types import PostgresException, PostgresRow, PostgresValue
4
+
5
+ __all__ = [
6
+ "Postgres",
7
+ "PostgresClient",
8
+ "PostgresConnection",
9
+ "PostgresException",
10
+ "PostgresRow",
11
+ "PostgresValue",
12
+ ]