{"id":18521758,"url":"https://github.com/simphotonics/lockattrs","last_synced_at":"2025-05-14T18:09:15.589Z","repository":{"id":62576604,"uuid":"428811407","full_name":"simphotonics/lockattrs","owner":"simphotonics","description":"Python decorator used to lock class attributes.","archived":false,"fork":false,"pushed_at":"2021-12-01T18:15:49.000Z","size":88,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-18T09:46:18.637Z","etag":null,"topics":["attributes","locking","modifier","python3","visibility"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/lockattrs","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simphotonics.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}},"created_at":"2021-11-16T20:58:36.000Z","updated_at":"2021-12-01T18:15:52.000Z","dependencies_parsed_at":"2022-11-03T18:44:32.501Z","dependency_job_id":null,"html_url":"https://github.com/simphotonics/lockattrs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flockattrs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flockattrs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flockattrs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flockattrs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simphotonics","download_url":"https://codeload.github.com/simphotonics/lockattrs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198510,"owners_count":22030966,"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":["attributes","locking","modifier","python3","visibility"],"created_at":"2024-11-06T17:27:31.118Z","updated_at":"2025-05-14T18:09:10.581Z","avatar_url":"https://github.com/simphotonics.png","language":"Python","readme":"# Locking Class Attributes\n[![tests](https://github.com/simphotonics/lockattrs/actions/workflows/tests.yml/badge.svg)](https://github.com/simphotonics/lockattrs/actions/workflows/tests.yml)\n[![docs](https://raw.githubusercontent.com/simphotonics/lockattrs/main/images/docs-badge.svg)](https://lockattrs.simphotonics.com)\n\nMost object oriented languages (C++, Java, Dart, Kotlin, Swift)\ninclude visibiliy modifiers. This enables\nencapsulation where for example the inner workings of a class\ncan be detached from the outside world and thus protected from\ndirect modification.\n\nPython on the other hand does not have a language-backed concept\nof privacy. Instead functions or variables with an identifier\nthat starts with an underscore are\ndeemed private and should not be modified or otherwise\nrelied upon since they may change in a future version of the module.\n\nIn some cases, certain attributes may be crucial for the\ncorrect working a class and the programmer might\nwant to pervent any inadvertent modification.\n\nThe package [`lockattrs`][lockattrs] provides a decorator that can\nbe used with the method `__setattr__` to lock certain attributes\nor all attributes.\n\nNote that despite the name similarity [`lockattrs`][lockattrs] is\nnot related to the package [`attrs`][attrs] providing\na concise way of creating and validating data classes.\n\n\n## Installation\n\nTo install the package [`lockattrs`][lockattrs] use the command:\n```Console\n$ pip install lockattrs\n```\n\n## Usage\n\nThis package provides the decorator function [`protect`][protect] which can be\nused to prevent modification of attributes\nafter they have been initially set.\n\n### 1. Locking Class Attributes\n\nThe intended use-case is demonstrated below. Locking the\ninstance attributes of a meta-class is equivalent to\nlocking the class attributes of the class (the meta-class instance).\n\nUsing the decorator [`protect`][protect] involves the following steps:\n\n1. Declare a meta-class.\n2. Override the method `__setattr__`.\n3. Decorate `__setattr__` with the function [`protect`][protect].\n4. Optionally: Specify which attributes should be locked and\n   what type of error should be raised during an attribute\n   modification attempt.\n\n``` Python\nfrom lockattrs import protect\n\nclass AMeta(type):\n    \"\"\"\n    Meta class of A.\n    \"\"\"\n    @protect(('data','id'), )\n    def __setattr__(self, name: str, value: Any) -\u003e None:\n        return super().__setattr__(name, value)\n\nclass A(metaclass=AMeta):\n    id = 'a01'\n    pass\n\nA.id = 'b02'            # Raises an error. Attribute 'id' is set and locked.\n\nA.data = 'initial-data' # First initiation is OK. Attribute 'data' is now locked.\nA.data = 'new-data'     # Raises an error (default type: ProtectedAttributeError).\n\nA.name = 'A'\nA.name = 'A1'           # OK, since the attribute 'name' is not locked.\n```\n\n### 2. Locking Instance Attributes\n\nThe code below demonstrates how to use the decorator\nfunction `@protect` to lock certain attributes of a class instance.\n\n``` Python\nfrom lockattrs import protect\n\nclass B():\n    \"\"\"\n    Sample class with locked attributes.\n    \"\"\"\n    id = 57\n\n    @protect(('data','id'), ) # To lock all attributes use: @protect()\n    def __setattr__(self, name: str, value: Any) -\u003e None:\n        return super().__setattr__(name, value)\n\n\n\nB.id = 28               # OK. Class attributes are not locked.\n                        # To lock class attributes see section above.\n\n# Creating an instance of B.\nb = B()\n\nb.id = 77               # Modification of the attribute 'id' via 'self' raises\n                        # an error since the annotated method `__setattr__` is\n                        # called. \n\nb.data = 'initial-data' # First initiation is OK. Attribute 'data' is now locked.\nb.data = 'new-data'     # Raises an error (default type: ProtectedAttributeError).\n\nb.name = 'b'\nb.name = 'b1'           # OK, since the attribute 'name' is not locked.\n```\n\n\n## Performance\n\nNote: Locking certain attributes may be prohibitively\ncostly in terms of computational time\nwhen used with objects that are\ninstantiated often (for example in a loop)\nand where attributes are set/modified frequently.\n\nThe benchmarks below were produced using the package\n[`pytest-benchmark`][pytest-benchmark] on a PC with 32GB RAM\nand an Intel Core i5-6260U CPU running at 1.80GHz.\nAs the mean runtimes show, setting an attribute of class `A`\ntakes approximately 40 times as long compared to a standard class\n(without an annotated `__setattr__` method).\n\n\n``` Console\n--------------------------------- benchmark: 2 tests -----------------------------------\nName (time in ns)                   Mean              StdDev          Rounds  Iterations\n----------------------------------------------------------------------------------------\ntest_benchmark_set_attrs        348.8611 (1.0)       66.8829 (1.0)         4       20000\ntest_benchmark_set_attrs_A   13,496.0524 (38.69)    912.2178 (13.64)       4       20000\n----------------------------------------------------------------------------------------\n```\n\n\n## Features and bugs\n\nPlease file feature requests and bugs at the [issue tracker].\nContributions are welcome.\n\n[issue tracker]: https://github.com/simphotonics/lockattrs/issues\n\n[attrs]: https://pypi.org/project/attrs\n\n[protect]: http://lockattrs.simphotonics.com/reference/lockattrs/decorators/#protect\n\n[pypi]: https:://pypi.org\n\n[pytest]: https://pypi.org/project/pytest/\n\n[pytest-benchmark]: https://pypi.org/project/pytest-benchmark/\n\n[lockattrs]: https://github.com/simphotonics/lockattrs","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Flockattrs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimphotonics%2Flockattrs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Flockattrs/lists"}