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
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.6.2"
rev: "v0.16.6"
hooks:
- id: ruff
args: [--fix, --show-fixes]
types_or: [python]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v6.0.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/psf/black
rev: 24.8.0
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 26.5.1
hooks:
- id: black
6 changes: 2 additions & 4 deletions fhirflat/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@

def main():
if len(sys.argv) < 2:
print(
"""fhirflat: specify subcommand to run
print("""fhirflat: specify subcommand to run

Available subcommands:
transform - Convert raw data into FHIRflat files
validate - Validate FHIRflat files against FHIR schemas
"""
)
""")
sys.exit(1)
subcommand = sys.argv[1]
if subcommand not in ["transform", "validate"]:
Expand Down
10 changes: 4 additions & 6 deletions fhirflat/flat2fhir.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@

quant = {}

for attribute in df.keys():
for attribute in df:
attr = attribute.split(".")[-1]
if attr == "code":
if group + ".system" in df.keys():
if group + ".system" in df:
# reading in from ingestion pipeline
quant["code"] = df[group + ".code"]
quant["system"] = df[group + ".system"]
Expand Down Expand Up @@ -213,7 +213,7 @@
klass = get_local_extension_type(k)

prop = klass.schema()["properties"]
value_type = [key for key in prop.keys() if key.startswith("value")]

Check failure on line 216 in fhirflat/flat2fhir.py

View workflow job for this annotation

GitHub Actions / build

ruff (SIM118)

fhirflat/flat2fhir.py:216:27: SIM118 Use `key in dict` instead of `key in dict.keys()` help: Remove `.keys()`

if not value_type: # pragma: no cover
raise RuntimeError("Inappropriate entry into create_single_extension")
Expand Down Expand Up @@ -249,7 +249,7 @@
except ValidationError:
continue
else:
raise e # pragma: no cover

Check failure on line 252 in fhirflat/flat2fhir.py

View workflow job for this annotation

GitHub Actions / build

ruff (TRY201)

fhirflat/flat2fhir.py:252:23: TRY201 Use `raise` without specifying exception name help: Remove exception name

raise RuntimeError(f"extension not created from {k, v}") # pragma: no cover

Expand Down Expand Up @@ -309,7 +309,7 @@

if klass.nested_extension:
classes = find_data_class_options(klass, "extension")
short_extensions = [s for s in v_dict.keys() if s.count(".") == 0]
short_extensions = [s for s in v_dict if s.count(".") == 0]
expanded_short_extensions = []
if short_extensions:
# these get skipped over in expand_concepts because they don't get grouped
Expand Down Expand Up @@ -393,7 +393,7 @@
groups = group_keys(data.keys())
group_classes = {}

for k in groups.keys():

Check failure on line 396 in fhirflat/flat2fhir.py

View workflow job for this annotation

GitHub Actions / build

ruff (SIM118)

fhirflat/flat2fhir.py:396:9: SIM118 Use `key in dict` instead of `key in dict.keys()` help: Remove `.keys()`
group_classes[k] = find_data_class_options(data_class, k)

expanded = {}
Expand Down Expand Up @@ -448,9 +448,7 @@
else:
expanded[k] = [expanded[k]]

dense_cols = {
k: k.removesuffix("_dense") for k in data.keys() if k.endswith("_dense")
}
dense_cols = {k: k.removesuffix("_dense") for k in data if k.endswith("_dense")}
if dense_cols:
for old_k, new_k in dense_cols.items():
data[new_k] = data[old_k]
Expand Down
8 changes: 3 additions & 5 deletions fhirflat/ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
new_tz = ZoneInfo(timezone)

try:
date_time = datetime.strptime(date_str, date_format)

Check failure on line 109 in fhirflat/ingest.py

View workflow job for this annotation

GitHub Actions / build

ruff (DTZ007)

fhirflat/ingest.py:109:21: DTZ007 Naive datetime constructed using `datetime.datetime.strptime()` without %z help: Call `.replace(tzinfo=<timezone>)` or `.astimezone()` to convert to an aware datetime
date_time_aware = date_time.replace(tzinfo=new_tz)
if "%H" not in date_format:
date_time_aware = date_time_aware.date()
Expand All @@ -114,7 +114,7 @@
try:
# Unconverted data remains in the string (i.e. time is present)
date, time = date_str.split(" ")
date = datetime.strptime(date, date_format)

