{ "info": { "author": "Piotr Roszatycki", "author_email": "piotr.roszatycki@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Environment :: Web Environment", "License :: OSI Approved :: Artistic License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Internet :: WWW/HTTP :: WSGI :: Server", "Topic :: Software Development :: Testing", "Topic :: Text Processing :: Markup :: HTML" ], "description": ".. image:: https://img.shields.io/pypi/v/Pyjoyment.png\r\n :target: https://pypi.python.org/pypi/Pyjoyment\r\n.. image:: https://travis-ci.org/dex4er/Pyjoyment.png?branch=master\r\n :target: https://travis-ci.org/dex4er/Pyjoyment\r\n.. image:: https://readthedocs.org/projects/pyjoyment/badge/?version=latest\r\n :target: http://pyjoyment.readthedocs.org/en/latest/\r\n\r\nPyjoyment\r\n=========\r\n\r\nAn asynchronous, event driver web framework for the Python programming language.\r\n\r\nPyjoyment provides own reactor which handles I/O and timer events in its own\r\nmain event loop but it supports other loops, ie. libev, asyncio.\r\n\r\nPyjoyment uses intensively own event emmiter which should be familiar for\r\nNode.JS programmers.\r\n\r\nIt provides tool set for parsing and creating HTTP messages and HTML documents.\r\nIt also supports WSGI interface.\r\n\r\nPyjoyment is compatible with Python 2.7+, Python 3.3+ and PyPy 2.4+. It doesn't\r\nrequire any external libraries or compilers.\r\n\r\nSee http://www.pyjoyment.net/\r\n\r\nPyjoyment is based on `Mojolicious `_: a next generation\r\nweb framework for the Perl programming language.\r\n\r\nStatus\r\n======\r\n\r\nEarly developement stage. Implemented already:\r\n\r\n* WSGI adapter\r\n* HTTP standalone async-io server\r\n* WebSockets client and server\r\n* HTTP user agent with TLS/SSL support\r\n* JSON pointers implementation based on ``RFC6901``\r\n* Embedded files loader\r\n* HTML/XML DOM parser with CSS selectors\r\n* URL parser with container classes for URL, path and querystring\r\n* Non-blocking TCP client and server\r\n* Simple logging object\r\n* Synchronizer and sequentializer of multiple events\r\n* Main event loop which handle IO and timer events\r\n* Event emitter with subscriptions\r\n* Low level event reactor based on ``select(2)`` and ``poll(2)``\r\n* Convenient functions and classed for unicode and byte strings and lists\r\n* Lazy properties for objects\r\n* Test units with API based on Perl's ``Test::More`` and `TAP `_ protocol\r\n\r\nExamples\r\n========\r\n\r\nWeb scraping\r\n------------\r\n\r\n.. code-block:: python\r\n\r\n import Pyjo.UserAgent\r\n from Pyjo.String.Unicode import u\r\n\r\n tx = Pyjo.UserAgent.new().get('https://html.spec.whatwg.org')\r\n for n in tx.res.dom('#named-character-references-table tbody > tr').each():\r\n u(n.at('td > code').text + ' ' + n.children('td')[1].text).trim().say()\r\n\r\n\r\n\r\nURL manipulation\r\n----------------\r\n\r\n.. code-block:: python\r\n\r\n import Pyjo.URL\r\n from Pyjo.String.Unicode import u\r\n\r\n # 'ssh+git://git@github.com/dex4er/Pyjoyment.git'\r\n url = Pyjo.URL.new('https://github.com/dex4er/Pyjoyment')\r\n print(url.set(scheme='ssh+git', userinfo='git', path=u(url.path) + '.git'))\r\n\r\n # 'http://metacpan.org/search?q=Mojo::URL&size=20'\r\n print(Pyjo.URL.new('http://metacpan.org/search')\r\n .set(query={'q': 'Mojo::URL', 'size': 20}))\r\n\r\n\r\nNon-blocking TCP client/server\r\n------------------------------\r\n\r\n.. code-block:: python\r\n\r\n import Pyjo.IOLoop\r\n\r\n\r\n # Listen on port 3000\r\n @Pyjo.IOLoop.server(port=3000)\r\n def server(loop, stream, cid):\r\n\r\n @stream.on\r\n def read(stream, chunk):\r\n # Process input chunk\r\n print(\"Server: {0}\".format(chunk.decode('utf-8')))\r\n\r\n # Write response\r\n stream.write(b\"HTTP/1.1 200 OK\\x0d\\x0a\\x0d\\x0a\")\r\n\r\n # Disconnect client\r\n stream.close_gracefully()\r\n\r\n\r\n # Connect to port 3000\r\n @Pyjo.IOLoop.client(port=3000)\r\n def client(loop, err, stream):\r\n\r\n @stream.on\r\n def read(stream, chunk):\r\n # Process input\r\n print(\"Client: {0}\".format(chunk.decode('utf-8')))\r\n\r\n # Write request\r\n stream.write(b\"GET / HTTP/1.1\\x0d\\x0a\\x0d\\x0a\")\r\n\r\n\r\n # Add a timer\r\n @Pyjo.IOLoop.timer(3)\r\n def timeouter(loop):\r\n print(\"Timeout\")\r\n # Shutdown server\r\n loop.remove(server)\r\n\r\n\r\n # Start event loop\r\n Pyjo.IOLoop.start()\r\n\r\n\r\nStandalone HTTP server serving embedded template file\r\n------------------------------------------------------\r\n\r\n.. code-block:: python\r\n\r\n # -*- coding: utf-8 -*-\r\n\r\n import Pyjo.Server.Daemon\r\n import Pyjo.URL\r\n\r\n from Pyjo.Loader import embedded_file\r\n from Pyjo.Util import b, u\r\n\r\n import sys\r\n\r\n\r\n opts = dict([['address', '0.0.0.0'], ['port', 3000]] + list(map(lambda a: a.split('='), sys.argv[1:])))\r\n listen = str(Pyjo.URL.new(scheme='http', host=opts['address'], port=opts['port']))\r\n\r\n daemon = Pyjo.Server.Daemon.new(listen=[listen])\r\n daemon.unsubscribe('request')\r\n\r\n\r\n # Embedded template file\r\n DATA = u(r'''\r\n @@ index.html.tpl\r\n \r\n \r\n \r\n \r\n Pyjoyment\r\n \r\n \r\n

\u2665 Pyjoyment \u2665

\r\n

This page is served by Pyjoyment framework.

\r\n

{method} request for {path}

\r\n \r\n \r\n ''')\r\n\r\n\r\n @daemon.on\r\n def request(daemon, tx):\r\n # Request\r\n method = tx.req.method\r\n path = tx.req.url.path\r\n\r\n # Template\r\n template = embedded_file(sys.modules[__name__], 'index.html.tpl')\r\n\r\n # Response\r\n tx.res.code = 200\r\n tx.res.headers.content_type = 'text/html; charset=utf-8'\r\n tx.res.body = b(template.format(**locals()))\r\n\r\n # Resume transaction\r\n tx.resume()\r\n\r\n\r\n daemon.run()", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/dex4er/Pyjoyment/archive/master.zip", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/dex4er/Pyjoyment", "keywords": "async framework html http mojo mojolicious pyjo pyjoyment tap test websocket wsgi", "license": "Artistic", "maintainer": "", "maintainer_email": "", "name": "Pyjoyment", "package_url": "https://pypi.org/project/Pyjoyment/", "platform": "", "project_url": "https://pypi.org/project/Pyjoyment/", "project_urls": { "Download": "https://github.com/dex4er/Pyjoyment/archive/master.zip", "Homepage": "http://github.com/dex4er/Pyjoyment" }, "release_url": "https://pypi.org/project/Pyjoyment/0.0.1/", "requires_dist": null, "requires_python": null, "summary": "An asynchronous, event driver web framework for the Python programming language.", "version": "0.0.1" }, "last_serial": 2029765, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "31b9372add03cf9c52a31bc74d22027c", "sha256": "2cb11f7d77661348a00d8834456e68a7bcf4c5470c155a697e88096fc04915d5" }, "downloads": -1, "filename": "Pyjoyment-0.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "31b9372add03cf9c52a31bc74d22027c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 163622, "upload_time": "2016-03-27T12:18:32", "url": "https://files.pythonhosted.org/packages/d2/87/70ea3ef912637ae2370bfa58a4a6692d9e3c91258f862aea808546bce16b/Pyjoyment-0.0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "abd90f78eecc6c1d9e6e093df3c503bb", "sha256": "95439ec44979d839f46a80a54b6fe15899ad1c435166405a1aac0b12bdcee7f0" }, "downloads": -1, "filename": "Pyjoyment-0.0.1.tar.gz", "has_sig": false, "md5_digest": "abd90f78eecc6c1d9e6e093df3c503bb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 127736, "upload_time": "2016-03-27T12:18:42", "url": "https://files.pythonhosted.org/packages/2d/d6/1ab9fca946665ed9482c52a80def86f72a330586e20433fc5114848f7515/Pyjoyment-0.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "31b9372add03cf9c52a31bc74d22027c", "sha256": "2cb11f7d77661348a00d8834456e68a7bcf4c5470c155a697e88096fc04915d5" }, "downloads": -1, "filename": "Pyjoyment-0.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "31b9372add03cf9c52a31bc74d22027c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 163622, "upload_time": "2016-03-27T12:18:32", "url": "https://files.pythonhosted.org/packages/d2/87/70ea3ef912637ae2370bfa58a4a6692d9e3c91258f862aea808546bce16b/Pyjoyment-0.0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "abd90f78eecc6c1d9e6e093df3c503bb", "sha256": "95439ec44979d839f46a80a54b6fe15899ad1c435166405a1aac0b12bdcee7f0" }, "downloads": -1, "filename": "Pyjoyment-0.0.1.tar.gz", "has_sig": false, "md5_digest": "abd90f78eecc6c1d9e6e093df3c503bb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 127736, "upload_time": "2016-03-27T12:18:42", "url": "https://files.pythonhosted.org/packages/2d/d6/1ab9fca946665ed9482c52a80def86f72a330586e20433fc5114848f7515/Pyjoyment-0.0.1.tar.gz" } ] }