sqlmesh.core.config.base API documentation

Edit on GitHub

# sqlmesh.core.config.base

View Source

      1from __future__ import annotations
      2
      3import typing as t
      4from enum import Enum, auto
      5
      6from sqlmesh.utils.errors import ConfigError
      7from sqlmesh.utils.pydantic import PydanticModel
      8
      9T = t.TypeVar("T", bound="BaseConfig")
     10
     11
     12class UpdateStrategy(Enum):
     13    """Supported strategies for adding new config to existing config"""
     14
     15    REPLACE = auto()  # Replace with new value
     16    EXTEND = auto()  # Extend list to existing list
     17    KEY_UPDATE = auto()  # Update dict key value with new dict key value
     18    KEY_EXTEND = auto()  # Extend dict key value to existing dict key value
     19    IMMUTABLE = auto()  # Raise if a key tries to change this value
     20    NESTED_UPDATE = auto()  # Recursively updates the nested config
     21
     22
     23def update_field(
     24    old: t.Optional[t.Any],
     25    new: t.Any,
     26    update_strategy: t.Optional[UpdateStrategy] = None,
     27) -> t.Any:
     28    """
     29    Update config field with new config value
     30
     31    Args:
     32        old: The existing config value
     33        new: The new config value
     34        update_strategy: The strategy to use when updating the field
     35
     36
     37        The updated field
     38    """
     39    if not old:
     40        return new
     41
     42    update_strategy = update_strategy or UpdateStrategy.REPLACE
     43
     44    if update_strategy == UpdateStrategy.IMMUTABLE:
     45        raise ConfigError(f"Cannot modify property: {old}.")
     46
     47    if update_strategy == UpdateStrategy.REPLACE:
     48        return new
     49    if update_strategy == UpdateStrategy.EXTEND:
     50        if not isinstance(old, list) or not isinstance(new, list):
     51            raise ConfigError("EXTEND behavior requires list field.")
     52
     53        return old + new
     54    if update_strategy == UpdateStrategy.KEY_UPDATE:
     55        if not isinstance(old, dict) or not isinstance(new, dict):
     56            raise ConfigError("KEY_UPDATE behavior requires dictionary field.")
     57
     58        combined = old.copy()
     59        combined.update(new)
     60        return combined
     61    if update_strategy == UpdateStrategy.KEY_EXTEND:
     62        if not isinstance(old, dict) or not isinstance(new, dict):
     63            raise ConfigError("KEY_EXTEND behavior requires dictionary field.")
     64
     65        combined = old.copy()
     66        for key, value in new.items():
     67            if not isinstance(value, list):
     68                raise ConfigError("KEY_EXTEND behavior requires list values in dictionary.")
     69
     70            old_value = combined.get(key)
     71            if old_value:
     72                if not isinstance(old_value, list):
     73                    raise ConfigError("KEY_EXTEND behavior requires list values in dictionary.")
     74
     75                combined[key] = old_value + value
     76            else:
     77                combined[key] = value
     78
     79        return combined
     80    if update_strategy == UpdateStrategy.NESTED_UPDATE:
     81        if not isinstance(old, BaseConfig):
     82            raise ConfigError(
     83                f"NESTED_UPDATE behavior requires a config object. {type(old)} was given instead."
     84            )
     85
     86        if type(new) != type(old):
     87            raise ConfigError(
     88                "NESTED_UPDATE behavior requires both values to have the same type. "
     89                f"{type(old)} and {type(new)} were given instead."
     90            )
     91
     92        return old.update_with(new)
     93
     94    raise ConfigError(f"Unknown update strategy {update_strategy}.")
     95
     96
     97class BaseConfig(PydanticModel):
     98    """Base configuration functionality for configuration classes."""
     99
    100    _FIELD_UPDATE_STRATEGY: t.ClassVar[t.Dict[str, UpdateStrategy]] = {}
    101
    102    def update_with(self: T, other: t.Union[t.Dict[str, t.Any], T]) -> T:
    103        """Updates this instance's fields with the passed in config fields and returns a new instance.
    104
    105        Args:
    106            other: Other configuration.
    107
    108        Returns:
    109            New instance updated with the passed in config fields
    110        """
    111        if isinstance(other, dict):
    112            other = self.__class__(**other)
    113
    114        updated_fields = {}
    115
    116        for field in other.__fields_set__:
    117            if field in self.__fields__:
    118                updated_fields[field] = update_field(
    119                    getattr(self, field),
    120                    getattr(other, field),
    121                    self._FIELD_UPDATE_STRATEGY.get(field),
    122                )
    123            else:
    124                updated_fields[field] = getattr(other, field)
    125
    126        return self.copy(update=updated_fields)

class UpdateStrategy(enum.Enum): View Source

    13class UpdateStrategy(Enum):
    14    """Supported strategies for adding new config to existing config"""
    15
    16    REPLACE = auto()  # Replace with new value
    17    EXTEND = auto()  # Extend list to existing list
    18    KEY_UPDATE = auto()  # Update dict key value with new dict key value
    19    KEY_EXTEND = auto()  # Extend dict key value to existing dict key value
    20    IMMUTABLE = auto()  # Raise if a key tries to change this value
    21    NESTED_UPDATE = auto()  # Recursively updates the nested config

Supported strategies for adding new config to existing config

REPLACE = <UpdateStrategy.REPLACE: 1>
EXTEND = <UpdateStrategy.EXTEND: 2>
KEY_UPDATE = <UpdateStrategy.KEY_UPDATE: 3>
KEY_EXTEND = <UpdateStrategy.KEY_EXTEND: 4>
IMMUTABLE = <UpdateStrategy.IMMUTABLE: 5>
NESTED_UPDATE = <UpdateStrategy.NESTED_UPDATE: 6>

