|
23 | 23 | get_args, |
24 | 24 | get_origin, |
25 | 25 | get_type_hints, |
| 26 | + TypeVar, |
26 | 27 | ) |
27 | 28 |
|
28 | 29 | from isodate import parse_duration |
|
615 | 616 | from airbyte_cdk.sources.streams.http.error_handlers.response_models import ResponseAction |
616 | 617 | from airbyte_cdk.sources.types import Config |
617 | 618 | from airbyte_cdk.sources.utils.transform import TransformConfig, TypeTransformer |
| 619 | +from airbyte_cdk.sources.declarative.parsers.component_constructor import ComponentConstructor |
| 620 | + |
618 | 621 |
|
619 | 622 | ComponentDefinition = Mapping[str, Any] |
620 | 623 |
|
|
623 | 626 | SchemaNormalizationModel.Default: TransformConfig.DefaultSchemaNormalization, |
624 | 627 | } |
625 | 628 |
|
| 629 | +M = TypeVar("M", bound=BaseModel) |
| 630 | +D = TypeVar("D", bound=BaseModel) |
| 631 | + |
626 | 632 |
|
627 | 633 | class ModelToComponentFactory: |
| 634 | + """ |
| 635 | + The default Model > Component Factory implementation. |
| 636 | + The Custom components are built separately from the default implementations, |
| 637 | + to provide the reasonable decoupling from the standard and Custom implementation build technique. |
| 638 | + """ |
| 639 | + |
628 | 640 | EPOCH_DATETIME_FORMAT = "%s" |
629 | 641 |
|
630 | 642 | def __init__( |
@@ -655,8 +667,19 @@ def __init__( |
655 | 667 | # placeholder for deprecation warnings |
656 | 668 | self._collected_deprecation_logs: List[ConnectorBuilderLogMessage] = [] |
657 | 669 |
|
| 670 | + # support the dependency constructors with the re-usable parts from this Factory |
| 671 | + self._flags = { |
| 672 | + "_limit_pages_fetched_per_slice": self._limit_pages_fetched_per_slice, |
| 673 | + "_limit_slices_fetched": self._limit_slices_fetched, |
| 674 | + "_emit_connector_builder_messages": self._emit_connector_builder_messages, |
| 675 | + "_disable_retries": self._disable_retries, |
| 676 | + "_message_repository": self._message_repository, |
| 677 | + } |
| 678 | + |
658 | 679 | def _init_mappings(self) -> None: |
659 | | - self.PYDANTIC_MODEL_TO_CONSTRUCTOR: Mapping[Type[BaseModel], Callable[..., Any]] = { |
| 680 | + self.PYDANTIC_MODEL_TO_CONSTRUCTOR: Dict[ |
| 681 | + Type[BaseModel], Union[Type[ComponentConstructor], Callable[..., Any]] |
| 682 | + ] = { |
660 | 683 | AddedFieldDefinitionModel: self.create_added_field_definition, |
661 | 684 | AddFieldsModel: self.create_add_fields, |
662 | 685 | ApiKeyAuthenticatorModel: self.create_api_key_authenticator, |
@@ -734,7 +757,7 @@ def _init_mappings(self) -> None: |
734 | 757 | PropertiesFromEndpointModel: self.create_properties_from_endpoint, |
735 | 758 | PropertyChunkingModel: self.create_property_chunking, |
736 | 759 | QueryPropertiesModel: self.create_query_properties, |
737 | | - RecordFilterModel: self.create_record_filter, |
| 760 | + RecordFilterModel: RecordFilter, |
738 | 761 | RecordSelectorModel: self.create_record_selector, |
739 | 762 | RemoveFieldsModel: self.create_remove_fields, |
740 | 763 | RequestPathModel: self.create_request_path, |
@@ -803,20 +826,30 @@ def create_component( |
803 | 826 | model=declarative_component_model, config=config, **kwargs |
804 | 827 | ) |
805 | 828 |
|
806 | | - def _create_component_from_model(self, model: BaseModel, config: Config, **kwargs: Any) -> Any: |
| 829 | + def _create_component_from_model( |
| 830 | + self, model: BaseModel, config: Config, **kwargs: Any |
| 831 | + ) -> ComponentConstructor[BaseModel]: |
807 | 832 | if model.__class__ not in self.PYDANTIC_MODEL_TO_CONSTRUCTOR: |
808 | 833 | raise ValueError( |
809 | 834 | f"{model.__class__} with attributes {model} is not a valid component type" |
810 | 835 | ) |
811 | | - component_constructor = self.PYDANTIC_MODEL_TO_CONSTRUCTOR.get(model.__class__) |
812 | | - if not component_constructor: |
813 | | - raise ValueError(f"Could not find constructor for {model.__class__}") |
814 | 836 |
|
815 | | - # collect deprecation warnings for supported models. |
816 | | - if isinstance(model, BaseModelWithDeprecations): |
817 | | - self._collect_model_deprecations(model) |
| 837 | + component = self.PYDANTIC_MODEL_TO_CONSTRUCTOR.get(model.__class__) |
| 838 | + if not component: |
| 839 | + raise ValueError(f"Could not find constructor for {model.__class__}") |
818 | 840 |
|
819 | | - return component_constructor(model=model, config=config, **kwargs) |
| 841 | + if inspect.isclass(component) and issubclass(component, ComponentConstructor): |
| 842 | + # Default components flow |
| 843 | + component_instance: ComponentConstructor[BaseModel] = component.build( |
| 844 | + model=model, |
| 845 | + config=config, |
| 846 | + dependency_constructor=self._create_component_from_model, |
| 847 | + additional_flags=self._flags, |
| 848 | + **kwargs, |
| 849 | + ) |
| 850 | + return component_instance |
| 851 | + else: |
| 852 | + return component(model=model, config=config, **kwargs) |
820 | 853 |
|
821 | 854 | def get_model_deprecations(self) -> List[ConnectorBuilderLogMessage]: |
822 | 855 | """ |
@@ -2999,14 +3032,6 @@ def create_query_properties( |
2999 | 3032 | parameters=model.parameters or {}, |
3000 | 3033 | ) |
3001 | 3034 |
|
3002 | | - @staticmethod |
3003 | | - def create_record_filter( |
3004 | | - model: RecordFilterModel, config: Config, **kwargs: Any |
3005 | | - ) -> RecordFilter: |
3006 | | - return RecordFilter( |
3007 | | - condition=model.condition or "", config=config, parameters=model.parameters or {} |
3008 | | - ) |
3009 | | - |
3010 | 3035 | @staticmethod |
3011 | 3036 | def create_request_path(model: RequestPathModel, config: Config, **kwargs: Any) -> RequestPath: |
3012 | 3037 | return RequestPath(parameters={}) |
|
0 commit comments