{
"info": {
"author": "Paulo Scardine",
"author_email": "paulo@xtend.com.br",
"bugtrack_url": null,
"classifiers": [
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3"
],
"description": "
\n\n> **doid** (plural doids)\n>\n> 1. (zoology) Any member of the Doidae, a family of moths.\n\n# DOID - Django ORM inspired DSL\n\n> \u201cTalent borrows. Genius Steals!\u201d - Oscar Wilde.\n\nDOID is a generic DSL for filtering and sorting inspired by projects like \nthe Django ORM and SQLAlchemy. It is a generic container with `filter` and `order_by`\nmethods much like the result set managers from Django. This should be useful\nif you are fond of Django's ORM idioms and would like to use the same patterns\non objects that are not Django Models like objects from API responses.\n\n\n## Filter Interface\n\nA filter object is a callable that receives an object and returns True or False. \nFilters can be combined using the bitwise and e or operators: `&` and `|`. For example:\n\n filter4 = filter1 | (filter2 & filter3)\n\nYou can turn any callable into a filter using a decorator:\n\n from doid.filter import generic_filter\n\n @doid_filter\n def milenials(value):\n return value.born.year > 2000\n\nFilter should never mutate the value they receive.\n\n## Sample data\n\nIt is easier to explain using examples. The containers are totally agnostic and \ntake any dataclasses-style object, so lets generate some fake data:\n\n >>> data =[\n ['Adrian Mathews', 'Wilsonview', datetime.date(1944, 9, 5), 'PM'],\n ['Amanda Kaufman', 'East Franklin', datetime.date(1972, 8, 6), 'AM'],\n ['Benjamin Mcconnell', 'Wilsonview', datetime.date(1928, 8, 8), 'AM'],\n ['Carolyn Wilcox', 'Lake Benjaminbury', datetime.date(1944, 4, 21), 'PM'],\n ['Christina White', 'Angelamouth', datetime.date(1963, 10, 22), 'PM'],\n ['David Berry', 'Lake Benjaminbury', datetime.date(1950, 2, 10), 'PM'],\n ['Jacob Johnson', 'Wilsonview', datetime.date(1950, 5, 8), 'AM'],\n ['Jasmine Sanchez', 'Port Janefort', datetime.date(2008, 5, 13), 'AM'],\n ['John Robinson', 'Angelamouth', datetime.date(1945, 7, 16), 'PM'],\n ['Kenneth Hernandez', 'Port Janefort', datetime.date(1978, 10, 23), 'PM'],\n ['Monica Conley', 'East Franklin', datetime.date(1918, 9, 27), 'AM'],\n ['Paula Melendez', 'East Franklin', datetime.date(2017, 5, 21), 'AM'],\n ['Robin Harris', 'Angelamouth', datetime.date(1976, 2, 9), 'PM'],\n ['Sheri Kerr', 'East Franklin', datetime.date(1904, 1, 3), 'AM'],\n ['Shirley Gray', 'Lake Benjaminbury', datetime.date(1996, 8, 2), 'AM'],\n ['Stacy Weaver', 'East Franklin', datetime.date(1931, 10, 31), 'PM'],\n ['Tiffany Sullivan DVM', 'Wilsonview', datetime.date(1909, 1, 7), 'PM'],\n ['Tracy Norman', 'Wilsonview', datetime.date(1932, 5, 2), 'PM'],\n ['William Johnson', 'Angelamouth', datetime.date(1950, 3, 27), 'PM'],\n ['Xavier Harris', 'East Franklin', datetime.date(1903, 10, 5), 'AM']\n ]\n\n >>> class GenericObject(object):\n def __init__(self, **kwargs):\n for k, v in kwargs.items():\n setattr(self, k, v)\n def __repr__(self):\n return \"<\" + \", \".join(f\"{k}={v}\" for k, v in self.__dict__.items()) + \">\"\n\n >>> from doid.container import ListContainer\n >>> results = ListContainer(\n GenericObject(name=name, city=city, born=born, ampm=ampm) for\n name, city, born, ampm in data\n )\n\n >>> results\n [,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ,\n ]\n\n\n## Attribute getter protocol\n\nThe filter protocol folows a attribute-getter protocol much like one used by Django.\nWe can filter by any attribute using `.filter(name=value)`:\n\n >>> results.filter(city=\"East Franklin\")\n [,\n ,\n ,\n ,\n ,\n ]\n\nWe can access nested attributes replacing the `.` by double underscores: \n\n >>> results.filter(born__month=5)\n [,\n ,\n ,\n ]\n\nSome operators ara available using the same names from the `operator` module, for example\nyou can append `__gt` to represent the `>` operator:\n\n >>> from doid.filter import Q\n >>> milenials = Q(born__year__gt=1980)\n >>> results.filter(milenials)\n [,\n ,\n ]\n\nWe can filter using regular expressions by appending `__match`:\n\n >>> results.filter(name__match='^S')\n [,\n ,\n ]\n\nLike in the Django ORM, methods can be chained:\n\n >>> results.filter(name__match='^S').filter(milenials)\n []\n\nThis is the same as:\n\n >>> results.filter(name__match='^S', milenials)\n []\n\nAgain like in Django, we can express OR filters using Q objects:\n\n >>> results.filter(Q(name__match='^S') | milenials)\n [,\n ,\n ,\n ,\n ]\n\nThe `order_by` method accepts strings following the same protocol (keyword\narguments will be passed directly to the sort method):\n\n >>> results.order_by('born__year')[:5]\n [,\n ,\n ,\n ,\n ,\n\n >>> results.order_by('born__year', reverse=True)[:5]\n [,\n ,\n ,\n ,\n ]\n\n## Other ideas\n\nThis is pretty much a work in progress. Some ideas are:\n\n 1. Implement getters that works also for dicts and lists\n 1. Implement getters that fail gracefully it the attribute/key does not exist\n 1. Create other container types like ordered sets\n\n\n\n",
"description_content_type": "text/markdown",
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/scardine/doid",
"keywords": "",
"license": "",
"maintainer": "",
"maintainer_email": "",
"name": "doid",
"package_url": "https://pypi.org/project/doid/",
"platform": "",
"project_url": "https://pypi.org/project/doid/",
"project_urls": {
"Homepage": "https://github.com/scardine/doid"
},
"release_url": "https://pypi.org/project/doid/0.0.1/",
"requires_dist": null,
"requires_python": "",
"summary": "Generic container with complex filter/sorting",
"version": "0.0.1"
},
"last_serial": 4311341,
"releases": {
"0.0.1": [
{
"comment_text": "",
"digests": {
"md5": "4675c9783fcc8d967ac7a4fe750a522d",
"sha256": "212ec208c0b200d984ea3e66708f08b06a57c306609fb1748971a380f71dcf7a"
},
"downloads": -1,
"filename": "doid-0.0.1.macosx-10.12-x86_64.tar.gz",
"has_sig": false,
"md5_digest": "4675c9783fcc8d967ac7a4fe750a522d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 12329,
"upload_time": "2018-09-26T06:36:25",
"url": "https://files.pythonhosted.org/packages/91/0e/5341e6083aad6ba00a6b920d6553c39d35fadbf7d8e3707e30e979dc1920/doid-0.0.1.macosx-10.12-x86_64.tar.gz"
},
{
"comment_text": "",
"digests": {
"md5": "d20af24fa5002f889ca755dda3ae84cf",
"sha256": "34474e7287fb11330b4d028ebba607010f13db68b6d07688eb1288fd577d798d"
},
"downloads": -1,
"filename": "doid-0.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d20af24fa5002f889ca755dda3ae84cf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 7603,
"upload_time": "2018-09-26T06:36:23",
"url": "https://files.pythonhosted.org/packages/62/10/aa1264fc11982c415c2c3c5fcf3e1efe042a785e27cdf5ac226c35a6a5cc/doid-0.0.1-py3-none-any.whl"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "4675c9783fcc8d967ac7a4fe750a522d",
"sha256": "212ec208c0b200d984ea3e66708f08b06a57c306609fb1748971a380f71dcf7a"
},
"downloads": -1,
"filename": "doid-0.0.1.macosx-10.12-x86_64.tar.gz",
"has_sig": false,
"md5_digest": "4675c9783fcc8d967ac7a4fe750a522d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 12329,
"upload_time": "2018-09-26T06:36:25",
"url": "https://files.pythonhosted.org/packages/91/0e/5341e6083aad6ba00a6b920d6553c39d35fadbf7d8e3707e30e979dc1920/doid-0.0.1.macosx-10.12-x86_64.tar.gz"
},
{
"comment_text": "",
"digests": {
"md5": "d20af24fa5002f889ca755dda3ae84cf",
"sha256": "34474e7287fb11330b4d028ebba607010f13db68b6d07688eb1288fd577d798d"
},
"downloads": -1,
"filename": "doid-0.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d20af24fa5002f889ca755dda3ae84cf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 7603,
"upload_time": "2018-09-26T06:36:23",
"url": "https://files.pythonhosted.org/packages/62/10/aa1264fc11982c415c2c3c5fcf3e1efe042a785e27cdf5ac226c35a6a5cc/doid-0.0.1-py3-none-any.whl"
}
]
}