Package: pyrsistent-mutable
OverviewThepyrsistent-mutablepackage presents a decorator that will transform a decorated function to use thepyrsistentAPI.This means that a set of specific operations are transformed:Construction of literalsets,dicts andlists are transformed into calls topset,pvectorandpmap.Assignments are rewritten to handle:Assignments to attributes become evolve calls; nesting is handled correctly.Augmented assignments are transformed into regular assignments.Standalone method invocations are transformed into assignments.frompyrsistent_mutableimportpyrmutefrompyrsistentimportPRecord,fieldclassSimple(PRecord):attr=field()other=field()@pyrmutedefexample_func():# Built in referential integritysave_vector=my_vector=[0,1,2,3,4]# Mapped to a pvectordelmy_vector[3]# Does *not* change save_vector# Evolve nested attributesmy_precord=Simple(attr=Simple(),other=[])my_precord.attr.attr=5my_precord.other.append(20)# Transforms literals and comprehensionsmy_maps=[{'filling':key}forkeyin('apple','banana')]my_maps[0]['crust']='flaky'returnmy_vector,save_vector,my_precord,my_mapsThis example is tested intests/test_readme.py.What’s the point?It’s entirely that the imperative form is easier to read, and that pyrsistent’s API is tedious for nested collections,
at least compared to native Python syntax.Also, I’m working on a language that uses this technique more extensively, so this was an opportunity to turn a
prototype into something more generally useful.InstallingInstallation should just be:# Install via pip, preferred.pip3installpyrsistent-mutable# Install traditionally.python3setup.pyinstallUsageBeyond the example shown above, the main things to keep in mind when using this module:You function still needs to return values.A “copy” can be made by simple assignment.Lists, dicts and sets literals and comprehensions are transformed.Tuples arenottransformed, nor are generators.Method calls areonlytransformed if they are standalone expressions.Rewritten operations should fall back to normal behavior for non-pyrsistentvalues.The decorated function can’t allownonlocalnames.globalmay not work.TroubleshootingThis is really just trying to take a prototype and do something useful with it.If a function isn’t calling something in a useful manner, the culprit is probably my very lame implementations inpyrsistent_mutable.globals.Don’t forget toreturnThis only munges assignments and expression statements.Read the__source__The transformed code is written into your function under__source__which may be helpful in debugging.Known limitsMost of these are because I’ve only done very preliminary work to map imperative operations to pyrsistent values.Assignment of slices uses the evolver framework, which doesn’t handle complex slices.Deletion of slices similarly doesn’t work.Augmented assignment generally requires a pyrsistent value on the rhs.This is mitigated now that the module translates literals.It is not tested on asynchronous functions or generators. It shouldn’t care about them, though.It’s all or nothing.The top level function can’t havenonlocalnames. Embedded functions can, though.DebuggingBy default, the decorator will write the transformed source to your function as__source__. I just pulled that name
out my hat. You can call the decorator withwrite_source=Falseto disable this.Package maintainer notespipinstalltwinepythonsetup.pybdist_wheeltwineuploaddist/pyrsistent_mutable-0.0.x-py3-none-any.whl