# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['dict_deep']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'dict-deep',
    'version': '4.0.1',
    'description': "Very simple deep_set and deep_get functions to access nested dicts (or any object) using 'dotted strings' as key.",
    'long_description': '## Description\n\nSimple functions to set or get values from a nested dict structure or in fact a deep structure of any object, because\nsince version 2 we no longer assume we are dealing with dicts.\n\nYou may use a custom accessor or pass your own getter, setter, deleter callables so that you can traverse a nested\nstructure of any kind of object.\n\nThis module DOES NOT implement dotted notation as an alternative access method for dicts.\nI generally do not like changing python dicts to enable dot notation, hence no available\npackage fitted my needs for a simple deep accessor.\n\nNEW IN VERSION 4:\nSince version 3 we make no assumption that we are dealing with dicts, so you can have your nested\nstructure of any type. However, in version 4 we reintroduce better defaults so that for those that\nare indeed working with nested dicts the default values shall be enough without having to define an\naccessor or a getter.\n\nNotes:\nWith deep_get, you could use \'lambda o, k: o[k]\' or \'lambda o, k: o.get(k)\' as either the getter or the accessor.\nThe only \'special\' thing about the \'getter\' function is that when it is invoked with \'o\' being a list and \'k\' being a\nstring, it will instead iterate over the list and call the accessor for each item in the list.\n\nIn a simplified way, this is how deep_get works:\n\n1. The key is broken down into a list of keys: "customer.address.city" -> [\'customer\', \'address\', \'city\'] \n\n2. The list of keys is iterated over, calling the getter for each key and the last value retrieved is returned.\n```\nfor k in keys[:-1]:\n    if o is None:\n        return o\n    o = getter(o, k)\n\n    o = getter_last_step(o, k[-1])\n\nreturn o\n```\n\nYou see that getter could be as simple as \'lambda o, k: o.get(k)\'. However, by default the code uses a smarter getter as\ndefined below, which tries to deal properly with nested lists.\n\n```\ndef __default_getter(o, k):\n    if isinstance(o, list):\n        return [accessor(i, k) for i in o]\n    else:\n        return accessor(o, k)\n```\n\nIf you do not want this checks for nested lists, just pass your own getter which could just as well\nbe \'lambda o, k: o.get(k)\'.\n\nThe default setter also knows how to deal with nested lists:\n```\ndef __default_setter(o, k, v):\n    n_set = 0\n    if isinstance(o, list):\n        for i in o:\n            i[k] = v\n            n_set += 1\n        return n_set\n    else:\n        o[k] = v\n        return 1\n```\nYou could just as well replace if with your own \'setter=lambda o, k, v: o[k]=v\' if you know that\nyou have no nested lists in your structures and want to avoid the overhead, but in that case you should\nalso change the getter \'getter=lambda o, k: o.get(k)\'.\n\nHowever, if you like the list handling skills of the code but just needs to change the way the value is retrieved,\nin this case you pass an accessor only to deep_get or deep_set which could be, say, \'lambda o, k: o.getValueById(k)\'\n\n\n## Functions\n\n*deep_get* accepts:\n- o: required. Any object, usually a dictionary\n- k: required. The key or keys, must be a string or anything accepted by the list() constructor\n- accessor: optional, callable: Takes o, k (object and key) and returns the value. Default accessor is\n  \'lambda o, k: o.get(k) if hasattr(o, "get") else o[k]\'\n- getter: optional, callable. If getter is set, accessor is ignored. Takes an object and a key as arguments and returns\n  a value\n- getter_last_step: optional, callable. The getter to be used on the last step (with the last key). By default,\n  if the last key is a list of keys, it returns a dict {k[0]: o[k[0]], k[1]: o[k[1]]}. If the last object is a list, it returns a list\n  of dicts [{k[0]: o[0][k[0]]], k[1]: o[0][k[1]]}, {k[0]: o[1][k[0]]], k[1]: o[1][k[1]]}, ...]\n- sep: optional, string: by default it is a dot \'.\', you can use anything the string function split will accept\n\nReturns o[k]\n\n\n*deep_set* accepts:\n- o: see \'deep_get\'\n- k: see \'deep_get\'\n- v: required, the value that will be set\n- accessor: optional, callable: see \'deep_get\'. For the deep_set function, the default accessor is:\n  \'lambda o, k: o.setdefault(k, dict()) if hasattr(o, "setdefault") else o[k]\'\n- getter: optional, callable: see \'deep_get\'\n- setter: optional, callable. A callable that takes 3 parameters: o, k, v - where o = any object, k = key, v = value\n- sep: optional, string: see \'deep_get\'\n\nNo return value\n\n\n*deep_del* accepts:\n- o: required: see \'deep_get\'\n- k: required: see \'deep_get\'\n- accessor: optional, callable: see \'deep_get\'\n- getter: optional, callable: see \'deep_get\'\n- deleter: optional, callable: Takes 2 parameters: o, k (object and key).\n- sep: optional, string: see \'deep_get\'\n\nReturns an integer with the number of entries that were deleted.\n\n\n## Example / Usage\n\n```\nfrom dict_deep import deep_get, deep_set, deep_del\n\n\ni = 0\n\n# 1\ni += 1\no = {\'a\': {\'b\': {}}}\ndeep_set(o, "a.b.c", "Hello World")\nprint("{}: {}".format(i, deep_get(o, "a.b.c")))\n\n# 2\ni += 1\no = {}\ndeep_set(o, [\'a\', \'b\', \'c\'], "Hello World")\nprint("{}: {}".format(i, deep_get(o, "a.b.c")))\n\n# 3\ni += 1\no = {}\ndeep_set(o, "a->b->c", "Hello World", sep="->")\nprint("{}: {}".format(i, deep_get(o, "a->b->c", sep="->")))\n\n# 4\ni += 1\no = {}\ndeep_set(o, "a->b->c", "Hello World", getter=lambda o, k: o.setdefault(k, dict()), sep="->")\nprint("{}: {}".format(i, deep_get(o, "a->b->c", sep="->")))\n\n# 5\ni += 1\no = {}\nkeys = \'a.b.c\'\nkeys = keys.split(\'.\')\n_ = deep_get(o=o, k=keys[0:-1], accessor=lambda o, k: o.setdefault(k, dict()), sep=".")\n_[keys[-1]] = "Hello World"\nprint("{}: {}".format(i, deep_get(o, keys)))\n\n# 6\ni += 1\no = {}\ndeep_set(o, "1.1.1", \'a\', accessor=lambda o, k: o.setdefault(k, dict()))\ndeep_set(o, "1.1.2", \'Hello World\')\ndeep_set(o, "1.1.3", \'c\')\ndeep_del(o, "1.1.2")\nprint("{}: {}".format(i, o))\n\n# 7\ni += 1\no = {\'students\': [{\'name\': \'Joe\', \'age\': 10, \'gender\': \'male\'}, {\'name\': \'Maria\', \'age\': 12, \'gender\': \'female\'}]}\nkeys = [\'students\', \'name\']\nprint("{}: {}".format(i, deep_get(o, keys)))\n\n# 8\ni += 1\nkeys = [\'students\', [\'name\', \'age\']]\nprint("{}: {}".format(i, deep_get(o, keys)))\n\n# 9\ni += 1\nkeys = [\'students\', \'gender\']\ndeep_set(o, keys, \'Nowadays better not ask\')\nprint("{}: {}".format(i, o))\n\n# 10\ni += 1\nkeys = [\'students\', \'gender\']\ndeep_del(o, keys)\nprint("{}: {}".format(i, o))\n```\n',
    'author': 'mbello',
    'author_email': 'mbello@users.noreply.github.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/mbello/dict-deep',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.5,<4.0',
}


setup(**setup_kwargs)