##### Inherited Members

enum.Enum
  name
  value

def update_field( old: Optional[Any], new: Any, update_strategy: Optional[sqlmesh.core.config.base.UpdateStrategy] = None) -> Any: View Source

    24def update_field(
    25    old: t.Optional[t.Any],
    26    new: t.Any,
    27    update_strategy: t.Optional[UpdateStrategy] = None,
    28) -> t.Any:
    29    """
    30    Update config field with new config value
    31
    32    Args:
    33        old: The existing config value
    34        new: The new config value
    35        update_strategy: The strategy to use when updating the field
    36
    37
    38        The updated field
    39    """
    40    if not old:
    41        return new
    42
    43    update_strategy = update_strategy or UpdateStrategy.REPLACE
    44
    45    if update_strategy == UpdateStrategy.IMMUTABLE:
    46        raise ConfigError(f"Cannot modify property: {old}.")
    47
    48    if update_strategy == UpdateStrategy.REPLACE:
    49        return new
    50    if update_strategy == UpdateStrategy.EXTEND:
    51        if not isinstance(old, list) or not isinstance(new, list):
    52            raise ConfigError("EXTEND behavior requires list field.")
    53
    54        return old + new
    55    if update_strategy == UpdateStrategy.KEY_UPDATE:
    56        if not isinstance(old, dict) or not isinstance(new, dict):
    57            raise ConfigError("KEY_UPDATE behavior requires dictionary field.")
    58
    59        combined = old.copy()
    60        combined.update(new)
    61        return combined
    62    if update_strategy == UpdateStrategy.KEY_EXTEND:
    63        if not isinstance(old, dict) or not isinstance(new, dict):
    64            raise ConfigError("KEY_EXTEND behavior requires dictionary field.")
    65
    66        combined = old.copy()
    67        for key, value in new.items():
    68            if not isinstance(value, list):
    69                raise ConfigError("KEY_EXTEND behavior requires list values in dictionary.")
    70
    71            old_value = combined.get(key)
    72            if old_value:
    73                if not isinstance(old_value, list):
    74                    raise ConfigError("KEY_EXTEND behavior requires list values in dictionary.")
    75
    76                combined[key] = old_value + value
    77            else:
    78                combined[key] = value
    79
    80        return combined
    81    if update_strategy == UpdateStrategy.NESTED_UPDATE:
    82        if not isinstance(old, BaseConfig):
    83            raise ConfigError(
    84                f"NESTED_UPDATE behavior requires a config object. {type(old)} was given instead."
    85            )
    86
    87        if type(new) != type(old):
    88            raise ConfigError(
    89                "NESTED_UPDATE behavior requires both values to have the same type. "
    90                f"{type(old)} and {type(new)} were given instead."
    91            )
    92
    93        return old.update_with(new)
    94
    95    raise ConfigError(f"Unknown update strategy {update_strategy}.")

Update config field with new config value

###### Arguments:

- old: The existing config value
- new: The new config value
- update_strategy: The strategy to use when updating the field
- The updated field

class BaseConfig(sqlmesh.utils.pydantic.PydanticModel): View Source

     98class BaseConfig(PydanticModel):
     99    """Base configuration functionality for configuration classes."""
    100
    101    _FIELD_UPDATE_STRATEGY: t.ClassVar[t.Dict[str, UpdateStrategy]] = {}
    102
    103    def update_with(self: T, other: t.Union[t.Dict[str, t.Any], T]) -> T:
    104        """Updates this instance's fields with the passed in config fields and returns a new instance.
    105
    106        Args:
    107            other: Other configuration.
    108
    109        Returns:
    110            New instance updated with the passed in config fields
    111        """
    112        if isinstance(other, dict):
    113            other = self.__class__(**other)
    114
    115        updated_fields = {}
    116
    117        for field in other.__fields_set__:
    118            if field in self.__fields__:
    119                updated_fields[field] = update_field(
    120                    getattr(self, field),
    121                    getattr(other, field),
    122                    self._FIELD_UPDATE_STRATEGY.get(field),
    123                )
    124            else:
    125                updated_fields[field] = getattr(other, field)
    126
    127        return self.copy(update=updated_fields)

Base configuration functionality for configuration classes.

def update_with(self: ~T, other: Union[Dict[str, Any], ~T]) -> ~T: View Source

    103    def update_with(self: T, other: t.Union[t.Dict[str, t.Any], T]) -> T:
    104        """Updates this instance's fields with the passed in config fields and returns a new instance.
    105
    106        Args:
    107            other: Other configuration.
    108
    109        Returns:
    110            New instance updated with the passed in config fields
    111        """
    112        if isinstance(other, dict):
    113            other = self.__class__(**other)
    114
    115        updated_fields = {}
    116
    117        for field in other.__fields_set__:
    118            if field in self.__fields__:
    119                updated_fields[field] = update_field(
    120                    getattr(self, field),
    121                    getattr(other, field),
    122                    self._FIELD_UPDATE_STRATEGY.get(field),
    123                )
    124            else:
    125                updated_fields[field] = getattr(other, field)
    126
    127        return self.copy(update=updated_fields)

Updates this instance's fields with the passed in config fields and returns a new instance.

###### Arguments:

- other: Other configuration.

###### Returns:

> New instance updated with the passed in config fields

##### Inherited Members

pydantic.main.BaseModel
  BaseModel
  parse_obj
  parse_raw
  parse_file
  from_orm
  construct
  copy
  schema
  schema_json
  validate
  update_forward_refs
sqlmesh.utils.pydantic.PydanticModel
  Config
  dict
  json
  missing_required_fields
  extra_fields
  all_fields
  required_fields