{ "info": { "author": "Guillaume Paulet", "author_email": "guillaume.paulet@giome.fr", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: Public Domain", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": ".. image:: https://raw.githubusercontent.com/ducdetronquito/scalpl/master/assets/scalpl.png\n :target: https://github.com/ducdetronquito/scalpl\n\nScalpl\n======\n\n.. image:: https://img.shields.io/badge/license-public%20domain-ff69b4.svg\n :target: https://github.com/ducdetronquito/scalpl#license\n\n.. image:: https://img.shields.io/badge/coverage-100%25-green.svg\n :target: #\n\n.. image:: https://img.shields.io/badge/pypi-v0.3.0-blue.svg\n :target: https://pypi.python.org/pypi/scalpl/\n\n.. image:: https://travis-ci.org/ducdetronquito/scalpl.svg?branch=master\n :target: https://travis-ci.org/ducdetronquito/scalpl\n\n\nOutline\n~~~~~~~\n\n1. `Overview `_\n2. `Benefits `_\n3. `Installation `_\n4. `Usage `_\n5. `Benchmark `_\n6. `Frequently Asked Questions `_\n7. `How to Contribute `_\n8. `License `_\n\n\nOverview\n~~~~~~~~\n\n\n**Scalpl** provides a **lightweight wrapper** that helps you to operate\non **nested dictionaries** seamlessly **through the built-in** ``dict``\n**API**, by using dot-separated string keys.\n\nIt's not a drop-in replacement for your dictionnaries, just syntactic\nsugar to avoid ``this['annoying']['kind']['of']['things']`` and\n``prefer['a.different.approach']``.\n\nNo conversion cost, a thin computation overhead: that's **Scalpl** in a\nnutshell.\n\n\nBenefits\n~~~~~~~~\n\nThere are a lot of good libraries to operate on nested dictionaries,\nsuch as `Addict `_ or \n`Box `_ , but if you give **Scalpl**\na try, you will find it:\n\n* \ud83d\ude80 Powerful as the standard dict API\n* \u26a1 Lightweight\n* \ud83d\udc4c Well tested\n\n\nInstallation\n~~~~~~~~~~~~\n\n**Scalpl** is a Python3 library that you can install via ``pip``\n\n.. code:: sh\n\n pip3 install scalpl\n\n\nUsage\n~~~~~\n\n**Scalpl** provides a simple class named **Cut** that wraps around your dictionary\nand handles operations on nested ``dict`` and that can cut accross ``list`` item.\n\nThis wrapper strictly follows the standard ``dict``\n`API `_, which\nmeans you can operate seamlessly on ``dict``,\n``collections.defaultdict`` or ``collections.OrderedDict`` by using their methods\nwith dot-separated keys.\n \nLet's see what it looks like with an example ! \ud83d\udc47\n\n.. code:: python\n\n from scalpl import Cut\n\n data = {\n 'pokemons': [\n {\n 'name': 'Bulbasaur',\n 'type': ['Grass', 'Poison'],\n 'category': 'Seed',\n 'ability': 'Overgrow'\n },\n { \n 'name': 'Charmander',\n 'type': 'Fire',\n 'category': 'Lizard',\n 'ability': 'Blaze',\n },\n {\n 'name': 'Squirtle',\n 'type': 'Water',\n 'category': 'Tiny Turtle',\n 'ability': 'Torrent',\n }\n ],\n 'trainers': [\n {\n 'name': 'Ash',\n 'hometown': 'Pallet Town'\n }\n ]\n }\n # Just wrap your data, and you're ready to go deeper !\n proxy = Cut(data)\n\nYou can use the built-in ``dict`` API to access its values.\n\n.. code:: python\n\n proxy['pokemons[0].name']\n # 'Bulbasaur'\n proxy.get('pokemons[1].sex', 'Unknown')\n # 'Unknown'\n 'trainers[0].hometown' in proxy\n # True\n\nBy default, **Scalpl** uses dot as a key separator, but you are free to\nuse a different character that better suits your needs.\n\n.. code:: python\n\n # You just have to provide one when you wrap your data.\n proxy = Cut(data, sep='->')\n # Yarrr!\n proxy['pokemons[0]->name']\n\nYou can also easily create or update any key/value pair.\n\n.. code:: python\n\n proxy['pokemons[1].weaknesses'] = ['Ground', 'Rock', 'Water']\n proxy['pokemons[1].weaknesses']\n # ['Ground', 'Rock', 'Water']\n proxy.update({\n 'trainers[0].region': 'Kanto',\n })\n\n\nFollowing its purpose in the standard API, the *setdefault* method allows\nyou to create any missing dictionary when you try to access a nested key.\n\n.. code:: python\n\n proxy.setdefault('pokemons[2].moves.Scratch.power', 40)\n # 40\n\n\nAnd it is still possible to iterate over your data.\n\n.. code:: python\n\n proxy.items()\n # [('pokemons', [...]), ('trainers', [...])]\n proxy.keys()\n # ['pokemons', 'trainers']\n proxy.values()\n # [[...], [...]]\n\nBy the way, if you have to operate on a list of dictionaries, the\n``Cut.all`` method is what you are looking for.\n\n.. code:: python\n\n # Let's teach these pokemons some sick moves !\n for pokemon in proxy.all('pokemons'):\n pokemon.setdefault('moves.Scratch.power', 40)\n\nAlso, you can remove a specific or an arbitrary key/value pair.\n\n.. code:: python\n\n proxy.pop('pokemons[0].category')\n # 'Seed'\n proxy.popitem()\n # ('trainers', [...])\n del proxy['pokemons[1].type']\n\nBecause **Scalpl** is only a wrapper around your data, it means you can\nget it back at will without any conversion cost. If you use an external\nAPI that operates on dictionary, it will just work.\n\n.. code:: python\n\n import json\n json.dumps(proxy.data)\n # \"{'pokemons': [...]}\"\n\nFinally, you can retrieve a shallow copy of the inner dictionary or\nremove all keys.\n\n.. code:: python\n\n shallow_copy = proxy.copy()\n\n proxy.clear()\n\n\nBenchmark\n~~~~~~~~~\n\nThis humble benchmark is an attempt to give you an overview of the performance\nof `Scalpl `_ compared to `Addict `_,\n`Box `_ and the built-in ``dict``.\n\nIt will summarize the *number of operations per second* that each library is \nable to perform on a portion of the JSON dump of the `Python subreddit main page `_.\n\nYou can run this benchmark on your machine with the following command:\n\n python3 ./benchmarks/performance_comparison.py\n\nHere are the results obtained on an Intel Core i5-7500U CPU (2.50GHz) with **Python 3.6.4**.\n\n\n**Addict** 2.2.1::\n\n instanciate:-------- 271,132 ops per second.\n get:---------------- 276,090 ops per second.\n get through list:--- 293,773 ops per second.\n set:---------------- 300,324 ops per second.\n set through list:--- 282,149 ops per second.\n\n\n**Box** 3.4.2::\n\n instanciate:--------- 4,093,439 ops per second.\n get:----------------- 957,069 ops per second.\n get through list:---- 164,013 ops per second.\n set:----------------- 900,466 ops per second.\n set through list:---- 165,522 ops per second.\n\n\n**Scalpl** latest::\n\n instanciate:-------- 183,879,865 ops per second.\n get:---------------- 14,941,355 ops per second.\n get through list:--- 14,175,349 ops per second.\n set:---------------- 11,320,968 ops per second.\n set through list:--- 11,956,001 ops per second.\n\n\n**dict**::\n\n instanciate:--------- 37,816,714 ops per second.\n get:----------------- 84,317,032 ops per second.\n get through list:---- 62,480,474 ops per second.\n set:----------------- 146,484,375 ops per second.\n set through list :--- 122,473,974 ops per second.\n\n\nAs a conclusion and despite being an order of magniture slower than the built-in\n``dict``, **Scalpl** is faster than Box and Addict by an order of magnitude for any operations.\nBesides, the gap increase in favor of **Scalpl** when wrapping large dictionaries.\n\nKeeping in mind that this benchmark may vary depending on your use-case, it is very unlikely that\n**Scalpl** will become a bottleneck of your application.\n\n\nFrequently Asked Questions:\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* **What if my keys contain dots ?**\n If your keys contain a lot of dots, you should use an other\n key separator when wrapping your data::\n\n proxy = Cut(data, sep='->')\n proxy['computer->network->127.0.0.1']\n\n Otherwise, split your key in two part::\n\n proxy = Cut(data)\n proxy['computer.network']['127.0.0.1']\n\n* **What if my keys contain spaces ?**::\n \n proxy = Cut(data)\n proxy['it works perfectly'] = 'fine'\n\n\nHow to Contribute\n~~~~~~~~~~~~~~~~~\n\nContributions are welcomed and anyone can feel free to submit a patch, report a bug or ask for a feature. Please open an issue first in order to encourage and keep tracks of potential discussions \u270d\ufe0f\n\n\nLicense\n~~~~~~~\n\n**Scalpl** is released into the **Public Domain**. \ud83c\udf89\n\nPs: If we meet some day, and you think this small stuff worths it, you\ncan give me a beer, a coffee or a high-five in return: I would be really\nhappy to share a moment with you ! \ud83c\udf7b", "description_content_type": "", "docs_url": null, "download_url": "https://github.com/ducdetronquito/scalpl/archive/0.3.0.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ducdetronquito/scalpl", "keywords": "dict,nested,proxy,traversable,dictionary,box,addict,munch,scalpl,scalpel,wrapper", "license": "Public Domain", "maintainer": "", "maintainer_email": "", "name": "scalpl", "package_url": "https://pypi.org/project/scalpl/", "platform": "", "project_url": "https://pypi.org/project/scalpl/", "project_urls": { "Download": "https://github.com/ducdetronquito/scalpl/archive/0.3.0.tar.gz", "Homepage": "https://github.com/ducdetronquito/scalpl" }, "release_url": "https://pypi.org/project/scalpl/0.3.0/", "requires_dist": null, "requires_python": "", "summary": "A lightweight wrapper to operate on nested dictionaries seamlessly.", "version": "0.3.0" }, "last_serial": 5884828, "releases": { "0.2.3": [ { "comment_text": "", "digests": { "md5": "3e555773ed09cde5b860c4061b036240", "sha256": "0316bfcd3b72d7bfcfce05ce9d2a8687c6b04afeb222979c09e5874c60ff0269" }, "downloads": -1, "filename": "scalpl-0.2.3-py3-none-any.whl", "has_sig": false, "md5_digest": "3e555773ed09cde5b860c4061b036240", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8063, "upload_time": "2017-05-26T20:30:53", "url": "https://files.pythonhosted.org/packages/d9/84/e900922d1a1385ece4edc5e427c1828b774016dcd025728172c09cfaa418/scalpl-0.2.3-py3-none-any.whl" } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "4511099626aa6552fff8f8d50d7ef5bb", "sha256": "6f1adddafa65eae54ba747f05e15103d31b7617482b4fad6b764856cd99a1c95" }, "downloads": -1, "filename": "scalpl-0.2.4-py3-none-any.whl", "has_sig": false, "md5_digest": "4511099626aa6552fff8f8d50d7ef5bb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10127, "upload_time": "2017-06-07T22:44:40", "url": "https://files.pythonhosted.org/packages/23/14/4bea4a0922fbfb5096d71b1d3512f7e160e6f6af0aa3a2edb27d1e376738/scalpl-0.2.4-py3-none-any.whl" } ], "0.2.5": [ { "comment_text": "", "digests": { "md5": "44d551dfd48e6b85f6d47dc395d9084b", "sha256": "893e293140d9716b0103a12cac6cfe096690b584b629f3504671c2b7d778515c" }, "downloads": -1, "filename": "scalpl-0.2.5.tar.gz", "has_sig": false, "md5_digest": "44d551dfd48e6b85f6d47dc395d9084b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6644, "upload_time": "2017-06-26T14:32:35", "url": "https://files.pythonhosted.org/packages/b0/a9/cff0ada8a2b6eb794eaf92faffd9a4fb2286845f7cb4d9bcc971b77f4efa/scalpl-0.2.5.tar.gz" } ], "0.2.6": [ { "comment_text": "", "digests": { "md5": "6fc4402da3dc2a21fe1800bf7a70ef2b", "sha256": "06113d6bcec0a77239754e6fb5bc6920f8fbc37c954acdb3320d552938efc986" }, "downloads": -1, "filename": "scalpl-0.2.6-py3-none-any.whl", "has_sig": false, "md5_digest": "6fc4402da3dc2a21fe1800bf7a70ef2b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 5919, "upload_time": "2018-09-04T20:17:20", "url": "https://files.pythonhosted.org/packages/29/a6/64d413e6b0dbffab30f09c5bfa8dadeaf7252afbb011d16dcd6c71c6c576/scalpl-0.2.6-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "619d3a2a8dd2be6f24624c11f98dc380", "sha256": "8078ebec893f60b60d3301011039eb512e73be6d91fbb3d78ea3b3eb3b907c63" }, "downloads": -1, "filename": "scalpl-0.2.6.tar.gz", "has_sig": false, "md5_digest": "619d3a2a8dd2be6f24624c11f98dc380", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6540, "upload_time": "2018-09-04T20:17:22", "url": "https://files.pythonhosted.org/packages/4c/2f/735be75e9569850033fc87f682e92874b44c768e5ada0755a202e2ef19b3/scalpl-0.2.6.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "a52488969ef4500e7c41e600bbeec5df", "sha256": "51d07d720d0f26bb70502e42297b45a63d6fa14ab1f9af1683ed64ab49db27f9" }, "downloads": -1, "filename": "scalpl-0.3.0.tar.gz", "has_sig": false, "md5_digest": "a52488969ef4500e7c41e600bbeec5df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8415, "upload_time": "2019-08-08T11:19:41", "url": "https://files.pythonhosted.org/packages/fe/c9/ac25ec1d4a5347629453916d1cbdac217b226486e87266b5d466fad595b9/scalpl-0.3.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a52488969ef4500e7c41e600bbeec5df", "sha256": "51d07d720d0f26bb70502e42297b45a63d6fa14ab1f9af1683ed64ab49db27f9" }, "downloads": -1, "filename": "scalpl-0.3.0.tar.gz", "has_sig": false, "md5_digest": "a52488969ef4500e7c41e600bbeec5df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8415, "upload_time": "2019-08-08T11:19:41", "url": "https://files.pythonhosted.org/packages/fe/c9/ac25ec1d4a5347629453916d1cbdac217b226486e87266b5d466fad595b9/scalpl-0.3.0.tar.gz" } ] }