Module xdynamo.common_types
Global variables
var operator_alias_map
-
Used to normalize some common operators (that we use in other systems) to the one used in Dynamo.
Functions
def get_dynamo_type_from_python_type(some_type: Type) ‑> str
Classes
class DynKey (api: DynApi, id: str = None, hash_key: Any = None, range_key: Optional[Any] = None, range_operator: str = None, require_full_key: bool = True)
-
DynKey(api: 'DynApi', id: str = None, hash_key: Any = None, range_key: Optional[Any] = None, range_operator: str = None, require_full_key: bool = True)
Expand source code
@dataclasses.dataclass(frozen=True, eq=True) class DynKey: api: 'DynApi' = dataclasses.field(compare=False) # We only compare with `id`, this should represent our identity sufficiently. id: str = None hash_key: Union[Any] = dataclasses.field(default=None, compare=False) range_key: Optional[Any] = ( dataclasses.field(default=None, compare=False) ) range_operator: str = dataclasses.field(default=None, compare=False) require_full_key: bool = dataclasses.field(default=True, compare=False) def __str__(self): return self.id or '' @classmethod def via_obj(cls, obj: 'DynModel') -> 'DynKey': structure = obj.api.structure hash_name = structure.dyn_hash_key_name if not hash_name: raise XModelDynamoNoHashKeyDefinedError( f"While constructing {structure.model_cls}, found no hash-key field. " f"You must have at least one hash-key field." ) hash_value = getattr(obj, hash_name) if hash_value is None: raise XModelDynamoError( f"Unable to get DynKey due to `None` for dynamo hash-key ({hash_value}) " f"on object {obj}." ) range_name = structure.dyn_range_key_name range_value = None if range_name: range_value = getattr(obj, range_name) if range_value is None: raise XModelDynamoError( f"Unable to get DynKey due to `None` for dynamo range-key ({range_name}) " f"on object {obj}." ) return DynKey(api=obj.api, hash_key=hash_value, range_key=range_value) def key_as_dict(self): structure = self.api.structure hash_field = structure.dyn_hash_field range_field = structure.dyn_range_field def run_converter(field: 'DynField', value) -> Any: converter = field.converter if not converter: return value return converter( self.api, Converter.Direction.to_json, field, value ) # Append the keys for the items we want into what we will request. item_request = {hash_field.name: run_converter(hash_field, self.hash_key)} if range_field: item_request[range_field.name] = run_converter(range_field, self.range_key) return item_request def __post_init__(self): structure = self.api.structure delimiter = structure.dyn_id_delimiter range_name = structure.dyn_range_key_name need_range_key = bool(range_name) hash_key = self.hash_key range_key = self.range_key api = self.api _id = self.id if _id is not None and not isinstance(_id, str): # `self.id` must always be a string. # todo: Must check for standard converter method _id = str(_id) object.__setattr__(self, 'id', _id) require_full_key = self.require_full_key # First, figure out `self.id` if not provided. if not _id: if not hash_key: raise XRemoteError( f"Tried to create DynKey with no id ({_id}) or no hash key ({hash_key})." ) if require_full_key and need_range_key and not range_key: raise XRemoteError( f"Tried to create DynKey with no id ({_id}) or no range key ({range_key})." ) key_names = [(structure.dyn_hash_key_name, hash_key)] # Generate ID without delimiter to represent an entire hash-page (ie: any range value) if need_range_key and range_key is not None: key_names.append((range_name, range_key)) keys = [] for key_name, key_value in key_names: field = structure.get_field(key_name) converter = field.converter final_value = key_value if converter: if self.range_operator == 'between' and isinstance(key_value, list): sub_v_result = [] for sub_v in key_value: sub_v = converter( api, Converter.Direction.to_json, field, sub_v ) sub_v_result.append(str(sub_v)) final_value = ",".join(sub_v_result) else: final_value = converter( api, Converter.Direction.to_json, field, key_value ) keys.append(final_value) _id = delimiter.join([str(x) for x in keys]) object.__setattr__(self, 'id', _id) elif need_range_key and delimiter not in _id: raise XRemoteError( f"Tried to create DynKey with an `id` ({_id}) " f"that did not have delimiter ({delimiter}) in it. " f"This means we are missing the range-key part for field ({range_name}) " f"in the `id` that was provided. Trying providing the id like this: " f'"{_id}{delimiter}' r'{range-key-value-goes-here}".' # <-- want to directly-output the `{` part. ) # If we got provided a hash-key directly, no need to continue any farther. if hash_key: if require_full_key and need_range_key and not range_key: raise XRemoteError( f"Have hash_key ({hash_key}) without needed range_key while creating DynKey." ) # We were provided the hash/range key already, as an optimization I don't use time # checking to see if they passed in the same values that they may have passed in `id`. return # They did not pass in hash_key, so we must parse the `id` they provided # and then set them on self. if not need_range_key: # If we don't need range key, there is no delimiter to look for. hash_key = _id else: split_id = _id.split(delimiter) if len(split_id) != 2: raise XRemoteError( f"For dynamo table ({self.api.model_type}): Have id ({_id}) but delimiter " f"({delimiter}) is either not present, or is in it more than once. " f"'id' needs to contain exactly one hash and range key combined together " f"with the delimiter, ie: 'hash-key-value{delimiter}range-key-value'. " f"See xdynamo.dyn_connections documentation for more details on how " f"this works." ) # todo: Consider converting these `from_json`, like we convert `to_json` # when we put the keys into the `id` (see above, where we generate `id` if needed)? hash_key = split_id[0] range_key = split_id[1] object.__setattr__(self, 'hash_key', hash_key) object.__setattr__(self, 'range_key', range_key)
Class variables
var api : DynApi
var hash_key : Any
var id : str
var range_key : Optional[Any]
var range_operator : str
var require_full_key : bool
Static methods
def via_obj(obj: DynModel)
Methods
def key_as_dict(self)
class DynKeyType (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
Possible values for field option keys.
Expand source code
class DynKeyType(Enum): """ Possible values for field option keys. """ hash = EnumAuto() range = EnumAuto()
Ancestors
- enum.Enum
Class variables
var hash
var range