autumn-core 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. autumn_core-1.0.0/PKG-INFO +157 -0
  2. autumn_core-1.0.0/README.md +140 -0
  3. autumn_core-1.0.0/pyproject.toml +48 -0
  4. autumn_core-1.0.0/src/Autumn/Naming/__init__.py +57 -0
  5. autumn_core-1.0.0/src/Autumn/Naming/attribute_selector.py +19 -0
  6. autumn_core-1.0.0/src/Autumn/Naming/class_.py +21 -0
  7. autumn_core-1.0.0/src/Autumn/Naming/identifier.py +21 -0
  8. autumn_core-1.0.0/src/Autumn/Naming/name.py +55 -0
  9. autumn_core-1.0.0/src/Autumn/Page/__init__.py +2 -0
  10. autumn_core-1.0.0/src/Autumn/Page/page.py +84 -0
  11. autumn_core-1.0.0/src/Autumn/Page/page_manager.py +119 -0
  12. autumn_core-1.0.0/src/Autumn/Style/Styles/__init__.py +11 -0
  13. autumn_core-1.0.0/src/Autumn/Style/Styles/style_holder.py +56 -0
  14. autumn_core-1.0.0/src/Autumn/Style/__init__.py +7 -0
  15. autumn_core-1.0.0/src/Autumn/Style/abstract_style.py +83 -0
  16. autumn_core-1.0.0/src/Autumn/Style/sheet.py +32 -0
  17. autumn_core-1.0.0/src/Autumn/Style/style_manager.py +46 -0
  18. autumn_core-1.0.0/src/Autumn/Tag/Enums/Meta/__init__.py +13 -0
  19. autumn_core-1.0.0/src/Autumn/Tag/Enums/Meta/as_attribute.py +46 -0
  20. autumn_core-1.0.0/src/Autumn/Tag/Enums/Meta/link_type.py +131 -0
  21. autumn_core-1.0.0/src/Autumn/Tag/Enums/Meta/script_type.py +17 -0
  22. autumn_core-1.0.0/src/Autumn/Tag/Enums/__init__.py +12 -0
  23. autumn_core-1.0.0/src/Autumn/Tag/Enums/language.py +295 -0
  24. autumn_core-1.0.0/src/Autumn/Tag/Enums/mime_type.py +147 -0
  25. autumn_core-1.0.0/src/Autumn/Tag/Meta/__init__.py +24 -0
  26. autumn_core-1.0.0/src/Autumn/Tag/Meta/_cdn.py +32 -0
  27. autumn_core-1.0.0/src/Autumn/Tag/Meta/_head.py +18 -0
  28. autumn_core-1.0.0/src/Autumn/Tag/Meta/_link.py +46 -0
  29. autumn_core-1.0.0/src/Autumn/Tag/Meta/_meta.py +28 -0
  30. autumn_core-1.0.0/src/Autumn/Tag/Meta/_script.py +26 -0
  31. autumn_core-1.0.0/src/Autumn/Tag/Meta/_script_unavailable.py +13 -0
  32. autumn_core-1.0.0/src/Autumn/Tag/Meta/_title.py +14 -0
  33. autumn_core-1.0.0/src/Autumn/Tag/__init__.py +5 -0
  34. autumn_core-1.0.0/src/Autumn/Tag/abstract_tag.py +313 -0
  35. autumn_core-1.0.0/src/Autumn/Tag/comment.py +27 -0
  36. autumn_core-1.0.0/src/Autumn/Tag/tag_manager.py +98 -0
  37. autumn_core-1.0.0/src/Autumn/__init__.py +30 -0
  38. autumn_core-1.0.0/src/Autumn/abstract_base.py +123 -0
  39. autumn_core-1.0.0/src/Autumn/base.py +338 -0
  40. autumn_core-1.0.0/src/Autumn/exceptions.py +23 -0
  41. autumn_core-1.0.0/src/Autumn/py.typed +0 -0
  42. autumn_core-1.0.0/src/Autumn/typing/__init__.py +0 -0
  43. autumn_core-1.0.0/src/Autumn/typing/types.py +8 -0
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.5
2
+ Name: autumn-core
3
+ Version: 1.0.0
4
+ Summary: Autumn - Build CSS and HTML right in your backend
5
+ Author-email: Nerina0Coder <github.py.coder@gmail.com>
6
+ License-Expression: MIT
7
+ Classifier: Environment :: Web Environment
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
12
+ Requires-Python: ~=3.12
13
+ Requires-Dist: coloraide~=8.12.1
14
+ Requires-Dist: markupsafe~=3.0.3
15
+ Requires-Dist: werkzeug~=3.1.8
16
+ Description-Content-Type: text/markdown
17
+
18
+ # Autumn Framework - Build front-end in the back-end
19
+ ### What are we?
20
+ Autumn framework, a framework built to make front-end work as close as possible to back-end work.
21
+ Our goal is not to provide a server or back-end, but a tool that makes front-end look like back-end.
22
+ By making an ORM(Object Relational Mapping), we add an object-oriented way to write HTML documents and CSS styles
23
+ directly from Python.
24
+ ### Why us?
25
+ You are not limited to us, there are Jinja2 and so many other libraries.
26
+ What makes us unique is making you to look at a Python class rather than a div tag.
27
+
28
+ Tests proven Autumn's speed is less than one millisecond,
29
+ and removing the prettifier actually makes it even faster(tho
30
+ not visibly faster in some cases).
31
+ ### How?
32
+ The process is straight.
33
+ But there are important things to consider:
34
+ - Thread safety:
35
+ While we try our best to promise thread safety,
36
+ such as features like before_build, we cannot
37
+ lock every read/write. Your elements are up to you,
38
+ So, for reads/writes, it's best to access self._lock.
39
+ - Dynamicity:
40
+ When elements are dynamic, their dynamic
41
+ must be set to True. However, if any of the tags owned
42
+ are dynamic, the parent will be inferred as dynamic,
43
+ therefore no need to set dynamic to True.
44
+
45
+ here is an example with HTML, another with CSS.
46
+ #### HTML
47
+ Instead of writing:
48
+ ```html
49
+ <div id="hello-world">Hello World!</div>
50
+ ```
51
+ You write:
52
+ ```python
53
+ from Autumn import new
54
+
55
+ Base = new()
56
+
57
+ tag = Base.tag
58
+
59
+ class MyDiv(tag.Tag):
60
+ def __init__(self):
61
+ self.name = "div"
62
+ self.closable = True
63
+ self.identifier = "hello-world"
64
+ self.tags = ["Hello World!"]
65
+ # How we recommend it.
66
+ # However, you can place spaces, tabs, and newlines, but be aware that they will be
67
+ # Replaced with -.
68
+
69
+ super().__init__()
70
+ ```
71
+ While this seems like writing too much, it's core benefit will be seen when writing **dynamic** tags or when you don't know about HTML too much.
72
+ Let's see an example for a dynamic tag.
73
+
74
+ ```python
75
+ import time
76
+ from Autumn import new
77
+
78
+ Base = new()
79
+
80
+
81
+ class MyText(Base.tag.Tag):
82
+ def __init__(self, classes: list[str]):
83
+ self.name = "p"
84
+ self.closable = True
85
+ self.classes = classes
86
+ self.dynamic = True
87
+
88
+ super().__init__()
89
+
90
+ def before_build(self, **_kwargs): # Recommended.
91
+ self.tags.append(time.time())
92
+ ```
93
+ This will produce a well behaving Paragraph with dynamic elements.
94
+ #### CSS
95
+ Well, this is straight forward.
96
+ ```css
97
+ div.any-div#my-div-used-for-footer {color: #000000;}
98
+ ```
99
+ will simply turn into:
100
+ ```python
101
+ from typing import Any
102
+ from Autumn import new
103
+
104
+ Base = new()
105
+
106
+ class MyStyle(Base.style.Style):
107
+
108
+ def __init__(self):
109
+ self.name = Base.name.Name("div", Base.name.Identifier("my-div-used-for-footer"),
110
+ [Base.name.Class("any-div")])
111
+ self.styles = [
112
+ "color: #000000;"
113
+ ]
114
+
115
+ super().__init__()
116
+
117
+ ```
118
+ This will also become valuable when writing **dynamic** CSS or when you simply don't know CSS.
119
+ Let's see an example for that too.
120
+ ```python
121
+ from typing import Any
122
+ from Autumn import new
123
+
124
+ Base = new()
125
+
126
+ class MyStyle(Base.style.Style):
127
+
128
+ def __init__(self):
129
+ self.name = Base.name.Name("div", Base.name.Identifier("my-div-used-for-footer"),
130
+ [Base.name.Class("any-div")])
131
+ self.styles = [
132
+ "color: #000000;"
133
+ ]
134
+
135
+ self.dynamic = True
136
+
137
+ super().__init__()
138
+
139
+ def before_build(self, **kwargs):
140
+ if "style" in kwargs:
141
+ self.styles.append(kwargs["style"])
142
+
143
+ ```
144
+
145
+ #### A note on Thread safety
146
+ Thread safety is one of the most important parts to remember,
147
+ every public and private method is thread-safe if it inherits from AbstractBase.
148
+ Well, excluding __getattribute__, __setattr__, every public/private method is thread-safe,
149
+ unless it's a protected method. We do not lock protected methods, as they are (mostly, by convenience)
150
+ used by the public/private methods themselves.
151
+
152
+ ### Our future goals
153
+ Our future goals (currently) can be listed as:
154
+ 1. Out of the box experience.
155
+ 2. A stable and mature ecosystem.
156
+ 3. Complete support for HTML/CSS.
157
+ 4. Support for JavaScript, etc...
@@ -0,0 +1,140 @@
1
+ # Autumn Framework - Build front-end in the back-end
2
+ ### What are we?
3
+ Autumn framework, a framework built to make front-end work as close as possible to back-end work.
4
+ Our goal is not to provide a server or back-end, but a tool that makes front-end look like back-end.
5
+ By making an ORM(Object Relational Mapping), we add an object-oriented way to write HTML documents and CSS styles
6
+ directly from Python.
7
+ ### Why us?
8
+ You are not limited to us, there are Jinja2 and so many other libraries.
9
+ What makes us unique is making you to look at a Python class rather than a div tag.
10
+
11
+ Tests proven Autumn's speed is less than one millisecond,
12
+ and removing the prettifier actually makes it even faster(tho
13
+ not visibly faster in some cases).
14
+ ### How?
15
+ The process is straight.
16
+ But there are important things to consider:
17
+ - Thread safety:
18
+ While we try our best to promise thread safety,
19
+ such as features like before_build, we cannot
20
+ lock every read/write. Your elements are up to you,
21
+ So, for reads/writes, it's best to access self._lock.
22
+ - Dynamicity:
23
+ When elements are dynamic, their dynamic
24
+ must be set to True. However, if any of the tags owned
25
+ are dynamic, the parent will be inferred as dynamic,
26
+ therefore no need to set dynamic to True.
27
+
28
+ here is an example with HTML, another with CSS.
29
+ #### HTML
30
+ Instead of writing:
31
+ ```html
32
+ <div id="hello-world">Hello World!</div>
33
+ ```
34
+ You write:
35
+ ```python
36
+ from Autumn import new
37
+
38
+ Base = new()
39
+
40
+ tag = Base.tag
41
+
42
+ class MyDiv(tag.Tag):
43
+ def __init__(self):
44
+ self.name = "div"
45
+ self.closable = True
46
+ self.identifier = "hello-world"
47
+ self.tags = ["Hello World!"]
48
+ # How we recommend it.
49
+ # However, you can place spaces, tabs, and newlines, but be aware that they will be
50
+ # Replaced with -.
51
+
52
+ super().__init__()
53
+ ```
54
+ While this seems like writing too much, it's core benefit will be seen when writing **dynamic** tags or when you don't know about HTML too much.
55
+ Let's see an example for a dynamic tag.
56
+
57
+ ```python
58
+ import time
59
+ from Autumn import new
60
+
61
+ Base = new()
62
+
63
+
64
+ class MyText(Base.tag.Tag):
65
+ def __init__(self, classes: list[str]):
66
+ self.name = "p"
67
+ self.closable = True
68
+ self.classes = classes
69
+ self.dynamic = True
70
+
71
+ super().__init__()
72
+
73
+ def before_build(self, **_kwargs): # Recommended.
74
+ self.tags.append(time.time())
75
+ ```
76
+ This will produce a well behaving Paragraph with dynamic elements.
77
+ #### CSS
78
+ Well, this is straight forward.
79
+ ```css
80
+ div.any-div#my-div-used-for-footer {color: #000000;}
81
+ ```
82
+ will simply turn into:
83
+ ```python
84
+ from typing import Any
85
+ from Autumn import new
86
+
87
+ Base = new()
88
+
89
+ class MyStyle(Base.style.Style):
90
+
91
+ def __init__(self):
92
+ self.name = Base.name.Name("div", Base.name.Identifier("my-div-used-for-footer"),
93
+ [Base.name.Class("any-div")])
94
+ self.styles = [
95
+ "color: #000000;"
96
+ ]
97
+
98
+ super().__init__()
99
+
100
+ ```
101
+ This will also become valuable when writing **dynamic** CSS or when you simply don't know CSS.
102
+ Let's see an example for that too.
103
+ ```python
104
+ from typing import Any
105
+ from Autumn import new
106
+
107
+ Base = new()
108
+
109
+ class MyStyle(Base.style.Style):
110
+
111
+ def __init__(self):
112
+ self.name = Base.name.Name("div", Base.name.Identifier("my-div-used-for-footer"),
113
+ [Base.name.Class("any-div")])
114
+ self.styles = [
115
+ "color: #000000;"
116
+ ]
117
+
118
+ self.dynamic = True
119
+
120
+ super().__init__()
121
+
122
+ def before_build(self, **kwargs):
123
+ if "style" in kwargs:
124
+ self.styles.append(kwargs["style"])
125
+
126
+ ```
127
+
128
+ #### A note on Thread safety
129
+ Thread safety is one of the most important parts to remember,
130
+ every public and private method is thread-safe if it inherits from AbstractBase.
131
+ Well, excluding __getattribute__, __setattr__, every public/private method is thread-safe,
132
+ unless it's a protected method. We do not lock protected methods, as they are (mostly, by convenience)
133
+ used by the public/private methods themselves.
134
+
135
+ ### Our future goals
136
+ Our future goals (currently) can be listed as:
137
+ 1. Out of the box experience.
138
+ 2. A stable and mature ecosystem.
139
+ 3. Complete support for HTML/CSS.
140
+ 4. Support for JavaScript, etc...
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+
3
+ requires = ["hatchling >= 1.26"]
4
+ build-backend = "hatchling.build"
5
+
6
+ [tool.hatch.build.targets.wheel]
7
+
8
+ packages = ["src/Autumn/"]
9
+
10
+ [tool.hatch.build.targets.sdist]
11
+
12
+ include = [
13
+ "src/Autumn/**/*.py",
14
+ "src/Autumn/**/.pyi",
15
+ "src/Autumn/py.typed",
16
+ ]
17
+
18
+ [project]
19
+
20
+ name = "autumn-core"
21
+ version = "1.0.0"
22
+ description = "Autumn - Build CSS and HTML right in your backend"
23
+ requires-python = "~=3.12"
24
+ license = "MIT"
25
+ readme = "README.md"
26
+ authors = [
27
+ {name = "Nerina0Coder", email = "github.py.coder@gmail.com"},
28
+ ]
29
+ dependencies = [
30
+ "markupsafe ~= 3.0.3",
31
+ "coloraide ~= 8.12.1",
32
+ "werkzeug ~= 3.1.8"
33
+ ]
34
+ classifiers = [
35
+ "Programming Language :: Python :: 3",
36
+ "Operating System :: OS Independent",
37
+ "License :: OSI Approved :: MIT License",
38
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
39
+ "Environment :: Web Environment"
40
+ ]
41
+
42
+ [dependency-groups]
43
+
44
+ docs = [
45
+ "sphinx>=7.0",
46
+ "myst-parser>=2.0",
47
+ "furo>=2.0",
48
+ ]
@@ -0,0 +1,57 @@
1
+ from .class_ import Class
2
+ from .identifier import Identifier
3
+ from .attribute_selector import AttributeSelector
4
+ from .name import Name
5
+
6
+ # --- Special Function ---
7
+
8
+ def MakeSelector(state = None,
9
+ identifier = None,
10
+ cls = None,
11
+ selector = None,):
12
+ out = []
13
+
14
+ if state is not None:
15
+ if not isinstance(state, list):
16
+ state = [state]
17
+ else:
18
+ state = []
19
+
20
+ if identifier is not None:
21
+ if not isinstance(identifier, list):
22
+ identifier = [identifier]
23
+ else:
24
+ identifier = [identifier]
25
+
26
+ if cls is not None:
27
+ if not isinstance(cls, list):
28
+ cls = [cls]
29
+ else:
30
+ cls = []
31
+
32
+ if selector is not None:
33
+ if not isinstance(selector, list):
34
+ selector = [selector]
35
+ else:
36
+ selector = []
37
+
38
+ mixed = [*state, *identifier, *cls, *selector]
39
+
40
+ for i in mixed:
41
+ adding = str(i) if not hasattr(i, "build") else i.build()
42
+ out.append(f"{adding if len(out) == 1 else f",{adding}"}")
43
+
44
+ return "".join(out)
45
+
46
+ # API
47
+
48
+ class Naming:
49
+ """
50
+ Naming - Contains classes used for naming.
51
+ """
52
+
53
+ MakeSelector = MakeSelector
54
+ Name = Name
55
+ Identifier = Identifier
56
+ Class = Class
57
+ AttributeSelector = AttributeSelector
@@ -0,0 +1,19 @@
1
+ import threading
2
+
3
+ from markupsafe import escape
4
+
5
+ from Autumn.abstract_base import AbstractBase
6
+
7
+
8
+ class AttributeSelector(AbstractBase):
9
+
10
+ def __init__(self, attr, value):
11
+ self._attr = attr
12
+ self._value = value
13
+
14
+ self._lock = threading.Lock()
15
+
16
+ def build(self, **kwargs) -> str:
17
+ with self._lock:
18
+ self.before_build(**kwargs)
19
+ return f'[{escape(self._attr)}="{escape(self._attr)}"]'
@@ -0,0 +1,21 @@
1
+ import dataclasses
2
+ import threading
3
+
4
+ from markupsafe import escape
5
+
6
+
7
+ @dataclasses.dataclass
8
+ class Class:
9
+ """
10
+ The class used to hold CSS/HTML class names.
11
+ """
12
+ name: str
13
+
14
+ _lock = threading.Lock()
15
+
16
+ def __post_init__(self):
17
+ self.name = escape(self.name)
18
+
19
+ def __str__(self):
20
+ with self._lock:
21
+ return self.name.replace(" ", "-").replace("\n", "-").replace("\t", "-")
@@ -0,0 +1,21 @@
1
+ import dataclasses
2
+ import threading
3
+
4
+ from markupsafe import escape
5
+
6
+
7
+ @dataclasses.dataclass
8
+ class Identifier:
9
+ """
10
+ The class used to hold CSS/HTML identifiers.
11
+ """
12
+ name: str
13
+
14
+ _lock = threading.Lock()
15
+
16
+ def __post_init__(self):
17
+ self.name = escape(self.name)
18
+
19
+ def __str__(self):
20
+ with self._lock:
21
+ return self.name.replace(" ", "-").replace("\n", "-").replace("\t", "-")
@@ -0,0 +1,55 @@
1
+ import copy
2
+ import threading
3
+
4
+ from markupsafe import escape
5
+
6
+ from Autumn.abstract_base import AbstractBase
7
+
8
+
9
+ class Name(AbstractBase):
10
+ """
11
+ Represents a CSS name.
12
+ """
13
+
14
+ def __init__(self,
15
+ name,
16
+ id_,
17
+ classes,
18
+ /, *,
19
+ attributes = None):
20
+ """
21
+ :param attributes: CSS/JS only
22
+ """
23
+ self.name = name
24
+ self.identifier = id_
25
+ self.classes = classes
26
+
27
+ self.attrs = attributes
28
+
29
+ self._lock = threading.Lock()
30
+
31
+ self._cache = []
32
+
33
+ def build(self, cache_if_possible = True, **kwargs):
34
+
35
+ with self._lock:
36
+ out = [self.name]
37
+
38
+ self.before_build(**kwargs)
39
+
40
+ if self.identifier:
41
+ out.append(f"#{self.identifier}")
42
+
43
+ if self.classes:
44
+ for cls in self.classes:
45
+ out.append(f".{cls}")
46
+
47
+ if self.attrs:
48
+ for k, v in self.attrs.items():
49
+ out.append(f'[{escape(k)}="{escape(v)}"]')
50
+
51
+ return ''.join(out)
52
+
53
+ @staticmethod
54
+ def from_tag(tag):
55
+ return Name(tag.name, tag.identifier, copy.deepcopy(tag.classes))
@@ -0,0 +1,2 @@
1
+ from .page import Page as Page
2
+ from .page_manager import PageManager as PageManager
@@ -0,0 +1,84 @@
1
+ import html
2
+ import threading
3
+ from typing import Literal, Any
4
+
5
+ from Autumn.Tag.Enums import Language
6
+ from Autumn.Tag.Meta import Title
7
+ from Autumn.Tag.abstract_tag import AbstractTag
8
+ from Autumn.Tag.Meta import Cdn
9
+ from Autumn.Tag.Meta import Head
10
+ from Autumn.abstract_base import AbstractBase
11
+
12
+
13
+ class Page(AbstractBase):
14
+ """
15
+ A page class representing an HTML document.
16
+ """
17
+
18
+ def __init__(self, name: str, /, *, direction: Literal["ltr", "rtl", "auto"] = "auto", language: Language | str = "en"):
19
+ """
20
+ Initializes a new page object.
21
+ :param name: The name of the page.
22
+ :param direction: The direction of the page.
23
+ :param language: The language of the page.
24
+ """
25
+ self.name = name
26
+ self.direction = direction
27
+ self.language = language.value if isinstance(language, Language) else language
28
+ self._tags: list[AbstractTag] = []
29
+ self._requirements: list[Cdn] = []
30
+
31
+ self._cache: list[str] = []
32
+
33
+ self._lock = threading.Lock()
34
+
35
+ def require(self, cdn: list[Cdn] | Cdn, /) -> "Page":
36
+ """
37
+ Requires CDN URL(s) for this specific page.
38
+ :param cdn: The CDN URL(s).
39
+ :return: This instance for chaining operations.
40
+ """
41
+ self._requirements.extend(cdn if isinstance(cdn, list) else [cdn])
42
+ return self
43
+
44
+ def tag(self, tag: list[AbstractTag] | AbstractTag, /) -> "Page":
45
+ """
46
+ Adds tag(s) to this page, which is often only a head and a body.
47
+ :param tag: The tag(s) to add.
48
+ :return: This instance for chaining operations.
49
+ """
50
+ self._tags.extend(tag if isinstance(tag, list) else [tag])
51
+ return self
52
+
53
+ def build(self, **build_kwargs: Any) -> str:
54
+ dynamic = any(tag.dynamic for tag in self._tags)
55
+
56
+ if not dynamic and self._cache:
57
+ return self._cache[-1]
58
+
59
+ self.before_build(**build_kwargs)
60
+
61
+ head: Head | None = next(filter(lambda tag: isinstance(tag, Head), self._tags), None) # type: ignore
62
+ if head is None:
63
+ self._tags.insert(0, Head(Title(self.name), *self._requirements))
64
+ else:
65
+ head.tags.extend([Title(self.name), *self._requirements])
66
+
67
+ out = ("<!DOCTYPE html>" +
68
+ f'<html lang="{html.escape(self.language)}" dir="{html.escape(self.direction)}">' +
69
+ "".join(tag.build(dynamic, **build_kwargs) for tag in self._tags) +
70
+ "</html>")
71
+
72
+ if not dynamic and not self._cache:
73
+ self._cache.append(out)
74
+ return out
75
+
76
+ @property
77
+ def dynamic(self) -> bool:
78
+ return any(tag.dynamic for tag in self._tags)
79
+ @property
80
+ def tags(self) -> list[AbstractTag]:
81
+ return self._tags.copy()
82
+ @property
83
+ def requirements(self) -> list[Cdn]:
84
+ return self._requirements.copy()