Package: amethyst-core
A sober python base library for python 3. (Full Documentation)Caution!EXPERIMENTAL CODE. The interface to this library is not yet
stable. At this time, improvements will be made to the interface without
regard to backward compatibility. Backward-incompatible changes will not
necessarily be documented in the changelog, and changes may be added
which eat your puppy.A Generic Serializable ObjectThe primary product of this module is a base python object class designed
for easy serialization. JSON serialization and de-serialization come for
free for attributes of (most of the) core python object types.A Basic Class:fromamethyst.coreimportObject,AttrclassMyObject(Object):foo=Attr(int)bar=Attr(isa=str).strip()myobj=MyObject(foo="23")print(myobj.foo+1)# => 24Validation / CoersionclassMyObject(Object):amethyst_verifyclass=False# don't check json for class namefoo=Attr(int)# coerce to intbar=Attr(isa=str).strip()# ensure str then strip whitespaceValidatedconstructorsmyobj=MyObject({"foo":"23","bar":"Hello "})myobj=MyObject(foo="23",bar="Hello ")print(isinstance(myobj.foo,int))# Trueprint(myobj.bar)# "Hello"assignmentmyobj["foo"]="23"# Converts to intmyobj["foo"]="Not an int"# Raises exceptionmyobj.foo="23"# Converts to intmyobj.foo="Not an int"# Raises exceptionset and update methodsmyobj.set("foo",value)# Convert to int or raise exceptionmyobj.update(foo=value)# Convert to int or raise exceptionmyobj.setdefault("foo",value)# Convert or raise only if foo unsetloading fresh from dict or json# Converts and trimsmyobj.load_data({"foo":"23","bar":"Hello "})# Converts and trimsmyobj=MyObject.newFromJSON('{"foo": "23", "bar": "Hello "}')myobj.fromJSON('{"foo": "23", "bar": "Hello "}')Not Validatedmyobj.direct_set("foo","Not an int")# DANGER: Not an exception!myobj.direct_update(foo="Not an int")# DANGER: Not an exception!SerializationJSON text can be produced and loaded, even for nested objects.json_string=myobj.toJSON()myobj2=MyObject.newFromJSON(json_string)Other serialization libraries can easily be used as well.yaml_string=yaml.dump(myobj.deflate_data())myobj2=MyObject.inflate_new(yaml.safe_load(yaml_string))By default the JSON serializer injects type hints to ensure that objects
are de-serialized into the correct class:# print(MyObject(foo=23, bar="plugh").toJSON()){"__class__":"__mymodule.MyObject__","foo":23,"bar":"plugh"}When building an object from JSON, the constructor will look for these
hints and raise a ValueError if the type hint is missing or imported into
the wrong class.# These raise ValueErrorMyObject.newFromJSON('{"foo":23, "bar":"plugh"}')MyObject.newFromJSON('{"__class__": "__mymodule.MyOtherObject__", "foo":23}')Class verification can be skipped by passingverifyclass=Falseto the loader.myobj=MyObject.newFromJSON('{"foo":23, "bar":"plugh"}',verifyclass=False)If you want no munging or class verification at all, set the class parameters:classMyObject(Object):amethyst_includeclass=Falseamethyst_verifyclass=Falsefoo=Attr(int)bar=Attr(isa=str).strip()# No extra class info due to modified defaults:myobj=MyObject.newFromJSON('{"foo":"23", "bar":"plugh"}')print(myobj.toJSON())# => { "foo": 23, "bar": "plugh" }Ecosystem integrationWorks withsqlite3.Rowobjects:importsqlite3conn=sqlite3.connect(myfile)conn.row_factory=sqlite3.Rowforrowinconn.execute('SELECT * FROM mytable')obj=MyObject(row)...Works withsix.iteritems():importsixfork,vinsix.iteritems(myobj):...