{ "info": { "author": "Nick Blundell", "author_email": "blundeln [AT] gmail [DOT] com", "bugtrack_url": null, "classifiers": [ "Topic :: Text Processing" ], "description": "Pylens - Object Serialisation through a Lens\n====================================================\n\nAuthor: Nick Blundell (http://www.nickblundell.org.uk)\n\n.. TOC\n\nHere is the Problem\n-----------------------------------------------------\n\nSuppose that you wish to programatically change part of a potentially complex\nstructure stored within a string (e.g. perhaps a UNIX configuration file) such that\nthe rest of the structure is left untouched, perhaps things like comments and\nspacing, to still allow for manual maintenance.\n\nIf we parsed such a structure using a typical parser, we will certainly\nextract an abstract model of the structure that we can work with and change,\nbut the problem comes when we wish to write those changes back out as a\nstring, since all of the non-semantic artifacts (e.g. whitespace, comments,\netc.) get lost in the parsing process.\n\nTo put it another way, we wish in certain circumstances to make *surgical* changes to\nthe string, leaving undisturbed those parts that do not concern our\nalteration, and therefore without us stomping over artifacts that may be\nimportant to other co-operating systems or manual editors.\n\nThis is where the concept of bi-directional programming (see references below\nfor more of the background) can really help us. Here we specify a so-called *lens*,\nwhich is a parser that works not only in the classical sense to parse a string\ninto an abstract model (for easy manipulation) but that can also be used to weave\nour modified structure back into the original string.\n\nThe lens concept is a generalisation of the classic view-update problem often\nfound in database technology, where we wish to modify a simplified view of\nsome data and have the changes reflected in the data proper.\n\nThe Approach of pylens\n-----------------------------------------------------\n\nThe pylens framework closely relates the concept of a lens with python code, such\nthat lenses may be defined simply in python (greatly inspired by\n`pyparsing `_) and may be mapped to and from python\nstructures, such as lists, dicts, and classes.\n\nThis resembles a special kind of serialisation where we can extract python\nstructures from arbitrary string structures, easily modify the structure, and\nthen surgically put the model back into the original string structure such\nthat it embodies our changes.\n\nSince lenses are represented as python classes, it is straightforward to\nextend their functionality.\n\nExample\n-----------------------------------------------------\n\nSuppose we have a config file that looks like this, and let's assume it has\nbeen read into a variable **CONFIG_STRING**::\n\n # Auto interfaces.\n auto lo eth0\n\n allow-hotplug eth1\n\n # Define mapping for eth0.\n mapping eth0\n # Mapping script\n script /usr/local/sbin/map-scheme\n map HOME eth0-home\n map WORK eth0-work\n\n # eth0 home configuration.\n iface eth0-home inet static\n address 192.168.1.1\n netmask 255.255.255.0\n up flush-mail\n\nand we wish to programatically make some changes, so that it becomes this (the\nchanges are highlighted with square brackets)::\n\n # Auto interfaces.\n auto lo [wlan0] eth0\n\n allow-hotplug eth1\n\n # Define mapping for eth0.\n mapping eth0\n # Mapping script\n script [/home/fred/map_script]\n map HOME eth0-home\n map WORK eth0-work\n\n # eth0 home configuration.\n iface eth0-home inet static\n address 192.168.1.1\n [dns-nameservers 192.168.1.4 192.168.1.5]\n netmask 255.255.255.0\n up flush-mail\n \n [iface wlan0 inet dhcp]\n\nWe use the pylens framework as follows::\n \n from pylens import *\n\n # Define our python model and a lens for mapping our model to\n # and from the string structure.\n class NetworkConfiguration(LensObject) :\n # Our definition of the lens which maps between the string structure and\n # this class - this will become clearer in the tutorials.\n __lens__ = ZeroOrMore(NetworkInterface | auto_lens | HashComment() | BlankLine())\n \n # We can add whatever functions we like for manipulating our class, such\n # as a constructor.\n def __init__(self, ...) :\n ...\n \n # Now extract our model's representation from the config string.\n net_config = get(NetworkConfiguration, CONFIG_STRING)\n\n # Then modify the structure using standard python.\n net_config.auto_interfaces[0].insert(1, \"wlan0\")\n net_config.interface_mappings[\"eth0\"].script = \"/home/fred/map_script\"\n net_config.interfaces[\"eth0-home\"].dns_nameservers = [\"192.168.1.4\", \"192.168.1.5\"]\n net_config.interfaces[\"wlan0\"] = Interface(address_family=\"inet\", method=\"dhcp\")\n\n # Then weave the changes back into the original config string (i.e. change\n # only what needs to be changed, disturbing as little of the original config\n # string as possible).\n CONFIG_STRING = lens.put(net_config)\n\n\nDocumentation\n-----------------------------------------------------\n\nYou can find online documentation for pylens here:\nhttp://packages.python.org/pylens/\n\nFor more of a detailed insight into pylens, you might also wish to look at some of the\nsource files, which contain extensive testing code that works fully but which\nhas yet to be documented (e.g. recursion, etc.)::\n\n examples/*.py\n testing/tests.py\n pylens/*_lenses.py\n\n\nLimitations\n-----------------------------------------------------\n\nNote that the initial aim of this project was to see if the concept of lenses\nand bi-directional programming could be integrated more closely with a\nlanguage such as python, allowing rich models to be composed of classes and\nother native types (e.g. strings, floats, lists, dicts, etc.), but this has\nbeen achieved through compromise, since there is currently no validation of\nlens behavedness (as you will find in the tool Augeas, referenced below),\nwhich requires the expensive analysis of finite state automata. Put simply, a\nwell-behaved lens will always adhere to the following rules::\n\n lens.get(lens.put(x)) == x\n lens.put(lens.get(y)) == y\n\nI am interested in exploring how we can implement some kind of certainty of\nbehavedness into the framework, if not full ambiguity checking, but for now\nsanity checking is left down to the lens author, though I have provided within the\nframework aids to support the incremental development and testing of lenses,\nwhich should help you to create something that works for you.\n\nThe Theory\n-----------------------------------------------------\n\nFor more details on the theory and inspiration of pylens, please see the\nfollowing links.\n\n* Lens theory: Nate Foster, et al.: http://www.cs.cornell.edu/~jnfoster/\n* Functionality: http://augeas.net/\n* Ease of parser definition: pyparsing: http://pyparsing.wikispaces.com/\n* Design: The clean design of Yean, by Markus Brueckner: http://www.slash-me.net/dev/snippets/yeanpypa/documentation.html", "description_content_type": null, "docs_url": "https://pythonhosted.org/pylens/", "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://www.nickblundell.org.uk", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "pylens", "package_url": "https://pypi.org/project/pylens/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/pylens/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://www.nickblundell.org.uk" }, "release_url": "https://pypi.org/project/pylens/1.0.0b6/", "requires_dist": null, "requires_python": null, "summary": "Pylens - Object Serialisation through a Lens", "version": "1.0.0b6" }, "last_serial": 797345, "releases": { "1.0.0a1": [ { "comment_text": "", "digests": { "md5": "5940b8b69718e1da25b2bb9eeaa84745", "sha256": "9946f57f8b0a35a2f1046909fd26a7f9ab8f64d4e79b69ebcb736cc8fd6c975e" }, "downloads": -1, "filename": "pylens-1.0.0a1.tar.gz", "has_sig": false, "md5_digest": "5940b8b69718e1da25b2bb9eeaa84745", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28583, "upload_time": "2011-06-15T13:01:58", "url": "https://files.pythonhosted.org/packages/26/34/0aac6d2885c4db24f45c2b5d9906942c7f292904413e35a47b6e02d1da28/pylens-1.0.0a1.tar.gz" } ], "1.0.0a2": [ { "comment_text": "", "digests": { "md5": "acc7b396843dd99a62924268aa751699", "sha256": "484ad1484408e00572a52d6265945a18094504c1abb336b93d1a3c25ea24c61a" }, "downloads": -1, "filename": "pylens-1.0.0a2.tar.gz", "has_sig": false, "md5_digest": "acc7b396843dd99a62924268aa751699", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28592, "upload_time": "2011-06-15T13:45:58", "url": "https://files.pythonhosted.org/packages/9d/b2/77e1204ce937b9d3c1709849def7735e62f8e3bf3fb63aa6ad82fb11bf80/pylens-1.0.0a2.tar.gz" } ], "1.0.0b1": [ { "comment_text": "", "digests": { "md5": "a43f3938f196c37a85e21f9da681d0e8", "sha256": "a17fe5952a7d7e14f21a27166d3f0c9e94407733a95d4722d916adc80fc5fbfb" }, "downloads": -1, "filename": "pylens-1.0.0b1.tar.gz", "has_sig": false, "md5_digest": "a43f3938f196c37a85e21f9da681d0e8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 62820, "upload_time": "2011-07-05T23:13:06", "url": "https://files.pythonhosted.org/packages/a4/a3/c839ae9596f4ef81b867be54a2df413b148817429f021d2dcc9247f913cd/pylens-1.0.0b1.tar.gz" } ], "1.0.0b2": [ { "comment_text": "", "digests": { "md5": "49579877322f3e3e6064eea3970ad7a8", "sha256": "b9ca094ebcd928fdf37444f784029dfc9185beb1668ce1727baacade6b3a70c0" }, "downloads": -1, "filename": "pylens-1.0.0b2.tar.gz", "has_sig": false, "md5_digest": "49579877322f3e3e6064eea3970ad7a8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38090, "upload_time": "2011-07-08T01:57:46", "url": "https://files.pythonhosted.org/packages/aa/b1/a5b04c12a9d8c4bcde309ee2ef09acc5dd9c41f4f76ea1fed33ef5410f94/pylens-1.0.0b2.tar.gz" } ], "1.0.0b3": [ { "comment_text": "", "digests": { "md5": "e3294a3efa78b186d285db927fd18923", "sha256": "3e3cc83324ecc998c44553e543b409bb8fbc3efc0bae7e35b107cb8a5332b309" }, "downloads": -1, "filename": "pylens-1.0.0b3.tar.gz", "has_sig": false, "md5_digest": "e3294a3efa78b186d285db927fd18923", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38604, "upload_time": "2011-07-12T09:22:44", "url": "https://files.pythonhosted.org/packages/00/55/ac858e28d7b937a539084cf53744fbacf0520feee92cd195a5def65988e5/pylens-1.0.0b3.tar.gz" } ], "1.0.0b4": [ { "comment_text": "", "digests": { "md5": "e87241d766bf7140faea2dbf5b063277", "sha256": "3dec8c7effaae5fa80f5fc30d292d8d52714640025e68619dc8c9714708b2126" }, "downloads": -1, "filename": "pylens-1.0.0b4.tar.gz", "has_sig": false, "md5_digest": "e87241d766bf7140faea2dbf5b063277", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38620, "upload_time": "2011-07-12T09:28:53", "url": "https://files.pythonhosted.org/packages/2d/41/2ab19cb53e04a3c2118507cb13021b5d33e706cd6eb619844e83b77d9957/pylens-1.0.0b4.tar.gz" } ], "1.0.0b5": [ { "comment_text": "", "digests": { "md5": "8c5dd35984a966750d6e2ecfac0f2062", "sha256": "64a24fec92542269464f95346ad9e2cd587d9d38b6283234da282bfcfa738e0b" }, "downloads": -1, "filename": "pylens-1.0.0b5.tar.gz", "has_sig": false, "md5_digest": "8c5dd35984a966750d6e2ecfac0f2062", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38717, "upload_time": "2011-07-14T17:53:44", "url": "https://files.pythonhosted.org/packages/b6/80/1eb281dcde0755108e7061845e59a560fa05d2a778e592824c602c36b2c1/pylens-1.0.0b5.tar.gz" } ], "1.0.0b6": [ { "comment_text": "", "digests": { "md5": "130702ccf821e6076950194ac0640d9f", "sha256": "a2dd6e31299670740c3028bb0ba1e42c7756a3f4c13716fb06d408681a119540" }, "downloads": -1, "filename": "pylens-1.0.0b6.tar.gz", "has_sig": false, "md5_digest": "130702ccf821e6076950194ac0640d9f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 69507, "upload_time": "2011-07-16T12:28:34", "url": "https://files.pythonhosted.org/packages/9e/68/1989f92a5a41b69e12eea182d8604e0816cbaea2aca9dbbf56a1d3a62fda/pylens-1.0.0b6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "130702ccf821e6076950194ac0640d9f", "sha256": "a2dd6e31299670740c3028bb0ba1e42c7756a3f4c13716fb06d408681a119540" }, "downloads": -1, "filename": "pylens-1.0.0b6.tar.gz", "has_sig": false, "md5_digest": "130702ccf821e6076950194ac0640d9f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 69507, "upload_time": "2011-07-16T12:28:34", "url": "https://files.pythonhosted.org/packages/9e/68/1989f92a5a41b69e12eea182d8604e0816cbaea2aca9dbbf56a1d3a62fda/pylens-1.0.0b6.tar.gz" } ] }