in glean-core/python/glean/_loader.py [0:0]
def _event_extra_factory(name: str, argnames: List[Tuple[str, str]]) -> Any:
"""
Generate a new class, inheriting from `metrics.EventExtras`
and implementing the `to_ffi_extra` method,
which serializes expected attributes to pass over FFI.
"""
def __init__(self, **kwargs):
for key, value in kwargs.items():
typ = next((t for (k, t) in argnames if key == k), None)
if typ is None:
raise TypeError(f"Argument '{key}' not valid for {self.__class__.__name__}")
elif typ == "boolean" and isinstance(value, bool):
pass
elif typ == "string" and isinstance(value, str):
pass
elif typ == "quantity" and isinstance(value, int):
pass
else:
raise TypeError(f"Field '{key}' requires type {typ} in {self.__class__.__name__}")
setattr(self, key, value)
def to_ffi_extra(self):
extras = {}
for name, typ in argnames:
attr = getattr(self, name, None)
if attr is not None:
if typ == "boolean" and isinstance(attr, bool):
# Special-case needed for booleans to turn them lowercase (true/false)
extras[name] = str(attr).lower()
elif typ == "string" and isinstance(attr, str):
extras[name] = str(attr)
elif typ == "quantity" and isinstance(attr, int):
extras[name] = str(attr)
# Don't support other data types
else:
raise TypeError(f"Type {type(attr)} not supported for {name}")
return extras
attr = {name: None for (name, _) in argnames} # type: Dict[str, Any]
attr["__init__"] = __init__
attr["to_ffi_extra"] = to_ffi_extra
newclass = type(name, (metrics.EventExtras,), attr)
return newclass