{ "info": { "author": "Brian Kirkpatrick", "author_email": "code@tythos.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Topic :: Internet :: WWW/HTTP", "Topic :: Scientific/Engineering :: Information Analysis" ], "description": "remisc\n======\n\nAnother framework!? What's the point? Aren't there a thousand-and-one web\nframeworks out there already? Don't *some* of them already support REST-oriented\noperations? (Spoiler: Sort of...) Who cares about scientific computing anyways?\n\nHere's the problem... Who needs a full-up MVC framework if all you're doing is\npassing system model data back and forth, or hosting a simulation service in a\ncloud environment? You don't. You need something model-centric, which doesn't\nassume clients are using a web browser. You need something that's going to\nprovide the supporting infrastructure, like WSGI mapping and automated operation\n& model documentation, with the least possible overhead of work and processing\npower. Focus on the unique part of your work--defining operations and the models\nthey use--and let *remisc* take care of everything else.\n\nServices\n--------\n\nA new microservice is defined by subclassing *remisc.service.Service*. Methods\nof this class can be decorated by *@remisc.service.isop*. These operations take\ntwo inputs, the urlparse object of the request and a dictionary of any arguments\nparsed from the URL's query string segment. They should return a textual\nresponse. A request will be mapped to an operation method by matching the method\nname to the top-level directory in the request URL (i.e., if a service is hosted\non http://mysvcs.com/, the request to http://mysvcs.com/test will look for the\nmethod *test* of the host Service-derived class.\n\nThe base Service class includes an *app()* method that defines a WSGI-compliant\napplication interface used to parse request arguments, map them to the\nappropriate method, and wrap the response generation process to return content.\n\nModels\n------\n\nFrequently, users must provide--or expect to receive--data formatted in\naccordance with specific models. Such data exchange formats can be defined by\nany class co-located with a Service-derived class, so long as they are\ndecorated by *@remisc.dxm.isdxm*.\n\nOperations\n----------\n\nSeveral default operations are built into the base Service class:\n\n_root\n~~~~~\n\nAny request without a top-level directory name will be routed to the *_root*\nmethod. As with any other method, this operation can be overridden by the user.\n\n_null\n~~~~~\n\nThis built-in operation returns an empty response. This is one way to hide error\nhandling--if you're really into that sort of thing.\n\n_help\n~~~~~\n\nThis is one of the most powerful behaviors of the *remisc* framework. The *_help*\noperation returns documentation of all operations and data exchange models for\nthe current Service-derived object. Operations are determined by evaluating all\ninstance methods for the @isdxm decorator. Data exchange models are determined\nby evaluating all classes co-located in the same module as the Service-derived\nclass for the @isdxm decorator. The response maps a JSON object to the\ndocstrings for each operation and data exchange model, so users can determine\nwhat operations the service provides and how it may utilize them.\n\nServing\n-------\n\nBy default, the *remisc* package includs a *server* module that utilizes the\ncore module *wsgiref*'s *simple_server* model to host a Service. All\nService-derived classes include a WSGI-compliant *app()* method invoked by the\nserver host process. For production runs, it is strongly advised to invoke that\nmethods from a production-level WSGI server instead.\n\nGetting Started\n---------------\n\nIn Action\n~~~~~~~~~\n\nWhen the *remisc.server.main* method is invoked directly, the reference WSGI\nserver in Python's core module *wsgiref* is used to host an instance of a given\n*remisc.service.Service* class. (If no class is provided, the base class is used\ninstead.) This can be done procedurally::\n\n >>> from remisc import server\n >>> server.main()\n Serving \"remisc.service.Service\" with wsgiref.simple_server @ 127.0.0.1:8000\n\nIf you use your web browser to load *http://127.0.0.1:8000*, you will see the\ndefault operation implemented by the *remisc.service.Service._root()* method\n(\"Here is the base.\"). You will also see, in the Python environment where you\nlaunched the server, how that request was mapped to an operation by the WSGI\napplication interface implemented by *remisc.service.Service.app()*::\n\n \"http://127.0.0.1:8000/\" => \"_root\"\n 127.0.0.1 - - [{date} {time}] \"GET / HTTP/1.1\" 200 {response time}\n \"http://127.0.0.1:8000/favicon.ico\" => \"_null\"\n 127.0.0.1 - - [{date} {time}] \"GET /favicon.ico HTTP/1.1\" 200 {response time}\n\nNote that most browsers implicitly request *favicon.ico* with each page request;\nthis is one useful application of the *_null* method, which is hard-coded to\nreply to such requests with an empty response.\n\nYou can view the base responses directly by browsing to the following URLs while\nyour test server is still running. Once you have seen the responses, press\nCTRL-C in the Python environment to stop the server.\n\n - http://127.0.0.1:8000/_root\n - http://127.0.0.1:8000/_null\n - http://127.0.0.1:8000/_help\n\nYour Own Service\n~~~~~~~~~~~~~~~~\n\nSubclassing *remisc.service.Service* will let you define your own operations and\noverride those already implemented. Make sure you decorate each method that\nimplements an operation with *@remisc.service.isop*. Such methods should take\ntwo arguments: a *urlparse* object capturing the original request, and an args\ndictionary constructed from the URL query string. The operation should return\nthe textual content of the response.\n\nFor example, let's implement a simple service *Joker* that implements a *joke*\noperation::\n\n >>> from remisc import service\n >>> class Joker(service.Service):\n >>> @service.isop\n >>> def joke(self, urlobj, args):\n >>> return 'Why did the spam cross the road?\\n\\nTo evade the dead parrot!'\n\nWe can host this service by passing the class to the *remisc.server.main*\nfunction as the *Svc* parameter::\n\n >>> server.main(Svc=Joker)\n\nNow, try browsing to http://127.0.0.1:8000/joke. For a bonus, note that your new\noperation has automatically been added to the response at\nhttp://127.0.0.1:8000/_help!", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Tythos/remisc", "keywords": "rest server scientific computing microservice", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "remisc", "package_url": "https://pypi.org/project/remisc/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/remisc/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/Tythos/remisc" }, "release_url": "https://pypi.org/project/remisc/0.0.3/", "requires_dist": null, "requires_python": null, "summary": "REST-ful microservice framework for scientific computing", "version": "0.0.3" }, "last_serial": 2169765, "releases": { "0.0.1": [], "0.0.2": [ { "comment_text": "", "digests": { "md5": "28a5c170f762ede634b11a40580a5b51", "sha256": "1da73722dbfd62888368db352c55c1fc1986196e325b01ea6a94275320dff103" }, "downloads": -1, "filename": "remisc-0.0.2.tar.gz", "has_sig": false, "md5_digest": "28a5c170f762ede634b11a40580a5b51", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17381, "upload_time": "2016-06-15T23:45:40", "url": "https://files.pythonhosted.org/packages/9e/dd/768c6a0d5ddaaaf1312ee16f5e8bcfa78a1c376aa23770b4d5f10cea0b62/remisc-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "b9688a2e92bffedde2b8739ea55fc2f0", "sha256": "cfceb99837dc4296be480d35d4e51630f09411f7d73268cf4f74a4d53a76ecc7" }, "downloads": -1, "filename": "remisc-0.0.3.tar.gz", "has_sig": false, "md5_digest": "b9688a2e92bffedde2b8739ea55fc2f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20612, "upload_time": "2016-06-16T01:04:23", "url": "https://files.pythonhosted.org/packages/81/4b/4b9ce4236bc5b555d97b6a43f0241215c2a2d8aa76b11d617fbceae3a64c/remisc-0.0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b9688a2e92bffedde2b8739ea55fc2f0", "sha256": "cfceb99837dc4296be480d35d4e51630f09411f7d73268cf4f74a4d53a76ecc7" }, "downloads": -1, "filename": "remisc-0.0.3.tar.gz", "has_sig": false, "md5_digest": "b9688a2e92bffedde2b8739ea55fc2f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20612, "upload_time": "2016-06-16T01:04:23", "url": "https://files.pythonhosted.org/packages/81/4b/4b9ce4236bc5b555d97b6a43f0241215c2a2d8aa76b11d617fbceae3a64c/remisc-0.0.3.tar.gz" } ] }