Check failure on line 117 in fhirflat/ingest.py

View workflow job for this annotation

GitHub Actions / build

ruff (DTZ007)

fhirflat/ingest.py:117:20: DTZ007 Naive datetime constructed using `datetime.datetime.strptime()` without %z help: Call `.replace(tzinfo=<timezone>)` or `.astimezone()` to convert to an aware datetime
time = dateutil.parser.parse(time).time()
date_time = datetime.combine(date, time)
date_time_aware = date_time.replace(tzinfo=new_tz)
Expand Down Expand Up @@ -220,9 +220,7 @@
target_length = max(map(len, relevant_result.values()))
for k, v in relevant_result.items():
if len(v) < target_length:
result[k] = relevant_result[k] + [None] * (
target_length - len(v)
)
result[k] = v + [None] * (target_length - len(v))
return result


Expand Down Expand Up @@ -441,7 +439,7 @@
sheet_id: str | None = None,
subject_id="subjid",
validate: bool = True,
compress_format: None | str = None,

Check failure on line 442 in fhirflat/ingest.py

View workflow job for this annotation

GitHub Actions / build

ruff (RUF036)

fhirflat/ingest.py:442:22: RUF036 `None` not at the end of the type union. help: Move `None` to the end of the type union
parallel: bool = False,
):
"""
Expand Down Expand Up @@ -500,7 +498,7 @@

df_types = pd.read_csv(sheet_link, header=0, index_col="Resources")
types = dict(zip(df_types.index, df_types["Resource Type"], strict=True))
sheet_keys = {r: df_types.loc[r, "Sheet ID"] for r in types.keys()}

Check failure on line 501 in fhirflat/ingest.py

View workflow job for this annotation

GitHub Actions / build

ruff (SIM118)

fhirflat/ingest.py:501:58: SIM118 Use `key in dict` instead of `key in dict.keys()` help: Remove `.keys()`
mappings = {
get_local_resource(r): sheet_link + f"&gid={i}"
for r, i in sheet_keys.items()
Expand All @@ -523,7 +521,7 @@
timezone=timezone,
)
if df is None:
return None
return
else:
raise ValueError(f"Unknown mapping type {t}")

Expand Down Expand Up @@ -557,7 +555,7 @@
UserWarning,
stacklevel=2,
)
return None
return

valid_time = timeit.default_timer()
print(f"{resource.__name__} validation in " + str(valid_time - dict_time))
Expand Down
4 changes: 2 additions & 2 deletions fhirflat/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
data = expand_concepts(data, cls)

# create lists for properties which are lists of FHIR types
for field in [x for x in data.keys() if x in cls.attr_lists()]:

Check failure on line 80 in fhirflat/resources/base.py

View workflow job for this annotation

GitHub Actions / build

ruff (SIM118)

fhirflat/resources/base.py:80:29: SIM118 Use `key in dict` instead of `key in dict.keys()` help: Remove `.keys()`
if not isinstance(data[field], list):
data[field] = [data[field]]

Expand All @@ -89,7 +89,7 @@
@classmethod
def validate_fhirflat(
cls, df: pd.DataFrame, return_frames: bool = False
) -> tuple[FHIRFlatBase | pd.DataFrame, None | pd.DataFrame]:
) -> tuple[FHIRFlatBase | pd.DataFrame, pd.DataFrame | None]:
"""
Takes a FHIRflat dataframe and validates the data against the FHIR
schema. Returns a dataframe of valid resources and a dataframe of the
Expand Down Expand Up @@ -276,7 +276,7 @@
flat_df.drop(columns=system_columns, inplace=True)

potential_dense_cols = [
x for x in cls.backbone_elements.keys() if x in flat_df.columns

Check failure on line 279 in fhirflat/resources/base.py

View workflow job for this annotation

GitHub Actions / build

ruff (SIM118)

fhirflat/resources/base.py:279:23: SIM118 Use `key in dict` instead of `key in dict.keys()` help: Remove `.keys()`
]

