airbyte-cdk 0.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airbyte_cdk/__init__.py +358 -0
- airbyte_cdk/cli/__init__.py +1 -0
- airbyte_cdk/cli/source_declarative_manifest/__init__.py +5 -0
- airbyte_cdk/cli/source_declarative_manifest/_run.py +236 -0
- airbyte_cdk/cli/source_declarative_manifest/spec.json +17 -0
- airbyte_cdk/config_observation.py +104 -0
- airbyte_cdk/connector.py +123 -0
- airbyte_cdk/connector_builder/README.md +53 -0
- airbyte_cdk/connector_builder/__init__.py +3 -0
- airbyte_cdk/connector_builder/connector_builder_handler.py +121 -0
- airbyte_cdk/connector_builder/main.py +107 -0
- airbyte_cdk/connector_builder/models.py +73 -0
- airbyte_cdk/connector_builder/test_reader/__init__.py +7 -0
- airbyte_cdk/connector_builder/test_reader/helpers.py +689 -0
- airbyte_cdk/connector_builder/test_reader/message_grouper.py +173 -0
- airbyte_cdk/connector_builder/test_reader/reader.py +441 -0
- airbyte_cdk/connector_builder/test_reader/types.py +83 -0
- airbyte_cdk/destinations/__init__.py +8 -0
- airbyte_cdk/destinations/destination.py +154 -0
- airbyte_cdk/destinations/vector_db_based/README.md +37 -0
- airbyte_cdk/destinations/vector_db_based/__init__.py +38 -0
- airbyte_cdk/destinations/vector_db_based/config.py +298 -0
- airbyte_cdk/destinations/vector_db_based/document_processor.py +223 -0
- airbyte_cdk/destinations/vector_db_based/embedder.py +303 -0
- airbyte_cdk/destinations/vector_db_based/indexer.py +78 -0
- airbyte_cdk/destinations/vector_db_based/test_utils.py +63 -0
- airbyte_cdk/destinations/vector_db_based/utils.py +35 -0
- airbyte_cdk/destinations/vector_db_based/writer.py +104 -0
- airbyte_cdk/entrypoint.py +414 -0
- airbyte_cdk/exception_handler.py +56 -0
- airbyte_cdk/logger.py +109 -0
- airbyte_cdk/models/__init__.py +72 -0
- airbyte_cdk/models/airbyte_protocol.py +88 -0
- airbyte_cdk/models/airbyte_protocol_serializers.py +44 -0
- airbyte_cdk/models/well_known_types.py +5 -0
- airbyte_cdk/py.typed +0 -0
- airbyte_cdk/sources/__init__.py +26 -0
- airbyte_cdk/sources/abstract_source.py +326 -0
- airbyte_cdk/sources/concurrent_source/__init__.py +8 -0
- airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py +255 -0
- airbyte_cdk/sources/concurrent_source/concurrent_source.py +165 -0
- airbyte_cdk/sources/concurrent_source/concurrent_source_adapter.py +147 -0
- airbyte_cdk/sources/concurrent_source/partition_generation_completed_sentinel.py +24 -0
- airbyte_cdk/sources/concurrent_source/stream_thread_exception.py +25 -0
- airbyte_cdk/sources/concurrent_source/thread_pool_manager.py +115 -0
- airbyte_cdk/sources/config.py +27 -0
- airbyte_cdk/sources/connector_state_manager.py +161 -0
- airbyte_cdk/sources/declarative/__init__.py +3 -0
- airbyte_cdk/sources/declarative/async_job/__init__.py +0 -0
- airbyte_cdk/sources/declarative/async_job/job.py +52 -0
- airbyte_cdk/sources/declarative/async_job/job_orchestrator.py +525 -0
- airbyte_cdk/sources/declarative/async_job/job_tracker.py +79 -0
- airbyte_cdk/sources/declarative/async_job/repository.py +35 -0
- airbyte_cdk/sources/declarative/async_job/status.py +24 -0
- airbyte_cdk/sources/declarative/async_job/timer.py +39 -0
- airbyte_cdk/sources/declarative/auth/__init__.py +8 -0
- airbyte_cdk/sources/declarative/auth/declarative_authenticator.py +42 -0
- airbyte_cdk/sources/declarative/auth/jwt.py +197 -0
- airbyte_cdk/sources/declarative/auth/oauth.py +293 -0
- airbyte_cdk/sources/declarative/auth/selective_authenticator.py +45 -0
- airbyte_cdk/sources/declarative/auth/token.py +267 -0
- airbyte_cdk/sources/declarative/auth/token_provider.py +82 -0
- airbyte_cdk/sources/declarative/checks/__init__.py +24 -0
- airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py +61 -0
- airbyte_cdk/sources/declarative/checks/check_stream.py +56 -0
- airbyte_cdk/sources/declarative/checks/connection_checker.py +35 -0
- airbyte_cdk/sources/declarative/concurrency_level/__init__.py +7 -0
- airbyte_cdk/sources/declarative/concurrency_level/concurrency_level.py +50 -0
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py +526 -0
- airbyte_cdk/sources/declarative/datetime/__init__.py +3 -0
- airbyte_cdk/sources/declarative/datetime/datetime_parser.py +65 -0
- airbyte_cdk/sources/declarative/datetime/min_max_datetime.py +118 -0
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +3975 -0
- airbyte_cdk/sources/declarative/declarative_source.py +36 -0
- airbyte_cdk/sources/declarative/declarative_stream.py +241 -0
- airbyte_cdk/sources/declarative/decoders/__init__.py +33 -0
- airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py +218 -0
- airbyte_cdk/sources/declarative/decoders/decoder.py +32 -0
- airbyte_cdk/sources/declarative/decoders/decoder_parser.py +30 -0
- airbyte_cdk/sources/declarative/decoders/json_decoder.py +65 -0
- airbyte_cdk/sources/declarative/decoders/noop_decoder.py +21 -0
- airbyte_cdk/sources/declarative/decoders/pagination_decoder_decorator.py +39 -0
- airbyte_cdk/sources/declarative/decoders/xml_decoder.py +98 -0
- airbyte_cdk/sources/declarative/decoders/zipfile_decoder.py +56 -0
- airbyte_cdk/sources/declarative/exceptions.py +9 -0
- airbyte_cdk/sources/declarative/extractors/__init__.py +21 -0
- airbyte_cdk/sources/declarative/extractors/dpath_extractor.py +86 -0
- airbyte_cdk/sources/declarative/extractors/http_selector.py +37 -0
- airbyte_cdk/sources/declarative/extractors/record_extractor.py +27 -0
- airbyte_cdk/sources/declarative/extractors/record_filter.py +91 -0
- airbyte_cdk/sources/declarative/extractors/record_selector.py +170 -0
- airbyte_cdk/sources/declarative/extractors/response_to_file_extractor.py +176 -0
- airbyte_cdk/sources/declarative/extractors/type_transformer.py +55 -0
- airbyte_cdk/sources/declarative/incremental/__init__.py +37 -0
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +497 -0
- airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py +459 -0
- airbyte_cdk/sources/declarative/incremental/declarative_cursor.py +13 -0
- airbyte_cdk/sources/declarative/incremental/global_substream_cursor.py +357 -0
- airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +380 -0
- airbyte_cdk/sources/declarative/incremental/per_partition_with_global.py +200 -0
- airbyte_cdk/sources/declarative/incremental/resumable_full_refresh_cursor.py +122 -0
- airbyte_cdk/sources/declarative/interpolation/__init__.py +9 -0
- airbyte_cdk/sources/declarative/interpolation/filters.py +139 -0
- airbyte_cdk/sources/declarative/interpolation/interpolated_boolean.py +66 -0
- airbyte_cdk/sources/declarative/interpolation/interpolated_mapping.py +56 -0
- airbyte_cdk/sources/declarative/interpolation/interpolated_nested_mapping.py +52 -0
- airbyte_cdk/sources/declarative/interpolation/interpolated_string.py +79 -0
- airbyte_cdk/sources/declarative/interpolation/interpolation.py +34 -0
- airbyte_cdk/sources/declarative/interpolation/jinja.py +161 -0
- airbyte_cdk/sources/declarative/interpolation/macros.py +191 -0
- airbyte_cdk/sources/declarative/manifest_declarative_source.py +421 -0
- airbyte_cdk/sources/declarative/migrations/__init__.py +0 -0
- airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py +98 -0
- airbyte_cdk/sources/declarative/migrations/state_migration.py +24 -0
- airbyte_cdk/sources/declarative/models/__init__.py +2 -0
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +2503 -0
- airbyte_cdk/sources/declarative/parsers/__init__.py +3 -0
- airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py +157 -0
- airbyte_cdk/sources/declarative/parsers/custom_exceptions.py +21 -0
- airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py +172 -0
- airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py +213 -0
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +3407 -0
- airbyte_cdk/sources/declarative/partition_routers/__init__.py +29 -0
- airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py +65 -0
- airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py +176 -0
- airbyte_cdk/sources/declarative/partition_routers/list_partition_router.py +121 -0
- airbyte_cdk/sources/declarative/partition_routers/partition_router.py +62 -0
- airbyte_cdk/sources/declarative/partition_routers/single_partition_router.py +63 -0
- airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +437 -0
- airbyte_cdk/sources/declarative/requesters/README.md +56 -0
- airbyte_cdk/sources/declarative/requesters/__init__.py +9 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/__init__.py +25 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/__init__.py +23 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/constant_backoff_strategy.py +45 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/exponential_backoff_strategy.py +45 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/header_helper.py +41 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_time_from_header_backoff_strategy.py +70 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategies/wait_until_time_from_header_backoff_strategy.py +77 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/backoff_strategy.py +17 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py +101 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py +147 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/default_http_response_filter.py +40 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/error_handler.py +17 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py +179 -0
- airbyte_cdk/sources/declarative/requesters/http_job_repository.py +350 -0
- airbyte_cdk/sources/declarative/requesters/http_requester.py +433 -0
- airbyte_cdk/sources/declarative/requesters/paginators/__init__.py +21 -0
- airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py +327 -0
- airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py +76 -0
- airbyte_cdk/sources/declarative/requesters/paginators/paginator.py +65 -0
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/__init__.py +25 -0
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/cursor_pagination_strategy.py +98 -0
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/offset_increment.py +102 -0
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/page_increment.py +71 -0
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/pagination_strategy.py +48 -0
- airbyte_cdk/sources/declarative/requesters/paginators/strategies/stop_condition.py +66 -0
- airbyte_cdk/sources/declarative/requesters/request_option.py +117 -0
- airbyte_cdk/sources/declarative/requesters/request_options/__init__.py +23 -0
- airbyte_cdk/sources/declarative/requesters/request_options/datetime_based_request_options_provider.py +92 -0
- airbyte_cdk/sources/declarative/requesters/request_options/default_request_options_provider.py +60 -0
- airbyte_cdk/sources/declarative/requesters/request_options/interpolated_nested_request_input_provider.py +59 -0
- airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_input_provider.py +68 -0
- airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py +119 -0
- airbyte_cdk/sources/declarative/requesters/request_options/request_options_provider.py +79 -0
- airbyte_cdk/sources/declarative/requesters/request_path.py +15 -0
- airbyte_cdk/sources/declarative/requesters/requester.py +144 -0
- airbyte_cdk/sources/declarative/resolvers/__init__.py +41 -0
- airbyte_cdk/sources/declarative/resolvers/components_resolver.py +55 -0
- airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py +136 -0
- airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py +112 -0
- airbyte_cdk/sources/declarative/retrievers/__init__.py +19 -0
- airbyte_cdk/sources/declarative/retrievers/async_retriever.py +124 -0
- airbyte_cdk/sources/declarative/retrievers/file_uploader.py +89 -0
- airbyte_cdk/sources/declarative/retrievers/retriever.py +54 -0
- airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +702 -0
- airbyte_cdk/sources/declarative/schema/__init__.py +25 -0
- airbyte_cdk/sources/declarative/schema/default_schema_loader.py +47 -0
- airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py +285 -0
- airbyte_cdk/sources/declarative/schema/inline_schema_loader.py +19 -0
- airbyte_cdk/sources/declarative/schema/json_file_schema_loader.py +92 -0
- airbyte_cdk/sources/declarative/schema/schema_loader.py +17 -0
- airbyte_cdk/sources/declarative/spec/__init__.py +7 -0
- airbyte_cdk/sources/declarative/spec/spec.py +48 -0
- airbyte_cdk/sources/declarative/stream_slicers/__init__.py +7 -0
- airbyte_cdk/sources/declarative/stream_slicers/declarative_partition_generator.py +93 -0
- airbyte_cdk/sources/declarative/stream_slicers/stream_slicer.py +25 -0
- airbyte_cdk/sources/declarative/transformations/__init__.py +17 -0
- airbyte_cdk/sources/declarative/transformations/add_fields.py +146 -0
- airbyte_cdk/sources/declarative/transformations/dpath_flatten_fields.py +61 -0
- airbyte_cdk/sources/declarative/transformations/flatten_fields.py +52 -0
- airbyte_cdk/sources/declarative/transformations/keys_replace_transformation.py +61 -0
- airbyte_cdk/sources/declarative/transformations/keys_to_lower_transformation.py +22 -0
- airbyte_cdk/sources/declarative/transformations/keys_to_snake_transformation.py +68 -0
- airbyte_cdk/sources/declarative/transformations/remove_fields.py +75 -0
- airbyte_cdk/sources/declarative/transformations/transformation.py +37 -0
- airbyte_cdk/sources/declarative/types.py +25 -0
- airbyte_cdk/sources/declarative/yaml_declarative_source.py +67 -0
- airbyte_cdk/sources/file_based/README.md +152 -0
- airbyte_cdk/sources/file_based/__init__.py +24 -0
- airbyte_cdk/sources/file_based/availability_strategy/__init__.py +11 -0
- airbyte_cdk/sources/file_based/availability_strategy/abstract_file_based_availability_strategy.py +73 -0
- airbyte_cdk/sources/file_based/availability_strategy/default_file_based_availability_strategy.py +149 -0
- airbyte_cdk/sources/file_based/config/__init__.py +0 -0
- airbyte_cdk/sources/file_based/config/abstract_file_based_spec.py +153 -0
- airbyte_cdk/sources/file_based/config/avro_format.py +25 -0
- airbyte_cdk/sources/file_based/config/csv_format.py +210 -0
- airbyte_cdk/sources/file_based/config/excel_format.py +18 -0
- airbyte_cdk/sources/file_based/config/file_based_stream_config.py +99 -0
- airbyte_cdk/sources/file_based/config/jsonl_format.py +18 -0
- airbyte_cdk/sources/file_based/config/parquet_format.py +25 -0
- airbyte_cdk/sources/file_based/config/unstructured_format.py +102 -0
- airbyte_cdk/sources/file_based/config/validate_config_transfer_modes.py +81 -0
- airbyte_cdk/sources/file_based/discovery_policy/__init__.py +8 -0
- airbyte_cdk/sources/file_based/discovery_policy/abstract_discovery_policy.py +21 -0
- airbyte_cdk/sources/file_based/discovery_policy/default_discovery_policy.py +33 -0
- airbyte_cdk/sources/file_based/exceptions.py +159 -0
- airbyte_cdk/sources/file_based/file_based_source.py +466 -0
- airbyte_cdk/sources/file_based/file_based_stream_permissions_reader.py +123 -0
- airbyte_cdk/sources/file_based/file_based_stream_reader.py +209 -0
- airbyte_cdk/sources/file_based/file_record_data.py +22 -0
- airbyte_cdk/sources/file_based/file_types/__init__.py +37 -0
- airbyte_cdk/sources/file_based/file_types/avro_parser.py +233 -0
- airbyte_cdk/sources/file_based/file_types/csv_parser.py +527 -0
- airbyte_cdk/sources/file_based/file_types/excel_parser.py +196 -0
- airbyte_cdk/sources/file_based/file_types/file_transfer.py +30 -0
- airbyte_cdk/sources/file_based/file_types/file_type_parser.py +86 -0
- airbyte_cdk/sources/file_based/file_types/jsonl_parser.py +145 -0
- airbyte_cdk/sources/file_based/file_types/parquet_parser.py +275 -0
- airbyte_cdk/sources/file_based/file_types/unstructured_parser.py +480 -0
- airbyte_cdk/sources/file_based/remote_file.py +18 -0
- airbyte_cdk/sources/file_based/schema_helpers.py +281 -0
- airbyte_cdk/sources/file_based/schema_validation_policies/__init__.py +17 -0
- airbyte_cdk/sources/file_based/schema_validation_policies/abstract_schema_validation_policy.py +20 -0
- airbyte_cdk/sources/file_based/schema_validation_policies/default_schema_validation_policies.py +52 -0
- airbyte_cdk/sources/file_based/stream/__init__.py +13 -0
- airbyte_cdk/sources/file_based/stream/abstract_file_based_stream.py +197 -0
- airbyte_cdk/sources/file_based/stream/concurrent/__init__.py +0 -0
- airbyte_cdk/sources/file_based/stream/concurrent/adapters.py +343 -0
- airbyte_cdk/sources/file_based/stream/concurrent/cursor/__init__.py +9 -0
- airbyte_cdk/sources/file_based/stream/concurrent/cursor/abstract_concurrent_file_based_cursor.py +59 -0
- airbyte_cdk/sources/file_based/stream/concurrent/cursor/file_based_concurrent_cursor.py +313 -0
- airbyte_cdk/sources/file_based/stream/concurrent/cursor/file_based_final_state_cursor.py +83 -0
- airbyte_cdk/sources/file_based/stream/cursor/__init__.py +4 -0
- airbyte_cdk/sources/file_based/stream/cursor/abstract_file_based_cursor.py +66 -0
- airbyte_cdk/sources/file_based/stream/cursor/default_file_based_cursor.py +149 -0
- airbyte_cdk/sources/file_based/stream/default_file_based_stream.py +396 -0
- airbyte_cdk/sources/file_based/stream/identities_stream.py +49 -0
- airbyte_cdk/sources/file_based/stream/permissions_file_based_stream.py +92 -0
- airbyte_cdk/sources/file_based/types.py +10 -0
- airbyte_cdk/sources/http_config.py +10 -0
- airbyte_cdk/sources/http_logger.py +55 -0
- airbyte_cdk/sources/message/__init__.py +19 -0
- airbyte_cdk/sources/message/repository.py +137 -0
- airbyte_cdk/sources/source.py +95 -0
- airbyte_cdk/sources/specs/transfer_modes.py +26 -0
- airbyte_cdk/sources/streams/__init__.py +8 -0
- airbyte_cdk/sources/streams/availability_strategy.py +84 -0
- airbyte_cdk/sources/streams/call_rate.py +704 -0
- airbyte_cdk/sources/streams/checkpoint/__init__.py +26 -0
- airbyte_cdk/sources/streams/checkpoint/checkpoint_reader.py +335 -0
- airbyte_cdk/sources/streams/checkpoint/cursor.py +77 -0
- airbyte_cdk/sources/streams/checkpoint/per_partition_key_serializer.py +22 -0
- airbyte_cdk/sources/streams/checkpoint/resumable_full_refresh_cursor.py +51 -0
- airbyte_cdk/sources/streams/checkpoint/substream_resumable_full_refresh_cursor.py +110 -0
- airbyte_cdk/sources/streams/concurrent/README.md +7 -0
- airbyte_cdk/sources/streams/concurrent/__init__.py +3 -0
- airbyte_cdk/sources/streams/concurrent/abstract_stream.py +96 -0
- airbyte_cdk/sources/streams/concurrent/abstract_stream_facade.py +37 -0
- airbyte_cdk/sources/streams/concurrent/adapters.py +397 -0
- airbyte_cdk/sources/streams/concurrent/availability_strategy.py +94 -0
- airbyte_cdk/sources/streams/concurrent/clamping.py +99 -0
- airbyte_cdk/sources/streams/concurrent/cursor.py +481 -0
- airbyte_cdk/sources/streams/concurrent/cursor_types.py +32 -0
- airbyte_cdk/sources/streams/concurrent/default_stream.py +102 -0
- airbyte_cdk/sources/streams/concurrent/exceptions.py +18 -0
- airbyte_cdk/sources/streams/concurrent/helpers.py +42 -0
- airbyte_cdk/sources/streams/concurrent/partition_enqueuer.py +64 -0
- airbyte_cdk/sources/streams/concurrent/partition_reader.py +45 -0
- airbyte_cdk/sources/streams/concurrent/partitions/__init__.py +3 -0
- airbyte_cdk/sources/streams/concurrent/partitions/partition.py +48 -0
- airbyte_cdk/sources/streams/concurrent/partitions/partition_generator.py +18 -0
- airbyte_cdk/sources/streams/concurrent/partitions/stream_slicer.py +21 -0
- airbyte_cdk/sources/streams/concurrent/partitions/types.py +38 -0
- airbyte_cdk/sources/streams/concurrent/state_converters/__init__.py +0 -0
- airbyte_cdk/sources/streams/concurrent/state_converters/abstract_stream_state_converter.py +182 -0
- airbyte_cdk/sources/streams/concurrent/state_converters/datetime_stream_state_converter.py +223 -0
- airbyte_cdk/sources/streams/concurrent/state_converters/incrementing_count_stream_state_converter.py +92 -0
- airbyte_cdk/sources/streams/core.py +703 -0
- airbyte_cdk/sources/streams/http/__init__.py +10 -0
- airbyte_cdk/sources/streams/http/availability_strategy.py +54 -0
- airbyte_cdk/sources/streams/http/error_handlers/__init__.py +22 -0
- airbyte_cdk/sources/streams/http/error_handlers/backoff_strategy.py +28 -0
- airbyte_cdk/sources/streams/http/error_handlers/default_backoff_strategy.py +17 -0
- airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py +86 -0
- airbyte_cdk/sources/streams/http/error_handlers/error_handler.py +42 -0
- airbyte_cdk/sources/streams/http/error_handlers/error_message_parser.py +19 -0
- airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py +110 -0
- airbyte_cdk/sources/streams/http/error_handlers/json_error_message_parser.py +52 -0
- airbyte_cdk/sources/streams/http/error_handlers/response_models.py +65 -0
- airbyte_cdk/sources/streams/http/exceptions.py +61 -0
- airbyte_cdk/sources/streams/http/http.py +673 -0
- airbyte_cdk/sources/streams/http/http_client.py +531 -0
- airbyte_cdk/sources/streams/http/rate_limiting.py +158 -0
- airbyte_cdk/sources/streams/http/requests_native_auth/__init__.py +14 -0
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +479 -0
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py +34 -0
- airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +436 -0
- airbyte_cdk/sources/streams/http/requests_native_auth/token.py +83 -0
- airbyte_cdk/sources/streams/permissions/identities_stream.py +75 -0
- airbyte_cdk/sources/streams/utils/__init__.py +3 -0
- airbyte_cdk/sources/types.py +169 -0
- airbyte_cdk/sources/utils/__init__.py +7 -0
- airbyte_cdk/sources/utils/casing.py +12 -0
- airbyte_cdk/sources/utils/files_directory.py +15 -0
- airbyte_cdk/sources/utils/record_helper.py +53 -0
- airbyte_cdk/sources/utils/schema_helpers.py +230 -0
- airbyte_cdk/sources/utils/slice_logger.py +57 -0
- airbyte_cdk/sources/utils/transform.py +277 -0
- airbyte_cdk/sources/utils/types.py +7 -0
- airbyte_cdk/sql/__init__.py +0 -0
- airbyte_cdk/sql/_util/__init__.py +0 -0
- airbyte_cdk/sql/_util/hashing.py +34 -0
- airbyte_cdk/sql/_util/name_normalizers.py +92 -0
- airbyte_cdk/sql/constants.py +32 -0
- airbyte_cdk/sql/exceptions.py +235 -0
- airbyte_cdk/sql/secrets.py +123 -0
- airbyte_cdk/sql/shared/__init__.py +15 -0
- airbyte_cdk/sql/shared/catalog_providers.py +145 -0
- airbyte_cdk/sql/shared/sql_processor.py +786 -0
- airbyte_cdk/sql/types.py +160 -0
- airbyte_cdk/test/__init__.py +7 -0
- airbyte_cdk/test/catalog_builder.py +81 -0
- airbyte_cdk/test/entrypoint_wrapper.py +250 -0
- airbyte_cdk/test/mock_http/__init__.py +6 -0
- airbyte_cdk/test/mock_http/matcher.py +41 -0
- airbyte_cdk/test/mock_http/mocker.py +185 -0
- airbyte_cdk/test/mock_http/request.py +103 -0
- airbyte_cdk/test/mock_http/response.py +28 -0
- airbyte_cdk/test/mock_http/response_builder.py +237 -0
- airbyte_cdk/test/state_builder.py +33 -0
- airbyte_cdk/test/utils/__init__.py +1 -0
- airbyte_cdk/test/utils/data.py +24 -0
- airbyte_cdk/test/utils/http_mocking.py +16 -0
- airbyte_cdk/test/utils/manifest_only_fixtures.py +59 -0
- airbyte_cdk/test/utils/reading.py +26 -0
- airbyte_cdk/utils/__init__.py +10 -0
- airbyte_cdk/utils/airbyte_secrets_utils.py +80 -0
- airbyte_cdk/utils/analytics_message.py +25 -0
- airbyte_cdk/utils/constants.py +5 -0
- airbyte_cdk/utils/datetime_format_inferrer.py +94 -0
- airbyte_cdk/utils/datetime_helpers.py +499 -0
- airbyte_cdk/utils/event_timing.py +85 -0
- airbyte_cdk/utils/is_cloud_environment.py +18 -0
- airbyte_cdk/utils/mapping_helpers.py +162 -0
- airbyte_cdk/utils/message_utils.py +26 -0
- airbyte_cdk/utils/oneof_option_config.py +33 -0
- airbyte_cdk/utils/print_buffer.py +75 -0
- airbyte_cdk/utils/schema_inferrer.py +270 -0
- airbyte_cdk/utils/slice_hasher.py +37 -0
- airbyte_cdk/utils/spec_schema_transformations.py +26 -0
- airbyte_cdk/utils/stream_status_utils.py +43 -0
- airbyte_cdk/utils/traced_exception.py +145 -0
- airbyte_cdk-0.0.0.dev0.dist-info/LICENSE.txt +19 -0
- airbyte_cdk-0.0.0.dev0.dist-info/LICENSE_SHORT +1 -0
- airbyte_cdk-0.0.0.dev0.dist-info/METADATA +111 -0
- airbyte_cdk-0.0.0.dev0.dist-info/RECORD +368 -0
- airbyte_cdk-0.0.0.dev0.dist-info/WHEEL +4 -0
- airbyte_cdk-0.0.0.dev0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
from functools import cache
|
|
7
|
+
from typing import Any, Mapping, Optional, Set, Tuple, Type
|
|
8
|
+
|
|
9
|
+
from jinja2 import meta
|
|
10
|
+
from jinja2.environment import Template
|
|
11
|
+
from jinja2.exceptions import UndefinedError
|
|
12
|
+
from jinja2.sandbox import SandboxedEnvironment
|
|
13
|
+
|
|
14
|
+
from airbyte_cdk.models import FailureType
|
|
15
|
+
from airbyte_cdk.sources.declarative.interpolation.filters import filters
|
|
16
|
+
from airbyte_cdk.sources.declarative.interpolation.interpolation import Interpolation
|
|
17
|
+
from airbyte_cdk.sources.declarative.interpolation.macros import macros
|
|
18
|
+
from airbyte_cdk.sources.types import Config
|
|
19
|
+
from airbyte_cdk.utils import AirbyteTracedException
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class StreamPartitionAccessEnvironment(SandboxedEnvironment):
|
|
23
|
+
"""
|
|
24
|
+
Currently, source-jira is setting an attribute to StreamSlice specific to its use case which because of the PerPartitionCursor is set to
|
|
25
|
+
StreamSlice._partition but not exposed through StreamSlice.partition. This is a patch to still allow source-jira to have access to this
|
|
26
|
+
parameter
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def is_safe_attribute(self, obj: Any, attr: str, value: Any) -> bool:
|
|
30
|
+
if attr in ["_partition"]:
|
|
31
|
+
return True
|
|
32
|
+
return super().is_safe_attribute(obj, attr, value) # type: ignore # for some reason, mypy says 'Returning Any from function declared to return "bool"'
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# These aliases are used to deprecate existing keywords without breaking all existing connectors.
|
|
36
|
+
_ALIASES = {
|
|
37
|
+
"stream_interval": "stream_slice", # Use stream_interval to access incremental_sync values
|
|
38
|
+
"stream_partition": "stream_slice", # Use stream_partition to access partition router's values
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_UNSUPPORTED_INTERPOLATION_VARIABLES: Mapping[str, str] = {
|
|
42
|
+
"stream_state": "`stream_state` is no longer supported for interpolation. We recommend using `stream_interval` instead. Please reference the CDK Migration Guide for more information.",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# These extensions are not installed so they're not currently a problem,
|
|
46
|
+
# but we're still explicitly removing them from the jinja context.
|
|
47
|
+
# At worst, this is documentation that we do NOT want to include these extensions because of the potential security risks
|
|
48
|
+
_RESTRICTED_EXTENSIONS = ["jinja2.ext.loopcontrols"] # Adds support for break continue in loops
|
|
49
|
+
|
|
50
|
+
# By default, these Python builtin functions are available in the Jinja context.
|
|
51
|
+
# We explicitly remove them because of the potential security risk.
|
|
52
|
+
# Please add a unit test to test_jinja.py when adding a restriction.
|
|
53
|
+
_RESTRICTED_BUILTIN_FUNCTIONS = [
|
|
54
|
+
"range"
|
|
55
|
+
] # The range function can cause very expensive computations
|
|
56
|
+
|
|
57
|
+
_ENVIRONMENT = StreamPartitionAccessEnvironment()
|
|
58
|
+
_ENVIRONMENT.filters.update(**filters)
|
|
59
|
+
_ENVIRONMENT.globals.update(**macros)
|
|
60
|
+
|
|
61
|
+
for extension in _RESTRICTED_EXTENSIONS:
|
|
62
|
+
_ENVIRONMENT.extensions.pop(extension, None)
|
|
63
|
+
for builtin in _RESTRICTED_BUILTIN_FUNCTIONS:
|
|
64
|
+
_ENVIRONMENT.globals.pop(builtin, None)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class JinjaInterpolation(Interpolation):
|
|
68
|
+
"""
|
|
69
|
+
Interpolation strategy using the Jinja2 template engine.
|
|
70
|
+
|
|
71
|
+
If the input string is a raw string, the interpolated string will be the same.
|
|
72
|
+
`eval("hello world") -> "hello world"`
|
|
73
|
+
|
|
74
|
+
The engine will evaluate the content passed within {{}}, interpolating the keys from the config and context-specific arguments.
|
|
75
|
+
`eval("hello {{ name }}", name="airbyte") -> "hello airbyte")`
|
|
76
|
+
`eval("hello {{ config.name }}", config={"name": "airbyte"}) -> "hello airbyte")`
|
|
77
|
+
|
|
78
|
+
In additional to passing additional values through the kwargs argument, macros can be called from within the string interpolation.
|
|
79
|
+
For example,
|
|
80
|
+
"{{ max(2, 3) }}" will return 3
|
|
81
|
+
|
|
82
|
+
Additional information on jinja templating can be found at https://jinja.palletsprojects.com/en/3.1.x/templates/#
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def eval(
|
|
86
|
+
self,
|
|
87
|
+
input_str: str,
|
|
88
|
+
config: Config,
|
|
89
|
+
default: Optional[str] = None,
|
|
90
|
+
valid_types: Optional[Tuple[Type[Any]]] = None,
|
|
91
|
+
**additional_parameters: Any,
|
|
92
|
+
) -> Any:
|
|
93
|
+
context = {"config": config, **additional_parameters}
|
|
94
|
+
|
|
95
|
+
for alias, equivalent in _ALIASES.items():
|
|
96
|
+
if alias in context:
|
|
97
|
+
# This is unexpected. We could ignore or log a warning, but failing loudly should result in fewer surprises
|
|
98
|
+
raise ValueError(
|
|
99
|
+
f"Found reserved keyword {alias} in interpolation context. This is unexpected and indicative of a bug in the CDK."
|
|
100
|
+
)
|
|
101
|
+
elif equivalent in context:
|
|
102
|
+
context[alias] = context[equivalent]
|
|
103
|
+
|
|
104
|
+
for variable_name in _UNSUPPORTED_INTERPOLATION_VARIABLES:
|
|
105
|
+
if variable_name in input_str:
|
|
106
|
+
raise AirbyteTracedException(
|
|
107
|
+
message=_UNSUPPORTED_INTERPOLATION_VARIABLES[variable_name],
|
|
108
|
+
internal_message=_UNSUPPORTED_INTERPOLATION_VARIABLES[variable_name],
|
|
109
|
+
failure_type=FailureType.config_error,
|
|
110
|
+
)
|
|
111
|
+
try:
|
|
112
|
+
if isinstance(input_str, str):
|
|
113
|
+
result = self._eval(input_str, context)
|
|
114
|
+
if result:
|
|
115
|
+
return self._literal_eval(result, valid_types)
|
|
116
|
+
else:
|
|
117
|
+
# If input is not a string, return it as is
|
|
118
|
+
raise Exception(f"Expected a string, got {input_str}")
|
|
119
|
+
except UndefinedError:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
# If result is empty or resulted in an undefined error, evaluate and return the default string
|
|
123
|
+
return self._literal_eval(self._eval(default, context), valid_types)
|
|
124
|
+
|
|
125
|
+
def _literal_eval(self, result: Optional[str], valid_types: Optional[Tuple[Type[Any]]]) -> Any:
|
|
126
|
+
try:
|
|
127
|
+
evaluated = ast.literal_eval(result) # type: ignore # literal_eval is able to handle None
|
|
128
|
+
except (ValueError, SyntaxError):
|
|
129
|
+
return result
|
|
130
|
+
if not valid_types or (valid_types and isinstance(evaluated, valid_types)):
|
|
131
|
+
return evaluated
|
|
132
|
+
return result
|
|
133
|
+
|
|
134
|
+
def _eval(self, s: Optional[str], context: Mapping[str, Any]) -> Optional[str]:
|
|
135
|
+
try:
|
|
136
|
+
undeclared = self._find_undeclared_variables(s)
|
|
137
|
+
undeclared_not_in_context = {var for var in undeclared if var not in context}
|
|
138
|
+
if undeclared_not_in_context:
|
|
139
|
+
raise ValueError(
|
|
140
|
+
f"Jinja macro has undeclared variables: {undeclared_not_in_context}. Context: {context}"
|
|
141
|
+
)
|
|
142
|
+
return self._compile(s).render(context) # type: ignore # from_string is able to handle None
|
|
143
|
+
except TypeError:
|
|
144
|
+
# The string is a static value, not a jinja template
|
|
145
|
+
# It can be returned as is
|
|
146
|
+
return s
|
|
147
|
+
|
|
148
|
+
@cache
|
|
149
|
+
def _find_undeclared_variables(self, s: Optional[str]) -> Set[str]:
|
|
150
|
+
"""
|
|
151
|
+
Find undeclared variables and cache them
|
|
152
|
+
"""
|
|
153
|
+
ast = _ENVIRONMENT.parse(s) # type: ignore # parse is able to handle None
|
|
154
|
+
return meta.find_undeclared_variables(ast)
|
|
155
|
+
|
|
156
|
+
@cache
|
|
157
|
+
def _compile(self, s: str) -> Template:
|
|
158
|
+
"""
|
|
159
|
+
We must cache the Jinja Template ourselves because we're using `from_string` instead of a template loader
|
|
160
|
+
"""
|
|
161
|
+
return _ENVIRONMENT.from_string(s)
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
import builtins
|
|
6
|
+
import datetime
|
|
7
|
+
import typing
|
|
8
|
+
from typing import Optional, Union
|
|
9
|
+
|
|
10
|
+
import isodate
|
|
11
|
+
import pytz
|
|
12
|
+
from dateutil import parser
|
|
13
|
+
from isodate import parse_duration
|
|
14
|
+
|
|
15
|
+
from airbyte_cdk.sources.declarative.datetime.datetime_parser import DatetimeParser
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
This file contains macros that can be evaluated by a `JinjaInterpolation` object
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def now_utc() -> datetime.datetime:
|
|
23
|
+
"""
|
|
24
|
+
Current local date and time in UTC timezone
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
`"{{ now_utc() }}"`
|
|
28
|
+
"""
|
|
29
|
+
return datetime.datetime.now(datetime.timezone.utc)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def today_utc() -> datetime.date:
|
|
33
|
+
"""
|
|
34
|
+
Current date in UTC timezone
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
`"{{ today_utc() }}"`
|
|
38
|
+
"""
|
|
39
|
+
return datetime.datetime.now(datetime.timezone.utc).date()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def today_with_timezone(timezone: str) -> datetime.date:
|
|
43
|
+
"""
|
|
44
|
+
Current date in custom timezone
|
|
45
|
+
|
|
46
|
+
:param timezone: timezone expressed as IANA keys format. Example: "Pacific/Tarawa"
|
|
47
|
+
:return:
|
|
48
|
+
"""
|
|
49
|
+
return datetime.datetime.now(tz=pytz.timezone(timezone)).date()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def timestamp(dt: Union[float, str]) -> Union[int, float]:
|
|
53
|
+
"""
|
|
54
|
+
Converts a number or a string to a timestamp
|
|
55
|
+
|
|
56
|
+
If dt is a number, then convert to an int
|
|
57
|
+
If dt is a string, then parse it using dateutil.parser
|
|
58
|
+
|
|
59
|
+
Usage:
|
|
60
|
+
`"{{ timestamp(1658505815.223235) }}"
|
|
61
|
+
|
|
62
|
+
:param dt: datetime to convert to timestamp
|
|
63
|
+
:return: unix timestamp
|
|
64
|
+
"""
|
|
65
|
+
if isinstance(dt, (int, float)):
|
|
66
|
+
return int(dt)
|
|
67
|
+
else:
|
|
68
|
+
return str_to_datetime(dt).astimezone(pytz.utc).timestamp()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def str_to_datetime(s: str) -> datetime.datetime:
|
|
72
|
+
"""
|
|
73
|
+
Converts a string to a datetime object with UTC timezone
|
|
74
|
+
|
|
75
|
+
If the input string does not contain timezone information, UTC is assumed.
|
|
76
|
+
Supports both basic date strings like "2022-01-14" and datetime strings with optional timezone
|
|
77
|
+
like "2022-01-01T13:45:30+00:00".
|
|
78
|
+
|
|
79
|
+
Usage:
|
|
80
|
+
`"{{ str_to_datetime('2022-01-14') }}"`
|
|
81
|
+
|
|
82
|
+
:param s: string to parse as datetime
|
|
83
|
+
:return: datetime object in UTC timezone
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
parsed_date = parser.isoparse(s)
|
|
87
|
+
if not parsed_date.tzinfo:
|
|
88
|
+
# Assume UTC if the input does not contain a timezone
|
|
89
|
+
parsed_date = parsed_date.replace(tzinfo=pytz.utc)
|
|
90
|
+
return parsed_date.astimezone(pytz.utc)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def max(*args: typing.Any) -> typing.Any:
|
|
94
|
+
"""
|
|
95
|
+
Returns biggest object of an iterable, or two or more arguments.
|
|
96
|
+
|
|
97
|
+
max(iterable, *[, default=obj, key=func]) -> value
|
|
98
|
+
max(arg1, arg2, *args, *[, key=func]) -> value
|
|
99
|
+
|
|
100
|
+
Usage:
|
|
101
|
+
`"{{ max(2,3) }}"
|
|
102
|
+
|
|
103
|
+
With a single iterable argument, return its biggest item. The
|
|
104
|
+
default keyword-only argument specifies an object to return if
|
|
105
|
+
the provided iterable is empty.
|
|
106
|
+
With two or more arguments, return the largest argument.
|
|
107
|
+
:param args: args to compare
|
|
108
|
+
:return: largest argument
|
|
109
|
+
"""
|
|
110
|
+
return builtins.max(*args)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def min(*args: typing.Any) -> typing.Any:
|
|
114
|
+
"""
|
|
115
|
+
Returns smallest object of an iterable, or two or more arguments.
|
|
116
|
+
|
|
117
|
+
min(iterable, *[, default=obj, key=func]) -> value
|
|
118
|
+
min(arg1, arg2, *args, *[, key=func]) -> value
|
|
119
|
+
|
|
120
|
+
Usage:
|
|
121
|
+
`"{{ min(2,3) }}"
|
|
122
|
+
|
|
123
|
+
With a single iterable argument, return its smallest item. The
|
|
124
|
+
default keyword-only argument specifies an object to return if
|
|
125
|
+
the provided iterable is empty.
|
|
126
|
+
With two or more arguments, return the smallest argument.
|
|
127
|
+
:param args: args to compare
|
|
128
|
+
:return: smallest argument
|
|
129
|
+
"""
|
|
130
|
+
return builtins.min(*args)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def day_delta(num_days: int, format: str = "%Y-%m-%dT%H:%M:%S.%f%z") -> str:
|
|
134
|
+
"""
|
|
135
|
+
Returns datetime of now() + num_days
|
|
136
|
+
|
|
137
|
+
Usage:
|
|
138
|
+
`"{{ day_delta(25) }}"`
|
|
139
|
+
|
|
140
|
+
:param num_days: number of days to add to current date time
|
|
141
|
+
:return: datetime formatted as RFC3339
|
|
142
|
+
"""
|
|
143
|
+
return (
|
|
144
|
+
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=num_days)
|
|
145
|
+
).strftime(format)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def duration(datestring: str) -> Union[datetime.timedelta, isodate.Duration]:
|
|
149
|
+
"""
|
|
150
|
+
Converts ISO8601 duration to datetime.timedelta
|
|
151
|
+
|
|
152
|
+
Usage:
|
|
153
|
+
`"{{ now_utc() - duration('P1D') }}"`
|
|
154
|
+
"""
|
|
155
|
+
return parse_duration(datestring)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def format_datetime(
|
|
159
|
+
dt: Union[str, datetime.datetime], format: str, input_format: Optional[str] = None
|
|
160
|
+
) -> str:
|
|
161
|
+
"""
|
|
162
|
+
Converts datetime to another format
|
|
163
|
+
|
|
164
|
+
Usage:
|
|
165
|
+
`"{{ format_datetime(config.start_date, '%Y-%m-%d') }}"`
|
|
166
|
+
|
|
167
|
+
CPython Datetime package has known bug with `stfrtime` method: '%s' formatting uses locale timezone
|
|
168
|
+
https://github.com/python/cpython/issues/77169
|
|
169
|
+
https://github.com/python/cpython/issues/56959
|
|
170
|
+
"""
|
|
171
|
+
if isinstance(dt, datetime.datetime):
|
|
172
|
+
return dt.strftime(format)
|
|
173
|
+
dt_datetime = (
|
|
174
|
+
datetime.datetime.strptime(dt, input_format) if input_format else str_to_datetime(dt)
|
|
175
|
+
)
|
|
176
|
+
return DatetimeParser().format(dt=dt_datetime, format=format)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
_macros_list = [
|
|
180
|
+
now_utc,
|
|
181
|
+
today_utc,
|
|
182
|
+
timestamp,
|
|
183
|
+
max,
|
|
184
|
+
min,
|
|
185
|
+
day_delta,
|
|
186
|
+
duration,
|
|
187
|
+
format_datetime,
|
|
188
|
+
today_with_timezone,
|
|
189
|
+
str_to_datetime,
|
|
190
|
+
]
|
|
191
|
+
macros = {f.__name__: f for f in _macros_list}
|