-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
219 lines (194 loc) · 7.38 KB
/
Copy pathpyproject.toml
File metadata and controls
219 lines (194 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
[project]
name = "flyquery"
# CalVer YY.MM.PP per memory `firefly_uses_calver`.
version = "26.6.0"
description = "Operational Structured-Data Intelligence (upload-driven) -- multi-tenant ingestion + Text-to-SQL service over user-uploaded structured files. Part of Firefly OperationOS."
readme = "README.md"
requires-python = ">=3.13,<3.14"
# Released under the Apache License 2.0 -- see the LICENSE file. The SDKs
# under ``sdks/python`` and ``sdks/java`` carry their own LICENSE files.
license = { text = "Apache-2.0" }
authors = [
{ name = "Firefly Software Foundation" },
]
dependencies = [
# Firefly Framework runtime -- same extras canon uses so a fresh
# `uv sync` boots the full stack.
"pyfly[fastapi,observability,security,data-relational,postgresql,eda,redis,client,scheduling,cli]>=26.6.113",
# GenAI metaframework -- FireflyAgent over pydantic-ai + the OpenAI
# embeddings provider. flyquery builds its own pgvector hybrid retriever
# and declares sqlglot directly below for its Text-to-SQL pipeline.
"fireflyframework-agentic[rest,security,redis,openai-embeddings]>=26.5.11",
# HTTP + tenacity (outbound).
"httpx>=0.28.0",
"tenacity>=9.0.0",
# Configuration.
"pydantic>=2.10.0",
"pydantic-settings>=2.7.0",
# Persistence. asyncpg for runtime, psycopg for Alembic; alembic env
# rewrites +asyncpg -> +psycopg so one URL covers both.
"sqlalchemy[asyncio]>=2.0",
"asyncpg>=0.30",
"psycopg[binary]>=3.2",
"aiosqlite>=0.22",
"alembic>=1.14",
"redis>=5.2",
"pgvector>=0.3.6",
# Object store
"aiofiles>=24",
# DuckDB -- query engine; pinned here so the extras boundary stays stable.
"duckdb>=1.1",
"pyarrow>=17.0",
# sqlglot -- SQL AST parser / validator / transpiler for the
# Text-to-SQL pipeline (query classification, example mining,
# dialect handling). Declared as a direct dependency.
"sqlglot>=26.0.0",
# Logging.
"structlog>=25.5.0",
# Prompt engine -- YAML files under ``flyquery/resources/prompts``
# rendered through Jinja2 (byte-equivalent pattern to flycanon +
# flyradar). Operators tune agent instructions and user-prompt
# templates without a Python redeploy.
"PyYAML>=6.0",
"jinja2>=3.1",
]
[project.scripts]
flyquery = "flyquery.cli:main"
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.24",
"pytest-cov>=5.0",
"pytest-timeout>=2.3",
"ruff>=0.8",
"pyright>=1.1",
"testcontainers[postgres,redis,minio]>=4.0",
"respx>=0.21",
"httpx>=0.28",
]
# ObjectStore adapter extras
s3 = [
"aiobotocore>=2.15",
"botocore>=1.35",
]
gcs = [
"gcloud-aio-storage>=9.3",
]
azure = [
"azure-storage-blob>=12.23",
"aiohttp>=3.10",
]
# PII detection / anonymization
presidio = [
"presidio-analyzer>=2.2",
"presidio-anonymizer>=2.2",
]
# Cross-encoder reranker
ml-reranker = [
"sentence-transformers>=3.3",
]
# File-format readers
file-readers = [
"python-calamine>=0.3",
"openpyxl>=3.1",
"fastavro>=1.9",
]
[build-system]
requires = ["hatchling>=1.18"]
build-backend = "hatchling.build"
[tool.uv]
# fireflyframework-agentic depends on pydantic-ai>=1.99, whose transitive
# ``pydantic-ai-slim[mistral]`` drags in ``mistralai>=2.0.0`` (PyPI pre-release
# only) and forces ``opentelemetry-semantic-conventions==0.60b1``. flyquery
# never uses the mistral provider, so pin mistralai to the stable 1.x line.
# Drop once mistralai 2.x reaches stable or pydantic-ai stops requesting it.
override-dependencies = [
"mistralai>=1.0.0,<2.0.0",
]
[tool.uv.sources]
# pyfly and agentic are consumed from their published git tags so fresh
# clones / CI resolve them without any sibling path.
pyfly = { git = "https://github.com/fireflyframework/fireflyframework-pyfly.git", tag = "v26.06.113" }
fireflyframework-agentic = { git = "https://github.com/fireflyframework/fireflyframework-agentic.git", tag = "v26.05.30" }
[tool.hatch.build.targets.wheel]
packages = ["src/flyquery"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
asyncio_default_test_loop_scope = "session"
testpaths = ["tests"]
pythonpath = ["src"]
markers = [
"integration: requires docker compose stack (Postgres / Redis / MinIO)",
"s3: requires MinIO (covered by 'integration')",
"gcs: requires fake-gcs-server",
"azure_blob: requires Azurite",
"llm: requires a real LLM provider; skipped by default",
]
addopts = "-v --tb=short -m 'not llm'"
[tool.ruff]
target-version = "py313"
line-length = 110
extend-exclude = ["vendor"]
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "B", "SIM"]
[tool.ruff.lint.per-file-ignores]
"src/flyquery/interfaces/**" = ["N801", "N811", "N815", "N818"]
"src/flyquery/core/services/**" = ["N818", "E501"]
"src/flyquery/core/agents/**" = ["F401"]
"src/flyquery/web/conventions/**" = ["N818"]
# Pyfly's QueryParam resolver chokes on Python 3.10+ PEP 604 unions
# (``str | None`` -> ``types.UnionType`` has no ``__name__``) -- we
# pin ``typing.Optional`` here so the resolver gets ``Union[X, None]``
# which it knows how to introspect. UP007 + UP045 want to rewrite to
# the modern syntax; turn them off for the controller surface.
"src/flyquery/web/controllers/**" = ["UP007", "UP045"]
# Tests: tolerate long lines, blind ``Exception`` in validation-error
# tests, useless-attribute-access probes (assertion helpers), the
# openapi-generated mixedCase test names, and per-test unused imports.
"tests/**" = ["E501", "B017", "B018", "N802", "N806", "F401"]
[tool.pyright]
pythonVersion = "3.13"
typeCheckingMode = "basic"
include = ["src/flyquery"]
# Storage adapters import optional third-party SDKs that aren't part of
# the default install matrix (S3 via aiobotocore, GCS via gcloud-aio,
# Azure via azure-storage-blob). Pyright can't resolve those without
# the extras installed, so we exclude the adapter files from typecheck
# rather than pretending the imports always exist. The Protocol-based
# port stays under typecheck via ``object_store.py``.
exclude = [
"tests/**",
"**/__pycache__/**",
"vendor/**",
"src/flyquery/core/services/storage/adapters/s3.py",
"src/flyquery/core/services/storage/adapters/gcs.py",
"src/flyquery/core/services/storage/adapters/azure_blob.py",
]
# Pyfly's QueryParam[T] is opaque to pyright (it resolves to T at
# request time but the static annotation is QueryParam). Suppress the
# false-positive reportAssignmentType across the controller surface.
reportMissingImports = "warning"
reportOptionalMemberAccess = "warning"
reportOptionalSubscript = "warning"
reportArgumentType = "warning"
reportAttributeAccessIssue = "warning"
reportPrivateImportUsage = "warning"
reportGeneralTypeIssues = "warning"
reportCallIssue = "warning"
reportAssignmentType = "warning"
reportReturnType = "warning"
[[tool.pyright.executionEnvironments]]
# The controller layer is shaped by pyfly's metaprogramming: handlers
# annotate the success response model (consumed for OpenAPI schema
# generation) but return ``JSONResponse`` for non-2xx / multi-status
# escape hatches, and parameter binding uses ``Annotated[...]``
# subscripts pyright's basic mode can't resolve. Silence the resulting
# false positives here rather than scattering per-line ignores.
root = "src/flyquery/web/controllers"
reportArgumentType = "none"
reportAttributeAccessIssue = "none"
reportOperatorIssue = "none"
reportAssignmentType = "none"
reportReturnType = "none"
reportCallIssue = "none"