Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ruff format, line length 100
b84a31eee8373113ba20d9e89f4ff5b3d98cc58b
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ on:
jobs:
label-gate:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/label-gate.yml@main
ruff:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/ruff.yml@ruff-ty-workflows
ty:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/ty.yml@ruff-ty-workflows
build-test-sqlite:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test.yml@main
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-sqlite.yml@ruff-ty-workflows
build-test-duckdb:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-duckdb.yml@main
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-duckdb.yml@ruff-ty-workflows
build-test-postgres:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-postgres-v2.yml@main
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-postgres-v3.yml@ruff-ty-workflows
with:
postgres-db: orm_loader_test
setup-commands: |
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ It supports:
```python
from orm_loader.tables import ORMTableBase


class MyTable(ORMTableBase, Base):
__tablename__ = "my_table"

```
You can inherit from it directly or pick it up through one of the higher-level mixins.

Expand All @@ -56,7 +56,6 @@ Features include:
```python
class MyTable(FileLoadableTableInterface, ORMTableBase, Base):
__tablename__ = "my_table"

```

The main extension points here are reader choice and the normal SQLAlchemy model definitions themselves. Most downstream projects do not need to override much beyond the model schema.
Expand Down
4 changes: 2 additions & 2 deletions docs/loaders/conversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ class HexHandler(ConvertingHandler):
def arrow_type(self, sa_type):
return pa.int64()

def parse(self, cleaned, sa_type):
... # return Interpretation(values, invalid)
def parse(self, cleaned, sa_type): ... # return Interpretation(values, invalid)


policy = ConversionPolicy(handlers={MyHexType: HexHandler()})
```
Expand Down
20 changes: 9 additions & 11 deletions docs/registry/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,29 +66,25 @@ from orm_loader.tables import ORMTableBase

Base = declarative_base()


class Person(ORMTableBase, Base):
__tablename__ = "person"
# columns omitted for brevity


class VisitOccurrence(ORMTableBase, Base):
__tablename__ = "visit_occurrence"
# columns omitted for brevity

```

## 2. Create a ModelRegistry

The registry is the coordination object that holds models and specs.

```python

from orm_loader.registry import ModelRegistry

registry = ModelRegistry(
model_version="5.4",
model_name="OMOP"
)

registry = ModelRegistry(model_version="5.4", model_name="OMOP")
```

## 3. Load Specifications
Expand Down Expand Up @@ -116,10 +112,12 @@ At this point, the registry knows:
Models can be registered explicitly:

```python
registry.register_models([
Person,
VisitOccurrence,
])
registry.register_models(
[
Person,
VisitOccurrence,
]
)
```

Or discovered automatically from a package:
Expand Down
20 changes: 8 additions & 12 deletions docs/tables/mat_view.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,12 @@ The class declaration is the integration point that downstream code can import a
```python
class RecentObservationMV(Base, MaterializedViewMixin):
__mv_name__ = "mv_recent_observation"
__mv_select__ = (
sa.select(
Observation.observation_id,
Observation.person_id,
Observation.observation_date,
Observation.value_as_number,
)
.where(
Observation.observation_date
>= sa.func.current_date() - sa.text("INTERVAL '30 days'")
)
)
__mv_select__ = sa.select(
Observation.observation_id,
Observation.person_id,
Observation.observation_date,
Observation.value_as_number,
).where(Observation.observation_date >= sa.func.current_date() - sa.text("INTERVAL '30 days'"))
__mv_dependencies__ = {"observation"}
__mv_indexes__ = (
MaterializedViewIndex(
Expand Down Expand Up @@ -120,12 +114,14 @@ class VocabSummaryMV(MaterializedViewMixin):
__mv_select__ = ...
__mv_schema_tag__ = Role.VOCAB.value # resolves via the connection's vocab schema


# Uses __mv_schema_tag__ ("primary" by default) via the connection's own schema_translate_map.
RecentObservationMV.create_mv(engine)

# Override for one call.
RecentObservationMV.create_mv(engine, schema_tag=Role.VOCAB.value)


# Declaratively mapped: the mapped table's own schema is authoritative, no
# __mv_schema_tag__ needed (or consulted) at all.
class VocabPatientSummaryMV(Base, MaterializedViewMixin):
Expand Down
29 changes: 9 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ dev = [
"oa-configurator[postgres,duckdb]>=2.0.0,<3",
"pandas>=2.3.3",
"pytest>=9.0.3",
"ty>=0.0.59",
"ruff>=0.14.11",
"ty==0.0.90",
"ruff==0.17.1",
"mkdocs-material>=9.7.7",
"mkdocstrings-python>=2.0.1",
"requests>=2.33.0",
Expand All @@ -74,11 +74,6 @@ cache-keys = [{ file = "pyproject.toml" }, { git = { commit = true, tags = true

[tool.ruff]
line-length = 100
target-version = "py311"

[tool.mypy]
python_version = "3.11"
strict = true

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand All @@ -87,17 +82,11 @@ python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-ra -m 'not db_dialect'"

[tool.pyright]
reportMissingTypeStubs = false

# Temporary ty override until #43 picks it up in a follow-up
# with pyarrow-stubs, which type the compute functions too narrowly
[[tool.ty.overrides]]
include = ["src/orm_loader/conversion/**", "src/orm_loader/loaders/processor.py", "src/orm_loader/loaders/readers/**"]
[tool.ty.rules]
# raises on stale suppressions
unused-ignore-comment = "error"

[tool.ty.overrides.rules]
unresolved-attribute = "ignore"
invalid-argument-type = "ignore"
invalid-return-type = "ignore"
invalid-assignment = "ignore"
no-matching-overload = "ignore"
[tool.ty.analysis]
# pyarrow ships no inline types and pyarrow-stubs is being retired. Upstream typing is
# not finalised yet (https://github.com/apache/arrow/discussions/45919), so pyarrow is Any.
replace-imports-with-any = ["pyarrow", "pyarrow.**"]
24 changes: 12 additions & 12 deletions src/orm_loader/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
from .duckdb import DuckDBBackend
from .postgres import PostgresBackend
from .resolve import resolve_backend
from .sqlite import SQLiteBackend
from ..mappers.materialised_view_errors import (
ConcurrentRefreshNotEligibleError,
MaterializationError,
MaterializationFailure,
MaterializationOperation,
)
from .base import (
STAGING_SCHEMA,
DatabaseBackend,
DedupeResult,
Dialect,
ForeignKeyViolationError,
STAGING_SCHEMA,
staging_schema_claim,
)
from ..mappers.materialised_view_errors import (
ConcurrentRefreshNotEligibleError,
MaterializationError,
MaterializationFailure,
MaterializationOperation,
)
from .duckdb import DuckDBBackend
from .postgres import PostgresBackend
from .resolve import resolve_backend
from .sqlite import SQLiteBackend

__all__ = [
"STAGING_SCHEMA",
"ConcurrentRefreshNotEligibleError",
"DatabaseBackend",
"DedupeResult",
Expand All @@ -28,7 +29,6 @@
"MaterializationFailure",
"MaterializationOperation",
"PostgresBackend",
"STAGING_SCHEMA",
"SQLiteBackend",
"resolve_backend",
"staging_schema_claim",
Expand Down
Loading
Loading