{ "info": { "author": "tef", "author_email": "tef@twentygototen.org", "bugtrack_url": null, "classifiers": [], "description": "============================\n hyperglyph: duck typed ipc\n============================\n\nhyperglyph is ipc (inter process communication) for dynamic, duck typed languages. unlike\nother ipc libraries, the server can return different objects\nto the client, without the client breaking.\n\nthe protocol supports a reasonable selection of primitive datatypes, \nincluding integers, floating point, lists, sets, dictionaries, ordered\ndictonaries, utf-8 strings, byte arrays, and datetimes/timedeltas.\n\nhyperglyph works with existing http tools like caches and load balancers\nto grow services, as well as supporting redirecting or linking \nto services on other hosts.\n\na talk at src-fringe 2012 was given and is online: http://vimeo.com/45474360\n(before the project changed its name)\n\nwe're on irc.freenode.net #hyperglyph\n\n\nlicense\n-------\n\nhyperglyph is released under the MIT license\n\n\nstatus\n------\n\nhyperglyph is pre 1.0 software and so should be considered unstable\nand experimental. however, earlier versions have been successfully\nused in production for more than a year.\n\nthe underlying specification has been finalized, and the reference\nimplementations are catching up.\n\nthe ruby version trails behind the python version.\n\n1.0 roadmap\n-----------\n\n- finalize spec (done)\n\n- python implementation to spec (in progress)\n\n - client is complete\n - server does not make use of all the spec\n\n- ruby implementation to spec (in progress, but slower)\n\n - client, server is incomplete\n\n- full coverage of specification by tests (in progress, but slower)\n\n - ruby, python individually tested\n - need cross implementation tests\n\n- 1.0 release\n\n - documentation, tests, and two implementations complete\n\n\nexample\n=======\n\nTo show, rather than tell, let's begin with some server code::\n\n import glyph\n\n r = glyph.Router() # a wsgi application\n\n @r.add()\n def hello():\n return \"Hello World\"\n\n # and a http server running in a thread\n s = glyph.Server(r) \n s.start()\n\n print s.url\n s.join()\n\nAnd some client code::\n\n import glyph \n\n server = glyph.get('http://server/')\n\n print server.hello()\n\nAdding a new function is simple::\n\n @r.add()\n def goodbye(name):\n return \"Goodbye \" + name\n\nAnd you can change the functions a little::\n\n @r.add()\n def hello(name=\"World\"):\n return \"Hello \"+name\n\nAmazingly, The old client still works, without changes::\n\n print server.hello()\n\nTo call new methods, you just call them::\n\n print server.hello('dave')\n print server.goodbye('dave')\n\nFunctions can return lists, dicts, sets, byte strings, unicode,\ndates, booleans, ints & floats::\n\n @r.add()\n def woo():\n return [1,True, None, False, \"a\",u\"b\"]\n\nFunctions can even return other functions that are mapped::\n\n @r.add()\n def greeting(lang=\"en\"):\n if lang == \"en\":\n return hello\n elif lang == 'fr':\n return salut\n\nThe client doesn't care::\n\n greet = client.greeting()\n\n print greet()\n \n\nGlyph can map objects too::\n\n @r.add()\n def find_user(name):\n user_id = database.find_user(name)\n return User(user_id)\n\n @r.add()\n class User(glyph.Resource):\n def __init__(self, id):\n self.id = id\n\n def message(self, subject, body):\n database.send_message(self.id, subject, body)\n\n def bio(self):\n return database.get_bio(self.id)\n\nThe client can get a User and find details::\n\n bob = server.find_user('bob')\n bob.messsage('lol', 'feels good man')\n\nLike before, new methods can be added without breaking old clients.\nunlike before, we can change object internals::\n\n @r.add()\n @glyph.redirect()\n def find_user(name):\n user_id, shard = database.find_user(name)\n return User(user_id, shard)\n\n @r.add()\n class User(glyph.Resource):\n def __init__(self, id, shard):\n self.id = id\n self.shard = shard\n\n ...\n\nThe glyph.redirect means that instead of returning the User object\ndirectly, it should redirect to it's url. The client follows these\nredirects automatically.\n\nEven though the internals have changed, the names haven't, so the client\nworks as ever::\n\n bob = server.find_user('bob')\n bob.messsage('lol', 'feels good man')\n\nUnderneath all this - glyph maps all of this to http::\n\n # by default, a server returns an object with a bunch\n # of methods that redirect to the mapped obejcts\n\n server = glyph.get('http://server/')\n\n # in this case, it will have an attribute 'find_user'\n # find user is a special sort of object - a form\n # it has a url, method and arguments attached.\n\n\n # when we call server.find_user(...), it submits that form\n # find_user redirects to a url for User(bob_id, cluster_id)\n \n bob = server.find_user('bob')\n\n # each object is mapped to a url, which contains the internal state\n # of the object - i.e /User/?id=bob_id&cluster=cluster_id\n\n # the server is stateless - a new User object is created\n # for each request that comes in, before destroying it.\n\n # similarly, methods are mapped to a url too \n # bob.message is a form pointing to /User/message?id=bo_id&cluster=cluster_id\n \n bob.messsage('lol', 'feels good man')\n\n\nAlthough glyph maps urls to objects on the server side, these urls are\nopaque to the client - the server is free to change them to point to\nother objects, or to add new internal state without breaking the client.\n\nClient code doesn't need to know how to construct requests, or store all \nof the state needed to make requests - the server tells it, rather than\nthe programmer.\n\nThe server is stateless - the state of the objects is encapsulated\nin the links & forms. \n\nglyph now has large file support. wrap a file handle in glyph.blob,\nand pass it around. on the server side, large blobs are written\nto temporary files\n\ninternals\n=========\n\nglyph on the server end has four major parts - a router, a mapper, a handler, and\na resource.\n\nrouter - looks at url prefix, finds a resource class to use\nmapper - associated with a class, it creates an instance to use\nhandler - given an instance, handles mapping the deserialization and serialization of the request\nresource - the bit that actually services the request\n\n\nthe ruby client is currently the simplest, and the python client\nhas a lot more code for more generic http services.\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": null, "license": "MIT License", "maintainer": null, "maintainer_email": null, "name": "hyperglyph", "package_url": "https://pypi.org/project/hyperglyph/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/hyperglyph/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/hyperglyph/0.9-20140421/", "requires_dist": null, "requires_python": null, "summary": "hyperglyph is ducked typed ipc over http", "version": "0.9-20140421" }, "last_serial": 1066396, "releases": { "0.9-20140421": [ { "comment_text": "", "digests": { "md5": "92242bab3f31a7bfebaf2ba4de95503d", "sha256": "d5645b176eb35786f5480c3b67cc6d91d101423c4d826343020a6001d5fe0d30" }, "downloads": -1, "filename": "hyperglyph-0.9_20140421-py2-none-any.whl", "has_sig": false, "md5_digest": "92242bab3f31a7bfebaf2ba4de95503d", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 16072, "upload_time": "2014-04-21T12:37:20", "url": "https://files.pythonhosted.org/packages/fc/3c/d1058f1b821d658ea49bba233506f57c1562f1f73ad09ea34a445f256d40/hyperglyph-0.9_20140421-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9f5561c8d42e23bee587efbc7fa932d1", "sha256": "9d1ed2ca458852e1264ac2757eb584b390f3b94220bcdc4d2ba56801adf8b985" }, "downloads": -1, "filename": "hyperglyph-0.9-20140421.tar.gz", "has_sig": false, "md5_digest": "9f5561c8d42e23bee587efbc7fa932d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14253, "upload_time": "2014-04-21T12:34:58", "url": "https://files.pythonhosted.org/packages/2c/96/9389531cf1a4f505b0e3888b780a0d8ed05c5e25929c355b012b487a8b94/hyperglyph-0.9-20140421.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "92242bab3f31a7bfebaf2ba4de95503d", "sha256": "d5645b176eb35786f5480c3b67cc6d91d101423c4d826343020a6001d5fe0d30" }, "downloads": -1, "filename": "hyperglyph-0.9_20140421-py2-none-any.whl", "has_sig": false, "md5_digest": "92242bab3f31a7bfebaf2ba4de95503d", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 16072, "upload_time": "2014-04-21T12:37:20", "url": "https://files.pythonhosted.org/packages/fc/3c/d1058f1b821d658ea49bba233506f57c1562f1f73ad09ea34a445f256d40/hyperglyph-0.9_20140421-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9f5561c8d42e23bee587efbc7fa932d1", "sha256": "9d1ed2ca458852e1264ac2757eb584b390f3b94220bcdc4d2ba56801adf8b985" }, "downloads": -1, "filename": "hyperglyph-0.9-20140421.tar.gz", "has_sig": false, "md5_digest": "9f5561c8d42e23bee587efbc7fa932d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14253, "upload_time": "2014-04-21T12:34:58", "url": "https://files.pythonhosted.org/packages/2c/96/9389531cf1a4f505b0e3888b780a0d8ed05c5e25929c355b012b487a8b94/hyperglyph-0.9-20140421.tar.gz" } ] }