From 59796aebd2b8b24f9be295af0a593b677e144609 Mon Sep 17 00:00:00 2001 From: fderuiter <127706008+fderuiter@users.noreply.github.com> Date: Sun, 5 Apr 2026 18:34:21 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8F=9B=EF=B8=8F=20Architect:=20Refact?= =?UTF-8?q?or=20Endpoints=20to=20use=20Explicit=20Study=20Key=20Strategies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design Change: Replaced implicit boolean flags (`_pop_study_filter`) and exception class overrides (`_missing_study_exception`) with an explicit Strategy pattern (`STUDY_KEY_STRATEGY`). DRY Gains: Removed conditional branching in `ParamMixin.study_key_strategy` property, leaning completely on the explicit presence of `self.STUDY_KEY_STRATEGY`. Solidity: Enforces "Explicit > Implicit". The logic for handling study keys is now immediately visible at the endpoint definition level via instances like `PopStudyKeyStrategy`. Breaking Changes: None. The default fallback in `ParamMixin` when `requires_study_key` is True and no strategy is set maps exactly to the previous default behavior. Existing endpoints maintain their exact exception classes (`KeyError` or `ValueError`). Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- src/imednet/core/endpoint/mixins/params.py | 7 +------ src/imednet/core/endpoint/protocols.py | 2 -- src/imednet/endpoints/codings.py | 4 ++-- src/imednet/endpoints/forms.py | 4 ++-- src/imednet/endpoints/intervals.py | 4 ++-- src/imednet/endpoints/records.py | 4 ++-- src/imednet/endpoints/sites.py | 4 ++-- src/imednet/endpoints/users.py | 4 ++-- src/imednet/endpoints/variables.py | 4 ++-- 9 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/imednet/core/endpoint/mixins/params.py b/src/imednet/core/endpoint/mixins/params.py index cacad4f5..ce46eb41 100644 --- a/src/imednet/core/endpoint/mixins/params.py +++ b/src/imednet/core/endpoint/mixins/params.py @@ -20,8 +20,6 @@ class ParamMixin: """Mixin for handling endpoint parameters and filters.""" requires_study_key: bool = True - _pop_study_filter: bool = False - _missing_study_exception: type[Exception] = ValueError PARAM_PROCESSOR: Optional[ParamProcessor] = None PARAM_PROCESSOR_CLS: type[ParamProcessor] = DefaultParamProcessor @@ -38,11 +36,8 @@ def study_key_strategy(self) -> StudyKeyStrategy: if self.STUDY_KEY_STRATEGY: return self.STUDY_KEY_STRATEGY - # Backward compatibility logic if self.requires_study_key: - if self._pop_study_filter: - return PopStudyKeyStrategy(exception_cls=self._missing_study_exception) - return KeepStudyKeyStrategy(exception_cls=self._missing_study_exception) + return KeepStudyKeyStrategy() return OptionalStudyKeyStrategy() @property diff --git a/src/imednet/core/endpoint/protocols.py b/src/imednet/core/endpoint/protocols.py index fa92aebe..69f41790 100644 --- a/src/imednet/core/endpoint/protocols.py +++ b/src/imednet/core/endpoint/protocols.py @@ -17,8 +17,6 @@ class EndpointProtocol(Protocol): _enable_cache: bool requires_study_key: bool PAGE_SIZE: int - _pop_study_filter: bool - _missing_study_exception: type[Exception] def _auto_filter(self, filters: Dict[str, Any]) -> Dict[str, Any]: """Apply automatic filters (e.g., default study key).""" diff --git a/src/imednet/endpoints/codings.py b/src/imednet/endpoints/codings.py index e76711e7..bf71ae29 100644 --- a/src/imednet/endpoints/codings.py +++ b/src/imednet/endpoints/codings.py @@ -3,6 +3,7 @@ from imednet.core.endpoint.base import GenericEndpoint from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin +from imednet.core.endpoint.strategies import PopStudyKeyStrategy from imednet.models.codings import Coding @@ -21,5 +22,4 @@ class CodingsEndpoint( PATH = "codings" MODEL = Coding _id_param = "codingId" - _pop_study_filter = True - _missing_study_exception = KeyError + STUDY_KEY_STRATEGY = PopStudyKeyStrategy(exception_cls=KeyError) diff --git a/src/imednet/endpoints/forms.py b/src/imednet/endpoints/forms.py index ebcbca41..320dc41e 100644 --- a/src/imednet/endpoints/forms.py +++ b/src/imednet/endpoints/forms.py @@ -3,6 +3,7 @@ from imednet.core.endpoint.base import GenericEndpoint from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin +from imednet.core.endpoint.strategies import PopStudyKeyStrategy from imednet.models.forms import Form @@ -22,6 +23,5 @@ class FormsEndpoint( MODEL = Form _id_param = "formId" _enable_cache = True - _pop_study_filter = True - _missing_study_exception = KeyError + STUDY_KEY_STRATEGY = PopStudyKeyStrategy(exception_cls=KeyError) PAGE_SIZE = 500 diff --git a/src/imednet/endpoints/intervals.py b/src/imednet/endpoints/intervals.py index 0e6525e7..fb173491 100644 --- a/src/imednet/endpoints/intervals.py +++ b/src/imednet/endpoints/intervals.py @@ -3,6 +3,7 @@ from imednet.core.endpoint.base import GenericEndpoint from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin +from imednet.core.endpoint.strategies import PopStudyKeyStrategy from imednet.models.intervals import Interval @@ -22,6 +23,5 @@ class IntervalsEndpoint( MODEL = Interval _id_param = "intervalId" _enable_cache = True - _pop_study_filter = True - _missing_study_exception = KeyError + STUDY_KEY_STRATEGY = PopStudyKeyStrategy(exception_cls=KeyError) PAGE_SIZE = 500 diff --git a/src/imednet/endpoints/records.py b/src/imednet/endpoints/records.py index 2820c857..3fa4c231 100644 --- a/src/imednet/endpoints/records.py +++ b/src/imednet/endpoints/records.py @@ -6,7 +6,7 @@ from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin from imednet.core.endpoint.operations import RecordCreateOperation -from imednet.core.endpoint.strategies import MappingParamProcessor +from imednet.core.endpoint.strategies import KeepStudyKeyStrategy, MappingParamProcessor from imednet.models.jobs import Job from imednet.models.records import Record from imednet.validation.cache import SchemaCache @@ -27,7 +27,7 @@ class RecordsEndpoint( PATH = "records" MODEL = Record _id_param = "recordId" - _pop_study_filter = False + STUDY_KEY_STRATEGY = KeepStudyKeyStrategy() PARAM_PROCESSOR = MappingParamProcessor({"record_data_filter": "recordDataFilter"}) def create( diff --git a/src/imednet/endpoints/sites.py b/src/imednet/endpoints/sites.py index d128aad4..cd021eba 100644 --- a/src/imednet/endpoints/sites.py +++ b/src/imednet/endpoints/sites.py @@ -3,6 +3,7 @@ from imednet.core.endpoint.base import GenericEndpoint from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin +from imednet.core.endpoint.strategies import PopStudyKeyStrategy from imednet.models.sites import Site @@ -21,5 +22,4 @@ class SitesEndpoint( PATH = "sites" MODEL = Site _id_param = "siteId" - _pop_study_filter = True - _missing_study_exception = KeyError + STUDY_KEY_STRATEGY = PopStudyKeyStrategy(exception_cls=KeyError) diff --git a/src/imednet/endpoints/users.py b/src/imednet/endpoints/users.py index a073ed2d..259ec463 100644 --- a/src/imednet/endpoints/users.py +++ b/src/imednet/endpoints/users.py @@ -3,7 +3,7 @@ from imednet.core.endpoint.base import GenericEndpoint from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin -from imednet.core.endpoint.strategies import MappingParamProcessor +from imednet.core.endpoint.strategies import MappingParamProcessor, PopStudyKeyStrategy from imednet.models.users import User @@ -22,7 +22,7 @@ class UsersEndpoint( PATH = "users" MODEL = User _id_param = "userId" - _pop_study_filter = True + STUDY_KEY_STRATEGY = PopStudyKeyStrategy(exception_cls=ValueError) PARAM_PROCESSOR = MappingParamProcessor( mapping={"include_inactive": "includeInactive"}, defaults={"include_inactive": False}, diff --git a/src/imednet/endpoints/variables.py b/src/imednet/endpoints/variables.py index adb6a03e..ca95ec3c 100644 --- a/src/imednet/endpoints/variables.py +++ b/src/imednet/endpoints/variables.py @@ -3,6 +3,7 @@ from imednet.core.endpoint.base import GenericEndpoint from imednet.core.endpoint.edc_mixin import EdcEndpointMixin from imednet.core.endpoint.mixins import FilterGetEndpointMixin, ListEndpointMixin +from imednet.core.endpoint.strategies import PopStudyKeyStrategy from imednet.models.variables import Variable @@ -22,6 +23,5 @@ class VariablesEndpoint( MODEL = Variable _id_param = "variableId" _enable_cache = True - _pop_study_filter = True - _missing_study_exception = KeyError + STUDY_KEY_STRATEGY = PopStudyKeyStrategy(exception_cls=KeyError) PAGE_SIZE = 500 From df049805b1883a1cc90a31aeafdea155fbaccc16 Mon Sep 17 00:00:00 2001 From: fderuiter <127706008+fderuiter@users.noreply.github.com> Date: Sun, 5 Apr 2026 18:37:46 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8F=9B=EF=B8=8F=20Architect:=20Refact?= =?UTF-8?q?or=20Endpoints=20to=20use=20Explicit=20Study=20Key=20Strategies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design Change: Replaced implicit boolean flags (`_pop_study_filter`) and exception class overrides (`_missing_study_exception`) with an explicit Strategy pattern (`STUDY_KEY_STRATEGY`). DRY Gains: Removed conditional branching in `ParamMixin.study_key_strategy` property, leaning completely on the explicit presence of `self.STUDY_KEY_STRATEGY`. Solidity: Enforces "Explicit > Implicit". The logic for handling study keys is now immediately visible at the endpoint definition level via instances like `PopStudyKeyStrategy`. Breaking Changes: None. The default fallback in `ParamMixin` when `requires_study_key` is True and no strategy is set maps exactly to the previous default behavior. Existing endpoints maintain their exact exception classes (`KeyError` or `ValueError`). Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- src/imednet/core/endpoint/mixins/params.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/imednet/core/endpoint/mixins/params.py b/src/imednet/core/endpoint/mixins/params.py index ce46eb41..b5565010 100644 --- a/src/imednet/core/endpoint/mixins/params.py +++ b/src/imednet/core/endpoint/mixins/params.py @@ -6,7 +6,6 @@ DefaultParamProcessor, KeepStudyKeyStrategy, OptionalStudyKeyStrategy, - PopStudyKeyStrategy, StudyKeyStrategy, ) from imednet.core.endpoint.structs import ParamState