|
747 | 747 | " nm, fld_names:VAR_POSITIONAL, sup:NoneType=None, doc:NoneType=None, funcs:NoneType=None, anno:NoneType=None,\n", |
748 | 748 | " flds:VAR_KEYWORD\n", |
749 | 749 | "):\n", |
750 | | - "\"\"\"\n", |
751 | | - "Dynamically create a class, optionally inheriting from `sup`, containing `fld_names`\n", |
752 | | - "\"\"\"" |
| 750 | + "\"\"\"Dynamically create a class, optionally inheriting from `sup`, containing `fld_names`\"\"\"" |
753 | 751 | ] |
754 | 752 | }, |
755 | 753 | "execution_count": null, |
|
950 | 948 | "def ignore_exceptions(\n", |
951 | 949 | " args:VAR_POSITIONAL, kwargs:VAR_KEYWORD\n", |
952 | 950 | "):\n", |
953 | | - "\"\"\"\n", |
954 | | - "Context manager to ignore exceptions\n", |
955 | | - "\"\"\"" |
| 951 | + "\"\"\"Context manager to ignore exceptions\"\"\"" |
956 | 952 | ] |
957 | 953 | }, |
958 | 954 | "execution_count": null, |
|
1123 | 1119 | "def noop(\n", |
1124 | 1120 | " x:NoneType=None, args:VAR_POSITIONAL, kwargs:VAR_KEYWORD\n", |
1125 | 1121 | "):\n", |
1126 | | - "\"\"\"\n", |
1127 | | - "Do nothing\n", |
1128 | | - "\"\"\"" |
| 1122 | + "\"\"\"Do nothing\"\"\"" |
1129 | 1123 | ] |
1130 | 1124 | }, |
1131 | 1125 | "execution_count": null, |
|
1176 | 1170 | "def noops(\n", |
1177 | 1171 | " x:NoneType=None, args:VAR_POSITIONAL, kwargs:VAR_KEYWORD\n", |
1178 | 1172 | "):\n", |
1179 | | - "\"\"\"\n", |
1180 | | - "Do nothing (method)\n", |
1181 | | - "\"\"\"" |
| 1173 | + "\"\"\"Do nothing (method)\"\"\"" |
1182 | 1174 | ] |
1183 | 1175 | }, |
1184 | 1176 | "execution_count": null, |
|
2028 | 2020 | { |
2029 | 2021 | "data": { |
2030 | 2022 | "text/plain": [ |
2031 | | - "typing.Union[__main__._T2a, __main__._T2b]" |
| 2023 | + "__main__._T2a | __main__._T2b" |
2032 | 2024 | ] |
2033 | 2025 | }, |
2034 | 2026 | "execution_count": null, |
|
3305 | 3297 | "def GetAttr(\n", |
3306 | 3298 | " args:VAR_POSITIONAL, kwargs:VAR_KEYWORD\n", |
3307 | 3299 | "):\n", |
3308 | | - "\"\"\"\n", |
3309 | | - "Inherit from this to have all attr accesses in `self._xtra` passed down to `self.default`\n", |
3310 | | - "\"\"\"" |
| 3300 | + "\"\"\"Inherit from this to have all attr accesses in `self._xtra` passed down to `self.default`\"\"\"" |
3311 | 3301 | ] |
3312 | 3302 | }, |
3313 | 3303 | "execution_count": null, |
|
5280 | 5270 | "def fastuple(\n", |
5281 | 5271 | " args:VAR_POSITIONAL, kwargs:VAR_KEYWORD\n", |
5282 | 5272 | "):\n", |
5283 | | - "\"\"\"\n", |
5284 | | - "A `tuple` with elementwise ops and more friendly __init__ behavior\n", |
5285 | | - "\"\"\"" |
| 5273 | + "\"\"\"A `tuple` with elementwise ops and more friendly __init__ behavior\"\"\"" |
5286 | 5274 | ] |
5287 | 5275 | }, |
5288 | 5276 | "execution_count": null, |
|
5374 | 5362 | "def add(\n", |
5375 | 5363 | " args:VAR_POSITIONAL\n", |
5376 | 5364 | "):\n", |
5377 | | - "\"\"\"\n", |
5378 | | - "`+` is already defined in `tuple` for concat, so use `add` instead\n", |
5379 | | - "\"\"\"" |
| 5365 | + "\"\"\"`+` is already defined in `tuple` for concat, so use `add` instead\"\"\"" |
5380 | 5366 | ] |
5381 | 5367 | }, |
5382 | 5368 | "execution_count": null, |
|
5430 | 5416 | "def mul(\n", |
5431 | 5417 | " args:VAR_POSITIONAL\n", |
5432 | 5418 | "):\n", |
5433 | | - "\"\"\"\n", |
5434 | | - "`*` is already defined in `tuple` for replicating, so use `mul` instead\n", |
5435 | | - "\"\"\"" |
| 5419 | + "\"\"\"`*` is already defined in `tuple` for replicating, so use `mul` instead\"\"\"" |
5436 | 5420 | ] |
5437 | 5421 | }, |
5438 | 5422 | "execution_count": null, |
|
5607 | 5591 | "def bind(\n", |
5608 | 5592 | " func, pargs:VAR_POSITIONAL, pkwargs:VAR_KEYWORD\n", |
5609 | 5593 | "):\n", |
5610 | | - "\"\"\"\n", |
5611 | | - "Same as `partial`, except you can use `arg0` `arg1` etc param placeholders\n", |
5612 | | - "\"\"\"" |
| 5594 | + "\"\"\"Same as `partial`, except you can use `arg0` `arg1` etc param placeholders\"\"\"" |
5613 | 5595 | ] |
5614 | 5596 | }, |
5615 | 5597 | "execution_count": null, |
|
6508 | 6490 | "outputs": [], |
6509 | 6491 | "source": [ |
6510 | 6492 | "#| export\n", |
6511 | | - "def patch_to(cls, as_prop=False, cls_method=False, set_prop=False, nm=None, glb=None):\n", |
| 6493 | + "def patch_to(cls, as_prop=False, cls_method=False, set_prop=False, static_method=False, nm=None, glb=None):\n", |
6512 | 6494 | " \"Decorator: add `f` to `cls`\"\n", |
6513 | 6495 | " if glb is None: glb = sys._getframe(1).f_globals\n", |
6514 | 6496 | " def _inner(f):\n", |
|
6521 | 6503 | " nf.__qualname__ = f\"{c_.__name__}.{_nm}\"\n", |
6522 | 6504 | " if hasattr(c_, _nm) and not hasattr(c_, onm): setattr(c_, onm, getattr(c_, _nm))\n", |
6523 | 6505 | " if cls_method: attr = _clsmethod(nf)\n", |
| 6506 | + " elif static_method: attr = staticmethod(nf)\n", |
6524 | 6507 | " elif set_prop: attr = getattr(c_, _nm).setter(nf)\n", |
6525 | 6508 | " elif as_prop: attr = property(nf)\n", |
6526 | 6509 | " else: attr = nf\n", |
|
6715 | 6698 | "outputs": [], |
6716 | 6699 | "source": [ |
6717 | 6700 | "#| export\n", |
6718 | | - "def patch(f=None, *, as_prop=False, cls_method=False, set_prop=False, nm=None):\n", |
| 6701 | + "def patch(f=None, *, as_prop=False, cls_method=False, static_method=False, set_prop=False, nm=None):\n", |
6719 | 6702 | " \"Decorator: add `f` to the first parameter's class (based on f's type annotations)\"\n", |
6720 | | - " if f is None: return partial(patch, as_prop=as_prop, cls_method=cls_method, set_prop=set_prop, nm=nm)\n", |
| 6703 | + " if f is None: return partial(patch, as_prop=as_prop, cls_method=cls_method, static_method=static_method, set_prop=set_prop, nm=nm)\n", |
6721 | 6704 | " ann,glb,loc = get_annotations_ex(f)\n", |
6722 | 6705 | " if cls_method:\n", |
6723 | 6706 | " if 'cls' not in ann: raise TypeError(f\"@patch with cls_method=True requires 'cls' to have a type annotation\")\n", |
|
6726 | 6709 | " if not ann: raise TypeError(f\"@patch requires the first parameter of `{f.__name__}` to have a type annotation\")\n", |
6727 | 6710 | " cls = next(iter(ann.values()))\n", |
6728 | 6711 | " cls = union2tuple(eval_type(cls, glb, loc))\n", |
6729 | | - " return patch_to(cls, as_prop=as_prop, cls_method=cls_method, set_prop=set_prop, nm=nm, glb=sys._getframe(1).f_globals)(f)" |
| 6712 | + " glbs = sys._getframe(1).f_globals\n", |
| 6713 | + " return patch_to(cls, as_prop=as_prop, cls_method=cls_method, static_method=static_method, set_prop=set_prop, nm=nm, glb=glbs)(f)" |
6730 | 6714 | ] |
6731 | 6715 | }, |
6732 | 6716 | { |
|
6754 | 6738 | "test_eq(t.func.__qualname__, '_T8.func')" |
6755 | 6739 | ] |
6756 | 6740 | }, |
| 6741 | + { |
| 6742 | + "cell_type": "code", |
| 6743 | + "execution_count": null, |
| 6744 | + "id": "5583f90f", |
| 6745 | + "metadata": {}, |
| 6746 | + "outputs": [], |
| 6747 | + "source": [ |
| 6748 | + "class MyMath: pass\n", |
| 6749 | + "\n", |
| 6750 | + "@patch_to(MyMath, static_method=True)\n", |
| 6751 | + "def add(a, b): return a + b\n", |
| 6752 | + "\n", |
| 6753 | + "@patch(static_method=True)\n", |
| 6754 | + "def mul(a:MyMath, b): return a * b\n", |
| 6755 | + "\n", |
| 6756 | + "test_eq(MyMath.add(2, 3), 5)\n", |
| 6757 | + "test_eq(MyMath.mul(2, 3), 6)" |
| 6758 | + ] |
| 6759 | + }, |
6757 | 6760 | { |
6758 | 6761 | "cell_type": "markdown", |
6759 | 6762 | "id": "d96ec34b", |
|
6898 | 6901 | "## Other Helpers" |
6899 | 6902 | ] |
6900 | 6903 | }, |
| 6904 | + { |
| 6905 | + "cell_type": "code", |
| 6906 | + "execution_count": null, |
| 6907 | + "id": "c8805a92", |
| 6908 | + "metadata": {}, |
| 6909 | + "outputs": [], |
| 6910 | + "source": [ |
| 6911 | + "#| export\n", |
| 6912 | + "def extend_enum(\n", |
| 6913 | + " cls, # Enum class to modify\n", |
| 6914 | + " n, # Name of the new enum member\n", |
| 6915 | + " v # Value of the new enum member\n", |
| 6916 | + "):\n", |
| 6917 | + " \"Add new member `n` with value `v` to enum class `cls` at runtime\"\n", |
| 6918 | + " if n in cls._member_map_: return cls[n]\n", |
| 6919 | + " typ = cls._member_type_\n", |
| 6920 | + " res = object.__new__(cls) if typ is object else typ.__new__(cls, v)\n", |
| 6921 | + " res._name_,res._value_ = n,v\n", |
| 6922 | + " cls._member_names_.append(n)\n", |
| 6923 | + " cls._member_map_[n] = res\n", |
| 6924 | + " cls._value2member_map_[v] = res\n", |
| 6925 | + " type.__setattr__(cls, n, res)\n", |
| 6926 | + " return res" |
| 6927 | + ] |
| 6928 | + }, |
| 6929 | + { |
| 6930 | + "cell_type": "markdown", |
| 6931 | + "id": "c8d11c83", |
| 6932 | + "metadata": {}, |
| 6933 | + "source": [ |
| 6934 | + "`extend_enum` mutates an existing enum class by constructing a new member, registering it in the enum’s internal lookup tables, and attaching it as a class attribute, so it behaves like a normal enum member created in the original class definition." |
| 6935 | + ] |
| 6936 | + }, |
| 6937 | + { |
| 6938 | + "cell_type": "code", |
| 6939 | + "execution_count": null, |
| 6940 | + "id": "c0ded5de", |
| 6941 | + "metadata": {}, |
| 6942 | + "outputs": [], |
| 6943 | + "source": [ |
| 6944 | + "from enum import Enum" |
| 6945 | + ] |
| 6946 | + }, |
| 6947 | + { |
| 6948 | + "cell_type": "code", |
| 6949 | + "execution_count": null, |
| 6950 | + "id": "190756da", |
| 6951 | + "metadata": {}, |
| 6952 | + "outputs": [ |
| 6953 | + { |
| 6954 | + "data": { |
| 6955 | + "text/plain": [ |
| 6956 | + "(<Color.green: 3>, <Color.green: 3>, <Color.green: 3>)" |
| 6957 | + ] |
| 6958 | + }, |
| 6959 | + "execution_count": null, |
| 6960 | + "metadata": {}, |
| 6961 | + "output_type": "execute_result" |
| 6962 | + } |
| 6963 | + ], |
| 6964 | + "source": [ |
| 6965 | + "class Color(Enum): red = 1; blue = 2\n", |
| 6966 | + "\n", |
| 6967 | + "extend_enum(Color, 'green', 3)\n", |
| 6968 | + "Color.green, Color['green'], Color(3)" |
| 6969 | + ] |
| 6970 | + }, |
6901 | 6971 | { |
6902 | 6972 | "cell_type": "code", |
6903 | 6973 | "execution_count": null, |
|
0 commit comments