{ "info": { "author": "Igor Mandrichenko", "author_email": "igorvm@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "License :: OSI Approved :: BSD License", "Operating System :: POSIX", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP :: WSGI :: Server", "Topic :: Utilities" ], "description": "WebPie\n======\n\nWebPie (another way of spelling web-py) is a web application development framework for Python based on the WSGI standard.\nWebPie makes it simple to develop thread-safe object-oriented web applications.\n\nHello World in WebPie\n---------------------\n\nHere is the simplest web application you can write:\n\n.. code-block:: python\n\n\t# hello_world.py\n\n\tfrom webpie import WebPieApp, WebPieHandler\t\t\n\n\tclass MyHandler(WebPieHandler): # 1\n\n\t def hello(self, request, relpath): # 2\n\t return \"Hello, World!\\n\" # 3\n\n\tapplication = WebPieApp(MyHandler) # 4\n\n\nWhat did we just write ? Let's go over the code line by line.\n\n1. We created class MyHandler, which will handle HTTP requests. It has to be a subclass of WebPieHandler class.\n2. We defined one web method \"hello\".\n3. It will always return text \"Hello, World!\"\n4. Finally, we created a WSGI application as an instance of WebPieApp class, passing it the MyHandler class as an argument.\n\nNow we can plug our application into any WSGI framework such as uWSGI or Apache httpd, e.g.:\n\n.. code-block:: bash\n\n\tuwsgi --http :8080 --wsgi-file hello_world.py\n\n\nand try it:\n\n.. code-block:: bash\n\n\t$ curl http://localhost:8080/hello\n\tHello world!\n\t$ \n\n\nIf you do not want to use uWSGI or similar framework, you can use WebPie's own HTTP server to publich your application on the web:\n\n.. code-block:: python\n\n\t# hello_world_server.py\n\tfrom webpie import WebPieApp, WebPieHandler, run_server\n\timport time\n\n\tclass MyHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef hello(self, request, relpath):\t\t\t\t\n\t\t\treturn \"Hello, World!\\n\"\t\t\t\t\t\n\n\tapplication = WebPieApp(MyHandler)\n\tapplication.run_server(8080)\n\nURL Structure\n-------------\nNotice that MyHandler class has single method \"hello\" and it maps to the URL path \"hello\". This is general rule in WebPie - methods of handler classes map one to one to the elements of URI path. For example, we can add another method to our server called \"time\":\n\n.. code-block:: python\n\n\tfrom webpie import WebPieApp, WebPieHandler\n\timport time\n\n\tclass MyHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef hello(self, request, relpath):\t\t\t\t\n\t\t\treturn \"Hello, World!\\n\"\t\t\t\t\t\n\n\t\tdef time(self, request, relpath):\n\t\t\treturn time.ctime()+\"\\n\"\n\n\tapplication = WebPieApp(MyHandler)\n\tapplication.run_server(8080)\n\nNow our handler can handle 2 types of requests, it can say hello and it can tell local time:\n\n.. code-block:: bash\n\n\t$ curl http://localhost:8080/hello\n\tHello, World!\n\t$ curl http://localhost:8080/time\n\tSun May 5 06:47:15 2019\n\t$ \n\nNotice that handler methods names automatically become parts of the URL path. There is no need (and no other way) to map WebPie methods to URL.\n\nIf you want to split your handler into different classes to organize your code better, you can have multiple handler classes in your application. For example, we may want to have one handler which focuses on reporting time and the other which says hello:\n\n.. code-block:: python\n\n\t# time_hello_split.py\n\tfrom webpie import WebPieApp, WebPieHandler\n\timport time\n\n\tclass HelloHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef hello(self, request, relpath):\t\t\t\t\n\t\t\treturn \"Hello, World!\\n\"\t\t\t\t\t\n\n\tclass ClockHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef time(self, request, relpath):\t\t\t\n\t\t\treturn time.ctime()+\"\\n\", \"text/plain\"\t\n\n\tclass TopHandler(WebPieHandler):\n\n\t\tdef __init__(self, *params, **kv):\n\t\t\tWebPieHandler.__init__(self, *params, **kv)\n\t\t\tself.greet = HelloHandler(*params, **kv)\n\t\t\tself.clock = ClockHandler(*params, **kv)\n\n\n\tapplication = WebPieApp(TopHandler)\n\tapplication.run_server(8080)\n\n\nWebPie application is given top handler class as an argument. It will create the handler instances one per each\nweb request. Top handler can create child handlers recursively. This recirsive handler structure maps one-to-one to the URL structure. The URI is simply the path from the top handler through its child handlers to the method of one of them:\n\n.. code-block:: bash\n\n\tSun May 5 07:39:11 2019\n\t$ curl http://localhost:8080/greet/hello\n\tHello, World!\n\t$ \n\nFor example, to find the method for URI \"/greet/hello\", WebPie starts with top handler, finds its child handler \"greet\" of class Greeter and then calls its \"hello\" method.\n\nAny handler in the tree can have its own methods. For example:\n\n.. code-block:: python\n\n\t# time_hello_split2.py\n\tfrom webpie import WebPieApp, WebPieHandler\n\timport time\n\n\tclass HelloHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef hello(self, request, relpath):\t\t\t\t\n\t\t\treturn \"Hello, World!\\n\"\t\t\t\t\t\n\n\tclass ClockHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef time(self, request, relpath):\t\t\t\n\t\t\treturn time.ctime()+\"\\n\", \"text/plain\"\t\n\n\tclass TopHandler(WebPieHandler):\n\n\t\tdef __init__(self, *params, **kv):\n\t\t\tWebPieHandler.__init__(self, *params, **kv)\n\t\t\tself.greet = HelloHandler(*params, **kv)\n\t\t\tself.clock = ClockHandler(*params, **kv)\n\n\t\tdef version(self, request, relpath): # non-leaf handler can have a web method\n\t\t return \"1.0.3\"\n\n\tapplication = WebPieApp(TopHandler)\n\tapplication.run_server(8080)\n\n\n.. code-block:: bash\n\n\t$ curl http://localhost:8080/version\n\t1.0.2\n\n\nApplication and Handler\n-----------------------\n\nThe WebPieApp object is created *once* when the web server instance starts and it exists until the server stops whereas WebPieHandler objects are created for each individual HTTP request. When the handler object is created, it receives the pointer to the app object as its constructor argument. Also, for convenience, Handler object's App member always pointt to the app object. This allows the app object to keep some persistent information and let handler objects access it. For example, or clock application can also maintain number of requests it has received:\n\n.. code-block:: python\n\n\t# time_count.py\n\tfrom webpie import WebPieApp, WebPieHandler\n\timport time\n\n\tclass Handler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef time(self, request, relpath):\t\t\n\t\t\tself.App.Counter += 1\n\t\t\treturn time.ctime()+\"\\n\", \"text/plain\"\n\n\t\tdef count(self, request, relpath): \n\t\t\treturn str(self.App.Counter)+\"\\n\"\n\n\n\tclass App(WebPieApp):\n\n\t\tdef __init__(self, handler_class):\n\t\t\tWebPieApp.__init__(self, handler_class)\n\t\t\tself.Counter = 0\n\n\tapplication = App(Handler)\n\tapplication.run_server(8080)\n\n\n.. code-block:: bash\n\n\t$ curl http://localhost:8080/time\n\tSun May 5 08:10:12 2019\n\t$ curl http://localhost:8080/time\n\tSun May 5 08:10:14 2019\n\t$ curl http://localhost:8080/count\n\t2\n\t$ curl http://localhost:8080/time\n\tSun May 5 08:10:17 2019\n\t$ curl http://localhost:8080/count\n\t3\n\n\nOf course the way it is written, our application is not very therad-safe, but we will talk about this later.\n\nWeb Methods in Details\n----------------------\n\nThe web the WebPie server handler method has 2 fixed arguments and optional keyword arguments.\n\nFirst argiment is the request object, which encapsulates all the information about the HTTP request. Currently WebPie uses WebOb library Request and Response classes to handle HTTP requests and responses.\n\nArguments\n~~~~~~~~~\n\nMost generally, web method looks like this:\n\n.. code-block:: python\n\n def method(self, request, relpath, **url_args):\n # ...\n return response\n\n\nWeb method arguments are:\n\nrequest\n.......\n\nrequest is WebOb request object built from the WSGI environment. For convenience, it is also available as the handler's\nRequest member.\n\nrelpath\n.......\n\nSometimes the URI elements are used as web service method arguments and relpath is the tail of the URI remaining unused after the mapping from URI to the method is done. For example, in our clock example, we may want to use URL like this to specify the field of the current time we want to see:\n\n.. code-block::\n\n\thttp://localhost:8080/time/month # month only\n\thttp://localhost:8080/time/minute # minute only\n\thttp://localhost:8080/time # whole day/time\n\nHere is the code which does this:\n\n.. code-block:: python\n\n\tfrom webpie import WebPieApp, WebPieHandler\n\tfrom datetime import datetime\n\n\tclass MyHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef time(self, request, relpath):\t\t\t\n\t\t\tt = datetime.now()\n\t\t\tif not relpath:\n\t\t\t\treturn str(t)+\"\\n\"\n\t\t\telif relpath == \"year\":\n\t\t\t\treturn str(t.year)+\"\\n\"\n\t\t\telif relpath == \"month\":\n\t\t\t\treturn str(t.month)+\"\\n\"\n\t\t\telif relpath == \"day\":\n\t\t\t\treturn str(t.day)+\"\\n\"\n\t\t\telif relpath == \"hour\":\n\t\t\t\treturn str(t.hour)+\"\\n\"\n\t\t\telif relpath == \"minute\":\n\t\t\t\treturn str(t.minute)+\"\\n\"\n\t\t\telif relpath == \"second\":\n\t\t\t\treturn str(t.second)+\"\\n\"\n\n\tapplication = WebPieApp(MyHandler)\n\tapplication.run_server(8080)\n\nurl_args\n........\n\nTypically URL includes so called query parameters, e.g.:\n\n.. code-block::\n\n\thttp://localhost:8080/time?field=minute\n\nWebPie always parses query parameters and passes them to the handler method using keyword arguments. For example, we can write the method which extracts fields from current time like this:\n\n.. code-block:: python\n\n\t# time_args.py\n\tfrom webpie import WebPieApp, WebPieHandler\n\tfrom datetime import datetime\n\n\tclass MyHandler(WebPieHandler):\t\t\t\t\t\t\n\n\t\tdef time(self, request, relpath, field=\"all\"):\t\t\n\t\t\tt = datetime.now()\n\t\t\tif field == \"all\":\n\t\t\t\treturn str(t)+\"\\n\"\n\t\t\telif field == \"year\":\n\t\t\t\treturn str(t.year)+\"\\n\"\n\t\t\telif field == \"month\":\n\t\t\t\treturn str(t.month)+\"\\n\"\n\t\t\telif field == \"day\":\n\t\t\t\treturn str(t.day)+\"\\n\"\n\t\t\telif field == \"hour\":\n\t\t\t\treturn str(t.hour)+\"\\n\"\n\t\t\telif field == \"minute\":\n\t\t\t\treturn str(t.minute)+\"\\n\"\n\t\t\telif field == \"second\":\n\t\t\t\treturn str(t.second)+\"\\n\"\n\n\tWebPieApp(MyHandler).run_server(8080)\n\n\nand then call it like this:\n\n.. code-block:: bash\n\n\t$ curl http://localhost:8080/time\n\t2019-05-05 08:39:49.593855\n\t$ curl \"http://localhost:8080/time?field=month\"\n\t5\n\t$ curl \"http://localhost:8080/time?field=year\"\n\t2019\n\nReturn Value\n~~~~~~~~~~~~\nThe output of a web method is a Response object. Conveniently, there is a number of ways to return something from the web method. Ultimately, all of them are used to produce and return the Response object. Here is a list of possibile returns from the web oject and how the framework\nconverts the output to the Response object:\n\n====================================== =================================== ==================================================================\nreturn example equivalent Response object\n====================================== =================================== ==================================================================\nResponse object Response(\"OK\") same - Response(\"OK\")\ntext \"hello world\" Response(\"hello world\")\ntext, content type \"OK\", \"text/plain\" Response(\"OK\", content_type=\"text/plain\")\ntext, status \"Error\", 500 Response(\"Error\", status_code=500)\ntext, status, content type \"Error\", 500, \"text/plain\" Response(\"Error\", status_code=500, content_type=\"text/plain\")\ntext, headers \"OK\", {\"Content-Type\":\"text/plain\"} Response(\"OK\", headers={\"Content-Type\":\"text/plain\"})\nlist [\"Hello\",\"world\"] Response(app_iter=[\"Hello\",\"world\"])\niterable (x for x in [\"hi\",\"there\"]) Response(app_iter=(x for x in [\"hi\",\"there\"]))\niterable, content_type\niterable, status, content_type\niterable, status, headers\n====================================== =================================== ==================================================================\n\nStatic Content\n--------------\n\nSometimes the application needs to serve static content like HTML documents, CSS stylesheets, JavaScript code.\nWebPie App can be configured to serve static file from certain directory in the file system.\n\n\n.. code-block:: python\n\n class MyHandler(WebPieHandler):\n #...\n\n class MyApp(WebPieApp):\n #...\n\n application = MyApp(MyHandler, \n static_enabled = True,\n static_path = \"/static\", \n static_location = \"./scripts\")\n\n application.run_server(8002)\n\n\nIf you run such an application, a request for URL like \"http://..../static/code.js\" will result in\ndelivery of file local file ./scripts/code.js. static_location can be either relative to the working\ndirectory where the application runs or an absolute path.\n\nBecause serving files from local file system is a potential security vulnerability, this\nfunctionality must be explicitly enabled with static_enabled=True. static_path and static_locations\nhave defaults:\n\n.. code-block:: python\n\n static_path = \"/static\"\n static_location = \"./static\"\n\nThreaded Applications\n---------------------\nWebPie provides several mechanisms to build thread safe applications. When working in multithreaded environment, WebPie Handler\nobjects are concurrently created in their own threads, one for each request, whereas WebApp object is created only once and it\nis shared by all the threads handling the requests. This feature makes it possible to use the App object for inter-handler\nsynchronization. The App object has its own lock object and threads can use it in 2 different ways:\n\natomic decorator\n~~~~~~~~~~~~~~~~\nDecorating a web method with \"atomic\" decorator makes the web method atomic in the sense that if a handler thread enters such\na method, any other handler thread of the same application will block before entering any atomic method until the first thread returns from the method.\n\nFor example:\n\n.. code-block:: python\n\n from webpie import WebPieApp, WebPieHandler, atomic\n\n class MyApp(WebPieApp):\n\n def __init__(self, root_class):\n WebPieApp.__init__(self, root_class)\n self.Memory = {}\n\n class Handler(WebPieHandler):\n\n @atomic\n def set(self, req, relpath, name=None, value=None, **args):\n self.App.Memory[name]=value\n return \"OK\\n\"\n\n @atomic\n def get(self, req, relpath, name=None, **args):\n return self.App.Memory.get(name, \"(undefined)\")+\"\\n\"\n\n application = MyApp(Handler)\n application.run_server(8002)\n\nYou can also decorate methods of the App. For example:\n\n.. code-block:: python\n\n\tfrom webpie import WebPieApp, WebPieHandler, atomic\n\n\tclass MyApp(WebPieApp):\n\n\t RecordSize = 10\n\n\t def __init__(self, root_class):\n\t WebPieApp.__init__(self, root_class)\n\t self.Record = []\n\n\t @atomic\n\t def add(self, value):\n\t if value in self.Record:\n\t self.Record.remove(value)\n\t self.Record.insert(0, value)\n\t if len(self.Record) > self.RecordSize:\n\t self.Record = self.Record[:self.RecordSize]\n\n\t @atomic\n\t def find(self, value):\n\t try: i = self.Record.index(value)\n\t except ValueError:\n\t return \"not found\"\n\t self.Record.pop(i)\n\t self.Record.insert(0, value)\n\t return str(i)\n\n\tclass Handler(WebPieHandler):\n\n\t def add(self, req, relpath, **args):\n\t return self.App.add(relpath)\n\n\t def find(self, req, relpath, **args):\n\t return self.App.find(relpath)\n\n\tapplication = MyApp(Handler)\n\tapplication.run_server(8002)\n\n\nApp object as a context manager\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nAnother to implement a critical section is to use the App object as the context manager:\n\n\n.. code-block:: python\n\n from webpie import WebPieApp, WebPieHandler\n\n class MyApp(WebPieApp):\n\n def __init__(self, root_class):\n WebPieApp.__init__(self, root_class)\n self.Memory = {}\n\n class Handler(WebPieHandler):\n\n def set(self, req, relpath, name=None, value=None, **args):\n with self.App:\n self.App.Memory[name]=value\n return \"OK\\n\"\n\n def get(self, req, relpath, name=None, **args):\n with self.App:\n return self.App.Memory.get(name, \"(undefined)\") + \"\\n\"\n\n application = MyApp(Handler)\n application.run_server(8002)\n\n\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/imandr/webpie", "keywords": "web service,wsgi,web application", "license": "BSD 3-clause", "maintainer": "", "maintainer_email": "", "name": "webpie", "package_url": "https://pypi.org/project/webpie/", "platform": "", "project_url": "https://pypi.org/project/webpie/", "project_urls": { "Homepage": "https://github.com/imandr/webpie" }, "release_url": "https://pypi.org/project/webpie/4.5.2/", "requires_dist": [ "pythreader" ], "requires_python": "", "summary": "A set of useful tools built on top of standard Python threading module", "version": "4.5.2" }, "last_serial": 5932652, "releases": { "2.0": [ { "comment_text": "", "digests": { "md5": "d0b5cb00f42a105b843ef7816a507f76", "sha256": "1027138d58bc57dd2663d0b0d20691258986a6c7c3d911773c23da10def3ba2b" }, "downloads": -1, "filename": "webpie-2.0-py2.7.egg", "has_sig": false, "md5_digest": "d0b5cb00f42a105b843ef7816a507f76", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 309907, "upload_time": "2019-01-06T02:59:34", "url": "https://files.pythonhosted.org/packages/11/ce/54a7b991d77e5c93ae9df21971ee088f4aa9e2e5baface859cfdf2240842/webpie-2.0-py2.7.egg" } ], "3.1": [ { "comment_text": "", "digests": { "md5": "aa422ae297b65386163aeae56bb92235", "sha256": "62c064ecc1061d1e4b996d50e1369b69c9a534fb4526f9f161f9ad754c873891" }, "downloads": -1, "filename": "webpie-3.1-py2-none-any.whl", "has_sig": false, "md5_digest": "aa422ae297b65386163aeae56bb92235", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 132695, "upload_time": "2019-01-06T02:59:31", "url": "https://files.pythonhosted.org/packages/1b/1e/67190d4184afcdca012e8e93f368e9ffd7a759cdaeb98e85535c7a6445b8/webpie-3.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c8332ff0e0b308405744cf3c10e5762c", "sha256": "72d9052fa7a363ca1916c74696f63954f999b2d7062c806e85755f3d7ef3bcaf" }, "downloads": -1, "filename": "webpie-3.1.tar.gz", "has_sig": false, "md5_digest": "c8332ff0e0b308405744cf3c10e5762c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 112869, "upload_time": "2019-01-06T02:59:35", "url": "https://files.pythonhosted.org/packages/7d/12/33ad82514dadc2a850edf61f3c0c6bee6df61c773ca7098567e21e77c2ed/webpie-3.1.tar.gz" } ], "3.1.1": [ { "comment_text": "", "digests": { "md5": "9389b025680a9c8d4c8780487baf73c1", "sha256": "765a9f8e57dd140043fb9680b275159cec1a7ddbc18763a9deee2c23020dddb0" }, "downloads": -1, "filename": "webpie-3.1.1-py2-none-any.whl", "has_sig": false, "md5_digest": "9389b025680a9c8d4c8780487baf73c1", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 132740, "upload_time": "2019-01-06T03:12:38", "url": "https://files.pythonhosted.org/packages/95/ea/7e1b43ebebc63d2d705dd600d3e572e84c069214a01ca814eef2b7998f01/webpie-3.1.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b4e55fbab5ff3b564244a58624c5b2b0", "sha256": "059cc2d152b5dc787f055648f2fd675a777f37725c2f12eb0ee302e2b1240f4b" }, "downloads": -1, "filename": "webpie-3.1.1.tar.gz", "has_sig": false, "md5_digest": "b4e55fbab5ff3b564244a58624c5b2b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 112896, "upload_time": "2019-01-06T03:12:39", "url": "https://files.pythonhosted.org/packages/7f/a2/fe2ac2b45f3a83613b77e6d9a89c005e2469580720c5f7fca3a8004a7806/webpie-3.1.1.tar.gz" } ], "4.0.1": [ { "comment_text": "", "digests": { "md5": "fcba6a1562550e6aa34845d7053c3ef8", "sha256": "ccc0dad82baaf4e1b8c673fde7b0eec8a7ef72408ace16df6fdd62232f32bbff" }, "downloads": -1, "filename": "webpie-4.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "fcba6a1562550e6aa34845d7053c3ef8", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 132665, "upload_time": "2019-05-07T12:14:20", "url": "https://files.pythonhosted.org/packages/bd/2a/199fa3fdb0c57851ebfd921bbd19a6055f9a0679037be07e0730d5a2baca/webpie-4.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "254b4c16063b7cf88e703b86f746d3ea", "sha256": "2737b1a1d26adf376fc87a386e933476eb445303868572cc2feb5aca2c9598ae" }, "downloads": -1, "filename": "webpie-4.0.1.tar.gz", "has_sig": false, "md5_digest": "254b4c16063b7cf88e703b86f746d3ea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 121841, "upload_time": "2019-05-07T12:14:22", "url": "https://files.pythonhosted.org/packages/d0/f7/ad60eb2046e85657997613ddb51d4d011c2d7abeb27a0313c31772395791/webpie-4.0.1.tar.gz" } ], "4.0.2": [ { "comment_text": "", "digests": { "md5": "b11cc2439f91a2f2694451118e7423ff", "sha256": "3222d20e85f77a006ee3c6f430403439b74e01ce234eff7123b3eb55a7181616" }, "downloads": -1, "filename": "webpie-4.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "b11cc2439f91a2f2694451118e7423ff", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 133288, "upload_time": "2019-05-07T13:08:16", "url": "https://files.pythonhosted.org/packages/5a/52/8bd046bfbc568c549bb903558b8175a0ef379dbdf0d1e5f2232d41d7a177/webpie-4.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9e73b828d62b329fc100fd5d99577a77", "sha256": "7d76428068657228e5c03c5c9165bfa7c049a78b543b2a18065ca2dbbad8b751" }, "downloads": -1, "filename": "webpie-4.0.2.tar.gz", "has_sig": false, "md5_digest": "9e73b828d62b329fc100fd5d99577a77", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 122218, "upload_time": "2019-05-07T13:08:18", "url": "https://files.pythonhosted.org/packages/33/38/fb5fa649932b20a354eb5da274ad4f5454f4233d6631e42940c38d0ae4f6/webpie-4.0.2.tar.gz" } ], "4.5.1": [ { "comment_text": "", "digests": { "md5": "7c62aa63ca2affde67e8863267b4af79", "sha256": "fdbebd32ba790ac526432adb930d901e4ece2fb7ebd2d45316fdc790fab1a3d8" }, "downloads": -1, "filename": "webpie-4.5.1-py3-none-any.whl", "has_sig": false, "md5_digest": "7c62aa63ca2affde67e8863267b4af79", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 147724, "upload_time": "2019-10-05T17:29:41", "url": "https://files.pythonhosted.org/packages/da/00/8c2996373227dbca086c80c60af89ed352507873d295bb28ca46404a7fc6/webpie-4.5.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "dfda3245a4142929fcb293d54b45c260", "sha256": "3db06c5b3182dec6acc6ffb45f6be911e0385be97209b74280527276fa65ad07" }, "downloads": -1, "filename": "webpie-4.5.1.tar.gz", "has_sig": false, "md5_digest": "dfda3245a4142929fcb293d54b45c260", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 128922, "upload_time": "2019-10-05T17:29:44", "url": "https://files.pythonhosted.org/packages/79/6d/02081e8e5ce2f1d86bbba984556e8e1c107b6c0a04e88846c9a9fc5eff22/webpie-4.5.1.tar.gz" } ], "4.5.2": [ { "comment_text": "", "digests": { "md5": "12fedf6c80386050b1ffb872f709f535", "sha256": "ae2565d0dc1f3c7ce685eda47a1fde6c364f591b7c31ec649bd11c69bb2c1806" }, "downloads": -1, "filename": "webpie-4.5.2-py3-none-any.whl", "has_sig": false, "md5_digest": "12fedf6c80386050b1ffb872f709f535", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 147740, "upload_time": "2019-10-05T17:31:30", "url": "https://files.pythonhosted.org/packages/c7/25/d66ce516191f0befd7669678c2f2e413abb5dda1fc60618ef786728456e7/webpie-4.5.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f1a6ca8446576e0ee94bdb539a94fcda", "sha256": "89bd03e33473f4fd4b402e6cdc43aebcac444deae26ca855d47f671b5de8b29d" }, "downloads": -1, "filename": "webpie-4.5.2.tar.gz", "has_sig": false, "md5_digest": "f1a6ca8446576e0ee94bdb539a94fcda", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 128972, "upload_time": "2019-10-05T17:31:33", "url": "https://files.pythonhosted.org/packages/d2/c2/b7f35728e3cdcd45c450eb6c4d5181e81a0481c9302093a8c8bb711d13b5/webpie-4.5.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "12fedf6c80386050b1ffb872f709f535", "sha256": "ae2565d0dc1f3c7ce685eda47a1fde6c364f591b7c31ec649bd11c69bb2c1806" }, "downloads": -1, "filename": "webpie-4.5.2-py3-none-any.whl", "has_sig": false, "md5_digest": "12fedf6c80386050b1ffb872f709f535", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 147740, "upload_time": "2019-10-05T17:31:30", "url": "https://files.pythonhosted.org/packages/c7/25/d66ce516191f0befd7669678c2f2e413abb5dda1fc60618ef786728456e7/webpie-4.5.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f1a6ca8446576e0ee94bdb539a94fcda", "sha256": "89bd03e33473f4fd4b402e6cdc43aebcac444deae26ca855d47f671b5de8b29d" }, "downloads": -1, "filename": "webpie-4.5.2.tar.gz", "has_sig": false, "md5_digest": "f1a6ca8446576e0ee94bdb539a94fcda", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 128972, "upload_time": "2019-10-05T17:31:33", "url": "https://files.pythonhosted.org/packages/d2/c2/b7f35728e3cdcd45c450eb6c4d5181e81a0481c9302093a8c8bb711d13b5/webpie-4.5.2.tar.gz" } ] }