fca_api.types.base#

Base classes for FCA API type definitions.

This module provides the foundation classes for all FCA API response models. These base classes handle common patterns like:

  • Field normalization: Converting API field names to lowercase

  • Extra field handling: Capturing unexpected fields for compatibility

  • Validation configuration: Consistent validation behavior across types

  • Skip markers: Ignoring fields marked as “[notinuse]” by the API

The base classes ensure consistent behavior across all API response types while providing flexibility for handling API changes and variations.

Classes:
  • Base: Standard base class for most API types

  • RelaxedBase: Base class that captures extra/unknown fields

Example

Creating a custom API type:

class MyFirmData(Base):
    name: str
    frn: str
    status: str

# Validates and normalizes field names
data = MyFirmData.model_validate({
    "Name": "Test Firm",     # -> "name"
    "FRN": "123456",        # -> "frn"
    "Status": "Active"      # -> "status"
})

Using RelaxedBase for unknown fields:

class FlexibleType(RelaxedBase):
    required_field: str

data = FlexibleType.model_validate({
    "required_field": "value",
    "unknown_field": "captured"
})

print(data.get_additional_fields())  # {"unknown_field": "captured"}
class fca_api.types.base.Base[source]#

Base class for FCA API response models.

This base class provides common functionality for all FCA API types:

  • Field name normalization: Converts API field names to lowercase

  • Skip unused fields: Ignores fields marked with “[notinuse]”

  • Consistent validation: Uses package-wide validation settings

  • Type safety: Provides proper Pydantic model inheritance

All API response models should inherit from this class to ensure consistent behavior and proper handling of API response variations.

Features:
  • Automatic lowercase conversion of field names

  • Filtering of “[notinuse]” fields from API responses

  • Standardized validation configuration

  • Support for both strict and flexible validation modes

Example

Define a custom API model:

class FirmSummary(Base):
    name: str
    frn: str
    status: str

# API response with mixed case field names
api_data = {
    "Name": "Example Firm",
    "FRN": "123456",
    "Status": "Authorised",
    "Internal_Field[notinuse]": "ignored"
}

# Validation handles normalization automatically
firm = FirmSummary.model_validate(api_data)
print(firm.name)    # "Example Firm"
print(firm.frn)     # "123456"
print(firm.status)  # "Authorised"
# "Internal_Field[notinuse]" is automatically ignored

Note

The model_validate method is customized to handle FCA API response patterns. Use this instead of the standard Pydantic constructor when working with raw API data.

classmethod model_validate(data: Any) Base[source]#

Validate and create model instance from API response data.

This method extends Pydantic’s validation to handle FCA API response patterns including field name normalization and filtering of unused fields.

Parameters:

data – Raw data from API response, typically a dictionary with mixed-case field names and potential “[notinuse]” markers.

Returns:

Validated model instance with normalized field names.

Example

Validate API response data:

api_response = {
    "FirmName": "Test Corp",
    "FRN": "123456",
    "Old_Field[notinuse]": "ignored"
}

firm = FirmModel.model_validate(api_response)
# Field names normalized, unused fields filtered
__pydantic_fields_set__#

The names of fields explicitly set during instantiation.

__pydantic_extra__#

A dictionary containing extra values, if [extra][pydantic.config.ConfigDict.extra] is set to ‘allow’.

__pydantic_private__#

Values of private attributes set on the model instance.

__class_vars__ = {}#

The names of the class variables defined on the model.

__private_attributes__ = {}#

Metadata about the private attributes of the model.

__pydantic_complete__ = True#

Whether model building is completed, or if there are still undefined fields.

__pydantic_computed_fields__ = {}#

