{"id":16648632,"url":"https://github.com/utilmeta/utype","last_synced_at":"2026-03-14T12:10:38.932Z","repository":{"id":65337712,"uuid":"572141025","full_name":"utilmeta/utype","owner":"utilmeta","description":"Declare \u0026 parse types / dataclasses / functions based on Python type annotations","archived":false,"fork":false,"pushed_at":"2025-07-22T10:16:07.000Z","size":912,"stargazers_count":25,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-22T12:22:08.860Z","etag":null,"topics":["python","python-typing","type-hints"],"latest_commit_sha":null,"homepage":"https://utype.io","language":"Python","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/utilmeta.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":"2022-11-29T16:32:27.000Z","updated_at":"2025-07-22T10:16:11.000Z","dependencies_parsed_at":"2023-12-10T15:30:07.781Z","dependency_job_id":"563ae557-a163-412b-89e8-d19eb42a9fa6","html_url":"https://github.com/utilmeta/utype","commit_stats":{"total_commits":34,"total_committers":2,"mean_commits":17.0,"dds":0.05882352941176472,"last_synced_commit":"3e689976fd5cc13ad258f85987cf7056b451907b"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/utilmeta/utype","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilmeta%2Futype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilmeta%2Futype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilmeta%2Futype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilmeta%2Futype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/utilmeta","download_url":"https://codeload.github.com/utilmeta/utype/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utilmeta%2Futype/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266510094,"owners_count":23940599,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"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":["python","python-typing","type-hints"],"created_at":"2024-10-12T09:05:07.147Z","updated_at":"2026-03-14T12:10:38.884Z","avatar_url":"https://github.com/utilmeta.png","language":"Python","readme":"# uType\n[![Version](https://img.shields.io/pypi/v/utype)](https://pypi.org/project/utype/)\n[![Python Requires](https://img.shields.io/pypi/pyversions/utype)](https://pypi.org/project/utype/)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](https://github.com/utilmeta/utype/blob/main/LICENSE)\n[![CI](https://img.shields.io/github/actions/workflow/status/utilmeta/utype/test.yaml?branch=main\u0026label=CI)](https://github.com/utilmeta/utype/actions?query=branch%3Amain+)\n[![Test Coverage](https://img.shields.io/codecov/c/github/utilmeta/utype?color=green)](https://app.codecov.io/github/utilmeta/utype)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Downloads](https://pepy.tech/badge/utype/month)](https://pepy.tech/project/utype)\n\nutype is a data types declaration \u0026 parsing library based on Python type annotations, \nenforce types and constraints for classes and functions at runtime\n\n* Documentation: [https://utype.io](https://utype.io)\n* 中文文档: [https://utype.io/zh](https://utype.io/zh)\n* Source Code: [https://github.com/utilmeta/utype](https://github.com/utilmeta/utype)\n* Author: [@voidZXL](https://github.com/voidZXL)\n* License: Apache 2.0\n\n### Core Features\n\n* Enforce types, data classes, function params and result parsing at runtime based on Python type annotation\n* Support a variety of constraints, logical operators and flexible parsing options\n* Highly extensible, all type transformer can be register, extend and override\n\n### Installation\n\n```shell\npip install -U utype\n```\n\n\u003e utype requires Python \u003e= 3.7\n\n### Usage Example\n\n### Types and constraints\nThe utype support to add constraints on types, such as\n```Python\nfrom utype import Rule, exc\n\nclass PositiveInt(int, Rule):  \n    gt = 0\n\nassert PositiveInt(b'3') == 3\n\ntry:\n    PositiveInt(-0.5)\nexcept exc.ParseError as e:\n    print(e)\n    \"\"\"\n    Constraint: 0 violated\n    \"\"\"\n``` \n\n\nData that conforms to the type and constraints will complete the conversion, otherwise will throw a parse error indicating what went wrong\n\n### Parsing dataclasses\n\nutype supports the \"dataclass\" usage that convert a dict or JSON to a class instance, similar to `pydantic` and `attrs`\n```python\nfrom utype import Schema, Field, exc\nfrom datetime import datetime\n\nclass UserSchema(Schema):\n    username: str = Field(regex='[0-9a-zA-Z]{3,20}')\n    signup_time: datetime\n\n# 1. Valid input\ndata = {'username': 'bob', 'signup_time': '2022-10-11 10:11:12'}\nprint(UserSchema(**data))\n#\u003e UserSchema(username='bob', signup_time=datetime.datetime(2022, 10, 11, 10, 11, 12))\n\n# 2. Invalid input\ntry:\n    UserSchema(username='@invalid', signup_time='2022-10-11 10:11:12')\nexcept exc.ParseError as e:\n    print(e)\n    \"\"\"\n    parse item: ['username'] failed: \n    Constraint: \u003cregex\u003e: '[0-9a-zA-Z]{3,20}' violated\n    \"\"\"\n```\n\nAfter a simple declaration, you can get\n\n* Automatic `__init__` to take input data, perform validation and attribute assignment\n* Providing  `__repr__` and `__str__` to get the clearly print output of the instance\n* parse and protect attribute assignment and deletion to avoid dirty data\n\n### Parsing functions\n\nutype can also parse function params and result\n```python\nimport utype\nfrom typing import Optional\n\nclass PositiveInt(int, utype.Rule):  \n    gt = 0\n\nclass ArticleSchema(utype.Schema):\n    id: Optional[PositiveInt]\n    title: str = utype.Field(max_length=100)\n    slug: str = utype.Field(regex=r\"[a-z0-9]+(?:-[a-z0-9]+)*\")\n\n@utype.parse\ndef get_article(id: PositiveInt = None, title: str = '') -\u003e ArticleSchema:\n    return {\n        'id': id,\n        'title': title,\n        'slug': '-'.join([''.join(\n            filter(str.isalnum, v)) for v in title.split()]).lower()\n    }\n\nprint(get_article('3', title=b'My Awesome Article!'))\n#\u003e ArticleSchema(id=3, title='My Awesome Article!', slug='my-awesome-article')\n\ntry:\n    get_article('-1')\nexcept utype.exc.ParseError as e:\n    print(e)\n    \"\"\"\n    parse item: ['id'] failed: Constraint: : 0 violated\n    \"\"\"\n\ntry:\n    get_article(title='*' * 101)\nexcept utype.exc.ParseError as e:\n    print(e)\n    \"\"\"\n    parse item: ['\u003creturn\u003e'] failed: \n    parse item: ['title'] failed: \n    Constraint: \u003cmax_length\u003e: 100 violated\n    \"\"\"\n```\n\n\u003e You can easily get type checking and code completion of IDEs (such as Pycharm, VS Code) during development\n\nutype supports not only normal functions, but also generator functions, asynchronous functions, and asynchronous generator functions with the same usage\n```python\nimport utype  \nimport asyncio  \nfrom typing import AsyncGenerator  \n\n@utype.parse  \nasync def waiter(rounds: int = utype.Param(gt=0)) -\u003e AsyncGenerator[int, float]:  \n    assert isinstance(rounds, int)  \n    i = rounds  \n    while i:  \n        wait = yield str(i)  \n        if wait:  \n            assert isinstance(wait, float)  \n            print(f'sleep for: {wait} seconds')\n            await asyncio.sleep(wait)  \n        i -= 1  \n  \nasync def wait():  \n    wait_gen = waiter('2')  \n    async for index in wait_gen:  \n        assert isinstance(index, int)  \n        try:  \n            await wait_gen.asend(b'0.5')  \n            # sleep for: 0.5 seconds  \n        except StopAsyncIteration:  \n            return  \n  \nif __name__ == '__main__':  \n    asyncio.run(wait())\n```\n\n\u003e The `AsyncGenerator` type is used to annotate the return value of the asynchronous generator, which has two parameters: the type of the value output by `yield`, type of the value sent by `asend`\n\nAs you can see, the parameters passed to the function and the value received from `yield` were all converted to the expected type as declared\n\n\n### Logical operation of type\nutype supports logical operations on types and data structures using Python-native logical operators\n```python\nfrom utype import Schema, Field\nfrom typing import Tuple\n\nclass User(Schema):  \n    name: str = Field(max_length=10)  \n    age: int\n\none_of_user = User ^ Tuple[str, int]\n\nprint(one_of_user({'name': 'test', 'age': '1'}))\n# \u003e User(name='test', age=1)\n\nprint(one_of_user([b'test', '1']))\n# \u003e ('test', 1)\n```\n\nThe example uses the `^` exclusive or symbol to logically combine  `User` and `Tuple[str, int]`, and the new logical type gains the ability to convert data to one of those\n\n### Register transformer for type\nType transformation and validation strictness required by each project may be different, so in utype, all types support registraton, extension and override, such as\n```python\nfrom utype import Rule, Schema, register_transformer\nfrom typing import Type\n\nclass Slug(str, Rule):  \n    regex = r\"[a-z0-9]+(?:-[a-z0-9]+)*\"\n\n@register_transformer(Slug)\ndef to_slug(transformer, value, t: Type[Slug]):\n    str_value = transformer(value, str)\n    return t('-'.join([''.join(\n    filter(str.isalnum, v)) for v in str_value.split()]).lower())\n\n\nclass ArticleSchema(Schema):\n\tslug: Slug\n\nprint(dict(ArticleSchema(slug=b'My Awesome Article!')))\n# \u003e {'slug': 'my-awesome-article'}\n```\n\nYou can register transformers not only for custom types, but also for basic types (such as `str`, `int`, etc.) Or types in the standard library (such as `datetime`, `Enum`, etc.) To customize the conversion behavior\n\n## RoadMap and Contribution\nutype is still growing, and the following features are planned for implementation in the new version\n\n* Improve the handling mechanism of parsing errors, including error handling hook functions, etc.\n* Support the declaration and parse command line parameters\n* Support for Python generics, type variables, and more type annotation syntax\n* Develop Pycharm/VS Code plugin that supports IDE detection and hints for constraints, logical types, and nested types\n\nYou are also welcome to contribute features or submit issues.\n\n## Applications\n\n### UtilMeta Python Framework\nUtilMeta Python Framework is a progressive meta-framework for backend applications, which efficiently builds declarative APIs based on the Python type annotation standard, and supports the integration of mainstream Python frameworks as runtime backend\n* Homepage: [https://utilmeta.com/py](https://utilmeta.com/py)\n* Source Code: [https://github.com/utilmeta/utilmeta-py](https://github.com/utilmeta/utilmeta-py)\n\n## Community\n\nutype is a project of [UtilMeta](https://utilmeta.com), so you can join the community in\n\n* [Discord](https://discord.gg/JdmEkFS6dS)\n* [X(Twitter)](https://twitter.com/utilmeta)\n* [Reddit](https://www.reddit.com/r/utilmeta)\n* [中文讨论区](https://lnzhou.com/channels/utilmeta/community)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Futilmeta%2Futype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Futilmeta%2Futype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Futilmeta%2Futype/lists"}