long_list_cols = [
Expand Down Expand Up @@ -355,7 +355,7 @@

df.to_parquet(output_name)

def to_flat(self, filename: str | None = None) -> None | pd.Series:
def to_flat(self, filename: str | None = None) -> pd.Series | None:
"""
Generates a FHIRflat parquet file from the resource, or returns a Series

Expand Down
20 changes: 8 additions & 12 deletions fhirflat/resources/condition.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import ClassVar, TypeAlias, Union
from typing import ClassVar, TypeAlias

from fhir.resources import fhirtypes
from fhir.resources.condition import Condition as _Condition
Expand Down Expand Up @@ -30,22 +30,18 @@

class Condition(_Condition, FHIRFlatBase):
extension: list[
Union[
presenceAbsenceType,
prespecifiedQueryType,
timingPhaseType,
timingPhaseDetailType,
fhirtypes.ExtensionType,
]
presenceAbsenceType
| prespecifiedQueryType
| timingPhaseType
| timingPhaseDetailType
| fhirtypes.ExtensionType
] = Field(
None,
alias="extension",
title="Additional content defined by implementations",
description=(
"""
description=("""
Contains the G.H 'age' and 'birthSex' extensions,
and allows extensions from other implementations to be included."""
),
and allows extensions from other implementations to be included."""),
# if property is element of this resource.
element_property=True,
union_mode="smart",
Expand Down
12 changes: 5 additions & 7 deletions fhirflat/resources/diagnosticreport.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import ClassVar, Union
from typing import ClassVar

from fhir.resources import fhirtypes
from fhir.resources.diagnosticreport import (
Expand All @@ -21,17 +21,15 @@

class DiagnosticReport(_DiagnosticReport, FHIRFlatBase):
extension: list[
Union[timingPhaseType, timingPhaseDetailType, fhirtypes.ExtensionType]
timingPhaseType | timingPhaseDetailType | fhirtypes.ExtensionType
] = Field(
None,
alias="extension",
title="List of `Extension` items (represented as `dict` in JSON)",
description=(
"""
description=("""
Contains the Global.health 'timingPhase' extension,
and allows extensions from other implementations to be included.
"""
),
"""),
# if property is element of this resource.
element_property=True,
# this trys to match the type of the object to each of the union types
Expand Down Expand Up @@ -86,7 +84,7 @@ def cleanup(cls, data: dict) -> dict:
"study",
"composition",
}
| {x for x in data.keys() if x.endswith(".reference")}
| {x for x in data if x.endswith(".reference")}
).intersection(data.keys()):
data[field] = {"reference": data[field]}

Expand Down
18 changes: 7 additions & 11 deletions fhirflat/resources/encounter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import ClassVar, TypeAlias, Union
from typing import ClassVar, TypeAlias

from fhir.resources import fhirtypes
from fhir.resources.encounter import Encounter as _Encounter
Expand All @@ -22,22 +22,18 @@

class Encounter(_Encounter, FHIRFlatBase):
extension: list[
Union[
relativePeriodType,
timingPhaseType,
timingPhaseDetailType,
fhirtypes.ExtensionType,
]
relativePeriodType
| timingPhaseType
| timingPhaseDetailType
| fhirtypes.ExtensionType
] = Field(
None,
alias="extension",
title="List of `Extension` items (represented as `dict` in JSON)",
description=(
"""
description=("""
Contains the Global.health 'eventTiming' and 'relativePeriod' extensions,
and allows extensions from other implementations to be included.
"""
),
"""),
# if property is element of this resource.
element_property=True,
# this trys to match the type of the object to each of the union types
Expand Down
2 changes: 1 addition & 1 deletion fhirflat/resources/extension_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class AbstractType(_AbstractType):
@classmethod
def __get_validators__(cls) -> "CallableGenerator":
def __get_validators__(cls) -> CallableGenerator:
from . import extension_validators as validators

yield getattr(validators, cls.__resource_type__.lower() + "_validator")
Expand Down
42 changes: 21 additions & 21 deletions fhirflat/resources/extension_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import importlib
import typing
from pathlib import Path
from typing import TYPE_CHECKING, Type, Union
from typing import TYPE_CHECKING

from fhir.resources.core.fhirabstractmodel import FHIRAbstractModel
from pydantic.v1.class_validators import make_generic_validator
Expand Down Expand Up @@ -72,7 +72,7 @@ def __init__(self):
"dateTimeExtension": (None, ".extensions"),
}

def get_fhir_model_class(self, model_name: str) -> Type[FHIRAbstractModel]:
def get_fhir_model_class(self, model_name: str) -> type[FHIRAbstractModel]:
"""
Returns the extension class by finding the 'datetimeextension' file and
importing the type class.
Expand All @@ -95,11 +95,11 @@ def run_validator_for_fhir_type(self, model_type_cls, v, values, config, field):
return v

def fhir_model_validator(
self, model_name: str, v: Union[StrBytes, dict, Path, FHIRAbstractModel]
self, model_name: str, v: StrBytes | dict | Path | FHIRAbstractModel
):
""" """
model_class: Type[BaseModel] | Type[FHIRAbstractModel] = (
self.get_fhir_model_class(model_name)
model_class: type[BaseModel | FHIRAbstractModel] = self.get_fhir_model_class(
model_name
)

if isinstance(v, (str, bytes)):
Expand All @@ -108,7 +108,7 @@ def fhir_model_validator(
except ValidationError as exc:
if TYPE_CHECKING:
model_class = typing.cast(
Type[BaseModel], model_class
type[BaseModel], model_class
) # pragma: no cover
errors = exc.errors()
if (
Expand Down Expand Up @@ -200,61 +200,61 @@ def fhir_model_validator(
return v


def timingphase_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def timingphase_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("timingPhase", v)


def timingdetail_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def timingdetail_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("timingDetail", v)


def timingphasedetail_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def timingphasedetail_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("timingPhaseDetail", v)


def relativeday_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def relativeday_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("relativeDay", v)


def relativestart_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def relativestart_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("relativeStart", v)


def relativeend_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def relativeend_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("relativeEnd", v)


def relativeperiod_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def relativeperiod_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("relativePeriod", v)


def approximatedate_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def approximatedate_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("approximateDate", v)


def duration_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def duration_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("Duration", v)


def age_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def age_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("Age", v)


def birthsex_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def birthsex_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("birthSex", v)


def race_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def race_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("Race", v)


def presenceabsence_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def presenceabsence_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("presenceAbsence", v)


def prespecifiedquery_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def prespecifiedquery_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("prespecifiedQuery", v)


def datetimeextension_validator(v: Union[StrBytes, dict, Path, FHIRAbstractModel]):
def datetimeextension_validator(v: StrBytes | dict | Path | FHIRAbstractModel):
return Validators().fhir_model_validator("dateTimeExtension", v)
8 changes: 4 additions & 4 deletions fhirflat/resources/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from __future__ import annotations

from typing import Any, ClassVar, Union
from typing import Any, ClassVar

from fhir.resources import fhirtypes
from fhir.resources.datatype import DataType as _DataType
Expand Down Expand Up @@ -216,7 +216,7 @@ class timingPhaseDetail(_ISARICExtension):

nested_extension: ClassVar[bool] = True

extension: list[Union[et.timingPhaseType, et.timingDetailType]] = Field(
extension: list[et.timingPhaseType | et.timingDetailType] = Field(
None,
alias="extension",
title="List of `Extension` items (represented as `dict` in JSON)",
Expand Down Expand Up @@ -367,7 +367,7 @@ class relativePeriod(_ISARICExtension):

nested_extension: ClassVar[bool] = True

extension: list[Union[et.relativeStartType, et.relativeEndType]] = Field(
extension: list[et.relativeStartType | et.relativeEndType] = Field(
None,
alias="extension",
title="List of `Extension` items (represented as `dict` in JSON)",
Expand Down Expand Up @@ -712,7 +712,7 @@ class dateTimeExtension(_FHIRPrimitiveExtension):
resource_type: str = Field(default="dateTimeExtension", const=True)

extension: list[
Union[et.approximateDateType, et.relativeDayType, fhirtypes.ExtensionType]
et.approximateDateType | et.relativeDayType | fhirtypes.ExtensionType
] = Field(
None,
alias="extension",
Expand Down
Loading
Loading