{"id":20812140,"url":"https://github.com/skifli/pyattr","last_synced_at":"2025-05-07T10:16:09.953Z","repository":{"id":65958452,"uuid":"603437935","full_name":"skifli/pyattr","owner":"skifli","description":"Proper access modifiers for Python.","archived":false,"fork":false,"pushed_at":"2023-08-30T15:03:44.000Z","size":50,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-29T18:53:22.486Z","etag":null,"topics":["access-control","mangling","python"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/pyattr","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/skifli.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2023-02-18T14:11:19.000Z","updated_at":"2023-06-16T17:15:36.000Z","dependencies_parsed_at":"2024-11-17T20:50:58.913Z","dependency_job_id":"f752e63d-c053-4407-9885-3b00a967d29d","html_url":"https://github.com/skifli/pyattr","commit_stats":{"total_commits":21,"total_committers":1,"mean_commits":21.0,"dds":0.0,"last_synced_commit":"46408e23621b8ee333ac71bb07f982d983f7b6e9"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skifli%2Fpyattr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skifli%2Fpyattr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skifli%2Fpyattr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skifli%2Fpyattr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skifli","download_url":"https://codeload.github.com/skifli/pyattr/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252856562,"owners_count":21814858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["access-control","mangling","python"],"created_at":"2024-11-17T20:50:42.047Z","updated_at":"2025-05-07T10:16:09.929Z","avatar_url":"https://github.com/skifli.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pyattr\n\n[![PyPI](https://img.shields.io/pypi/v/pyattr)](https://pypi.org/project/pyattr)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/pyattr)](https://pypi.org/project/pyattr/#files)\n![Lines of Code](https://img.shields.io/github/languages/code-size/skifli/pyattr)\n\n- [pyattr](#pyattr)\n  - [Installation](#installation)\n  - [Usage](#usage)\n  - [Example](#example)\n  - [How it works](#how-it-works)\n  - [Benchmarks](#benchmarks)\n\nWhile Python does have name mangling, it is not nearly as powerful as access modifiers found in languages such as C++. **pyattr** provides an easy-to-use API for access modifiers in Python.\n\n## Installation\n\nInstallation via **pip**:\n\n```\npip install pyattr\n```\n\n## Usage\n\nAll you have to do is make your class inherit from the *`pyattr.Pyattr`* class, and add *`super().__init__()`* as the first line in the *`__init__`* function of your class. And that's it! **pyattr** will handle the magic to make sure variables cannot be accessed / set where the shouldn't be. It also provides useful error messages to users.\n\n## Example\n\nHere is a simple example involving a *private* variable.\n\n```python\nfrom pyattr import Pyattr\n\nclass Example(Pyattr):\n    def __init__(self) -\u003e None:\n        super().__init__()\n\n        self.__name = \"pyattr\"\n\nexample = Example()\nprint(example.__name) # Error - '__name' is a private attribute of 'Example'.\n```\n\nAs well as variables, **pyattr** also supports access control of *functions*!\n\n```python\nfrom pyattr import Pyattr\n\nclass Example(Pyattr):\n    def __init__(self) -\u003e None:\n        super().__init__()\n\n    def __example(self) -\u003e None:\n        pass\n\n\nexample = Example()\nprint(example.__example())  # Error - '__example' is a private attribute of 'Example'.\n```\n\n## How it works\n\n\u003e [!NOTE]\n\u003e For a more in-depth explanation on how **pyattr** works, see my [blog post](https://skifli.github.io/blog/2023/pyattr_in_depth_explanation.html#how-does-pyattr-work).\n\n**pyattr** overrides the default *set* and *get* functions of your class. The overridden functions defined by **pyattr** are merged into your class when you inherit from the *`pyattr.Pyattr`* class. As well as this, the *`pyattr.Pyattr`* class inherits from the *`pyattr._PyattrDict`* class, which provides a custom dictionary implementation. This is because you can change the variables in a class using *`class.__dict__[\"var\"] = \"val\"`*, meaning a custom dictionary would be the best way to prevent the access system being circumvented.\n\nThe overriden *set* and *get* functions of your class call the respective *set* and *get* functions of the custom dictionary. This dictionary, using *`sys._getframe()`*, works out the caller's function, and the caller's class (if any). It uses this data to work out if the caller should be allowed to access the specified variables. If it shouldn't, an *`AttributeError`* is raised, with an error message explaining the cause.\n\n## Benchmarks\n\nThe code for the benchmarks can be found in the [benchmark](https://github.com/skifli/pyattr/blob/main/benchmark/) folder.\n\n[![Benchmark Output](https://raw.githubusercontent.com/skifli/pyattr/main/benchmark/output.png)](https://github.com/skifli/pyattr/blob/main/benchmark/bench_test.py)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskifli%2Fpyattr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskifli%2Fpyattr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskifli%2Fpyattr/lists"}