haystack-py 0.1.3__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.
- haystack_py-0.1.3/.dockerignore +17 -0
- haystack_py-0.1.3/.github/workflows/ci.yml +102 -0
- haystack_py-0.1.3/.github/workflows/release.yml +164 -0
- haystack_py-0.1.3/.gitignore +49 -0
- haystack_py-0.1.3/.python-version +1 -0
- haystack_py-0.1.3/CHANGELOG.md +39 -0
- haystack_py-0.1.3/Dockerfile +36 -0
- haystack_py-0.1.3/LICENSE +21 -0
- haystack_py-0.1.3/Makefile +89 -0
- haystack_py-0.1.3/PKG-INFO +446 -0
- haystack_py-0.1.3/README.md +421 -0
- haystack_py-0.1.3/docker/docker-compose.yml +68 -0
- haystack_py-0.1.3/docker/gen_tls_certs.py +42 -0
- haystack_py-0.1.3/docker/tls/.gitignore +2 -0
- haystack_py-0.1.3/docs/_static/.gitkeep +0 -0
- haystack_py-0.1.3/docs/api/core.rst +40 -0
- haystack_py-0.1.3/docs/api/encoding.rst +47 -0
- haystack_py-0.1.3/docs/api/filter.rst +40 -0
- haystack_py-0.1.3/docs/api/ontology.rst +47 -0
- haystack_py-0.1.3/docs/api/security.rst +39 -0
- haystack_py-0.1.3/docs/api/storage.rst +47 -0
- haystack_py-0.1.3/docs/api/types.rst +33 -0
- haystack_py-0.1.3/docs/api/websocket.rst +39 -0
- haystack_py-0.1.3/docs/changelog.md +1 -0
- haystack_py-0.1.3/docs/conf.py +66 -0
- haystack_py-0.1.3/docs/features.rst +201 -0
- haystack_py-0.1.3/docs/getting-started.rst +206 -0
- haystack_py-0.1.3/docs/guide/client-guide.rst +379 -0
- haystack_py-0.1.3/docs/guide/data-types.rst +239 -0
- haystack_py-0.1.3/docs/guide/encoding-guide.rst +306 -0
- haystack_py-0.1.3/docs/guide/error-handling.rst +215 -0
- haystack_py-0.1.3/docs/guide/filter-guide.rst +222 -0
- haystack_py-0.1.3/docs/guide/observability.rst +187 -0
- haystack_py-0.1.3/docs/guide/ontology-guide.rst +355 -0
- haystack_py-0.1.3/docs/guide/server-guide.rst +327 -0
- haystack_py-0.1.3/docs/guide/storage-guide.rst +234 -0
- haystack_py-0.1.3/docs/guide/tls-guide.rst +227 -0
- haystack_py-0.1.3/docs/guide/watch-guide.rst +262 -0
- haystack_py-0.1.3/docs/guide/websocket-guide.rst +351 -0
- haystack_py-0.1.3/docs/index.rst +79 -0
- haystack_py-0.1.3/pyproject.toml +63 -0
- haystack_py-0.1.3/ruff.toml +56 -0
- haystack_py-0.1.3/scripts/exercise.py +363 -0
- haystack_py-0.1.3/scripts/stress.py +299 -0
- haystack_py-0.1.3/scripts/ws_stress.py +381 -0
- haystack_py-0.1.3/src/hs_py/__init__.py +160 -0
- haystack_py-0.1.3/src/hs_py/__main__.py +119 -0
- haystack_py-0.1.3/src/hs_py/_scram_core.py +309 -0
- haystack_py-0.1.3/src/hs_py/auth.py +406 -0
- haystack_py-0.1.3/src/hs_py/auth_types.py +107 -0
- haystack_py-0.1.3/src/hs_py/client.py +581 -0
- haystack_py-0.1.3/src/hs_py/content_negotiation.py +144 -0
- haystack_py-0.1.3/src/hs_py/convert.py +83 -0
- haystack_py-0.1.3/src/hs_py/encoding/__init__.py +37 -0
- haystack_py-0.1.3/src/hs_py/encoding/csv.py +103 -0
- haystack_py-0.1.3/src/hs_py/encoding/json.py +667 -0
- haystack_py-0.1.3/src/hs_py/encoding/scanner.py +638 -0
- haystack_py-0.1.3/src/hs_py/encoding/trio.py +292 -0
- haystack_py-0.1.3/src/hs_py/encoding/zinc.py +337 -0
- haystack_py-0.1.3/src/hs_py/errors.py +57 -0
- haystack_py-0.1.3/src/hs_py/fastapi_server.py +477 -0
- haystack_py-0.1.3/src/hs_py/filter/__init__.py +34 -0
- haystack_py-0.1.3/src/hs_py/filter/ast.py +121 -0
- haystack_py-0.1.3/src/hs_py/filter/eval.py +178 -0
- haystack_py-0.1.3/src/hs_py/filter/lexer.py +316 -0
- haystack_py-0.1.3/src/hs_py/filter/parser.py +168 -0
- haystack_py-0.1.3/src/hs_py/grid.py +212 -0
- haystack_py-0.1.3/src/hs_py/kinds.py +302 -0
- haystack_py-0.1.3/src/hs_py/metrics.py +68 -0
- haystack_py-0.1.3/src/hs_py/ontology/__init__.py +62 -0
- haystack_py-0.1.3/src/hs_py/ontology/defs.py +138 -0
- haystack_py-0.1.3/src/hs_py/ontology/namespace.py +261 -0
- haystack_py-0.1.3/src/hs_py/ontology/normalize.py +153 -0
- haystack_py-0.1.3/src/hs_py/ontology/rdf.py +131 -0
- haystack_py-0.1.3/src/hs_py/ontology/reflect.py +109 -0
- haystack_py-0.1.3/src/hs_py/ontology/taxonomy.py +114 -0
- haystack_py-0.1.3/src/hs_py/ops.py +423 -0
- haystack_py-0.1.3/src/hs_py/py.typed +0 -0
- haystack_py-0.1.3/src/hs_py/redis_ops.py +127 -0
- haystack_py-0.1.3/src/hs_py/storage/__init__.py +34 -0
- haystack_py-0.1.3/src/hs_py/storage/memory.py +338 -0
- haystack_py-0.1.3/src/hs_py/storage/protocol.py +178 -0
- haystack_py-0.1.3/src/hs_py/storage/redis.py +789 -0
- haystack_py-0.1.3/src/hs_py/storage/timescale.py +867 -0
- haystack_py-0.1.3/src/hs_py/tls.py +311 -0
- haystack_py-0.1.3/src/hs_py/watch.py +191 -0
- haystack_py-0.1.3/src/hs_py/ws.py +399 -0
- haystack_py-0.1.3/src/hs_py/ws_client.py +1432 -0
- haystack_py-0.1.3/src/hs_py/ws_codec.py +147 -0
- haystack_py-0.1.3/src/hs_py/ws_server.py +477 -0
- haystack_py-0.1.3/tests/__init__.py +0 -0
- haystack_py-0.1.3/tests/conftest.py +1 -0
- haystack_py-0.1.3/tests/test_auth.py +636 -0
- haystack_py-0.1.3/tests/test_client.py +272 -0
- haystack_py-0.1.3/tests/test_content_negotiation.py +173 -0
- haystack_py-0.1.3/tests/test_convert.py +237 -0
- haystack_py-0.1.3/tests/test_csv_encoding.py +311 -0
- haystack_py-0.1.3/tests/test_e2e_docker.py +786 -0
- haystack_py-0.1.3/tests/test_e2e_fastapi.py +451 -0
- haystack_py-0.1.3/tests/test_errors.py +56 -0
- haystack_py-0.1.3/tests/test_filter.py +376 -0
- haystack_py-0.1.3/tests/test_grid.py +116 -0
- haystack_py-0.1.3/tests/test_json_encoding.py +876 -0
- haystack_py-0.1.3/tests/test_kinds.py +281 -0
- haystack_py-0.1.3/tests/test_metrics.py +153 -0
- haystack_py-0.1.3/tests/test_ontology.py +271 -0
- haystack_py-0.1.3/tests/test_rdf_export.py +178 -0
- haystack_py-0.1.3/tests/test_redis_ops.py +1005 -0
- haystack_py-0.1.3/tests/test_redis_tls.py +365 -0
- haystack_py-0.1.3/tests/test_reflect.py +111 -0
- haystack_py-0.1.3/tests/test_scram_core.py +318 -0
- haystack_py-0.1.3/tests/test_server.py +1059 -0
- haystack_py-0.1.3/tests/test_smoke.py +5 -0
- haystack_py-0.1.3/tests/test_storage_memory.py +599 -0
- haystack_py-0.1.3/tests/test_storage_timescale.py +1688 -0
- haystack_py-0.1.3/tests/test_taxonomy.py +234 -0
- haystack_py-0.1.3/tests/test_tls.py +355 -0
- haystack_py-0.1.3/tests/test_trio.py +838 -0
- haystack_py-0.1.3/tests/test_watch.py +590 -0
- haystack_py-0.1.3/tests/test_ws.py +742 -0
- haystack_py-0.1.3/tests/test_ws_codec.py +180 -0
- haystack_py-0.1.3/tests/test_zinc_encoding.py +703 -0
- haystack_py-0.1.3/uv.lock +1900 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: astral-sh/setup-uv@v4
|
|
15
|
+
with:
|
|
16
|
+
enable-cache: true
|
|
17
|
+
- run: uv python install
|
|
18
|
+
- run: uv sync --locked --group lint
|
|
19
|
+
- name: Ruff check
|
|
20
|
+
run: uv run ruff check src/ tests/
|
|
21
|
+
- name: Ruff format check
|
|
22
|
+
run: uv run ruff format --check src/ tests/
|
|
23
|
+
|
|
24
|
+
typecheck:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: astral-sh/setup-uv@v4
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
- run: uv python install
|
|
32
|
+
- run: uv sync --locked --group type-check --all-extras
|
|
33
|
+
- name: Mypy
|
|
34
|
+
run: uv run mypy
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
- uses: astral-sh/setup-uv@v4
|
|
41
|
+
with:
|
|
42
|
+
enable-cache: true
|
|
43
|
+
- run: uv python install
|
|
44
|
+
- run: uv sync --locked --group test --all-extras
|
|
45
|
+
- name: Version consistency check
|
|
46
|
+
run: |
|
|
47
|
+
PYPROJECT_VER=$(python3 -c "
|
|
48
|
+
import re, pathlib
|
|
49
|
+
text = pathlib.Path('pyproject.toml').read_text()
|
|
50
|
+
print(re.search(r'^version\s*=\s*\"([^\"]+)\"', text, re.M).group(1))
|
|
51
|
+
")
|
|
52
|
+
INIT_VER=$(python3 -c "
|
|
53
|
+
import re, pathlib
|
|
54
|
+
text = pathlib.Path('src/hs_py/__init__.py').read_text()
|
|
55
|
+
print(re.search(r'^__version__\s*=\s*\"([^\"]+)\"', text, re.M).group(1))
|
|
56
|
+
")
|
|
57
|
+
echo "pyproject.toml: $PYPROJECT_VER"
|
|
58
|
+
echo "__init__.py: $INIT_VER"
|
|
59
|
+
if [ "$PYPROJECT_VER" != "$INIT_VER" ]; then
|
|
60
|
+
echo "::error::Version mismatch! pyproject.toml and __init__.py must declare the same version."
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
- name: Pytest
|
|
64
|
+
run: uv run pytest --tb=short -q
|
|
65
|
+
|
|
66
|
+
docs:
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
- uses: astral-sh/setup-uv@v4
|
|
71
|
+
with:
|
|
72
|
+
enable-cache: true
|
|
73
|
+
- run: uv python install
|
|
74
|
+
- run: uv sync --locked --group docs --all-extras
|
|
75
|
+
- name: Sphinx build
|
|
76
|
+
run: uv run sphinx-build -W -b html docs docs/_build/html
|
|
77
|
+
|
|
78
|
+
deploy-docs:
|
|
79
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
80
|
+
needs: [lint, typecheck, test, docs]
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
permissions:
|
|
83
|
+
contents: read
|
|
84
|
+
pages: write
|
|
85
|
+
id-token: write
|
|
86
|
+
environment:
|
|
87
|
+
name: github-pages
|
|
88
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@v4
|
|
91
|
+
- uses: astral-sh/setup-uv@v4
|
|
92
|
+
with:
|
|
93
|
+
enable-cache: true
|
|
94
|
+
- run: uv python install
|
|
95
|
+
- run: uv sync --locked --group docs --all-extras
|
|
96
|
+
- name: Sphinx build
|
|
97
|
+
run: uv run sphinx-build -W -b html docs docs/_build/html
|
|
98
|
+
- uses: actions/upload-pages-artifact@v3
|
|
99
|
+
with:
|
|
100
|
+
path: docs/_build/html
|
|
101
|
+
- id: deployment
|
|
102
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: ["CI"]
|
|
6
|
+
types: [completed]
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: release
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
release:
|
|
15
|
+
if: github.event.workflow_run.conclusion == 'success'
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: write
|
|
19
|
+
outputs:
|
|
20
|
+
new_release: ${{ steps.check_tag.outputs.exists == 'false' }}
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
ref: ${{ github.event.workflow_run.head_sha }}
|
|
25
|
+
fetch-depth: 0
|
|
26
|
+
|
|
27
|
+
- name: Extract version from pyproject.toml
|
|
28
|
+
id: version
|
|
29
|
+
run: |
|
|
30
|
+
VERSION=$(python3 -c "
|
|
31
|
+
import re, pathlib
|
|
32
|
+
text = pathlib.Path('pyproject.toml').read_text()
|
|
33
|
+
print(re.search(r'^version\s*=\s*\"([^\"]+)\"', text, re.M).group(1))
|
|
34
|
+
")
|
|
35
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
36
|
+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
|
|
37
|
+
|
|
38
|
+
- name: Check if tag already exists
|
|
39
|
+
id: check_tag
|
|
40
|
+
run: |
|
|
41
|
+
if git rev-parse "refs/tags/${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then
|
|
42
|
+
echo "exists=true" >> "$GITHUB_OUTPUT"
|
|
43
|
+
else
|
|
44
|
+
echo "exists=false" >> "$GITHUB_OUTPUT"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
- name: Extract changelog section
|
|
48
|
+
if: steps.check_tag.outputs.exists == 'false'
|
|
49
|
+
id: changelog
|
|
50
|
+
run: |
|
|
51
|
+
python3 -c "
|
|
52
|
+
import re, pathlib, os
|
|
53
|
+
text = pathlib.Path('CHANGELOG.md').read_text()
|
|
54
|
+
version = '${{ steps.version.outputs.version }}'
|
|
55
|
+
pattern = rf'## \[{re.escape(version)}\][^\n]*\n(.*?)(?=\n## \[|\Z)'
|
|
56
|
+
match = re.search(pattern, text, re.DOTALL)
|
|
57
|
+
body = match.group(1).strip() if match else 'No changelog entry found.'
|
|
58
|
+
# Write to file to avoid shell escaping issues
|
|
59
|
+
pathlib.Path('release_body.md').write_text(body)
|
|
60
|
+
"
|
|
61
|
+
|
|
62
|
+
- name: Create and push tag
|
|
63
|
+
if: steps.check_tag.outputs.exists == 'false'
|
|
64
|
+
run: |
|
|
65
|
+
git config user.name "github-actions[bot]"
|
|
66
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
67
|
+
git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}"
|
|
68
|
+
git push origin "${{ steps.version.outputs.tag }}"
|
|
69
|
+
|
|
70
|
+
- name: Create GitHub Release
|
|
71
|
+
if: steps.check_tag.outputs.exists == 'false'
|
|
72
|
+
uses: softprops/action-gh-release@v2
|
|
73
|
+
with:
|
|
74
|
+
tag_name: ${{ steps.version.outputs.tag }}
|
|
75
|
+
name: ${{ steps.version.outputs.tag }}
|
|
76
|
+
body_path: release_body.md
|
|
77
|
+
draft: false
|
|
78
|
+
prerelease: false
|
|
79
|
+
|
|
80
|
+
build:
|
|
81
|
+
needs: release
|
|
82
|
+
if: needs.release.outputs.new_release == 'true'
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
with:
|
|
87
|
+
ref: ${{ github.event.workflow_run.head_sha }}
|
|
88
|
+
|
|
89
|
+
- uses: actions/setup-python@v5
|
|
90
|
+
with:
|
|
91
|
+
python-version: "3.13"
|
|
92
|
+
|
|
93
|
+
- name: Build package
|
|
94
|
+
run: |
|
|
95
|
+
pip install build
|
|
96
|
+
python -m build
|
|
97
|
+
|
|
98
|
+
- name: Upload distributions
|
|
99
|
+
uses: actions/upload-artifact@v4
|
|
100
|
+
with:
|
|
101
|
+
name: python-package-distributions
|
|
102
|
+
path: dist/
|
|
103
|
+
|
|
104
|
+
upload-release-assets:
|
|
105
|
+
needs: [release, build]
|
|
106
|
+
if: needs.release.outputs.new_release == 'true'
|
|
107
|
+
runs-on: ubuntu-latest
|
|
108
|
+
permissions:
|
|
109
|
+
contents: write
|
|
110
|
+
steps:
|
|
111
|
+
- name: Download distributions
|
|
112
|
+
uses: actions/download-artifact@v4
|
|
113
|
+
with:
|
|
114
|
+
name: python-package-distributions
|
|
115
|
+
path: dist/
|
|
116
|
+
|
|
117
|
+
- name: Extract version tag
|
|
118
|
+
id: version
|
|
119
|
+
run: |
|
|
120
|
+
VERSION=$(ls dist/*.tar.gz | sed 's|dist/haystack_py-||;s|\.tar\.gz||')
|
|
121
|
+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
|
|
122
|
+
|
|
123
|
+
- name: Upload assets to GitHub Release
|
|
124
|
+
uses: softprops/action-gh-release@v2
|
|
125
|
+
with:
|
|
126
|
+
tag_name: ${{ steps.version.outputs.tag }}
|
|
127
|
+
files: dist/*
|
|
128
|
+
|
|
129
|
+
# ──────────────────────────────────────────────────────────
|
|
130
|
+
# PyPI Publish
|
|
131
|
+
#
|
|
132
|
+
# Prerequisites (one-time setup):
|
|
133
|
+
# 1. Go to https://pypi.org/manage/account/publishing/
|
|
134
|
+
# 2. Add a pending publisher:
|
|
135
|
+
# - Package name: haystack-py
|
|
136
|
+
# - Owner: jscott3201
|
|
137
|
+
# - Repository: hs-py
|
|
138
|
+
# - Workflow: release.yml
|
|
139
|
+
# - Environment: pypi
|
|
140
|
+
# 3. In GitHub repo Settings → Environments, create a "pypi"
|
|
141
|
+
# environment. Optionally enable required reviewers for
|
|
142
|
+
# manual approval before each publish.
|
|
143
|
+
# ──────────────────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
publish:
|
|
146
|
+
needs: build
|
|
147
|
+
runs-on: ubuntu-latest
|
|
148
|
+
environment:
|
|
149
|
+
name: pypi
|
|
150
|
+
url: https://pypi.org/p/haystack-py
|
|
151
|
+
permissions:
|
|
152
|
+
id-token: write
|
|
153
|
+
attestations: write
|
|
154
|
+
steps:
|
|
155
|
+
- name: Download distributions
|
|
156
|
+
uses: actions/download-artifact@v4
|
|
157
|
+
with:
|
|
158
|
+
name: python-package-distributions
|
|
159
|
+
path: dist/
|
|
160
|
+
|
|
161
|
+
- name: Publish to PyPI
|
|
162
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
163
|
+
with:
|
|
164
|
+
print-hash: true
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
wheels/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
*.egg
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv
|
|
16
|
+
|
|
17
|
+
# Environment variables
|
|
18
|
+
.env
|
|
19
|
+
.env.*
|
|
20
|
+
|
|
21
|
+
# IDE
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
24
|
+
*.swp
|
|
25
|
+
*.swo
|
|
26
|
+
|
|
27
|
+
# Testing / coverage
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
.coverage
|
|
30
|
+
htmlcov/
|
|
31
|
+
.mypy_cache/
|
|
32
|
+
|
|
33
|
+
# Jupyter
|
|
34
|
+
.ipynb_checkpoints/
|
|
35
|
+
|
|
36
|
+
# Claude Code
|
|
37
|
+
CLAUDE.md
|
|
38
|
+
.claude/
|
|
39
|
+
|
|
40
|
+
# Docs
|
|
41
|
+
docs/_build/
|
|
42
|
+
|
|
43
|
+
# Context & planning
|
|
44
|
+
_ctx/
|
|
45
|
+
_plan/
|
|
46
|
+
_data/
|
|
47
|
+
|
|
48
|
+
# Docker local certs
|
|
49
|
+
docker/.certs/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.3] - 2026-02-24
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Renamed PyPI package from ``hs-py`` to ``haystack-py``.
|
|
13
|
+
|
|
14
|
+
## [0.1.2] - 2026-02-24
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Fixed SCRAM middleware tests using monotonic-relative timestamps for reliable CI.
|
|
19
|
+
|
|
20
|
+
## [0.1.1] - 2026-02-24
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Made `rdflib` a core dependency (no longer optional).
|
|
25
|
+
- Local `make` targets now run with `--all-extras` to match CI.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Fixed SCRAM auth middleware tests (stale handshake purge and token expiry).
|
|
30
|
+
- Fixed RDF turtle export test assertion for prefixed namespace output.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- MIT license file.
|
|
35
|
+
- License metadata in `pyproject.toml`.
|
|
36
|
+
|
|
37
|
+
## [0.1.0] - 2026-02-24
|
|
38
|
+
|
|
39
|
+
Initial release.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Stage 1: build dependencies + install project
|
|
2
|
+
FROM ghcr.io/astral-sh/uv:python3.13-alpine AS builder
|
|
3
|
+
|
|
4
|
+
ENV UV_COMPILE_BYTECODE=1 \
|
|
5
|
+
UV_LINK_MODE=copy \
|
|
6
|
+
UV_PYTHON_DOWNLOADS=0
|
|
7
|
+
|
|
8
|
+
WORKDIR /app
|
|
9
|
+
|
|
10
|
+
# Install dependencies first (cached layer — changes only when lockfile changes)
|
|
11
|
+
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
12
|
+
--mount=type=bind,source=uv.lock,target=uv.lock \
|
|
13
|
+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
|
14
|
+
uv sync --locked --no-install-project --no-dev --extra server
|
|
15
|
+
|
|
16
|
+
# Copy source and install the project itself
|
|
17
|
+
COPY . /app
|
|
18
|
+
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
19
|
+
uv sync --locked --no-dev --extra server
|
|
20
|
+
|
|
21
|
+
# Stage 2: minimal runtime
|
|
22
|
+
FROM python:3.13-alpine
|
|
23
|
+
|
|
24
|
+
RUN addgroup -g 1000 app && adduser -u 1000 -G app -D app
|
|
25
|
+
|
|
26
|
+
COPY --from=builder --chown=app:app /app/.venv /app/.venv
|
|
27
|
+
COPY --from=builder --chown=app:app /app/src /app/src
|
|
28
|
+
|
|
29
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
30
|
+
DATA_DIR="/app/_data"
|
|
31
|
+
|
|
32
|
+
WORKDIR /app
|
|
33
|
+
USER app
|
|
34
|
+
EXPOSE 8080
|
|
35
|
+
|
|
36
|
+
CMD ["python", "-m", "hs_py"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Justin Scott
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
.PHONY: lint typecheck test check fix format coverage coverage-html docs \
|
|
2
|
+
docker-redis docker-test docker-clean \
|
|
3
|
+
docker-server docker-server-clean docker-test-e2e \
|
|
4
|
+
docker-tls-certs docker-redis-tls docker-test-tls \
|
|
5
|
+
docker-timescale docker-test-timescale docker-clean-timescale
|
|
6
|
+
|
|
7
|
+
lint:
|
|
8
|
+
uv run ruff check src/ tests/
|
|
9
|
+
uv run ruff format --check src/ tests/
|
|
10
|
+
|
|
11
|
+
typecheck:
|
|
12
|
+
uv run --all-extras mypy
|
|
13
|
+
|
|
14
|
+
test:
|
|
15
|
+
uv run --all-extras pytest --tb=short -q
|
|
16
|
+
|
|
17
|
+
check: lint typecheck test
|
|
18
|
+
|
|
19
|
+
fix:
|
|
20
|
+
uv run ruff check --fix src/ tests/
|
|
21
|
+
uv run ruff format src/ tests/
|
|
22
|
+
|
|
23
|
+
format:
|
|
24
|
+
uv run ruff format src/ tests/
|
|
25
|
+
|
|
26
|
+
coverage:
|
|
27
|
+
uv run --all-extras pytest --cov --cov-report=term-missing
|
|
28
|
+
|
|
29
|
+
coverage-html:
|
|
30
|
+
uv run --all-extras pytest --cov --cov-report=html
|
|
31
|
+
|
|
32
|
+
docs:
|
|
33
|
+
uv run --group docs sphinx-build -W -b html docs docs/_build/html
|
|
34
|
+
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
# Docker / Server
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
docker-server:
|
|
40
|
+
$(COMPOSE) up -d --build redis server
|
|
41
|
+
|
|
42
|
+
docker-server-clean:
|
|
43
|
+
$(COMPOSE) down
|
|
44
|
+
|
|
45
|
+
docker-test-e2e: docker-server
|
|
46
|
+
$(COMPOSE) up -d --wait server
|
|
47
|
+
HS_PY_DOCKER_E2E=1 uv run pytest tests/test_e2e_docker.py --tb=short -q
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------------------
|
|
50
|
+
# Docker / Redis integration tests
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
COMPOSE := docker compose -f docker/docker-compose.yml
|
|
54
|
+
|
|
55
|
+
docker-redis:
|
|
56
|
+
$(COMPOSE) up -d redis
|
|
57
|
+
|
|
58
|
+
docker-test: docker-redis
|
|
59
|
+
$(COMPOSE) up -d --wait redis
|
|
60
|
+
uv run pytest tests/test_redis_ops.py --tb=short -q
|
|
61
|
+
|
|
62
|
+
docker-clean:
|
|
63
|
+
$(COMPOSE) down -v --remove-orphans
|
|
64
|
+
|
|
65
|
+
# ---------------------------------------------------------------------------
|
|
66
|
+
# Docker / Redis TLS integration tests
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
docker-tls-certs:
|
|
70
|
+
uv run python docker/gen_tls_certs.py
|
|
71
|
+
|
|
72
|
+
docker-redis-tls: docker-tls-certs
|
|
73
|
+
$(COMPOSE) up -d --wait redis-tls
|
|
74
|
+
|
|
75
|
+
docker-test-tls: docker-redis-tls
|
|
76
|
+
uv run pytest tests/test_redis_tls.py --tb=short -q
|
|
77
|
+
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
# Docker / TimescaleDB integration tests
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
docker-timescale:
|
|
83
|
+
$(COMPOSE) up -d --wait timescaledb
|
|
84
|
+
|
|
85
|
+
docker-test-timescale: docker-timescale
|
|
86
|
+
uv run pytest tests/test_storage_timescale.py --tb=short -q
|
|
87
|
+
|
|
88
|
+
docker-clean-timescale:
|
|
89
|
+
$(COMPOSE) down -v --remove-orphans timescaledb
|