{ "info": { "author": "Feng Zhou", "author_email": "zf.pascal@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3.3", "Topic :: Internet :: WWW/HTTP :: WSGI" ], "description": "# klar\n\na micro web framework built for fun\n\n* argument annotation\n* jsonschema intergration\n\n```py\nfrom klar import App\n\napp = App()\n\n@app.get('/hello/')\ndef hello(name: str, times: int = 1):\n\treturn \"hello \" * times + name\n```\n\nrun it using [wsgi-supervisor](https://github.com/zweifisch/wsgi-supervisor)\n\n```sh\nwsgi-supervisor app:app\n```\n\n```sh\n$ curl 'localhost:3000/hello/klar?times=2'\nhello hello klar\n```\n\n## custom types using jsonschema\n\n```python\nproduct = {\n\t\"type\": \"object\"\n\t\"properties\": {\n\t\t\"name\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n\t\t\"price\": {\n\t\t\t\"type\": \"number\"\n\t\t},\n\t},\n\t\"additionalProperties\": False,\n}\n\n@app.post('/product')\ndef create(body: product, db):\n\tdb.products.insert(body)\n\treturn {\"ok\": True}\n```\n\nschemas can and should be imported from json or yaml files\n\n```\n|--app.py\n|--schemas.json\n```\n\nproduct in schema.json\n\n```\n{\n\tproduct: {...}\n}\n```\n\n```python\nfrom schemas import product\n\n@app.post('/product')\ndef create(body: product):\n\tpass\n```\n\n## dependency injection\n\nprovide a custom dependency using decorator\n\n```python\n@app.provide('db')\ndef get_db_connection():\n\tconn = SomeDB(url=\"localhost:3349\")\n\treturn conn\n\nimport redis\napp.provide('cache', (redis.Redis, {'host': 'localhost'}))\n```\n\nusing `db` and `cache` in request handler\n\n```python\n@get('/article/')\ndef get_article(article_id:int, db, cache):\n pass\n```\n\npredefined components:\n\n* req\n* session\n* cookie\n* router\n\n## rest\n\n```python\nfrom resource import product, catalog\n\napp = App()\n\napp.resources(product, catalog, prefix=\"/v1\")\n\nif __name__ == '__main__':\n\tapp.run()\n```\n\nin product\n\n```python\nfrom schema import product\n\n# curl -X POST $host/v1/product -d @body\ndef create(body: product, db):\n\treturn db.products.insert(body)\n\n# curl $host/v1/product/$id\ndef show(product_id: str):\n\titem = db.products.find_one({_id: product_id})\n\treturn item if item else 404\n\n# curl $host/v1/product?shift=10&limit=10\ndef query(shift: int, limit: int, db):\n\treturn db.products.find().skip(shift).limit(shift)\n\n# curl -X PATCH $host/v1/product/$id -d @body\ndef modify(body: product, product_id: str):\n\treturn db.products.update({_id: product_id}, {'$set': body})\n\n# curl -X PUT $host/v1/product/$id -d @body\ndef replace(body: product, product_id: str):\n\treturn db.products.update({_id: product_id}, body)\n\n# curl -X DELETE $host/v1/product/$id\ndef destroy(product_id: str):\n\treturn db.products.delete({_id: product_id})\n```\n\n### custom method\n\n```python\nfrom klar import method\n\n@method('patch')\ndef like(product_id):\n\treturn db.products.update({_id: product_id}, {'$inc': {'likes': 1}})\n\n# curl -X PATCH $host/v1/product/$id/like\n```\n\n## events\n\nlistening for an event\n\n```python\n@on(404)\ndef not_found(req, res):\n\tprint('%s not found' % req.path)\n res.body = \"%s not found on this server\" % req.path\n```\n\n### custom events\n\n```python\n@on('user-login')\ndef onlogin(userid, db):\n\tprint('user: %s logged in' % userid)\n\tdb.users.update({_id:userid}, {'$inc': {'logincount': 1}})\n```\n\nemit an event\n\n```python\ndef login(emitter):\n\temitter.emit('user-login', userid=id)\n```\n\n## post processing\n\n```python\ndef jsonp(req, res):\n callback = req.query.get('callback')\n if callback:\n res.body = \"%s(%s)\" % (callback, json.dumps(body))\n res.headers[\"Content-Type\"] = \"application/javascript\"\n\n@app.get('/resource') -> jsonp:\n\treturn {\"key\": \"value\"}\n```\n\nmore than one processors:\n\n```python\n@app.get('/resource') -> (jsonp, etag):\n\treturn {\"key\": \"value\"}\n```\n\n## template rendering\n\n```\n|--app.py\n|--templates\n |--home.html\n```\n\n```python\nimport templates.home\n\n@app.get('/') -> templates.home:\n\treturn {\"key\": \"value\"}\n```\n\n`templates.home` accecpts an optional dict as argument\nit's basically equivalent to this:\n\n```python\n@app.get('/'):\n\treturn templates.home({\"key\": \"value\"})\n```\n\n### mustache\n\ndepends on pystache, `pip install pystache`\n\nuse `.mustache` as extension\n\n```\n|--templates\n |--home.mustache\n```\n\n```python\nimport templates.home\n```\n\n## session\n\nsession depends on `cache`, but klar does't has it builtin\n\nto use redis as session backend:\n\n```python\nimport redis\n\n@app.provide('cache')\ndef cache():\n\treturn redis.Redis(host='localhost', port=6379, db=0)\n```\n\nor\n\n```python\napp.privide('cache', (redis.Redis, {'host': 'localhost'}))\n```\n\n### use session\n\n```python\n@app.post('/login')\ndef login(body, session):\n\t# check body.username and body.password\n\tif founduser:\n\t\tsession.set('userid', userid)\n\n@app.post('/login')\ndef logout(session):\n\tsession.destroy()\n\n@app.get('/admin')\ndef admin(session):\n\tif session.get('userid'):\n\t\tpass\n```\n\n## cookies\n\n```python\ncookies.get(key, default)\ncookies.set(key, value)\ncookies.delete(key)\n\ncookies.set(key, value, httponly=True)\ncookies.set_for_30_days(key, value)\n```\n\n## serving static files\n\nshould only be used in development enviroment\n\n```\napp.static('/public/')\n```\n\n```\napp.static('/public/', 'path/to/public/dir')\n```\n\n## config\n\nconfig file path will be read from enviroment variable `$CONFIG`\n\nif it's empty config.py will be loaded\n\nconfig.py\n\n```python\nmongo = {\n \"host\": \"127.0.0.1\"\n \"port\": 27017\n}\n```\n\n```python\nfrom pymongo import MongoClient\n\n@app.provide('db')\ndef db(config):\n return MongoClient(**config.mongo)\n```\n\n## reversed routing\n\n```python\n@app.get('user/')\ndef user(id:str):\n pass\n```\n\nget a link to previous handler\n\n```\ndef another_handler(router):\n href = router.path_for('user', id=3221)\n```\n\n## custom json encoder\n\n```python\nfrom bson.objectid import ObjectId\n\n@app.json_encode(ObjectId)\ndef encode_objectid(obj):\n return str(obj)\n```\n\nby default `Iterable` is converted to `list`", "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/zweifisch/klar", "keywords": "micro web framework restful", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "klar", "package_url": "https://pypi.org/project/klar/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/klar/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/zweifisch/klar" }, "release_url": "https://pypi.org/project/klar/0.0.6/", "requires_dist": null, "requires_python": null, "summary": "a micro web framework", "version": "0.0.6" }, "last_serial": 1038468, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "ddbc5717970109a1e19d8808e0bbb4d4", "sha256": "43a41f6eed0c25f52f0e495b8cf43955d335550d1b01f6b69126c1751dced5be" }, "downloads": -1, "filename": "klar-0.0.1.tar.gz", "has_sig": false, "md5_digest": "ddbc5717970109a1e19d8808e0bbb4d4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7229, "upload_time": "2014-03-03T13:43:16", "url": "https://files.pythonhosted.org/packages/aa/90/d627dbf22c46b96cb5fd876ddcb7538c5d88dccc06e5339c0d490f7eef58/klar-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "a880e2ecd8707800a09bec5a665371d8", "sha256": "35e7cf1cc3a66072ffb1b1eb31eebd8ff98988bda4e0c996068c91e55d2381c3" }, "downloads": -1, "filename": "klar-0.0.2.tar.gz", "has_sig": false, "md5_digest": "a880e2ecd8707800a09bec5a665371d8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7260, "upload_time": "2014-03-03T14:03:25", "url": "https://files.pythonhosted.org/packages/ef/9d/e458e0d111466a5c5c431d401e70e665e4942c8204f7c593b34246e3d15c/klar-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "0d10aaa8ea49ed296ba7cf2df17f593e", "sha256": "4ca44e1bacac07abb7d518e7448d022b260d45ac0b0f73a132f859f13a6a7349" }, "downloads": -1, "filename": "klar-0.0.3.tar.gz", "has_sig": false, "md5_digest": "0d10aaa8ea49ed296ba7cf2df17f593e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11989, "upload_time": "2014-03-14T10:24:39", "url": "https://files.pythonhosted.org/packages/5b/dd/0f14b216fee17a982981d475734586dc56a5e33b2385ef6aedd9c2a58cc7/klar-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "5376aa5d3b51a8072f4bd08f0257ce79", "sha256": "05760e85d7072bd33b83a91e4a215b9561765d10138a702bf2e7dc2d9254a365" }, "downloads": -1, "filename": "klar-0.0.4.tar.gz", "has_sig": false, "md5_digest": "5376aa5d3b51a8072f4bd08f0257ce79", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12123, "upload_time": "2014-03-19T05:33:33", "url": "https://files.pythonhosted.org/packages/3a/b4/14ec0ce05b62a50d6566d8d748e440bdef5ff052590712b2a75a4658f7e4/klar-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "6fa99cc74e73b254ae6e0e68eda9c84a", "sha256": "8fd22349120357f07a4b75695ec33f868121448ead0e22a660057bff9680683e" }, "downloads": -1, "filename": "klar-0.0.5.tar.gz", "has_sig": false, "md5_digest": "6fa99cc74e73b254ae6e0e68eda9c84a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12496, "upload_time": "2014-03-20T05:13:15", "url": "https://files.pythonhosted.org/packages/32/18/4c6c149ddf395ed631f62da478f1ff979bfd0410f7fd4dbc608fcf12c4a4/klar-0.0.5.tar.gz" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "25015e85cf9d797ee2993aaa029a01cc", "sha256": "aed1c2352f3e43db5ba999ad73fb5b272a7a5b4128469eb7820204996b8d6c99" }, "downloads": -1, "filename": "klar-0.0.6.tar.gz", "has_sig": false, "md5_digest": "25015e85cf9d797ee2993aaa029a01cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12729, "upload_time": "2014-03-23T14:44:18", "url": "https://files.pythonhosted.org/packages/76/35/48f95e0cf423e2eb6cd57cfb32a024f1b1d97bf642a3c98691d6c78b8d35/klar-0.0.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "25015e85cf9d797ee2993aaa029a01cc", "sha256": "aed1c2352f3e43db5ba999ad73fb5b272a7a5b4128469eb7820204996b8d6c99" }, "downloads": -1, "filename": "klar-0.0.6.tar.gz", "has_sig": false, "md5_digest": "25015e85cf9d797ee2993aaa029a01cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12729, "upload_time": "2014-03-23T14:44:18", "url": "https://files.pythonhosted.org/packages/76/35/48f95e0cf423e2eb6cd57cfb32a024f1b1d97bf642a3c98691d6c78b8d35/klar-0.0.6.tar.gz" } ] }