{ "info": { "author": "CodeLV", "author_email": "frmdstryr@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "# Enaml Web #\n\n[](https://travis-ci.org/codelv/enaml-web)\n[](https://codecov.io/gh/codelv/enaml-web)\n\n\nA web component toolkit for [enaml](https://github.com/nucleic/enaml) that\nlet's you build websites in python declaratively.\n\nYou can use enaml-web to build \"interactive\" websites using python, enaml, and a few lines of _simple_ javascript (see the simple pandas [dataframe viewer](https://github.com/codelv/enaml-web/tree/master/examples/dataframe_viewer) example). The view state (dom) is stored on the server as an enaml view and interaction works by syncing changes between\nbetween the client(s) and server using websockets (or polling).\n\nTo demonstrate, the following interaction is all handled with enaml-web\n\n\n\n### Examples\n\nSee the examples folder\n\n- [www.codelv.com](https://www.codelv.com/) - Built entirely using enaml-web\n- [SMD Component search](https://github.com/frmdstryr/smd-search) - View and search a pandas dataframe\n\n\n### Short intro\n\nTo use enaml web, you simply replace html tags with the enaml component\n(the capitalized tag name). For example:\n\n```python\nfrom web.components.api import *\n\nenamldef Index(Html):\n Head:\n Title:\n text = \"Hello world\"\n Body:\n H1:\n text = \"Hello world\"\n\n```\n\nCalling `render()` on an instance of this enaml view then generates the html\nfrom the view. This is shown in the simple case of a static site generator:\n\n```python\n\nimport enaml\nfrom web.core.app import WebApplication\n\n# Create an enaml Application that supports web components\napp = WebApplication()\n\n# Import Index from index.enaml\nwith enaml.imports():\n from index import Index\n\n# Render the Index.enaml to index.html\nview = Index()\nwith open('index.html', 'w') as f:\n f.write(view.render())\n\n```\n\nYou can also use it in a request handler with your favorite web framework. For example with tornado\nweb you can do something like this:\n\n\n```python\nimport enaml\nimport tornado.web\nimport tornado.ioloop\nfrom web.core.app import WebApplication\n\n# Import Index from index.enaml\nwith enaml.imports():\n from index import Index\n\nclass IndexHandler(tornado.web.RequestHandler):\n view = Index()\n def get(self, request):\n return self.view.render(request=request)\n\nclass Application(tornado.web.Application):\n def __init__(self):\n super(Application, self).__init__([\n (r'/',IndexHandler)\n ],\n )\n\nif __name__ == \"__main__\":\n web_app = WebApplication()\n app = Application()\n app.listen(8888)\n tornado.ioloop.IOLoop.current().start()\n\n```\n\n### So what's the advantage over plain html?\n\nIt's as simple as html but it's python so you can, loop over lists, render conditionally,\nformat variables, etc...\n\nAlso, it's not just formatting a template, the server maintains the page state so\nyou can interact with the page after it's rendered. This is something that no other\npython template frameworks can do (to my knowledge).\n\n### How it works\n\nIt generates a dom of [lxml](http://lxml.de/) elements.\n\n##### Inherently secure\n\nSince an lxml dom is generated it means that your code is inherently secure from\ninjection as it automatically escapes all attributes. Also a closing tag cannot\nbe accidentally missed.\n\nThe atom framework provides additional security by enforcing runtime type\nchecking and optional validation.\n\n\n##### Extendable via templates and blocks\n\nLike other template engines, enaml-web provides a \"Block\" node that allows\nyou to define a part of a template that can be overridden or extended.\n\nEnaml also provides pattern nodes for handling conditional statements, loops,\ndynamic nodes based on lists or models, and nodes generated from more complex\ntemplates (ex automatic form generation).\n\n\n##### No template tags needed\n\nMany template engines require the use of \"template tags\" wrapped in `{% %}`\nor similar to allow the use of python code to transform variables.\n\nSince enaml _is_ python, you can use any python code directly in\nyour enaml components and templates. You don't need any template tags.\n\n\n##### Testing is easier\n\nSince the internal representation is lxml nodes, you can use lxml's xpath\nqueries on the dom for e2e view testing. No need to use headless browsers and\nthat complicated stuff (unless you're using a lot of js).\n\n\n##### Component based\n\nSince enaml views are like python classes, you can \"subclass\" and extend any\ncomponent and extend it's functionality. This enables you to quickly build\nreusable components.\n\nI'm working on components for several common css frameworks so they can simply\nbe installed and used.\n\n1. [materialize-ui](https://github.com/frmdstryr/materialize)\n2. semantic-ui (coming soon)\n3. bootstrap (coming soon)\n\n\n### Data binding\n\nBecause enaml-web is generating a dom, you can use websockets and some js\nto manipulate the dom to do data binding between the client to server.\n\nThe dom can be shared per user or per session making it easy to create\ncollaborative pages or they can be unique to each page.\n\n\n\nEach node as a unique identifier and can be modified using change events. An\nexample of this is in the examples folder.\n\nYou can also have the client trigger events on the server and have the server\ntrigger JS events on the client.\n\nTo use:\n1. Include enaml.js in your page\n2. Observe the `modified` event of an Html node and pass these changes to the\nclient via websockets.\n3. Enamljs will send events back to the server, update the dom accordingly.\n\n\n#### Data models\n\nForms can automatically be generated and populated using enaml's DynamicTemplate\nnodes. An implementation of the `AutoForm` using the [materalize css](https://github.com/frmdstryr/materialize)\nframework is available on my personal repo. With this, we can take a model like:\n\n```python\n\nfrom atom.api import Atom, Unicode, Bool, Enum\n\nclass Message(Atom):\n name = Unicode()\n email = Unicode()\n message = Unicode()\n options = Enum(\"Email\",\"Phone\",\"Text\")\n sign_up = Bool(True)\n\n\n```\n\nThen use the `AutoForm` node and pass in either a new or populated instance of\nthe model to render the form.\n\n```python\n\nfrom templates import Base\nfrom web.components.api import *\nfrom web.core.api import Block\n\n\nenamldef AddMessageView(Base): page:\n attr message\n Block:\n block = page.content\n AutoForm:\n model << message\n\n```\n\n\n\n\n### Database ORM with Atom\n\nFor working with a database using atom see [atom-db](https://github.com/codelv/atom-db)\n\n\n#### Raw, Markdown, and Code nodes\n\nThe`Raw` node parses text into dom nodes (using lxml's html parser). Similarly\n`Markdown` and `Code` nodes parse markdown and highlight code respectively.\n\nFor example, you can use wagtal's richtext tag to render to a dom via:\n\n```python\n\nfrom web.components.api import *\nfrom web.core.api import *\nfrom wagtail.core.templatetags.wagtailcore_tags import richtext\nfrom myapp.views.base import Page\n\nenamldef BlogPage(Page):\n body.cls = 'template-blogpage'\n Block:\n block = parent.content\n Raw:\n source << richtext(page.body)\n\n```\n\nThis let's you use web wysiwyg editors to insert content into the dom.\n\n\n#### Block node\n\nYou can define a base template, then overwrite parts using the `Block` node.\n\nIn one file put:\n\n```python\n\nfrom web.components.api import *\nfrom web.core.api import Block\n\nenamldef Base(Html):\n attr user\n attr site\n attr request\n alias content\n Head:\n Title:\n text << site.title\n Body:\n Header:\n text = \"Header\"\n Block: content:\n pass\n Footer:\n text = \"Footer\"\n\n```\n\nThen you can import that view and _extend_ the template and override the\nblock's content.\n\n```python\nfrom templates import Base\nfrom web.components.api import *\nfrom web.core.api import Block\n\nenamldef Page(Base): page:\n Block:\n block = page.content\n P:\n text = \"Content inserted between Header and Footer\"\n\n```\n\nBlocks let you either replace, append, or prepend to the content.\n\n#### Custom Components\n\nWith enaml you can easily create reusable components and share them through\nthe views as you would any python class using regular python imports.\n\nFor instance, to create a\n[materalize breadcrumbs component](http://materializecss.com/breadcrumbs.html)\nthat automatically follows the current request path, simply include the required\ncss/scripts in your base template, define the component as shown below:\n\n```python\n\nfrom web.components.api import *\nfrom web.core.api import Looper\n\nenamldef Breadcrumbs(Nav): nav:\n attr path # ex. pass in a tornado request.path\n attr color = \"\"\n attr breadcrumbs << path[1:-1].split(\"/\")\n tag = 'nav'\n Div:\n cls = 'nav-wrapper {}'.format(nav.color)\n Div:\n cls = 'container'\n Div:\n cls = 'col s12'\n Looper:\n iterable << breadcrumbs\n A:\n href = \"/{}/\".format(\"/\".join(breadcrumbs[:loop_index+1]))\n cls = \"breadcrumb\"\n text = loop_item.title()\n```\n\nthen use it it as follows\n\n```python\n\n# in your template add\nBreadcrumbs:\n path << request.path\n\n```\n\n\n### Gotachas\n\n##### Text and tail nodes\n\nLxml uses text and tail properties to set text before and after child nodes, which can be confusing.\n\nFor instance in html you can do\n\n```html\n\n
This is a sentence click here then keep going
\n\n```\n\nTo make this with enaml you need to do this:\n\n```python\n\nP:\n text = \"This is a sentence\"\n A:\n href = \"#\"\n text = \"click here\"\n tail = \"then keep going\"\n\n```\n\nNotice how `tail` is set on the `A` NOT the `P`.\nSee [lxml etree documentation](http://lxml.de/tutorial.html#elements-contain-text) for more details.\n\n\n##### Tag attribute\n\nIn the current implementation the xml tag used is the lowercase of the class name.\nWhen you subclass a component you must explicity set the tag attribute to the\ndesired tag name. For example:\n\n```python\n\nenamldef Icon(I):\n tag = 'i' # Force tag to be 'i' instead of 'icon' since 'icon' is not a valid html element\n cls = 'material-icons'\n\n```\n\n\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/codelv/enaml-web", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "enaml-web", "package_url": "https://pypi.org/project/enaml-web/", "platform": "", "project_url": "https://pypi.org/project/enaml-web/", "project_urls": { "Homepage": "https://github.com/codelv/enaml-web" }, "release_url": "https://pypi.org/project/enaml-web/0.8.8/", "requires_dist": [ "enaml (>=0.9.8)", "lxml (>=3.4.0)" ], "requires_python": "", "summary": "Web component toolkit for Enaml", "version": "0.8.8" }, "last_serial": 5560853, "releases": { "0.3.1": [ { "comment_text": "", "digests": { "md5": "b082e19b076b9b64917fcc83c62dd2c9", "sha256": "1a5a9546168e2408790d5fdee9c1d04a58d3b28bc4ac1f1db45c44c9f6fcc835" }, "downloads": -1, "filename": "enaml_web-0.3.1-py2-none-any.whl", "has_sig": false, "md5_digest": "b082e19b076b9b64917fcc83c62dd2c9", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 25966, "upload_time": "2018-03-29T18:35:00", "url": "https://files.pythonhosted.org/packages/f8/2a/8dfbc5b4b3cb5a168ebd72a92eb304757cab193149ec44a21f77bc45347a/enaml_web-0.3.1-py2-none-any.whl" } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "a25151b1544200899820991873509395", "sha256": "68c852603fbca03c3499202e3910f42d66aa2c3adcd227f4914d8b03b2a132f5" }, "downloads": -1, "filename": "enaml_web-0.3.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a25151b1544200899820991873509395", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25951, "upload_time": "2018-05-16T16:20:21", "url": "https://files.pythonhosted.org/packages/6a/58/06d10129a7a21d3b16eda4056a3edb57c19185a057642231ac9abdd1b794/enaml_web-0.3.2-py2.py3-none-any.whl" } ], "0.3.3": [ { "comment_text": "", "digests": { "md5": "c54ff33652388a2c892112cdf239ab8b", "sha256": "ab3892483345ab6b3ea4a59055e276c860fcad78685464b48f6070efcd2c860a" }, "downloads": -1, "filename": "enaml_web-0.3.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c54ff33652388a2c892112cdf239ab8b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 26136, "upload_time": "2018-05-16T16:35:23", "url": "https://files.pythonhosted.org/packages/a9/58/44318c35696eb25305f74a7aef880ff150aab43280a5448a38f87526ce11/enaml_web-0.3.3-py2.py3-none-any.whl" } ], "0.3.4": [ { "comment_text": "", "digests": { "md5": "bec43932c773f1d23673064ff15961bd", "sha256": "3654ca5d36ef27c6daa72a24e44b7dba523c24c9b2b99ca20e36e4349a29e01a" }, "downloads": -1, "filename": "enaml_web-0.3.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "bec43932c773f1d23673064ff15961bd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7", "size": 26324, "upload_time": "2018-05-16T16:45:19", "url": "https://files.pythonhosted.org/packages/38/b7/65b8e2c324f0a8590d1bd3d7b908d51e74afc48b2480bcfed7670073d848/enaml_web-0.3.4-py2.py3-none-any.whl" } ], "0.3.5": [ { "comment_text": "", "digests": { "md5": "ab298d30a0b210985992142e3d514503", "sha256": "89c43c119cb98bd1c9f52ad8a050692c586c2400d8e6a99459c30d1c5b452bc3" }, "downloads": -1, "filename": "enaml_web-0.3.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ab298d30a0b210985992142e3d514503", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 20382, "upload_time": "2018-05-25T18:30:57", "url": "https://files.pythonhosted.org/packages/84/35/b1ada34f50ad8ff760f4a754f4782980a4a004f0a67486dfa215ffe514bf/enaml_web-0.3.5-py2.py3-none-any.whl" } ], "0.3.6": [ { "comment_text": "", "digests": { "md5": "0883e28dd117ccf1ec879e60f34dd3ab", "sha256": "7097afe4c53522fb55443e4eb2d1ca8ce7838f1dae90e573d89340bc6c99f15d" }, "downloads": -1, "filename": "enaml_web-0.3.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0883e28dd117ccf1ec879e60f34dd3ab", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28441, "upload_time": "2018-05-30T01:31:35", "url": "https://files.pythonhosted.org/packages/58/fe/ab3b8e4ac17999118ca0b41d1973b8004d8a08394876706bc2f64967a046/enaml_web-0.3.6-py2.py3-none-any.whl" } ], "0.3.7": [ { "comment_text": "", "digests": { "md5": "c12dcf4ed5e99e727dbd910e34ccbb28", "sha256": "40335db55499074e99d246f300dbcd8decc6925ff203035b7bc53914aa430dcf" }, "downloads": -1, "filename": "enaml_web-0.3.7-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c12dcf4ed5e99e727dbd910e34ccbb28", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28470, "upload_time": "2018-05-31T19:44:35", "url": "https://files.pythonhosted.org/packages/52/ee/2e1ed8494b14b066fdc0558aa7a00cd6f103f6f8e0cb39f7bc41fd7d315c/enaml_web-0.3.7-py2.py3-none-any.whl" } ], "0.3.8": [ { "comment_text": "", "digests": { "md5": "4ed38ae928187ed7e722b45ed65630a9", "sha256": "162d0355488ba1fd23ba9209a3598b31fef7325257905f19459aa23d62ddd73a" }, "downloads": -1, "filename": "enaml_web-0.3.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4ed38ae928187ed7e722b45ed65630a9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 28499, "upload_time": "2018-06-08T00:03:14", "url": "https://files.pythonhosted.org/packages/93/e0/0d6ee6d93006f532e69ac6e18ee74db46304c48de449c34cbeece580be97/enaml_web-0.3.8-py2.py3-none-any.whl" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "85c527217ad562c58b600689e5963fad", "sha256": "15d24f5f8949d0f7d8e6230d4946b8ab665e44c55bb3f6b058b1498eebb01644" }, "downloads": -1, "filename": "enaml_web-0.4.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "85c527217ad562c58b600689e5963fad", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 42697, "upload_time": "2018-06-27T17:33:30", "url": "https://files.pythonhosted.org/packages/74/20/680b85075ac7c35c511ca6e12c4d8f664c059eeb1450089175a4a937f396/enaml_web-0.4.0-py2.py3-none-any.whl" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "4a9f831a6cbd6102a1c8467badfa2afa", "sha256": "207512107dca934a9e6e33314bbc4fa652b9fabb5597f975761551b3c46e2e77" }, "downloads": -1, "filename": "enaml_web-0.4.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4a9f831a6cbd6102a1c8467badfa2afa", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 37604, "upload_time": "2018-06-27T17:34:58", "url": "https://files.pythonhosted.org/packages/9f/7c/a64185e34eae34966fa76ecd22ab1a4f732efe414254d21bfbd12ffa03bb/enaml_web-0.4.1-py2.py3-none-any.whl" } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "f6d3a3e6b2bb9c3737b227774e134f84", "sha256": "a2310f964b666f4ccade899398db461584beb75ae00352f839b4ed24b1a1221f" }, "downloads": -1, "filename": "enaml_web-0.4.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f6d3a3e6b2bb9c3737b227774e134f84", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 37629, "upload_time": "2018-06-27T18:08:46", "url": "https://files.pythonhosted.org/packages/d0/8d/58a92a7f687b758596b1ac45569034477dcdecc8921c3fd6f83ee9b1f065/enaml_web-0.4.2-py2.py3-none-any.whl" } ], "0.4.4": [ { "comment_text": "", "digests": { "md5": "fb47985a0181975c0aa10168427fa8b6", "sha256": "1ffc9e835345ec3f43695c17805a094de7bf987a63403f5295c704de1807f1d3" }, "downloads": -1, "filename": "enaml_web-0.4.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "fb47985a0181975c0aa10168427fa8b6", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 39308, "upload_time": "2018-07-11T23:03:31", "url": "https://files.pythonhosted.org/packages/04/c5/0c4e4650f16476b5ac1602e8f8cb8666c1dbb273371b15544b12bdff5801/enaml_web-0.4.4-py2.py3-none-any.whl" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "5c4fb1ca71dc14450e63cf55aea83fa0", "sha256": "9ae799b25cbf0cdb257ee74aa5b7ae294004d572c8c842d23eaacbe17f405dd1" }, "downloads": -1, "filename": "enaml_web-0.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "5c4fb1ca71dc14450e63cf55aea83fa0", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 38220, "upload_time": "2018-07-22T14:42:28", "url": "https://files.pythonhosted.org/packages/39/7c/2c17cac442ca31a1f706e48ea738871595e2786b2bdc899a44c869a52fdc/enaml_web-0.5.0-py2.py3-none-any.whl" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "a9c926cc876814426545779ca62fc79a", "sha256": "794f0771ab9f148812c02f1f6cb8959cba309e5b16a28aac735f5dd8cfc2279e" }, "downloads": -1, "filename": "enaml_web-0.5.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a9c926cc876814426545779ca62fc79a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 38348, "upload_time": "2018-08-01T12:38:23", "url": "https://files.pythonhosted.org/packages/9a/ef/d5e6e4f47b71785fd4057a7fb4b932f8d0e35976812aec82bb4cf7142f9c/enaml_web-0.5.1-py2.py3-none-any.whl" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "fed56f5776de73d47d9b797a7eb1dd52", "sha256": "8471f1267fca3f5dd6466ad1ead6aa85203940102218dd009fceaeac983c72f2" }, "downloads": -1, "filename": "enaml_web-0.6.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "fed56f5776de73d47d9b797a7eb1dd52", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45636, "upload_time": "2018-09-01T18:30:24", "url": "https://files.pythonhosted.org/packages/c5/29/57c45dd9dfae76796e2a76861f174a9f7d1be9f479935b72984143f43ea2/enaml_web-0.6.0-py2.py3-none-any.whl" } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "47f7a2ccc14c7ebfdfe3e8a6995ee38d", "sha256": "80089b12fe268da5ad317391887ab038b4b2d6548bab22f23f56725563199921" }, "downloads": -1, "filename": "enaml_web-0.6.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "47f7a2ccc14c7ebfdfe3e8a6995ee38d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45630, "upload_time": "2018-10-08T21:15:25", "url": "https://files.pythonhosted.org/packages/0d/60/16eb3f5d8269369f6ec5930748b84c095812b7bd52466a2789d6c3ffcd67/enaml_web-0.6.1-py2.py3-none-any.whl" } ], "0.6.2": [ { "comment_text": "", "digests": { "md5": "ff561296a55f39f3b17f9c97d8697783", "sha256": "891efa466b1c70e4575aa9a3c206b85c8c3ec5e8fa8d79d6f572b46719d46515" }, "downloads": -1, "filename": "enaml_web-0.6.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ff561296a55f39f3b17f9c97d8697783", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45910, "upload_time": "2018-10-09T17:32:58", "url": "https://files.pythonhosted.org/packages/e5/31/b5c3bdfeff63464e30a87a3ff12dde1e82cc089dd5f9c03270469ced7e22/enaml_web-0.6.2-py2.py3-none-any.whl" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "f074da8ea637917f63592d624cb8632a", "sha256": "85eac62130377087978374061942e417a28f419ddf42d705a59e00796e9ba744" }, "downloads": -1, "filename": "enaml_web-0.7.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f074da8ea637917f63592d624cb8632a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 46237, "upload_time": "2019-01-18T20:28:49", "url": "https://files.pythonhosted.org/packages/97/58/dc15ba8ac494304086e38a5986bdc8f165498083875afe7781c96df32f9e/enaml_web-0.7.0-py2.py3-none-any.whl" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "94b5f2e8b4f2bc8e4decf414b30ad61d", "sha256": "1f2a8c92bef217c267df9803bc6f918f3c2df8ad9f2844940e7fd14a29f2a3ee" }, "downloads": -1, "filename": "enaml_web-0.8.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "94b5f2e8b4f2bc8e4decf414b30ad61d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45662, "upload_time": "2019-02-22T16:54:46", "url": "https://files.pythonhosted.org/packages/f1/64/f54414cf8da2b2ed3f46264503cc36512eeba1778cf599045e09e1db93ab/enaml_web-0.8.0-py2.py3-none-any.whl" } ], "0.8.1": [ { "comment_text": "", "digests": { "md5": "3e7ff582f9bae4e6d50feebdbf1ec169", "sha256": "1b6bbb9ec17010ec0968ba3bba040b927ca7e8ab42796710a629131bcc4d3201" }, "downloads": -1, "filename": "enaml_web-0.8.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "3e7ff582f9bae4e6d50feebdbf1ec169", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45862, "upload_time": "2019-02-27T00:10:58", "url": "https://files.pythonhosted.org/packages/0c/30/68cdb82486896f5921d6129993940d5b4b0b1b6f7c5a57d06d1e7fc9b453/enaml_web-0.8.1-py2.py3-none-any.whl" } ], "0.8.2": [ { "comment_text": "", "digests": { "md5": "0e61b970a6142beabeb4bb1217ffc629", "sha256": "e5d7f99890ef5061b6cbd92c03f98b23cf3258c9f8a99da22163940a13fbef67" }, "downloads": -1, "filename": "enaml_web-0.8.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0e61b970a6142beabeb4bb1217ffc629", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45867, "upload_time": "2019-03-05T20:24:30", "url": "https://files.pythonhosted.org/packages/d6/4f/6be1b8326f8f647aea56d4b8d9f089a6ead9c2c18406c414caba21e4b174/enaml_web-0.8.2-py2.py3-none-any.whl" } ], "0.8.3": [ { "comment_text": "", "digests": { "md5": "db8bec0d7ace2a0f7ccfe4dc6cdcc5d1", "sha256": "9abdd891fb9809ba26afda6124feaca8e864770bdfe3d8e9e3fa04a325689bea" }, "downloads": -1, "filename": "enaml_web-0.8.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "db8bec0d7ace2a0f7ccfe4dc6cdcc5d1", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45875, "upload_time": "2019-03-08T05:05:30", "url": "https://files.pythonhosted.org/packages/6b/69/ba73bd47f3dea3663b7d08a41a9eedadbf687a41c260c3e8d49b17c41752/enaml_web-0.8.3-py2.py3-none-any.whl" } ], "0.8.4": [ { "comment_text": "", "digests": { "md5": "59d0c38a86a0b1e8c845398fdb6f9365", "sha256": "fd861f1d813e36297ba7aff9ca341ccdc64f45d0aba0d0f356b4b1fa8524742d" }, "downloads": -1, "filename": "enaml_web-0.8.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "59d0c38a86a0b1e8c845398fdb6f9365", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45698, "upload_time": "2019-03-22T16:29:21", "url": "https://files.pythonhosted.org/packages/d0/d9/1c19037afed70ecf24de989db0f9f43845d3af535f5d4f0c9fa9d389fc19/enaml_web-0.8.4-py2.py3-none-any.whl" } ], "0.8.5": [ { "comment_text": "", "digests": { "md5": "35fbb719395e1fa017ea86db94adacff", "sha256": "6dff419ac93ad8c0338d861507f101724e09dc4c885799e2a73fb44c8763ac4a" }, "downloads": -1, "filename": "enaml_web-0.8.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "35fbb719395e1fa017ea86db94adacff", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45652, "upload_time": "2019-03-28T16:39:20", "url": "https://files.pythonhosted.org/packages/43/5e/cb86ef7f6bb259bba03dddf65d2fbc7294fb8f580ba1b5a1053ebe10c909/enaml_web-0.8.5-py2.py3-none-any.whl" } ], "0.8.6": [ { "comment_text": "", "digests": { "md5": "a881e5543d8525e446f66b0a9959e392", "sha256": "887fe3b5588baf32174f646c5dd99810497b7ae0c97a0bf74ca0fe91915dac0b" }, "downloads": -1, "filename": "enaml_web-0.8.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a881e5543d8525e446f66b0a9959e392", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45654, "upload_time": "2019-06-11T15:18:32", "url": "https://files.pythonhosted.org/packages/3d/b0/242937c5d2982d8bf98d83f10980a2d9f15b72bebec8d3fd0de3d1c8f98b/enaml_web-0.8.6-py2.py3-none-any.whl" } ], "0.8.7": [ { "comment_text": "", "digests": { "md5": "8ef9405f22b05fcbd94ac4290ac5e5af", "sha256": "ff9d7cf47032be1c2261a991527eec30045599fe4cb014f8253264e1c0c68ea5" }, "downloads": -1, "filename": "enaml_web-0.8.7-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "8ef9405f22b05fcbd94ac4290ac5e5af", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 45756, "upload_time": "2019-06-24T18:48:48", "url": "https://files.pythonhosted.org/packages/04/51/2477857fa4d22bf7b638aea795f3d06f66c1d8ee46d3f6cc09b3f4842038/enaml_web-0.8.7-py2.py3-none-any.whl" } ], "0.8.8": [ { "comment_text": "", "digests": { "md5": "87d55c87bf122fb8b9915f58973f1da8", "sha256": "05e35d70f7294a55d83e03b63b9b449b4c5483d19d79a3c0ab7dddac9198db16" }, "downloads": -1, "filename": "enaml_web-0.8.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "87d55c87bf122fb8b9915f58973f1da8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 46055, "upload_time": "2019-07-20T14:53:39", "url": "https://files.pythonhosted.org/packages/4f/9c/3052851656adb2741deb21296448786c6248a3b1812274d8003d56ceed12/enaml_web-0.8.8-py2.py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "87d55c87bf122fb8b9915f58973f1da8", "sha256": "05e35d70f7294a55d83e03b63b9b449b4c5483d19d79a3c0ab7dddac9198db16" }, "downloads": -1, "filename": "enaml_web-0.8.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "87d55c87bf122fb8b9915f58973f1da8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 46055, "upload_time": "2019-07-20T14:53:39", "url": "https://files.pythonhosted.org/packages/4f/9c/3052851656adb2741deb21296448786c6248a3b1812274d8003d56ceed12/enaml_web-0.8.8-py2.py3-none-any.whl" } ] }