|
1215 | 1215 | "execution_count": null, |
1216 | 1216 | "id": "da11467b", |
1217 | 1217 | "metadata": {}, |
1218 | | - "outputs": [], |
| 1218 | + "outputs": [ |
| 1219 | + { |
| 1220 | + "data": { |
| 1221 | + "text/markdown": [ |
| 1222 | + "---\n", |
| 1223 | + "\n", |
| 1224 | + "[source](https://github.com/AnswerDotAI/fastcore/blob/main/fastcore/basics.py#L198){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 1225 | + "\n", |
| 1226 | + "### Inf\n", |
| 1227 | + "\n", |
| 1228 | + "> Inf ()\n", |
| 1229 | + "\n", |
| 1230 | + "*Infinite lists*" |
| 1231 | + ], |
| 1232 | + "text/plain": [ |
| 1233 | + "> Inf ()\n", |
| 1234 | + "\n", |
| 1235 | + "*Infinite lists*" |
| 1236 | + ] |
| 1237 | + }, |
| 1238 | + "execution_count": null, |
| 1239 | + "metadata": {}, |
| 1240 | + "output_type": "execute_result" |
| 1241 | + } |
| 1242 | + ], |
1219 | 1243 | "source": [ |
1220 | 1244 | "show_doc(Inf);" |
1221 | 1245 | ] |
|
6035 | 6059 | { |
6036 | 6060 | "cell_type": "code", |
6037 | 6061 | "execution_count": null, |
6038 | | - "id": "97f2fee5", |
| 6062 | + "id": "3f2733ef", |
6039 | 6063 | "metadata": {}, |
6040 | 6064 | "outputs": [], |
6041 | 6065 | "source": [ |
6042 | 6066 | "#| export\n", |
6043 | | - "def _strip_patch_name(nm):\n", |
6044 | | - " \"Strip trailing `__` from `nm` if it doesn't start with `_`\"\n", |
6045 | | - " return nm[:-2] if nm.endswith('__') and not nm.startswith('_') else nm\n", |
6046 | | - "\n", |
6047 | | - "def patch_to(cls, as_prop=False, cls_method=False, set_prop=False, nm=None):\n", |
| 6067 | + "def patch_to(cls, as_prop=False, cls_method=False, set_prop=False, nm=None, glb=None):\n", |
6048 | 6068 | " \"Decorator: add `f` to `cls`\"\n", |
6049 | | - " if not isinstance(cls, (tuple,list)): cls=(cls,)\n", |
| 6069 | + " if glb is None: glb = sys._getframe(1).f_globals\n", |
6050 | 6070 | " def _inner(f):\n", |
6051 | | - " for c_ in cls:\n", |
| 6071 | + " _nm = nm or f.__name__\n", |
| 6072 | + " for c_ in tuplify(cls):\n", |
6052 | 6073 | " nf = copy_func(f)\n", |
6053 | | - " fnm = nm or _strip_patch_name(f.__name__)\n", |
6054 | | - " # `functools.update_wrapper` when passing patched function to `Pipeline`, so we do it manually\n", |
6055 | 6074 | " for o in functools.WRAPPER_ASSIGNMENTS: setattr(nf, o, getattr(f,o))\n", |
6056 | | - " nf.__name__ = fnm\n", |
6057 | | - " nf.__qualname__ = f\"{c_.__name__}.{fnm}\"\n", |
6058 | | - " if cls_method: setattr(c_, fnm, _clsmethod(nf))\n", |
| 6075 | + " nf.__name__ = _nm\n", |
| 6076 | + " nf.__qualname__ = f\"{c_.__name__}.{_nm}\"\n", |
| 6077 | + " if cls_method: attr = _clsmethod(nf)\n", |
| 6078 | + " elif set_prop: attr = getattr(c_, _nm).setter(nf)\n", |
| 6079 | + " elif as_prop: attr = property(nf)\n", |
6059 | 6080 | " else:\n", |
6060 | | - " if set_prop: setattr(c_, fnm, getattr(c_, fnm).setter(nf))\n", |
6061 | | - " elif as_prop: setattr(c_, fnm, property(nf))\n", |
6062 | | - " else:\n", |
6063 | | - " onm = '_orig_'+fnm\n", |
6064 | | - " if hasattr(c_, fnm) and not hasattr(c_, onm): setattr(c_, onm, getattr(c_, fnm))\n", |
6065 | | - " setattr(c_, fnm, nf)\n", |
6066 | | - " # Avoid clobbering existing functions\n", |
6067 | | - " return globals().get(fnm, builtins.__dict__.get(fnm, None))\n", |
| 6081 | + " onm = '_orig_'+_nm\n", |
| 6082 | + " if hasattr(c_, _nm) and not hasattr(c_, onm): setattr(c_, onm, getattr(c_, _nm))\n", |
| 6083 | + " attr = nf\n", |
| 6084 | + " setattr(c_, _nm, attr)\n", |
| 6085 | + " return glb.get(_nm, builtins.__dict__.get(_nm, None))\n", |
6068 | 6086 | " return _inner" |
6069 | 6087 | ] |
6070 | 6088 | }, |
|
6246 | 6264 | "assert not hasattr(t, 'func2')" |
6247 | 6265 | ] |
6248 | 6266 | }, |
6249 | | - { |
6250 | | - "cell_type": "markdown", |
6251 | | - "id": "81877f71", |
6252 | | - "metadata": {}, |
6253 | | - "source": [ |
6254 | | - "A `__` suffix is stripped (unless there's also a `_` prefix):" |
6255 | | - ] |
6256 | | - }, |
6257 | | - { |
6258 | | - "cell_type": "code", |
6259 | | - "execution_count": null, |
6260 | | - "id": "cdd9dedb", |
6261 | | - "metadata": {}, |
6262 | | - "outputs": [], |
6263 | | - "source": [ |
6264 | | - "class _T9(int): pass \n", |
6265 | | - "\n", |
6266 | | - "@patch_to(_T9)\n", |
6267 | | - "def func__(self, a): return self+a\n", |
6268 | | - "\n", |
6269 | | - "t = _T9(1)\n", |
6270 | | - "test_eq(t.func(2), 3)\n", |
6271 | | - "test_eq(_T9.func.__name__, 'func')\n", |
6272 | | - "assert not hasattr(t, 'func__')" |
6273 | | - ] |
6274 | | - }, |
6275 | 6267 | { |
6276 | 6268 | "cell_type": "code", |
6277 | 6269 | "execution_count": null, |
|
6291 | 6283 | " if not ann: raise TypeError(f\"@patch requires the first parameter of `{f.__name__}` to have a type annotation\")\n", |
6292 | 6284 | " cls = next(iter(ann.values()))\n", |
6293 | 6285 | " cls = union2tuple(eval_type(cls, glb, loc))\n", |
6294 | | - " return patch_to(cls, as_prop=as_prop, cls_method=cls_method, set_prop=set_prop, nm=nm)(f)" |
| 6286 | + " 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)" |
6295 | 6287 | ] |
6296 | 6288 | }, |
6297 | 6289 | { |
|
6426 | 6418 | "assert not hasattr(t, 'func2')" |
6427 | 6419 | ] |
6428 | 6420 | }, |
6429 | | - { |
6430 | | - "cell_type": "code", |
6431 | | - "execution_count": null, |
6432 | | - "id": "fdbfff66", |
6433 | | - "metadata": {}, |
6434 | | - "outputs": [], |
6435 | | - "source": [ |
6436 | | - "class _T9(int): pass \n", |
6437 | | - "\n", |
6438 | | - "@patch\n", |
6439 | | - "def func__(self:_T9, a): return self+a\n", |
6440 | | - "\n", |
6441 | | - "t = _T9(1)\n", |
6442 | | - "test_eq(t.func(2), 3)\n", |
6443 | | - "test_eq(_T9.func.__name__, 'func')\n", |
6444 | | - "assert not hasattr(t, 'func__')" |
6445 | | - ] |
6446 | | - }, |
6447 | 6421 | { |
6448 | 6422 | "cell_type": "markdown", |
6449 | 6423 | "id": "d9310d77", |
|
0 commit comments