{ "info": { "author": "Michael Ortali", "author_email": "github at xethorn net", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "Sukimu\n======\n\n|License| |Build status|\n\nA pythonic interface for nosql databases (supports DynamoDb.)\n\nSukimu provides a standard way to write your table schema (fields,\nvalidators, indexes) and perform CRUD operations. This framework also\noffers model extensions, and field pickling for any read operations.\n\nInstallation\n------------\n\nUsing pypi:\n\n.. code:: bash\n\n pip install sukimu\n\nUsing git:\n\n.. code:: bash\n\n pip install git+https://github.com/xethorn/sukimu.git#egg=sukimu\n\nBasic usage\n-----------\n\nWhen building a new project from scratch, you often need a user table.\nFor this specific table, we have the following rules:\n\n- ``id``: this unique id used across our codebase to identify the\n content that is owned by the user.\n- ``username``: chain of characters that identify the user.\n- ``password``: encrypted field.\n- ``full_name``: nice to have but not required.\n- ``active``: if the account is active or not.\n\n.. code:: python\n\n # If you don't have dynamodb set, you can use a local dynamodb\n from boto.dynamodb2.layer1 import DynamoDBConnection\n\n from sukimu.dynamodb import TableDynamo, IndexDynamo\n from sukimu.fields import Field\n from sukimu.schema import Schema\n\n\n connection = DynamoDBConnection(\n host='localhost', port='3333', aws_secret_access_key='foo',\n aws_access_key_id='bar', is_secure=False)\n\n\n UserModel = Schema(\n TableDynamo('user', connection),\n\n IndexDynamo(\n Index.PRIMARY, 'id', read_capacity=1, write_capacity=1),\n\n IndexDynamo(\n Index.GLOBAL, 'username', name='username_index',\n read_capacity=1, write_capacity=1),\n\n id=Field(fields.id),\n\n # Login information\n username=Field(validator.username, required=True),\n password=Field(validator.password, required=True),\n\n # User personal informations\n full_name=Field(),\n active=Field(basetype=boolean))\n\nIf your table is not yet in DynamoDb, you can create it by running:\n\n.. code:: python\n\n UserModel.table.create_table()\n\nIndexes\n-------\n\nAn index defines which key (or set of keys) should be unique within your\ntable. The schema will perform checks on those indexes whenever an entry\nis being created or updated.\n\nSome examples:\n\n- If you have a user table, and need usernames and emails to be unique,\n you will have then at least 2 indexes.\n- If you have a session token table with a user id and a token number,\n you can have one index composed of two keys: user id (hash) and token\n number (range)\n\n**Note about DynamoDb Indexes:** DynamoDb indexes provides additional\nfeatures such as the ability to set the throughput (read and write\ncapacity.) In addition, Global Indexes do not require the combinaison\n(hash - range) to be unique, to enable this, set the flag\n``unique=False``.\n\nOperations\n----------\n\nBasics\n~~~~~~\n\nThe table is abstracted in a way that you can run any operations:\n\n- ``fetch``: fetch one or more entries.\n- ``fetch_one``: find one entry that matches the requirements.\n- ``create``: add a new entry (sukimu ensures index unicity.)\n- ``delete``: remove an entry.\n- ``update``: update an entry.\n\nExample:\n\n.. code:: python\n\n from sukimu.operations import Equal\n\n resp = UserModel.create(id='1a872nd', username='celine')\n assert resp\n\n resp = UserModel.fetch_one(username=Equal('celine'))\n assert resp.message.get('username') == 'celine'\n\n # See Validators section for more details.\n resp = UserModel.update(dict(id='1a872nd'), username='new$username')\n print(resp.errors) # an error will show on the `$`\n\n resp = UserModel.update(dict(id='1a872nd'), username='NewUsername')\n assert resp.message.get('username') == 'newusername'\n\n resp = UserModel.fetch_one(id=Equal('1a872nd'))\n assert resp.message.get('username') == 'newusername'\n\nResponse format\n~~~~~~~~~~~~~~~\n\nSukimu provides a response envelope that aims to help consumers\nunderstand the type of data being returned:\n\n- ``response.message``: If the operation was successful, this\n attributes contains the data.\n- ``response.errors``: Instead of showing one error at a time, all the\n errors detected during the validation populate this attribute.\n- ``response.status``: similar to http status codes. For example:\n fetching data that does not exist returns a 404.\n\nValidators\n----------\n\nValidators are health checks on the provided data.\n\nFor example: if you have a field ``age``, the field is most likely going\nto have a defined range (minimum and maximum). If a value provided is\nnot valid, the field validator throws an exception, caught by the\nschema, and returned as part of the response (so if more than one field\nis invalid, the user can be informed.)\n\n.. code:: python\n\n from schema import exceptions\n\n\n USERNAME_FORMAT = re.compile('^[a-z\\-\\d]+$')\n\n def username(value):\n \"\"\"Username validation.\n\n Args:\n value (str): the username.\n Return:\n str: All usernames should be lowercase.\n \"\"\"\n\n if not value or len(value) > 20:\n raise exceptions.FieldException(\n 'Username should be less than 20 characters.')\n\n if not len(value) > 3:\n raise exceptions.FieldException(\n 'Username should contain more than 3 characters.')\n\n if not USERNAME_FORMAT.match(value):\n raise exceptions.FieldException(\n 'Usernames can only have letters and digits.')\n\n return value.lower()\n\nChaining validators is possible and it happens on the schema:\n\n.. code:: python\n\n UserSchema = Schema(\n ...\n username=Field(\n validator.username,\n validator.lowercase,\n required=True)\n ...\n )\n\nExtensions\n----------\n\nExtensions are additional data that can be fetched on demand.\n\nThe use case for extension is very similar to a ``join``. It allows you\nto fetch from any source additional data, and this data will be appended\nto your object.\n\nFields are only available for ``fetch`` and ``fetch_one`` methods.\n\n.. code:: python\n\n from sukimu.operations import Equal\n\n @UserModel.extension('stats')\n def stats(item, fields):\n # You will observe here that fields is an array that contains\n # 'source.url' and 'user.id'.\n return {'days': 10, 'additional_fields': fields}\n\n\n @UserModel.extension('history')\n def history(item, fields):\n return {'length': 20}\n\n\n UserModel.create(id='random', username='michael')\n resp = UserModel.fetch(\n username=Equal('michael'),\n fields=[\n 'history',\n 'stats.days',\n 'stats.source.url',\n 'stats.user.id'])\n\n print(resp.message)\n\nAuthor\n------\n\n- Michael Ortali ([@xethorn](http://twitter.com/xethorn))\n\n.. |License| image:: http://img.shields.io/:license-mit-blue.svg\n :target: http://doge.mit-license.org\n.. |Build status| image:: https://travis-ci.org/xethorn/sukimu.svg?branch=master\n :target: https://travis-ci.org/xethorn/sukimu/", "description_content_type": null, "docs_url": null, "download_url": null, "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": null, "keywords": "dynamodb, boto3, nosql, schema, structure", "license": null, "maintainer": null, "maintainer_email": null, "name": "Sukimu", "package_url": "https://pypi.org/project/Sukimu/", "platform": null, "project_url": "https://pypi.org/project/Sukimu/", "project_urls": null, "release_url": "https://pypi.org/project/Sukimu/2.0.5/", "requires_dist": null, "requires_python": null, "summary": "A pythonic interface for nosql databases (supports AWS DynamoDb.)", "version": "2.0.5" }, "last_serial": 2457092, "releases": { "0.0.1a1": [ { "comment_text": "", "digests": { "md5": "26efa8348f970a588ccf446b10eb26ec", "sha256": "573b34f3418332978aa5d32ba9e48b34e6556ed45fbe1240fc7f617f00acafc5" }, "downloads": -1, "filename": "Sukimu-0.0.1a1.tar.gz", "has_sig": false, "md5_digest": "26efa8348f970a588ccf446b10eb26ec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13171, "upload_time": "2015-03-18T20:51:34", "url": "https://files.pythonhosted.org/packages/a7/65/7f6d4411bd5aa3a2a499486e1cfeac42ccfb0596a5355eaf9127fdcd8e64/Sukimu-0.0.1a1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "4670017712c7b269beec8d13b4704548", "sha256": "c2fc9838a037b51bc69769fdd6c694ac9a1409db729e88fd05a506fcb1942629" }, "downloads": -1, "filename": "Sukimu-0.0.2.tar.gz", "has_sig": false, "md5_digest": "4670017712c7b269beec8d13b4704548", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13183, "upload_time": "2015-03-23T15:07:04", "url": "https://files.pythonhosted.org/packages/57/b6/7883b76e79458f30daecbf1c0160229e1e23f2f4461a4f80dba1347c4ccc/Sukimu-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "ca5719dbb326d34c9a80537507d5edc4", "sha256": "e55c0edeefaacf2bb7bfb97cf3fdc4b1a52b988cc3897ee6c4b46213bba72909" }, "downloads": -1, "filename": "Sukimu-0.0.3.tar.gz", "has_sig": false, "md5_digest": "ca5719dbb326d34c9a80537507d5edc4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13256, "upload_time": "2015-06-07T02:42:54", "url": "https://files.pythonhosted.org/packages/33/4c/2a575de9f7ad5ebf48da5faf7b2caf20e9550154691db987f33d1a43a718/Sukimu-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "fd8d44bcecea5cf34bbfff7b880d3653", "sha256": "5fee2208bcfe179b8d20d843614bae04b107eda821ed252ca3c08af560a335ce" }, "downloads": -1, "filename": "Sukimu-0.0.4.tar.gz", "has_sig": false, "md5_digest": "fd8d44bcecea5cf34bbfff7b880d3653", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13386, "upload_time": "2015-06-11T03:16:45", "url": "https://files.pythonhosted.org/packages/b5/5d/4df09879739ca399a157bdcb35f66d1c8f11ac6b2a9d32c9cf1d7c1d70bc/Sukimu-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "8c3835963b53eb7299788aaa876d53f2", "sha256": "27e6432f73126ce8afe2c8ce34081e61345b2948df8f61742be72fffda2116be" }, "downloads": -1, "filename": "Sukimu-0.0.5.tar.gz", "has_sig": false, "md5_digest": "8c3835963b53eb7299788aaa876d53f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13359, "upload_time": "2015-10-19T00:36:25", "url": "https://files.pythonhosted.org/packages/8d/ad/d231568e1617a1f3837cb2b6fc1e8f52bef1fb5268c4e9cd72522b6e869e/Sukimu-0.0.5.tar.gz" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "1de4e03db771c5a89a832b3705838004", "sha256": "e490956ddc50196832a6775273eb6d0b619e4e13e2c104ed20947a184267b18c" }, "downloads": -1, "filename": "Sukimu-0.0.6.tar.gz", "has_sig": false, "md5_digest": "1de4e03db771c5a89a832b3705838004", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13389, "upload_time": "2016-01-08T19:00:33", "url": "https://files.pythonhosted.org/packages/43/75/53e88e0c83fe489781d82cba1104d17cb7d9ae78d0e15f185a6aba5fd906/Sukimu-0.0.6.tar.gz" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "f1265abeb59c9d02d17d0b3cf5f2f80d", "sha256": "b2d63b61ea66f6918b5994a528df73b95ae11093e7e65068ec76cdfaf02b8dcb" }, "downloads": -1, "filename": "Sukimu-0.0.7.tar.gz", "has_sig": false, "md5_digest": "f1265abeb59c9d02d17d0b3cf5f2f80d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13810, "upload_time": "2016-05-23T21:39:53", "url": "https://files.pythonhosted.org/packages/4f/12/b1e77b897add49a31775435788c422104dda725ff654095b9740ca585d88/Sukimu-0.0.7.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "7d63a359c084dd34744e3b72ddf42a07", "sha256": "39639fc57473b7f9d15f49974df1d9a0c5d843b1c4b15a6dea92bde81d2f97f7" }, "downloads": -1, "filename": "Sukimu-1.0.1.tar.gz", "has_sig": false, "md5_digest": "7d63a359c084dd34744e3b72ddf42a07", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12909, "upload_time": "2016-09-28T15:28:01", "url": "https://files.pythonhosted.org/packages/04/a4/7e9b749820cb2e65ce35dcf1212cb87adb631aef912084e823fe4cb72812/Sukimu-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "88e0ce288f83c712d21ce320ae385b5b", "sha256": "b216ef7ca0fd1e5f1dd47152f30d36bf9f11f2b198820eaa9562ced397643d45" }, "downloads": -1, "filename": "Sukimu-1.0.2.tar.gz", "has_sig": false, "md5_digest": "88e0ce288f83c712d21ce320ae385b5b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12911, "upload_time": "2016-10-03T20:06:34", "url": "https://files.pythonhosted.org/packages/24/45/563b12b0a86b90236cf25d118afdd35fe88f04411af55ff7fc5e3ce212b6/Sukimu-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "a0ceb19d8d9eed15159866514399a2cd", "sha256": "c9710eb1b136d1f9387f2d0d3a13fb5e47f5884770681af3356dfef4e94637b7" }, "downloads": -1, "filename": "Sukimu-1.0.3.tar.gz", "has_sig": false, "md5_digest": "a0ceb19d8d9eed15159866514399a2cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12924, "upload_time": "2016-10-03T20:26:27", "url": "https://files.pythonhosted.org/packages/e3/d6/2fe37004b927948a733e6075a2e5e69defdfdc2122fa05266c0ef1fcc194/Sukimu-1.0.3.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "8cbe2408b81ef582a04a8dd518e2560c", "sha256": "0ab51049de6efb7984c21688bee57a30daf533b8caa29a6d8c155d4fe18bb5b3" }, "downloads": -1, "filename": "Sukimu-2.0.0.tar.gz", "has_sig": false, "md5_digest": "8cbe2408b81ef582a04a8dd518e2560c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13274, "upload_time": "2016-10-10T15:36:14", "url": "https://files.pythonhosted.org/packages/5e/eb/2760bbc0fe46f2cc0bb21b5a222501d93570e103145745cedce3a0b5b45d/Sukimu-2.0.0.tar.gz" } ], "2.0.2": [ { "comment_text": "", "digests": { "md5": "2b6697fcd3dbf11e3853df57e76d6a3d", "sha256": "3dbd2fd65130338465c5fe95cd4e71d6919a80b8efd46d5c1a92ebdcf71e15b1" }, "downloads": -1, "filename": "Sukimu-2.0.2.tar.gz", "has_sig": false, "md5_digest": "2b6697fcd3dbf11e3853df57e76d6a3d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15915, "upload_time": "2016-11-03T21:05:41", "url": "https://files.pythonhosted.org/packages/24/90/3bc5aa80ecbe5617cb96f380fe3df4e8518f04af1e1700c43f3d88be522d/Sukimu-2.0.2.tar.gz" } ], "2.0.3": [ { "comment_text": "", "digests": { "md5": "4460af3a0576b48b693cd2f53df76a78", "sha256": "977679c31e3990f11dcef170a7a16ef3affeb733908284268f1c95ed752a8ba0" }, "downloads": -1, "filename": "Sukimu-2.0.3.tar.gz", "has_sig": false, "md5_digest": "4460af3a0576b48b693cd2f53df76a78", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15937, "upload_time": "2016-11-10T16:57:50", "url": "https://files.pythonhosted.org/packages/36/71/8216c6e003d3f8b8905cfe0438081b60450e966c282e92cbcfecb3dcb261/Sukimu-2.0.3.tar.gz" } ], "2.0.4": [ { "comment_text": "", "digests": { "md5": "684dcf206a15945277595f3ac9fadd0c", "sha256": "c4552ec10c7ca8d118e03300144c596a99cbb2407924e239c060c5380876d5f7" }, "downloads": -1, "filename": "Sukimu-2.0.4.tar.gz", "has_sig": false, "md5_digest": "684dcf206a15945277595f3ac9fadd0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15942, "upload_time": "2016-11-10T17:04:25", "url": "https://files.pythonhosted.org/packages/b0/eb/970f7798f511b923357860c50bde0767b48d9e20bedccafc070bd2c09572/Sukimu-2.0.4.tar.gz" } ], "2.0.5": [ { "comment_text": "", "digests": { "md5": "1c17a159ca1cf8e87823cfc340c3f11f", "sha256": "aaebe1dcfc7f03427c1f31eb26564e8f9681a2cb1f88f054335700e307e92517" }, "downloads": -1, "filename": "Sukimu-2.0.5.tar.gz", "has_sig": false, "md5_digest": "1c17a159ca1cf8e87823cfc340c3f11f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15944, "upload_time": "2016-11-12T23:37:49", "url": "https://files.pythonhosted.org/packages/43/9f/ed1c9701ac87b47d3a3dd7f486a754904099f48644e657d3783ad543a674/Sukimu-2.0.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "1c17a159ca1cf8e87823cfc340c3f11f", "sha256": "aaebe1dcfc7f03427c1f31eb26564e8f9681a2cb1f88f054335700e307e92517" }, "downloads": -1, "filename": "Sukimu-2.0.5.tar.gz", "has_sig": false, "md5_digest": "1c17a159ca1cf8e87823cfc340c3f11f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15944, "upload_time": "2016-11-12T23:37:49", "url": "https://files.pythonhosted.org/packages/43/9f/ed1c9701ac87b47d3a3dd7f486a754904099f48644e657d3783ad543a674/Sukimu-2.0.5.tar.gz" } ] }