{"id":13831765,"url":"https://github.com/zmitchell/annotation-abuse","last_synced_at":"2026-03-02T13:36:49.855Z","repository":{"id":134798374,"uuid":"142714222","full_name":"zmitchell/annotation-abuse","owner":"zmitchell","description":"Rust-like macros in Python by abusing type annotations","archived":false,"fork":false,"pushed_at":"2019-08-22T15:57:31.000Z","size":4562,"stargazers_count":63,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-02T15:11:14.692Z","etag":null,"topics":["ast","macros","metaprogramming","python","python-decorators","rust"],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zmitchell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","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":"2018-07-28T22:29:28.000Z","updated_at":"2025-01-21T20:35:37.000Z","dependencies_parsed_at":"2023-05-15T13:45:31.796Z","dependency_job_id":null,"html_url":"https://github.com/zmitchell/annotation-abuse","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/zmitchell%2Fannotation-abuse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitchell%2Fannotation-abuse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitchell%2Fannotation-abuse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmitchell%2Fannotation-abuse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zmitchell","download_url":"https://codeload.github.com/zmitchell/annotation-abuse/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250435121,"owners_count":21430220,"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":["ast","macros","metaprogramming","python","python-decorators","rust"],"created_at":"2024-08-04T10:01:39.332Z","updated_at":"2026-03-02T13:36:44.815Z","avatar_url":"https://github.com/zmitchell.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"# Abusing Type Annotations\n\nRust-like \"macros\" in Python via egregious abuse of type annotations.\n\n## About\n\nThis project started out as an exploration into whether Rust-like macros could be brought to Python. Spoiler: They can be (but it's not pretty). Rust has more than one kind of macro, but \"procedural\" macros operate on the abstract syntax tree of your code (an abstract syntax tree is a data structure that represents your parsed code). This allows you to generate code or derive functionality provided by a library with very little effort on your part. It's pretty great.\n\nThe code in this repository is just a proof of concept, so you probably shouldn't use it for anything mission critical. If you want to read about what's going on here, how it works, etc, you can read the blog post:\n\n- [Bringing macros to Python by abusing type annotations](https://tinkering.xyz/abusing-type-annotations/)\n\n### Example 1 - Generating Instance Properties\nI fully committed to the Rust way of doing things for this example, and worked on ASTs the whole way through. This example provides a decorator, `@inrange`, that generates properties based on the annotations of class variables.\n\nThe `@inrange` macro would take this class definition\n```python\n@inrange\nclass MyClass:\n    var: \"0 \u003c var \u003c 1\"\n```\nand turn it into\n```python\nclass MyClass:\n    var: \"0 \u003c var \u003c 1\"\n\n    def __init__(self):\n        self._var = None\n\n    @property\n    def var(self):\n        return self._var\n\n    @var.setter\n    def var(self, new_value):\n        if (0 \u003c new_value) and (new_value \u003c 1):\n            self._var = new_value\n```\n\nIn this example the getter, setter, and `__init__` are all constructed as ASTs, then compiled to functions, then bound to the class. I do not recommend this.\n\n### Example 2 - Notify on Write\nThe second example prints a notification to the terminal when writing to a variable that you've marked with a certain annotation. For example:\n```python\n@notify\nclass MyClass:\n    def __init__(self, x):\n        self.x: \"this one\" = x\n        self.y = True\n```\nThis would print a message to the terminal whenever you try to assign a new value to `foo.x` (where `foo` is an instance of `MyClass`).\n\nThis example is much less AST wrangling than the first example, but the AST is still used to determine which fields are marked with the `\"this one\"` annotation. To intercept writes to the the variables, the class's `__setattr__` method is overridden with one that will print messages before setting the new value.\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally\nsubmitted for inclusion in the work by you, as defined in the Apache-2.0\nlicense, shall be dual licensed as above, without any additional terms or\nconditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmitchell%2Fannotation-abuse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzmitchell%2Fannotation-abuse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmitchell%2Fannotation-abuse/lists"}