{"id":18498475,"url":"https://github.com/xpodev/extype","last_synced_at":"2026-02-09T22:07:08.540Z","repository":{"id":91064541,"uuid":"583988266","full_name":"xpodev/extype","owner":"xpodev","description":"A Python package that enables users to extend types externally.","archived":false,"fork":false,"pushed_at":"2023-08-06T10:22:17.000Z","size":145,"stargazers_count":9,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-18T13:54:58.094Z","etag":null,"topics":["python","python3"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/extype","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xpodev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-12-31T19:35:11.000Z","updated_at":"2024-09-09T08:27:33.000Z","dependencies_parsed_at":"2024-01-09T03:26:04.235Z","dependency_job_id":null,"html_url":"https://github.com/xpodev/extype","commit_stats":null,"previous_names":["xpodev/extypes"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpodev%2Fextype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpodev%2Fextype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpodev%2Fextype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xpodev%2Fextype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xpodev","download_url":"https://codeload.github.com/xpodev/extype/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247949886,"owners_count":21023409,"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":["python","python3"],"created_at":"2024-11-06T13:40:31.689Z","updated_at":"2026-02-09T22:07:08.512Z","avatar_url":"https://github.com/xpodev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExType\nExtype stands for extensible types, a Python package that enables extending types.\n\n[![PyPI version](https://badge.fury.io/py/extype.svg?)](https://badge.fury.io/py/extype)\n\n![Windows](https://github.com/xpodev/extypes/actions/workflows/python-test-windows.yml/badge.svg)\n![MacOS](https://github.com/xpodev/extypes/actions/workflows/python-test-macos.yml/badge.svg)\n![Linux](https://github.com/xpodev/extypes/actions/workflows/python-test-linux.yml/badge.svg)\n\n## Installation\n\n```sh\npip install extype\n```\n\nAlternatively, you can install through git (make sure to have pip 22.0 or higher):\n```sh\npython -m pip install --upgrade pip\npip install git+https://github.com/xpodev/extype/\n```\n\n## Usage\nFirst, in your Python code, import the package:\n```py\nimport extype\n```\n\nThen, you can use the built-in extensions for the builtin types. In order to apply these extensions, \nimport the `extend_all` module from the `extype.builtin_extensions` package:\n```py\nfrom extype.builtin_extensions import extend_all\n```\nThis will apply the extensions to all builtins we support, *as a side-effect of the import* (to extend only some builtins, you can use the dedicated modules, see below).\n\nSometimes you don't want to apply all the extensions that we provide, but only for some specific type(s).\n\nSay, for example, we only want to apply the provided extensions for `list`. We'll need to manually\napply them like so:\n```py\nfrom extype.builtin_extensions import list_ext\n\nlist_ext.extend()\n```\n\n\u003e **Note:** All built-in extension modules have an `extend` function which will apply the extensions in the module to the relevant type.\n\nCurrently, we provide the following extensions:\n\n\n|       file      |           extended types           |\n|:---------------:|:----------------------------------:|\n|   dict_ext.py   | dict_keys, dict_values, dict_items |\n|   float_ext.py  | float |\n| function_ext.py | FunctionType, LambdaType  |\n|    int_ext.py   | int |\n|   list_ext.py   | list |\n|    seq_ext.py   | map, filter, range, zip |\n|    str_ext.py   | str |\n\n\n\nThen you can use these extensions. Here's an example of using the `list.map` extension:\n```py\nprint([1, 2, 3].map(lambda x: x + 1))  # [2, 3, 4]\n```\n\nThere's a list of all the built-in extensions [here](#built-in-extensions)\n\n\n### Creating your own extensions\nYou can create your own extension methods, with which you can extend any type you want! (not only builtins)\nFor example, let's make our own `tofloat` function in the `int` type.\nWhat we want to have at the end is:\n```py\nx = 10\nprint(isinstance(x.tofloat(), float))  # True\n```\n\nFirst, we'll need some tools:\n```py\nfrom extype import extension, extend_type_with\n```\n\nNext, we'll define our class which will hold the extension method. Note that this class will not get instantiated.\nIt is also recommended to make this class inherit the type you want to extend, so you get better typing support.\n```py\nclass IntExtension(int):  # inheriting `int` for typing\n  @extension  # marks this method to be added as an extension\n  def tofloat(self):  # self will be of the same type we extend, which, in this case, is `int`\n    return float(self)  # convert the int to float and return the result\n```\n\nAfter we create the class which will contain the extension methods, we need to apply them to the types we want to extend:\n```py\nextend_type_with(int, IntExtension)\n```\n\nNow, we can run the code from above:\n```py\nx = 10\nprint(isinstance(x.tofloat(), float))  # True\n```\n\nWe can also apply multiple extensions to the same type or even the same extension to multiple types.\n\nOnly methods marked with `@extension` will be added as extension methods.\n\n**Note:**\nExtending a type will extend it in all modules, not just the one that called the `extend_type_with`, \nso make sure you don't override an existing function, unless, of course, it is what you want.\n\n\n## Features\n- [x] Exteranlly extend type via another type\n- [x] Basic support for magic method extensions\n  - [x] Number protocol\n  - [x] Mapping protocol\n  - [x] Sequence protocol\n- [x] Add support for reverse methods (e.g. `__radd__`)\n- [x] Make this features/todo list look nicer\n- [ ] Add support for the rich comparison function\n\n\n## Maintainers\n\n### Build \u0026 Installation\n\nWe use [Hatch](https://hatch.pypa.io/latest/) to manage the build environment,\n and [mesonpy]( https://github.com/mesonbuild/meson-python) to build the package.\n\u003e **Note:** Currently, we use unreleased mesonpy features, so we install it from git. \n\nFirst, install Hatch: https://hatch.pypa.io/latest/install/. We recommend using [pipx](https://hatch.pypa.io/latest/install/#pipx).\n\nAfter you've installed Hatch, you can build the package with the following command:\n```sh\nhatch run install_editable\n```\nWith this, you can start using the package in your code. \nSpawn shell within the build environment:\n```sh\nhatch shell\n```\nIt'll rebuild the package every time you import it, so you can test your changes.\nIf you don't want to rebuild the package every time you import it, you can install it with:\n```sh\nhatch run install\n```\nBut note that any changes you make won't be reflected in the installed package.\n\nTo build the wheel, you can use:\n```sh\nhatch run dist:build\n```\nThis will build the wheel for all python versions, and put it in the `dist` folder.\n\n### Testing\n\nTo run tests for all python versions, run:\n```sh\nhatch run dist:test\n```\nTo run tests for a specific python version, run:\n```sh\nhatch run +py=39 dist:test\n```\n\nBoth commands will build, install the package into an isolated environment,\n and run the tests in it.\n\n\n### Built-in Extensions\n\n\u003e **Note:** All of the following `list` extensions also exist on `dict_keys`, `dict_values` and `dict_items`.\n\n```py\nlist.all(self: List[T], fn: Callable[[T], bool] = bool) -\u003e bool\n```\nReturns true if all elements, mapped through the given `fn`, are `True`.\n\n```py\nlist.any(self: List[T], fn: Callable[[T], bool] = bool) -\u003e bool\n```\nReturns true if any of the elements, mapped through the given `fn`, is `True`.\n\n```py\nlist.map(self: List[T], fn: Callable[[T], U]) -\u003e List[U]\n```\nReturns a new list whose elements are the result of applying the given function on each element in the original list.\n\n```py\nlist.reduce(self: List[T], fn: Callable[[T, T], T]) -\u003e T\n```\nReduces the list to a single value, using the given function as the reduction (combination) function.\n\nRaises `TypeError` if the list is empty.\n\n```py\nlist.reduce(self: List[T], fn: Callable[[U, T], U], initial_value: U) -\u003e U\n```\nReduces the list to a single value, using the given function as the reduction (combination) function and the initial value.\n\n```py\nlist.filter(self: List[T], fn: Callable[[T], bool]) -\u003e List[T]\n```\nReturns a new list containing all the elements that match the given predicate `fn`.\n\n```py\nlist.first(self: List[T]) -\u003e T, raise IndexError\n```\nReturns the first element in the list, or raises an `IndexError` if the list is empty.\n\n```py\nlist.last(self: List[T]) -\u003e T, raise IndexError\n```\nReturns the last element in the list, or raises `IndexError` if the list is empty.\n\n```py\nfloat.round(self: float) -\u003e int\n```\nRounds the floating point number to the nearest integer.\n\n```py\nfloat.round(self: float, ndigits: int) -\u003e int | float\n```\nRound the floating point number to the nearest float with `ndigits` fraction digits.\n\n```py\n# function @ functioin\nfunction.__matmul__(self: Callable[[T], U], other: Callable[..., T]) -\u003e Callable[..., U]\n```\nCompose 2 functions such that doing `(foo @ bar)(*args, **kwargs)` will have the same result as calling `foo(bar(*args, **kwargs))`.\n\n```py\nint.hex(self: int) -\u003e str\n```\nReturns the hexadecimal representation of the integer.\n\n```py\nint.oct(self: int) -\u003e str\n```\nReturns the octal representation of the integer.\n\n```py\nint.bin(self: int) -\u003e str\n```\nReturns the binary representation of the integer.\n\n```py\nstr.to_int(self: str, base: int = 10, default: T = ...) -\u003e int | T\n```\nConverts the given string to an int with the given base. If it can't be\nconverted and `default` is given, it is returned. Otherwise, a `ValueError`\nis thrown.\n\n```py\nstr.to_float(self: str, default: T = ...) -\u003e float | T\n```\nConverts the given string to a float. If it can't be\nconverted and `default` is given, it is returned. Otherwise, a `ValueError`\nis thrown.\n\n* The following extensions are valid for `map`, `filter`, `range` and `zip`\n```py\n.tolist(self: Iterable[T]) -\u003e List[T]\n```\nExhausts the iterble and creates a list from it.\n\n```py\n.map(self: Iterable[T], fn: Callable[[T], U]) -\u003e Iterable[U]\n```\nMaps the iterable with the given function to create a new iterable.\n\nThis does not iterates through the original iterable.\n\n```py\n.filter(self: Iterable[T], fn: Callable[[T], bool]) -\u003e Iterable[T]\n```\nFilters the iterable with the given function as the predicate function.\n\nThis does not iterates through the original iterable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxpodev%2Fextype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxpodev%2Fextype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxpodev%2Fextype/lists"}