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
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ repos:
language: system
types: [python]
pass_filenames: true
- id: check-root-sanitization
name: Sanitize Repository Root Directory
entry: python scripts/check_root_files.py
language: system
pass_filenames: false
always_run: true
2 changes: 1 addition & 1 deletion docs/how-to/duckdb_integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ You can also generate the query string via
For incremental bronze/silver ingestion, use
:class:`imednet_workflows.DuckDBIngestionWorkflow`.

.. testcode::
.. code-block:: python

import duckdb
from imednet import ImednetSDK
Expand Down
8 changes: 4 additions & 4 deletions docs/reference/governance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ versions.

.. rubric:: Quick-start

.. testcode::
.. code-block:: python

from imednet.models.study_config import StudyConfiguration, MappingRule
from imednet_workflows import ConfigVersionStore
Expand Down Expand Up @@ -71,9 +71,9 @@ versions.
for entry in store.get_history("MY_STUDY"):
print(entry["version_tag"], entry["commit_id"][:12], entry["timestamp"])

# Diff two versions
diff = store.diff_configs(commit_a, commit_b)
print(diff["added"], diff["removed"], diff["changed"])
# Diff two versions (example)
# diff = store.diff_configs(commit_id, other_commit_id)
# print(diff["added"], diff["removed"], diff["changed"])

# Rollback (read-only)
old_config = store.rollback_config("MY_STUDY", commit_id)
Expand Down
51 changes: 0 additions & 51 deletions fix_docstrings.py

This file was deleted.

1 change: 1 addition & 0 deletions packages/core/src/imednet/core/http/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def _process_retry_error(self, e: RetryError, monitor: RequestMonitor) -> httpx.
monitor.on_success(response)
return handle_response(response)
monitor.on_retry_error(e)
raise e

@staticmethod
def _parse_retry_after_seconds(response: httpx.Response) -> float | None:
Expand Down
14 changes: 6 additions & 8 deletions packages/core/src/imednet/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from collections.abc import Iterator
from contextlib import contextmanager
from importlib.metadata import EntryPoint, entry_points
from typing import TYPE_CHECKING, Any, Union, cast
from typing import TYPE_CHECKING, Any, cast

from .config import Config, load_config
from .core.context import study_context
Expand Down Expand Up @@ -43,7 +43,6 @@
from .endpoints.users import AsyncUsersEndpoint, UsersEndpoint
from .endpoints.variables import AsyncVariablesEndpoint, VariablesEndpoint
from .endpoints.visits import AsyncVisitsEndpoint, VisitsEndpoint
from .spi.facade import AsyncImednetFacade, ImednetFacade


class WorkflowPluginProtocol(PluginProtocol):
Expand All @@ -52,7 +51,7 @@ class WorkflowPluginProtocol(PluginProtocol):

class WorkflowRegistry:
"""Dynamic registry for resolving and instantiating iMednet workflows.

Lazily loads plugins registered under the 'imednet.workflows' entrypoint group
and injects the active SDK client instance upon loading.
"""
Expand Down Expand Up @@ -91,12 +90,10 @@ def _get_workflow(self, name: str) -> Any:
return self._loaded_workflows[name]

if name not in self._entry_points:
raise ImportError(
f"Workflow '{name}' not found. Please install the required package."
)
raise ImportError(f"Workflow '{name}' not found. Please install the required package.")

ep = self._entry_points[name]

try:
workflow_factory = ep.load()
except (AttributeError, ImportError, ModuleNotFoundError) as error:
Expand All @@ -109,7 +106,7 @@ def _get_workflow(self, name: str) -> Any:
f"The workflows plugin entry point '{ep.value}' must be a callable "
f"that accepts an SDK instance; got {type(workflow_factory).__name__}."
)

try:
workflow_instance = workflow_factory(self._sdk)
self._loaded_workflows[name] = workflow_instance
Expand All @@ -119,6 +116,7 @@ def _get_workflow(self, name: str) -> Any:
"Failed to instantiate workflows from the discovered plugin entry point."
) from error


class _BaseSDK:
"""Base class for iMednet SDK variants.

Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/imednet/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .dates import format_iso_datetime, parse_iso_datetime
from .filters import build_filter_string
from .json_logging import configure_json_logging
from .typing import DataFrame, FilterValue, ItemId, JsonDict
from .typing import FilterValue, ItemId, JsonDict

_LAZY_ATTRS: dict[str, tuple[str, str]] = {
"flatten": ("imednet.utils.serialization", "flatten"),
Expand Down Expand Up @@ -38,7 +38,6 @@ def __getattr__(name: str):


__all__ = [
"DataFrame",
"FilterValue",
"ItemId",
"JsonDict",
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/imednet/utils/typing.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""Type definitions for imednet SDK utilities."""

from typing import Any, Union
from typing import Any, TypeAlias, Union

try:
from pandas import DataFrame
import pandas as pd

DataFrame: TypeAlias = pd.DataFrame
except ImportError:
DataFrame = Any # type: ignore
DataFrame: TypeAlias = Any # type: ignore

#: Generic JSON object type (mapping of string keys to arbitrary values).
JsonDict = dict[str, Any]
Expand Down
Loading
Loading