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

package_dir = \
{'': 'src'}

packages = \
['ldict']

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

install_requires = \
['garoupa>=2.210907.7,<3.0.0',
 'lange>=0.2101.24,<0.2102.0',
 'orjson>=3.5.0,<4.0.0',
 'pdoc3>=0.10.0,<0.11.0',
 'uncompyle6>=3.7.4,<4.0.0']

setup_kwargs = {
    'name': 'ldict',
    'version': '2.210908.8',
    'description': 'Lazy dict with universally unique identifier for values',
    'long_description': '![test](https://github.com/davips/ldict/workflows/test/badge.svg)\n[![codecov](https://codecov.io/gh/davips/ldict/branch/main/graph/badge.svg)](https://codecov.io/gh/davips/ldict)\n<div style="background-color: rgb(15, 20, 25);">\n\n# ldict\nUniquely identified lazy dict.\n\n[Latest version as a package](https://pypi.org/project/ldict)\n\n[Current code](https://github.com/davips/ldict)\n\n## Overview\nWe consider that every value or data object is generated by a process, starting from `empty`.\nThe process is a sequence of transformation steps that can be of two types:\nvalue insertion and function application.\nValue insertion is done using dict-like objects as shown below.\nThe operator `>>` concatenate the steps chronologically.\nEach value and each function have unique deterministic identifiers.\nIdentifiers for future values are predictable through the magic available [here](https://pypi.org/project/garoupa).\n![img.png](https://raw.githubusercontent.com/davips/ldict/main/examples/img.png)\n\nFunction application is done in the same way.\nThe parameter names define the input fields,\nwhile the keys in the returned dict define the output fields:\n![img_1.png](https://raw.githubusercontent.com/davips/ldict/main/examples/img_1.png)\n\nSimilarly, for anonymous functions:\n![img_5.png](https://raw.githubusercontent.com/davips/ldict/main/examples/img_5.png)\n\nFinally, the result is only evaluated at request:\n![img_6.png](https://raw.githubusercontent.com/davips/ldict/main/examples/img_6.png)\n![img_7.png](https://raw.githubusercontent.com/davips/ldict/main/examples/img_7.png)\n\n\n## Installation\n### ...as a standalone lib\n```bash\n# Set up a virtualenv. \npython3 -m venv venv\nsource venv/bin/activate\n\n# Install from PyPI...\npip install --upgrade pip\npip install -U ldict\n\n# ...or, install from updated source code.\npip install git+https://github.com/davips/ldict\n```\n\n### ...from source\n```bash\ngit clone https://github.com/davips/ldict\ncd ldict\npoetry install\n```\n\n## Examples\n**Merging two ldicts**\n<details>\n<p>\n\n```python3\nfrom ldict import ldict\n\na = ldict(x=3)\nprint(a)\n"""\n{\n    "id": "kr_4aee5c3bcac2c478be9901d57fd1ef8a9d002",\n    "ids": "kr_4aee5c3bcac2c478be9901d57fd1ef8a9d002",\n    "x": 3\n}\n"""\n```\n\n```python3\n\nb = ldict(y=5)\nprint(b)\n"""\n{\n    "id": "Uz_0af6d78f77734fad67e6de7cdba3ea368aae4",\n    "ids": "Uz_0af6d78f77734fad67e6de7cdba3ea368aae4",\n    "y": 5\n}\n"""\n```\n\n```python3\n\nprint(a >> b)\n"""\n{\n    "id": "c._2b0434ca422114262680df425b85cac028be6",\n    "ids": "kr_4aee5c3bcac2c478be9901d57fd1ef8a9d002 Uz_0af6d78f77734fad67e6de7cdba3ea368aae4",\n    "x": 3,\n    "y": 5\n}\n"""\n```\n\n\n</p>\n</details>\n\n**Lazily applying functions to ldict**\n<details>\n<p>\n\n```python3\nfrom ldict import ldict\n\na = ldict(x=3)\nprint(a)\n"""\n{\n    "id": "kr_4aee5c3bcac2c478be9901d57fd1ef8a9d002",\n    "ids": "kr_4aee5c3bcac2c478be9901d57fd1ef8a9d002",\n    "x": 3\n}\n"""\n```\n\n```python3\n\na = a >> ldict(y=5) >> {"z": 7} >> (lambda x, y, z: {"r": x ** y // z})\nprint(a)\n"""\n{\n    "id": "8jopGVdtSEyCk1NSKcrEF-Lfv8up9MQBdvkLxU2o",\n    "ids": "J3tsy4vUXPELySBicaAy-h-UK7Dp9MQBdvkLxU2o... +2 ...Ss_7dff0a161ba7462725cac7dcee71b67669f69",\n    "r": "→(x y z)",\n    "x": 3,\n    "y": 5,\n    "z": 7\n}\n"""\n```\n\n```python3\n\nprint(a.r)\n"""\n34\n"""\n```\n\n```python3\n\nprint(a)\n"""\n{\n    "id": "8jopGVdtSEyCk1NSKcrEF-Lfv8up9MQBdvkLxU2o",\n    "ids": "J3tsy4vUXPELySBicaAy-h-UK7Dp9MQBdvkLxU2o... +2 ...Ss_7dff0a161ba7462725cac7dcee71b67669f69",\n    "r": 34,\n    "x": 3,\n    "y": 5,\n    "z": 7\n}\n"""\n```\n\n\n</p>\n</details>\n\n**Parameterized functions and sampling**\n<details>\n<p>\n\n```python3\nfrom random import Random\n\nfrom ldict import ø\nfrom ldict.cfg import cfg\n\n\n# A function provide input fields and, optionally, parameters.\n# \'a\' is sampled from an arithmetic progression\n# \'b\' is sampled from a geometric progression\n# Here, the syntax for default parameter values is borrowed with a new meaning.\ndef fun(x, y, a=[-100, -99, -98, ..., 100], b=[0.0001, 0.001, 0.01, ..., 100000000]):\n    return {"z": a * x + b * y}\n\n\n# Creating an empty ldict. Alternatively: d = ldict().\nd = ø >> {}\nd.show(colored=False)\n"""\n{\n    "id": "0000000000000000000000000000000000000000",\n    "ids": {}\n}\n"""\n```\n\n```python3\n\n# Putting some values. Alternatively: d = ldict(x=5, y=7).\nd["x"] = 5\nd["y"] = 7\nd.show(colored=False)\n"""\n{\n    "id": "I0_39c94b4dfbc7a8579ca1304eba25917204a5e",\n    "ids": {\n        "x": "Tz_d158c49297834fad67e6de7cdba3ea368aae4",\n        "y": "Rs_92162dea64a7462725cac7dcee71b67669f69"\n    },\n    "x": 5,\n    "y": 7\n}\n"""\n```\n\n```python3\n\n# Parameter values are uniformly sampled.\nd1 = d >> fun\nd.show(colored=False)\n"""\n{\n    "id": "I0_39c94b4dfbc7a8579ca1304eba25917204a5e",\n    "ids": {\n        "x": "Tz_d158c49297834fad67e6de7cdba3ea368aae4",\n        "y": "Rs_92162dea64a7462725cac7dcee71b67669f69"\n    },\n    "x": 5,\n    "y": 7\n}\n"""\n```\n\n```python3\n\nprint(d1.z)\n"""\n125.007\n"""\n```\n\n```python3\n\nd2 = d >> fun\nd.show(colored=False)\n"""\n{\n    "id": "I0_39c94b4dfbc7a8579ca1304eba25917204a5e",\n    "ids": {\n        "x": "Tz_d158c49297834fad67e6de7cdba3ea368aae4",\n        "y": "Rs_92162dea64a7462725cac7dcee71b67669f69"\n    },\n    "x": 5,\n    "y": 7\n}\n"""\n```\n\n```python3\n\nprint(d2.z)\n"""\n245.0\n"""\n```\n\n```python3\n\n# Parameter values can also be manually set.\ne = d >> cfg(a=5, b=10) >> fun\nprint(e.z)\n"""\n95\n"""\n```\n\n```python3\n\n# Not all parameters need to be set.\ne = d >> cfg(a=5) >> fun\nprint(e.z)\n"""\n25.0007\n"""\n```\n\n```python3\n\n# Each run will be a different sample for the missing parameters.\ne = e >> cfg(a=5) >> fun\nprint(e.z)\n"""\n32.0\n"""\n```\n\n```python3\n\n# The metaparameter \'rnd\' defines the initial state of the random sampler for this point onwards processing the ldict.\ne = d >> cfg(a=5)(rnd=0) >> fun\nprint(e.z)\n"""\n725.0\n"""\n```\n\n```python3\n\n# All runs will yield the same result, if starting from the same random number generator seed.\ne = e >> cfg(a=5)(rnd=0) >> fun\nprint(e.z)\n"""\n725.0\n"""\n```\n\n```python3\n\n# Reproducible different runs are achievable by passing a stateful random number generator, instead of a seed.\nrnd = Random(0)\ne = d >> cfg(a=5)(rnd=rnd) >> fun\nprint(e.z)\n"""\n725.0\n"""\n```\n\n```python3\n\ne = d >> cfg(a=5)(rnd=rnd) >> fun\nprint(e.z)\n"""\n700000025.0\n"""\n```\n\n\n</p>\n</details>\n\n**Composition of sets of functions**\n<details>\n<p>\n\n```python3\nfrom random import Random\n\nfrom ldict import ø\n\n\n# A multistep process can be defined without applying its functions\nfrom ldict.cfg import cfg\n\n\ndef g(x, y, a=[1, 2, 3, ..., 10], b=[0.00001, 0.0001, 0.001, ..., 100000]):\n    return {"z": a * x + b * y}\n\n\ndef h(z, c=[1, 2, 3]):\n    return {"z": c * z}\n\n\n# In the ldict framework \'data is function\',\n# so the alias ø represents the \'empty data object\' and the \'reflexive function\' at the same time.\n# In other words: \'inserting nothing\' has the same effect as \'doing nothing\'.\nfun = ø * g * h  # ø enable the cartesian product of the subsequent sets of functions within the expression.\nprint(fun)\n"""\ng×h\n"""\n```\n\n```python3\n\n# The difference between \'ø * g * h\' and \'ldict(x=3) >> g >> h\' is that the functions in the latter are already applied\n# (resulting in an ldict object). The former still has its free parameters unsampled,\n# and results in an ordered set of composite functions.\n# It is a set because the parameter values of the functions are still undefined.\nd = {"x": 5, "y": 7} >> fun\nprint(d)\n"""\n{\n    "id": "fW1sfhJxYcI0bsnvzzvI4IivY4mX6Nqw027wEroQ",\n    "ids": "DNBcbS.LSuPNOX6CToaCuHK8KVlX6Nqw027wEroQ... +1 ...Rs_92162dea64a7462725cac7dcee71b67669f69",\n    "z": "→(z→(x y a b) c)",\n    "x": 5,\n    "y": 7\n}\n"""\n```\n\n```python3\n\nprint(d.z)\n"""\n14090.0\n"""\n```\n\n```python3\n\nd = {"x": 5, "y": 7} >> fun\nprint(d.z)\n"""\n7020.0\n"""\n```\n\n```python3\n\n# Reproducible different runs by passing a stateful random number generator.\nrnd = Random(0)\ne = d >> cfg()(rnd=rnd) >> fun\nprint(e.z)\n"""\n105.0\n"""\n```\n\n```python3\n\ne = d >> cfg()(rnd=rnd) >> fun\nprint(e.z)\n"""\n14050.0\n"""\n```\n\n```python3\n\nrnd = Random(0)\ne = d >> cfg()(rnd=rnd) >> fun\nprint(e.z)\n"""\n105.0\n"""\n```\n\n```python3\n\ne = d >> cfg()(rnd=rnd) >> fun\nprint(e.z)\n"""\n14050.0\n"""\n```\n\n\n</p>\n</details>\n\n<!--- ## Persistence\nExtra dependencies can be installed to support saving data to disk or to a server in the network. \n\n**[still an ongoing work...]**\n\n`poetry install -E full`\n--->\n\n## Concept\nA ldict is like a common Python dict, with extra functionality and lazy.\nIt is a mapping between string keys, called fields, and any serializable object.\nThe ldict `id` (identifier) and the field `ids` are also part of the mapping.  \n\nThe user can provide a unique identifier ([hosh](https://pypi.org/project/garoupa))\nfor each function or value object.\nOtherwise, they will be calculated through blake3 hashing of the content of data or bytecode of function.\nFor this reason, such functions should be simple, i.e.,\nwith minimal external dependencies, to avoid the unfortunate situation where two\nfunctions with identical local code actually perform different calculations through\ncalls to external code that implement different algorithms with the same name.\n<!--- Alternatively, a Hosh object can be passed inside the dict that is returned by the function, under the key "_id". --->\n\n## Grants\nThis work was partially supported by Fapesp under supervision of\nProf. André C. P. L. F. de Carvalho at CEPID-CeMEAI (Grants 2013/07375-0 – 2019/01735-0).\n\n</div>\n',
    'author': 'davips',
    'author_email': 'dpsabc@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'package_dir': package_dir,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
