amethyst.core.obj¶
Object (*args, **kwargs) |
Amethyst Base Object |
Attr ([convert, verify, isa, default, …]) |
Base class for Amethyst Object Attributes |
amethyst_deflate (obj[, deflator]) |
Deflate a structure of amethyst-encodable objects into a “dumb” structure of plain dicts, lists, numbers, and strings. |
amethyst_inflate (obj[, inflator, start]) |
Inflate an annotated “dumb” structure to a structure of objects, the opposite of amethyst_deflate() . |
register_amethyst_type (cls, encode, decode) |
Adds a type to the global list (global_amethyst_encoders ) for object encoding and decoding. |
SYNOPSIS¶
from amethyst.core import Object, Attr
class MyObject(Object):
# Attr() defines properties and will include in serialization.
foo = Attr(int)
bar = Attr(str).strip()
# foo and bar will be automatically extracted from kwargs.
# .other will not be serialized by .toJSON()
def __init__(self, other=None, **kwargs):
super().__init__(**kwargs)
self.other = other
# ...
myobj = MyObject(foo=23, other="Hello")
myobj.toJSON() # { "__my.module.MyObject__": { "foo": 23 } }
myobj = MyObject()
myobj.fromJSON('{ "foo": 23, "bar": " plugh " }')
print(myobj.bar) # "plugh" (no spaces)
DESCRIPTION¶
Object
implements the dictionary interface and stores
everything in self.dict.
Subclasses can define Attr
which will have properties defined
as shortcuts to read and write keys in the dictionary.
By storing all attributes in a dict, we can be trivially serialized.
toJSON() and fromJSON() methods exist to help with this, and should be used
for all JSON serialization since they will correctly handle set() and
other values (see the Object.JSONEncoder()
and
Object.JSONObjectHook()
methods). Additionally, the JSON methods
will perform automatic validation based on type information passed to the
Attr
objects and will ensure that it is loading data for the
correct class and that no unexpected keys are present.
-
exception
amethyst.core.obj.
AmethystException
¶
-
exception
amethyst.core.obj.
ImmutableObjectException
¶
-
exception
amethyst.core.obj.
DuplicateAttributeException
¶
-
class
amethyst.core.obj.
Attr
(convert=None, verify=None, isa=None, default=None, builder=None, fget=None, fset=None, fdel=None, doc=None, OVERRIDE=False)¶ Base class for Amethyst Object Attributes
Attribute descriptions primarily consist of a function which takes in a value and either returns a (possibly modified) value or else raises a
ValueError
. Python’s standard object constructors generally work well, though beware that str will generally accept anything.foo = Attr(int) # Coerce to int (strict parsing) foo = Attr(float).int() # Parse via float, but then integerize foo = 0 < Attr(int) # Positive integer foo = (0 <= Attr(int)) <= 200 # Alas, parens are necessary! # Stringify, then strip whitespace foo = Attr(str).strip() # Accept bytes or str, decoding if possible (only decodes # bytes since decode not a method of str) foo = Attr(isa=(bytes, str)).decode("UTF-8") # Coerce to a list via .split() foo = Attr(isa=(list, str)).split()
Anything based off of Amethyst’s
Object
class generally will work as well:class MyClass(amethyst.core.Object): ... class MyClass2(amethyst.core.Object): foo = Attr(MyClass)
Variables: name – Attribute name when assigned to an Object (auto-set by metaclass). -
__init__
(convert=None, verify=None, isa=None, default=None, builder=None, fget=None, fset=None, fdel=None, doc=None, OVERRIDE=False)¶ Parameters: - convert – Attribute converter. Must be a callable or else a
text string of a class or function name. Classes and functions
may be imported from other packages by prefixing prepending the
package name and a dot. For instance, numpy.array (see
amethyst.core.util.get_class()
for string processing details). Callable should accept a single argument, the value, and should return a canonicalized value. Invalid values should raise a ValueError(). If converter is None, values will be accepted unmodified. - isa – Called after conversion but before verification, ensures that the value is one of the passed types. Is a shortcut for verify=lambda val: isinstance(val, isa)
- verify – Attribute verifier. Called after conversion, this callable should return a truthy result if the value is acceptable.
- default –
Default value applied at object creation time. If default is a callable, it will be called to produce the default (e.g., list).
Note
The default value (or result of callable) is assumed valid and will not pass through conversion or verification.
- builder – Callable which will lazily build a default value when the attribute is first used.
- fget –
- fset –
- fdel – If any of fget, fset, or fdel are defined, they will be used to construct the object property. If all three are none (the default), then the functions which get/set/del the appropriate key in the object dictionary will be defined.
- doc – Documentation to be attached to the property.
- OVERRIDE – When true, allow attribute to replace an existing attribute (from a parent class).
- convert – Attribute converter. Must be a callable or else a
text string of a class or function name. Classes and functions
may be imported from other packages by prefixing prepending the
package name and a dot. For instance, numpy.array (see
-
build_property
(name)¶
-
get_default
()¶
-
copy_meta
(*others)¶ Copy metadata from another Attr object. This method is used when defining derived attributes (e.g.,
strip()
) to copy documentation and the OVERRIDE flag. Returns the object itself for chaining.
-
__call__
(value, key=None)¶
-
__and__
(other)¶
-
__rand__
(other)¶
-
__or__
(other)¶
-
__ror__
(other)¶
-
__eq__
(other)¶ Tests via
amethyst.core.util.smartmatch()
Warning
Hash lookups must be idempotent (looking up the result of a previous lookup had better return the same thing) since we offer no guarantees that validation may not happen more than once.
GOOD::
{ "a": "A", "b": "B", "A": "A", "B": "B" }
BAD::
{ "a": "A", "b": "B" } # will fail on repeated validation since "A" and "B" are not keys
-
__ne__
(other)¶ Ensure no smartmatch
-
__lt__
(other)¶
-
__le__
(other)¶
-
__ge__
(other)¶
-
__gt__
(other)¶
-
__mod__
(other)¶
-
__pos__
()¶
-
__abs__
()¶
-
float
()¶
-
int
()¶
-
complex
()¶
-
strip
(chars=None)¶ Return a new attribute which strips whitespace if applicable (duck typing).
-
rstrip
(chars=None)¶ Return a new attribute which strips whitespace from the right side if applicable (duck typing).
-
lstrip
(chars=None)¶ Return a new attribute which strips whitespace from the left side if applicable (duck typing).
-
encode
(encoding='UTF-8', errors='strict')¶ Return a new attribute which encodes value if applicable (duck typing). Defaults to UTF-8 encoding.
-
decode
(encoding='UTF-8', errors='strict')¶ Return a new attribute which decodes value if applicable (duck typing). Defaults to UTF-8 encoding.
-
lower
()¶ Return a new attribute which lower-cases value if applicable (duck typing).
-
upper
()¶ Return a new attribute which upper-cases value if applicable (duck typing).
-
title
()¶ Return a new attribute which title-cases value if applicable (duck typing).
-
capitalize
()¶ Return a new attribute which capitalizes value if applicable (duck typing).
-
casefold
()¶ Return a new attribute which casefolds value if applicable (duck typing).
-
split
(sep=None, maxsplit=-1)¶ Return a new attribute which splits its value if applicable (duck typing).
-
-
amethyst.core.obj.
register_amethyst_type
(cls, encode, decode, name=None, overwrite=False, wrap_encode=True)¶ Adds a type to the global list (
global_amethyst_encoders
) for object encoding and decoding. Subclasses ofObject
are automatically registered, so you should only need to register external objects that you use.Parameters: - cls (class) – Class to register
- encode (callable) – Callable which will transform the object into a “dumb” structure of primitive objects (dict, list, str, int, float).
- decode (callable) – Callable which will transform the “dumb” structure of primitive objects back into the object.
- name (str) – Globally unique string identifying the class. This name should be something which won’t appear as a dictionary key in normal data. Defaults to “__MODULENAME.CLASSNAME__”
- overwrite (bool) – By default, this function will raise an error if a class or name is aready registered. Pass True to override any existing registrations.
- wrap_encode (bool) –
By default, the encoded object will be wrapped in a single-key dict:
{ name: ENCODED_OBJECT }
so that the decoder can be called when inflating a structure containing the object. Pass True in this parameter in order to avoid wrapping the encoded structure.You might want to set this parameter if your object is naturally expressed as a basic object and you are certain that all uses after inflation will automatically coerce the value to your desired object when needed. For instance, a URL object where all functions and methods which accept the URL object also accept a plain string. You could pass an encoder which deflates to plain strings and set
wrap_encode=False
and then URLs would appear as plain strings in your exported structures, which may be easier to work with in external applications.This option also offers an escape hatch for hypothetical cases where you may need to wrap your encoded object in your encoder itself.
See also
-
amethyst.core.obj.
amethyst_deflate
(obj, deflator=None)¶ Deflate a structure of amethyst-encodable objects into a “dumb” structure of plain dicts, lists, numbers, and strings. The deflated structure should be easily serializable by most any reasonable serialization library (yaml, lxml, …)
Makes use of
global_amethyst_encoders
by default. Pass an amethyst Object as second argument to make use of any Object-local encoders.Note: If your target is JSON, the amethyst object’s
Object.toJSON()
method is probably better.
-
amethyst.core.obj.
amethyst_inflate
(obj, inflator=None, start=0)¶ Inflate an annotated “dumb” structure to a structure of objects, the opposite of
amethyst_deflate()
.This function should be used to assist in inflation of
Object
instances using alternative serialization tools. Any serializer that can produce plain dicts and lists should work with this function.This function handles either single-key or flat style annotations. Un-annotated constructions will pass through unchanged.
This function makes use of
global_amethyst_encoders
by default. Pass an amethystObject
as second argument to make use of any Object-local encoders.Note
If your source is JSON, the amethyst object’s
Object.fromJSON()
or classObject.newFromJSON()
method is probably better.
-
class
amethyst.core.obj.
Object
(*args, **kwargs)¶ Amethyst Base Object
Variables: - _attrs – Dictionary mapping attribute names to
Attr
objects. Should not be modified, but can be read for introspection of an Object. - _jsonencoders –
Dictionary mapping class objects to callable encoders which should produce a JSON-serializable object. These functions are called from the JSONEncoder method. Per the json documentation, these functions should return an object which is JSON serializable or else raise a TypeError. These encoders are specific to the class. Use
register_amethyst_type()
to register a class globally.Note
_jsonencoders is a lower-level tool than
register_amethyst_type()
and offers direct access to the encoders (behaves like overwrite=True, wrap_encode=False) - _jsonhooks –
Dictionary mapping class identifiers (strings of form “__MODULENAME.CLASSNAME__”) to callable decoders which should inflate simple structures to corresponding objects. These functions are called from the JSONObjectHook method when inflating data. These decoders are specific to the class. Use
register_amethyst_type()
to register a class globally.Note
_jsonhooks is a lower-level tool than
register_amethyst_type()
and offers direct access to the decoders (behaves like overwrite=True, wrap_encode=False)
-
amethyst_includeclass
= True¶ When True (the default), serialization will include a key “__class__” containing the class name of the object which can be used during loading to verify that the object is of the correct type.
-
amethyst_verifyclass
= True¶ When True (the default), loading data from JSON or a dict passed to
amethyst_load_data()
will check for the “__class__” key described above, and an exception will be thrown if it is not found.
-
amethyst_import_strategy
= 'strict'¶ When “strict” (the default), then loading data from JSON or a dictionary via
amethyst_load_data()
requires all keys present in the data structure to correspond with keys in the attribute list. If any additional keys are present, an exception will be raised. When “loose”, additional keys will be ignored and not copied into the object dictionary. When “sloppy”, unknown attributes will be copied unmodified into the object dict.
-
__init__
(*args, **kwargs)¶ Initializes self.dict with all passed kwargs. Object is mutable by default.
Warning
Passing a single argument that is an instance of the class itself is reserved for internal use only and behavior may change.
-
amethyst_assert_mutable
(msg='May not modify, object is immutable')¶
-
amethyst_is_mutable
()¶
-
amethyst_make_mutable
()¶
-
amethyst_make_immutable
()¶
-
__str__
()¶ Return str(self).
-
__repr__
()¶ Return repr(self).
-
__len__
()¶
-
__contains__
(key)¶
-
__iter__
()¶
-
__eq__
(other)¶ Object equality. Tests all :py:func:`Attr()`s and only :py:func:`Attr()`s. Other python properties or “garbage” in the underlying dict (which may arise from “sloppy” imports) will be ignored.
-
__ne__
(other)¶ Return self!=value.
-
items
(**kwargs)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
iteritems
(**kwargs)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
keys
(**kwargs)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
values
(**kwargs)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
__getitem__
(key)¶
-
__setitem__
(key, value)¶
-
__delitem__
(key)¶
-
get
(key, dflt=None)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
set
(*args, **kwargs)¶ Verify then set canonicalized value. Positional args take precedence over kwargs.
obj.set(key, val) obj.set(foo=val)
Subclasses: this method may be overridden with an unrelated implementation.
-
setdefault
(key, value)¶ If missing a value, verify then set
Subclasses: this method may be overridden with an unrelated implementation.
-
direct_set
(*args, **kwargs)¶ Set values BYPASSING VALIDATION but respecting mutability. Positional args take precedence over kwargs.
obj.direct_set(key, val) obj.direct_set(foo=val)
Subclasses: this method may be overridden with an unrelated implementation.
-
pop
(key, dflt=None)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
update
(*args, **kwargs)¶ Subclasses: this method may be overridden with an unrelated implementation.
-
direct_update
(*args, **kwargs)¶ Update internal dictionary BYPASSING VALIDATION but respecting mutability.
Subclasses: this method may be overridden with an unrelated implementation.
-
amethyst_validate_update
(d, import_strategy=None)¶ Convert and validate with the intention of updating only some of the object’s .dict values. Returns a new dictionary with canonicalized values, but does not initialize any missing keys with attribute default values (which distinguishes this from
amethyst_validate_data()
).This method does not change the object. Pass the resulting dict to the .update() method (or .direct_update() if you decide to accept the changes.
-
amethyst_validate_data
(d, import_strategy=None)¶ Convert and validate with the intention of replacing all of the object’s .dict values. Returns a new dictionary with canonicalized values, and defaults inserted (which distinguishes this from
amethyst_validate_update()
).This method does not change the object. Typical usage would look like either:
myobj.dict = myobj.amethyst_validate_data(data)
or
validated = myobj.amethyst_validate_data(data) mynewobj = MyClass(**validated)
Subclasses of
Object
can also use this method to inflate specific attibutes at load time. For instance, to inflate non-Object objects or ensure objects from hand-written config files. Be sure to overrideamethyst_validate_update()
as well if programmatic updates may need special inflation rules.
-
attr_value_ok
(name, value)¶ Validate a single value independently of any others. Just checks that the attribute validator does not raise an exception.
Subclasses: this method may be overridden with an unrelated implementation.
-
amethyst_load_data
(data, import_strategy=None, verifyclass=None)¶ Loads a data dictionary with validation. Modifies the passed dict and replaces current self.dict object with the one passed.
Parameters: - import_strategy – Provides a local override to the
amethyst_import_strategy
class attribute. - verifyclass – Provides a local override to the
amethyst_verifyclass
class attribute.
This method transparently loads data in either “single-key” or “flat” formats:
{ "__my.module.MyClass__": { ... obj.dict ... } } { "__class__": "MyClass", ... obj.dict ... }
Keep in mind that the default base value for
amethyst_verifyclass
is True, so, by default, at least one of the class identification keys is expected to be present.- import_strategy – Provides a local override to the
-
load_data
(data, import_strategy=None, verifyclass=None)¶ Alias for amethyst_load_data
Subclasses: this method may be overridden with an unrelated implementation.
-
JSONEncoder
(obj)¶ Fallback method for JSON encoding.
If the standard JSONEncoder is unable to encode an object, this method will be called. Per the json documentation, it should return an object which is JSON serializable or else raise a TypeError.
This base encoder, looks up an object’s class in a dict and calls the corresponding function to do the translation. The built-in translators map:
set => { "__set__": [ ... ] } frozenset => { "__frozenset__": [ ... ] }
Additional translators may be added by creating a class variable
jsonencoders
which is a dict mapping classes to a function. These translators will merged onto the base translators (silently replacing duplicates) by the metaclass at class (not object) creation.
-
JSONObjectHook
(obj)¶ Object hook for JSON decoding.
This method is called for every decoded JSON object. If necessary, it should return a new or modified object that should be used instead.
This base encoder, translates single-key dicts into new objects if the single-key is a special value. The built-in translators are:
{ "__set__": [ ... ] } => set { "__frozenset__": [ ... ] } => frozenset
Additional translators may be added by creating a class variable
jsonhooks
which is a dict mapping the special key to a function. These translators will merged onto the base translators (silently replacing duplicates) by the metaclass at class (not object) creation.Keep in mind that JSON input comes from untrusted sources, so translators will need to be robust against malformed structures.
-
toJSON
(includeclass=None, style=None, **kwargs)¶ Paramters are sent directly to json.dumps except:
Parameters: - includeclass – When true, include a class indicator using the
method requested by the
style
parameter. When None (the default), defer to the value of the class variableamethyst_includeclass
. - style –
When including class, what style to use (root-level object only). Options are:
- ”flat” to produce a JSON string in the form:
{ "__class__": "__my.module.MyClass__", ... obj.dict ... }
- ”single-key” to produce a JSON string in the form:
{ "__my.module.MyClass__": { ... obj.dict ... } }
- ”flat” to produce a JSON string in the form:
The default style is taken from the class
amethyst_classhint_style
attribute.- includeclass – When true, include a class indicator using the
method requested by the
-
classmethod
newFromJSON
(source, import_strategy=None, verifyclass=None, **kwargs)¶
-
fromJSON
(source, import_strategy=None, verifyclass=None, **kwargs)¶ Paramters are sent directly to json.load or json.loads except:
Parameters: - import_strategy – Provides a local override to the
amethyst_import_strategy
class attribute. - verifyclass – Provides a local override to the
amethyst_verifyclass
class attribute.
- import_strategy – Provides a local override to the
-
deflate_data
()¶ Deflate object into a “dumb” structure of plain dicts, lists, numbers, and strings. The deflated structure should be easily serializable by most any reasonable serialization library (yaml, lxml, …)
Subclasses: this method may be overridden with an unrelated implementation.
-
classmethod
inflate_new
(obj)¶ Inflate a “dumb” structure to a structure of objects, the opposite of
deflate_data()
. Allows inflation from arbitrary serialization tools, as long as they can produce dicts and lists.Subclasses: this method may be overridden with an unrelated implementation.
- _attrs – Dictionary mapping attribute names to