{"id":13737972,"url":"https://github.com/pwwang/diot","last_synced_at":"2026-03-06T17:07:30.757Z","repository":{"id":46965433,"uuid":"225976927","full_name":"pwwang/diot","owner":"pwwang","description":"Python dictionary with dot notation","archived":false,"fork":false,"pushed_at":"2025-04-19T03:04:49.000Z","size":1016,"stargazers_count":12,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-03-05T18:51:43.590Z","etag":null,"topics":["dictionaries","diot","dot-notation","python-dictionary"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pwwang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-12-04T23:38:42.000Z","updated_at":"2025-12-18T21:08:09.000Z","dependencies_parsed_at":"2022-09-07T22:23:03.991Z","dependency_job_id":"621e2455-75c7-4d0d-87d7-b56057cf7f1d","html_url":"https://github.com/pwwang/diot","commit_stats":{"total_commits":71,"total_committers":2,"mean_commits":35.5,"dds":"0.028169014084507005","last_synced_commit":"54b7494d143846b3cbc0224351322e5d4b64a86b"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":"pwwang/pyparam","purl":"pkg:github/pwwang/diot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fdiot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fdiot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fdiot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fdiot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwwang","download_url":"https://codeload.github.com/pwwang/diot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fdiot/sbom","scorecard":{"id":750945,"data":{"date":"2025-08-11","repo":{"name":"github.com/pwwang/diot","commit":"ca3a99a2add4b6f9d6ebd6b00ce3ddf421beaca8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/docs.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/docs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/docs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/docs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docs.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/pwwang/diot/docs.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:21","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:22","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:23","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:57","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:58","Warn: pipCommand not pinned by hash: .github/workflows/docs.yml:19","Warn: pipCommand not pinned by hash: .github/workflows/docs.yml:20","Warn: pipCommand not pinned by hash: .github/workflows/docs.yml:25","Warn: pipCommand not pinned by hash: .github/workflows/docs.yml:26","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of   9 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-gmj6-6f8f-6699","Warn: Project is vulnerable to: GHSA-h5c8-rqwp-cp95","Warn: Project is vulnerable to: GHSA-h75v-3vvj-5mfj","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h","Warn: Project is vulnerable to: GHSA-jh85-wwv9-24hv"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T20:21:18.286Z","repository_id":46965433,"created_at":"2025-08-22T20:21:18.286Z","updated_at":"2025-08-22T20:21:18.286Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30186781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T14:42:24.748Z","status":"ssl_error","status_checked_at":"2026-03-06T14:42:14.925Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dictionaries","diot","dot-notation","python-dictionary"],"created_at":"2024-08-03T03:02:07.596Z","updated_at":"2026-03-06T17:07:30.711Z","avatar_url":"https://github.com/pwwang.png","language":"Python","readme":"![Logo](https://raw.githubusercontent.com/pwwang/diot/master/logo.png)\n\n[![pypi][1]][2] [![tag][3]][4] [![codacy quality][7]][8] [![coverage][9]][8] ![pyver][10] ![building][6] ![docs][5]\n\nPython dictionary with dot notation (A re-implementation of [python-box](https://github.com/cdgriffith/Box) with some issues fixed and simplified)\n\n```python\nfrom diot import Diot\n\nmovie_data = {\n  \"movies\": {\n    \"Spaceballs\": {\n      \"imdb stars\": 7.1,\n      \"rating\": \"PG\",\n      \"length\": 96,\n      \"director\": \"Mel Brooks\",\n      \"stars\": [{\"name\": \"Mel Brooks\", \"imdb\": \"nm0000316\", \"role\": \"President Skroob\"},\n                {\"name\": \"John Candy\",\"imdb\": \"nm0001006\", \"role\": \"Barf\"},\n                {\"name\": \"Rick Moranis\", \"imdb\": \"nm0001548\", \"role\": \"Dark Helmet\"}\n      ]\n    },\n    \"Robin Hood: Men in Tights\": {\n      \"imdb stars\": 6.7,\n      \"rating\": \"PG-13\",\n      \"length\": 104,\n      \"director\": \"Mel Brooks\",\n      \"stars\": [\n                {\"name\": \"Cary Elwes\", \"imdb\": \"nm0000144\", \"role\": \"Robin Hood\"},\n                {\"name\": \"Richard Lewis\", \"imdb\": \"nm0507659\", \"role\": \"Prince John\"},\n                {\"name\": \"Roger Rees\", \"imdb\": \"nm0715953\", \"role\": \"Sheriff of Rottingham\"},\n                {\"name\": \"Amy Yasbeck\", \"imdb\": \"nm0001865\", \"role\": \"Marian\"}\n      ]\n    }\n  }\n}\n\n# Box is a conversion_box by default, pass in `conversion_box=False` to disable that behavior\n# Explicitly tell Diot to convert dict/list inside\nmovie_diot = Diot(movie_data)\n\nmovie_diot.movies.Robin_Hood_Men_in_Tights.imdb_stars\n# 6.7\n\nmovie_diot.movies.Spaceballs.stars[0].name\n# 'Mel Brooks'\n\n# Different as box, you have to use Diot for new data in a list\nmovie_diot.movies.Spaceballs.stars.append(\n\tDiot({\"name\": \"Bill Pullman\", \"imdb\": \"nm0000597\", \"role\": \"Lone Starr\"}))\nmovie_diot.movies.Spaceballs.stars[-1].role\n# 'Lone Starr'\n```\n\n## Install\n```shell\npip install -U diot\n```\n\n## API\n\nhttps://pwwang.github.io/diot/api/diot/\n\n\n## Usage\n\n### Diot\n\nInstantiated the same ways as `dict`\n```python\nDiot({'data': 2, 'count': 5})\nDiot(data=2, count=5)\nDiot({'data': 2, 'count': 1}, count=5)\nDiot([('data', 2), ('count', 5)])\n\n# All will create\n# Diot([('data', 2), ('count', 5)], diot_nest = True, diot_transform = 'safe')\n```\n\nSame as `python-box`, `Diot` is a subclass of dict which overrides some base functionality to make sure everything stored in the dict can be accessed as an attribute or key value.\n\n```python\ndiot = Diot({'data': 2, 'count': 5})\ndiot.data == diot['data'] == getattr(diot, 'data')\n```\n\nBy default, diot uses a safe transformation to transform keys into safe names that can be accessed by `diot.xxx`\n```python\ndt = Diot({\"321 Is a terrible Key!\": \"yes, really\"})\ndt._321_Is_a_terrible_Key_\n# 'yes, really'\n```\n\nDifferent as `python-box`, duplicate attributes are not allowed.\n```python\ndt = Diot({\"!bad!key!\": \"yes, really\", \".bad.key.\": \"no doubt\"})\n# KeyError\n```\n\nUse different transform functions:\n\n```python\ndt = Diot(oneTwo = 12, diot_transform = 'snake_case')\n# or use alias:\n# dt = SnakeDiot(oneTwo = 12)\ndt.one_two == dt['one_two'] == dt['oneTwo'] == 12\n\ndt = Diot(one_two = 12, diot_transform = 'camel_case')\n# or use alias:\n# dt = CamelDiot(one_two = 12)\ndt.oneTwo == dt['one_two'] == dt['oneTwo'] == 12\n\ndt = Diot(one_two = 12, diot_transform = 'upper')\ndt.ONE_TWO == dt['one_two'] == dt['ONETWO'] == 12\n\ndt = Diot(ONE_TWO = 12, diot_transform = 'lower')\ndt.one_two == dt['ONE_TWO'] == dt['one_two'] == 12\n```\n\nUse your own transform function:\n\n```python\nimport inflection\n\ndt = Diot(post = 10, diot_transform = inflection.pluralize)\ndt.posts == dt['posts'] == dt['post'] == 10\n```\n\n### OrderedDiot\n```python\ndiot_of_order = OrderedDiot()\ndiot_of_order.c = 1\ndiot_of_order.a = 2\ndiot_of_order.d = 3\n\nlist(diot_of_order.keys()) == ['c', 'a', 'd']\n\n# insertion allowed for OrderedDiot\nod = OrderedDiot()\nod.insert(0, \"c\", \"d\")\nod.insert(None, \"x\", \"y\")\nod.insert_before('c', \"e\", \"f\")\nod.insert_after(\"a\", (\"g\", \"h\"))\n\nod2 = OrderedDiot()\nod2.a1 = 'b1'\nod2.c1 = 'd1'\nod.insert(-1, od2)\n\nod3 = OrderedDiot()\nod3.a2 = 'b2'\nod3.c2 = 'd2'\nod.insert_before('c', od3)\n```\n\n### FrozenDiot\n\n```python\nfd = FrozenDiot(a=1, b=3)\nfd.c = 3 # DiotFrozenError\nwith fd.thaw():\n    fd.c = 3\nfd.c == 3\n```\n\n### Missing key handler\n\n```python\nd = Diot(a=1, b=2, diot_missing=ValueError)\nd['c'] # ValueError\nd.c # AttributeError from ValueError\n\nd = Diot(a=1, b=2, diot_missing=ValueError(\"Custom message\"))\n\nd = Diot(a=1, b=2, diot_missing=None)\n# d.c is None\n\nd = Diot(a=1, b=2, diot_missing=lambda key, diot: diot.a + diot.b)\n# d.c == 3\n```\n\n[1]: https://img.shields.io/pypi/v/diot?style=flat-square\n[2]: https://pypi.org/project/diot/\n[3]: https://img.shields.io/github/tag/pwwang/diot?style=flat-square\n[4]: https://github.com/pwwang/diot\n[5]: https://img.shields.io/github/actions/workflow/status/pwwang/diot/docs.yml?label=docs\u0026style=flat-square\n[6]: https://img.shields.io/github/actions/workflow/status/pwwang/diot/build.yml?style=flat-square\n[7]: https://img.shields.io/codacy/grade/738e49b9cc1745c4ae6a7bb3b198cc3d?style=flat-square\n[8]: https://app.codacy.com/gh/pwwang/diot/dashboard\n[9]: https://img.shields.io/codacy/coverage/738e49b9cc1745c4ae6a7bb3b198cc3d?style=flat-square\n[10]: https://img.shields.io/pypi/pyversions/diot?style=flat-square\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwwang%2Fdiot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwwang%2Fdiot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwwang%2Fdiot/lists"}