Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions fasthtml/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@

from .starlette import *

# %% ../nbs/api/00_core.ipynb #2b18bf01
@patch
def __deepcopy__(self:FT, memo):
"Fast `deepcopy` for `FT`, avoiding the slow generic object fallback. Unknown attr/child value types are delegated to `deepcopy` itself, so a user's own `__deepcopy__` is still respected"
y = self.__class__.__new__(self.__class__)
memo[id(self)] = y
y.tag = self.tag
y.children = tuple(deepcopy(c, memo) for c in self.children)
y.attrs = deepcopy(self.attrs, memo)
y.void_ = self.void_
y.listeners_ = deepcopy(self.listeners_, memo)
return y

# %% ../nbs/api/00_core.ipynb #19d3f2a7
def _params(f): return signature_ex(f, True).parameters

Expand Down
5 changes: 5 additions & 0 deletions fasthtml/core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ from base64 import b64encode, b64decode
from email.utils import format_datetime
from .starlette import *

@patch
def __deepcopy__(self: FT, memo):
"""Fast `deepcopy` for `FT`, avoiding the slow generic object fallback. Unknown attr/child value types are delegated to `deepcopy` itself, so a user's own `__deepcopy__` is still respected"""
...

def _params(f):
...
empty = Parameter.empty
Expand Down
103 changes: 103 additions & 0 deletions nbs/api/00_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,106 @@
"from starlette.datastructures import UploadFile"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2b18bf01",
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"@patch\n",
"def __deepcopy__(self:FT, memo):\n",
" \"Fast `deepcopy` for `FT`, avoiding the slow generic object fallback. Unknown attr/child value types are delegated to `deepcopy` itself, so a user's own `__deepcopy__` is still respected\"\n",
" y = self.__class__.__new__(self.__class__)\n",
" memo[id(self)] = y\n",
" y.tag = self.tag\n",
" y.children = tuple(deepcopy(c, memo) for c in self.children)\n",
" y.attrs = deepcopy(self.attrs, memo)\n",
" y.void_ = self.void_\n",
" y.listeners_ = deepcopy(self.listeners_, memo)\n",
" return y"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d9ecba07",
"metadata": {},
"outputs": [],
"source": [
"el = Div(Span('hi', cls='a'), id='x')\n",
"cp = deepcopy(el)\n",
"test_eq(cp, el)\n",
"test_ne(id(cp), id(el))\n",
"test_ne(id(cp.attrs), id(el.attrs))\n",
"test_ne(id(cp.children[0]), id(el.children[0]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6b69aa77",
"metadata": {},
"outputs": [],
"source": [
"nested = Div(Div(Span('hi', cls='a')))\n",
"cp = deepcopy(nested)\n",
"cp.children[0].children[0].attrs['class'] = 'mutated'\n",
"test_eq(nested.children[0].children[0].attrs['class'], 'a')\n",
"test_eq(cp.children[0].children[0].attrs['class'], 'mutated')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "50296a48",
"metadata": {},
"outputs": [],
"source": [
"v = Meta(charset='utf-8')\n",
"cp = deepcopy(v)\n",
"test_eq(cp.void_, True)\n",
"test_eq(cp, v)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "69795726",
"metadata": {},
"outputs": [],
"source": [
"class Custom:\n",
" def __init__(self, v): self.v = v\n",
" def __deepcopy__(self, memo):\n",
" c = Custom(self.v)\n",
" memo[id(self)] = c\n",
" return c\n",
" def __eq__(self, o): return isinstance(o, Custom) and o.v == self.v\n",
"\n",
"el = Div(x=Custom(5))\n",
"cp = deepcopy(el)\n",
"test_eq(type(cp.attrs['x']), Custom)\n",
"test_ne(id(cp.attrs['x']), id(el.attrs['x']))\n",
"test_eq(cp.attrs['x'].v, 5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fce2d92a",
"metadata": {},
"outputs": [],
"source": [
"app, rt = fast_app()\n",
"hdrs, ftrs, htmlkw, bodykw = app.hdrs, app.ftrs, app.htmlkw, app.bodykw\n",
"r = deepcopy((hdrs, ftrs, htmlkw, bodykw))\n",
"test_eq(r, (hdrs, ftrs, htmlkw, bodykw))\n",
"test_ne(id(r[0][0]), id(hdrs[0]))\n",
"test_ne(id(r[0][0].attrs), id(hdrs[0].attrs))"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -4989,6 +5089,9 @@
}
],
"metadata": {
"language_info": {
"name": "python"
},
"solveit": {
"default_code": false,
"mode": "concise",
Expand Down