A dictionary of computed field names and their corresponding [ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects.

__pydantic_core_schema__ = {'cls': <class 'fca_api.types.base.Base'>, 'config': {'title': 'Base'}, 'custom_init': False, 'metadata': {'pydantic_js_functions': [<bound method BaseModel.__get_pydantic_json_schema__ of <class 'fca_api.types.base.Base'>>]}, 'ref': 'fca_api.types.base.Base:93917380027008', 'root_model': False, 'schema': {'computed_fields': [], 'fields': {}, 'model_name': 'Base', 'type': 'model-fields'}, 'type': 'model'}#

The core schema of the model.

__pydantic_custom_init__ = False#

Whether the model has a custom __init__ method.

__pydantic_decorators__ = DecoratorInfos(validators={}, field_validators={}, root_validators={}, field_serializers={}, model_serializers={}, model_validators={}, computed_fields={})#

Metadata containing the decorators defined on the model. This replaces Model.__validators__ and Model.__root_validators__ from Pydantic V1.

__pydantic_extra_info__ = None#

A wrapper around the __pydantic_extra__ annotation, if explicitly annotated on a model.

This is a private attribute, not meant to be used outside Pydantic.

__pydantic_fields__ = {}#

A dictionary of field names and their corresponding [FieldInfo][pydantic.fields.FieldInfo] objects. This replaces Model.__fields__ from Pydantic V1.

__pydantic_generic_metadata__ = {'args': (), 'origin': None, 'parameters': ()}#

A dictionary containing metadata about generic Pydantic models.

The origin and args items map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and the parameter item maps to the __parameter__ attribute of generic classes.

__pydantic_parent_namespace__ = None#

Parent namespace of the model, used for automatic rebuilding of models.

__pydantic_post_init__ = None#

The name of the post-init method for the model, if defined.

__pydantic_serializer__ = SchemaSerializer(serializer=PolymorphismTrampoline(     PolymorphismTrampoline {         class: Py(             0x0000556ad8132280,         ),         serializer: PolymorphismTrampoline(             PolymorphismTrampoline {                 class: Py(                     0x0000556ad8132280,                 ),                 serializer: Model(                     ModelSerializer {                         class: Py(                             0x0000556ad8132280,                         ),                         serializer: Fields(                             GeneralFieldsSerializer {                                 fields: {},                                 computed_fields: Some(                                     ComputedFields(                                         [],                                     ),                                 ),                                 mode: SimpleDict,                                 extra_serializer: None,                                 filter: SchemaFilter {                                     include: None,                                     exclude: None,                                 },                                 required_fields: 0,                             },                         ),                         has_extra: false,                         root_model: false,                         name: "Base",                     },                 ),                 enabled_from_config: false,             },         ),         enabled_from_config: false,     }, ), definitions=[])#

The pydantic-core SchemaSerializer used to dump instances of the model.

__pydantic_setattr_handlers__ = {}#

__setattr__ handlers. Memoizing the handlers leads to a dramatic performance improvement in __setattr__

__pydantic_validator__ = SchemaValidator(title="Base", validator=Model(     ModelValidator {         revalidate: Never,         validator: ModelFields(             ModelFieldsValidator {                 fields: [],                 model_name: "Base",                 extra_behavior: Ignore,                 extras_validator: None,                 extras_keys_validator: None,                 strict: false,                 from_attributes: false,                 loc_by_alias: true,                 lookup: LookupTree {                     inner: {},                 },                 validate_by_alias: None,                 validate_by_name: None,             },         ),         class: Py(             0x0000556ad8132280,         ),         generic_origin: None,         post_init: None,         frozen: false,         custom_init: false,         root_model: false,         undefined: Py(             0x00007fe7e4c7c550,         ),         name: "Base",     }, ), definitions=[], cache_strings=True)#

The pydantic-core SchemaValidator used to validate instances of the model.

__signature__ = <Signature () -> None>#

The synthesized __init__ [Signature][inspect.Signature] of the model.

__weakref__#

list of weak references to the object

model_config = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class fca_api.types.base.RelaxedBase(**extra_data: Any)[source]#

Base class for API types that capture additional/unknown fields.

This class extends the standard Base class to capture and store any fields that are not explicitly defined in the model schema. This is useful for:

  • Forward compatibility: Capturing new API fields before updating schemas

  • Debugging: Seeing what unexpected data the API returns

  • Flexible processing: Accessing both known and unknown fields

  • API evolution: Handling API changes gracefully

The extra fields are stored in Pydantic’s __pydantic_extra__ and can be accessed via the get_additional_fields() method.

Example

Handle API responses with unknown fields:

class FlexibleFirmData(RelaxedBase):
    name: str
    frn: str

# API returns extra fields not in schema
api_data = {
    "name": "Test Firm",
    "frn": "123456",
    "new_field_v2": "future_data",
    "experimental_flag": True
}

firm = FlexibleFirmData.model_validate(api_data)
print(firm.name)  # "Test Firm"
print(firm.frn)   # "123456"

# Access additional fields
extra = firm.get_additional_fields()
print(extra)  # {"new_field_v2": "future_data", "experimental_flag": True}
Use Cases:
  • Capturing new API fields during development

  • Building flexible data processing pipelines

  • Debugging unexpected API responses

  • Future-proofing against API changes

Warning

While flexible, this approach can hide schema drift and API changes. Use primarily for development and debugging, not production parsing.

model_config = {'extra': 'allow'}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

get_additional_fields() dict[str, Any][source]#

Get all additional fields not defined in the model schema.

Returns:

Dictionary containing all extra fields captured during validation that were not part of the model’s defined fields.

Example

Access unexpected API fields:

firm = FlexibleFirmData.model_validate(api_response)

# Check for new/unknown fields
extra_fields = firm.get_additional_fields()
if extra_fields:
    print(f"API returned unexpected fields: {list(extra_fields.keys())}")

    # Log for analysis
    logger.info("Unknown API fields", extra=extra_fields)
__pydantic_fields_set__#

The names of fields explicitly set during instantiation.

__pydantic_extra__#

A dictionary containing extra values, if [extra][pydantic.config.ConfigDict.extra] is set to ‘allow’.

__pydantic_private__#

Values of private attributes set on the model instance.

__class_vars__ = {}#

The names of the class variables defined on the model.

__private_attributes__ = {}#

Metadata about the private attributes of the model.

__pydantic_complete__ = True#

Whether model building is completed, or if there are still undefined fields.

__pydantic_computed_fields__ = {}#

A dictionary of computed field names and their corresponding [ComputedFieldInfo][pydantic.fields.ComputedFieldInfo] objects.

__pydantic_core_schema__ = {'cls': <class 'fca_api.types.base.RelaxedBase'>, 'config': {'extra_fields_behavior': 'allow', 'title': 'RelaxedBase'}, 'custom_init': False, 'metadata': {'pydantic_js_functions': [<bound method BaseModel.__get_pydantic_json_schema__ of <class 'fca_api.types.base.RelaxedBase'>>]}, 'ref': 'fca_api.types.base.RelaxedBase:93917380026016', 'root_model': False, 'schema': {'computed_fields': [], 'fields': {}, 'model_name': 'RelaxedBase', 'type': 'model-fields'}, 'type': 'model'}#

The core schema of the model.

__pydantic_custom_init__ = False#

Whether the model has a custom __init__ method.

__pydantic_decorators__ = DecoratorInfos(validators={}, field_validators={}, root_validators={}, field_serializers={}, model_serializers={}, model_validators={}, computed_fields={})#

Metadata containing the decorators defined on the model. This replaces Model.__validators__ and Model.__root_validators__ from Pydantic V1.

__pydantic_extra_info__ = None#

A wrapper around the __pydantic_extra__ annotation, if explicitly annotated on a model.

This is a private attribute, not meant to be used outside Pydantic.

__pydantic_fields__ = {}#

A dictionary of field names and their corresponding [FieldInfo][pydantic.fields.FieldInfo] objects. This replaces Model.__fields__ from Pydantic V1.

__pydantic_generic_metadata__ = {'args': (), 'origin': None, 'parameters': ()}#

A dictionary containing metadata about generic Pydantic models.

The origin and args items map to the [__origin__][genericalias.__origin__] and [__args__][genericalias.__args__] attributes of [generic aliases][types-genericalias], and the parameter item maps to the __parameter__ attribute of generic classes.

__pydantic_parent_namespace__ = None#

Parent namespace of the model, used for automatic rebuilding of models.

__pydantic_post_init__ = None#

The name of the post-init method for the model, if defined.

__pydantic_serializer__ = SchemaSerializer(serializer=PolymorphismTrampoline(     PolymorphismTrampoline {         class: Py(             0x0000556ad8131ea0,         ),         serializer: PolymorphismTrampoline(             PolymorphismTrampoline {                 class: Py(                     0x0000556ad8131ea0,                 ),                 serializer: Model(                     ModelSerializer {                         class: Py(                             0x0000556ad8131ea0,                         ),                         serializer: Fields(                             GeneralFieldsSerializer {                                 fields: {},                                 computed_fields: Some(                                     ComputedFields(                                         [],                                     ),                                 ),                                 mode: ModelExtra,                                 extra_serializer: None,                                 filter: SchemaFilter {                                     include: None,                                     exclude: None,                                 },                                 required_fields: 0,                             },                         ),                         has_extra: true,                         root_model: false,                         name: "RelaxedBase",                     },                 ),                 enabled_from_config: false,             },         ),         enabled_from_config: false,     }, ), definitions=[])#

The pydantic-core SchemaSerializer used to dump instances of the model.

__pydantic_setattr_handlers__ = {}#

__setattr__ handlers. Memoizing the handlers leads to a dramatic performance improvement in __setattr__

__pydantic_validator__ = SchemaValidator(title="RelaxedBase", validator=Model(     ModelValidator {         revalidate: Never,         validator: ModelFields(             ModelFieldsValidator {                 fields: [],                 model_name: "RelaxedBase",                 extra_behavior: Allow,                 extras_validator: None,                 extras_keys_validator: None,                 strict: false,                 from_attributes: false,                 loc_by_alias: true,                 lookup: LookupTree {                     inner: {},                 },                 validate_by_alias: None,                 validate_by_name: None,             },         ),         class: Py(             0x0000556ad8131ea0,         ),         generic_origin: None,         post_init: None,         frozen: false,         custom_init: false,         root_model: false,         undefined: Py(             0x00007fe7e4c7c550,         ),         name: "RelaxedBase",     }, ), definitions=[], cache_strings=True)#

The pydantic-core SchemaValidator used to validate instances of the model.

__signature__ = <Signature (**extra_data: Any) -> None>#

The synthesized __init__ [Signature][inspect.Signature] of the model.