BryanW commited on
Commit
2c1bace
·
verified ·
1 Parent(s): 282a5a0

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/ElementInclude.py +244 -0
  2. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/__init__.py +22 -0
  3. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/_elementpath.py +343 -0
  4. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/apihelpers.pxi +1801 -0
  5. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/builder.py +243 -0
  6. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/classlookup.pxi +580 -0
  7. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/cleanup.pxi +215 -0
  8. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/cssselect.py +101 -0
  9. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/doctestcompare.py +488 -0
  10. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/etree.h +244 -0
  11. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/etree.pyx +0 -0
  12. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/etree_api.h +204 -0
  13. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/extensions.pxi +830 -0
  14. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/lxml.etree.h +244 -0
  15. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/objectpath.pxi +332 -0
  16. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/proxy.pxi +622 -0
  17. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/public-api.pxi +178 -0
  18. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/pyclasslookup.py +3 -0
  19. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/relaxng.pxi +165 -0
  20. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/sax.py +285 -0
  21. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/schematron.pxi +173 -0
  22. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/serializer.pxi +1849 -0
  23. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xinclude.pxi +67 -0
  24. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xmlerror.pxi +1662 -0
  25. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xpath.pxi +487 -0
  26. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xsltext.pxi +242 -0
  27. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/__init__.py +975 -0
  28. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/activations.py +356 -0
  29. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/activations_tf.py +147 -0
  30. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/audio_utils.py +1224 -0
  31. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/cache_utils.py +1493 -0
  32. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_tf_hub_seq_to_seq_bert_to_pytorch.py +86 -0
  33. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/debug_utils.py +346 -0
  34. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/dependency_versions_table.py +108 -0
  35. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/dynamic_module_utils.py +843 -0
  36. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/feature_extraction_sequence_utils.py +371 -0
  37. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/feature_extraction_utils.py +697 -0
  38. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/file_utils.py +130 -0
  39. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/hyperparameter_search.py +141 -0
  40. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_processing_base.py +543 -0
  41. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_processing_utils.py +317 -0
  42. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_utils.py +969 -0
  43. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/keras_callbacks.py +413 -0
  44. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/model_debugging_utils.py +456 -0
  45. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modelcard.py +914 -0
  46. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_attn_mask_utils.py +487 -0
  47. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flash_attention_utils.py +668 -0
  48. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flax_outputs.py +700 -0
  49. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flax_utils.py +1274 -0
  50. Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_gguf_pytorch_utils.py +532 -0
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/ElementInclude.py ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # ElementTree
3
+ # $Id: ElementInclude.py 1862 2004-06-18 07:31:02Z Fredrik $
4
+ #
5
+ # limited xinclude support for element trees
6
+ #
7
+ # history:
8
+ # 2003-08-15 fl created
9
+ # 2003-11-14 fl fixed default loader
10
+ #
11
+ # Copyright (c) 2003-2004 by Fredrik Lundh. All rights reserved.
12
+ #
13
+ # fredrik@pythonware.com
14
+ # http://www.pythonware.com
15
+ #
16
+ # --------------------------------------------------------------------
17
+ # The ElementTree toolkit is
18
+ #
19
+ # Copyright (c) 1999-2004 by Fredrik Lundh
20
+ #
21
+ # By obtaining, using, and/or copying this software and/or its
22
+ # associated documentation, you agree that you have read, understood,
23
+ # and will comply with the following terms and conditions:
24
+ #
25
+ # Permission to use, copy, modify, and distribute this software and
26
+ # its associated documentation for any purpose and without fee is
27
+ # hereby granted, provided that the above copyright notice appears in
28
+ # all copies, and that both that copyright notice and this permission
29
+ # notice appear in supporting documentation, and that the name of
30
+ # Secret Labs AB or the author not be used in advertising or publicity
31
+ # pertaining to distribution of the software without specific, written
32
+ # prior permission.
33
+ #
34
+ # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
35
+ # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
36
+ # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
37
+ # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
38
+ # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39
+ # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
40
+ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
41
+ # OF THIS SOFTWARE.
42
+ # --------------------------------------------------------------------
43
+
44
+ """
45
+ Limited XInclude support for the ElementTree package.
46
+
47
+ While lxml.etree has full support for XInclude (see
48
+ `etree.ElementTree.xinclude()`), this module provides a simpler, pure
49
+ Python, ElementTree compatible implementation that supports a simple
50
+ form of custom URL resolvers.
51
+ """
52
+
53
+ from lxml import etree
54
+ try:
55
+ from urlparse import urljoin
56
+ from urllib2 import urlopen
57
+ except ImportError:
58
+ # Python 3
59
+ from urllib.parse import urljoin
60
+ from urllib.request import urlopen
61
+
62
+ XINCLUDE = "{http://www.w3.org/2001/XInclude}"
63
+
64
+ XINCLUDE_INCLUDE = XINCLUDE + "include"
65
+ XINCLUDE_FALLBACK = XINCLUDE + "fallback"
66
+ XINCLUDE_ITER_TAG = XINCLUDE + "*"
67
+
68
+ # For security reasons, the inclusion depth is limited to this read-only value by default.
69
+ DEFAULT_MAX_INCLUSION_DEPTH = 6
70
+
71
+
72
+ ##
73
+ # Fatal include error.
74
+
75
+ class FatalIncludeError(etree.LxmlSyntaxError):
76
+ pass
77
+
78
+
79
+ class LimitedRecursiveIncludeError(FatalIncludeError):
80
+ pass
81
+
82
+
83
+ ##
84
+ # ET compatible default loader.
85
+ # This loader reads an included resource from disk.
86
+ #
87
+ # @param href Resource reference.
88
+ # @param parse Parse mode. Either "xml" or "text".
89
+ # @param encoding Optional text encoding.
90
+ # @return The expanded resource. If the parse mode is "xml", this
91
+ # is an ElementTree instance. If the parse mode is "text", this
92
+ # is a Unicode string. If the loader fails, it can return None
93
+ # or raise an IOError exception.
94
+ # @throws IOError If the loader fails to load the resource.
95
+
96
+ def default_loader(href, parse, encoding=None):
97
+ file = open(href, 'rb')
98
+ if parse == "xml":
99
+ data = etree.parse(file).getroot()
100
+ else:
101
+ data = file.read()
102
+ if not encoding:
103
+ encoding = 'utf-8'
104
+ data = data.decode(encoding)
105
+ file.close()
106
+ return data
107
+
108
+
109
+ ##
110
+ # Default loader used by lxml.etree - handles custom resolvers properly
111
+ #
112
+
113
+ def _lxml_default_loader(href, parse, encoding=None, parser=None):
114
+ if parse == "xml":
115
+ data = etree.parse(href, parser).getroot()
116
+ else:
117
+ if "://" in href:
118
+ f = urlopen(href)
119
+ else:
120
+ f = open(href, 'rb')
121
+ data = f.read()
122
+ f.close()
123
+ if not encoding:
124
+ encoding = 'utf-8'
125
+ data = data.decode(encoding)
126
+ return data
127
+
128
+
129
+ ##
130
+ # Wrapper for ET compatibility - drops the parser
131
+
132
+ def _wrap_et_loader(loader):
133
+ def load(href, parse, encoding=None, parser=None):
134
+ return loader(href, parse, encoding)
135
+ return load
136
+
137
+
138
+ ##
139
+ # Expand XInclude directives.
140
+ #
141
+ # @param elem Root element.
142
+ # @param loader Optional resource loader. If omitted, it defaults
143
+ # to {@link default_loader}. If given, it should be a callable
144
+ # that implements the same interface as <b>default_loader</b>.
145
+ # @param base_url The base URL of the original file, to resolve
146
+ # relative include file references.
147
+ # @param max_depth The maximum number of recursive inclusions.
148
+ # Limited to reduce the risk of malicious content explosion.
149
+ # Pass None to disable the limitation.
150
+ # @throws LimitedRecursiveIncludeError If the {@link max_depth} was exceeded.
151
+ # @throws FatalIncludeError If the function fails to include a given
152
+ # resource, or if the tree contains malformed XInclude elements.
153
+ # @throws IOError If the function fails to load a given resource.
154
+ # @returns the node or its replacement if it was an XInclude node
155
+
156
+ def include(elem, loader=None, base_url=None,
157
+ max_depth=DEFAULT_MAX_INCLUSION_DEPTH):
158
+ if max_depth is None:
159
+ max_depth = -1
160
+ elif max_depth < 0:
161
+ raise ValueError("expected non-negative depth or None for 'max_depth', got %r" % max_depth)
162
+
163
+ if base_url is None:
164
+ if hasattr(elem, 'getroot'):
165
+ tree = elem
166
+ elem = elem.getroot()
167
+ else:
168
+ tree = elem.getroottree()
169
+ if hasattr(tree, 'docinfo'):
170
+ base_url = tree.docinfo.URL
171
+ elif hasattr(elem, 'getroot'):
172
+ elem = elem.getroot()
173
+ _include(elem, loader, base_url, max_depth)
174
+
175
+
176
+ def _include(elem, loader=None, base_url=None,
177
+ max_depth=DEFAULT_MAX_INCLUSION_DEPTH, _parent_hrefs=None):
178
+ if loader is not None:
179
+ load_include = _wrap_et_loader(loader)
180
+ else:
181
+ load_include = _lxml_default_loader
182
+
183
+ if _parent_hrefs is None:
184
+ _parent_hrefs = set()
185
+
186
+ parser = elem.getroottree().parser
187
+
188
+ include_elements = list(
189
+ elem.iter(XINCLUDE_ITER_TAG))
190
+
191
+ for e in include_elements:
192
+ if e.tag == XINCLUDE_INCLUDE:
193
+ # process xinclude directive
194
+ href = urljoin(base_url, e.get("href"))
195
+ parse = e.get("parse", "xml")
196
+ parent = e.getparent()
197
+ if parse == "xml":
198
+ if href in _parent_hrefs:
199
+ raise FatalIncludeError(
200
+ "recursive include of %r detected" % href
201
+ )
202
+ if max_depth == 0:
203
+ raise LimitedRecursiveIncludeError(
204
+ "maximum xinclude depth reached when including file %s" % href)
205
+ node = load_include(href, parse, parser=parser)
206
+ if node is None:
207
+ raise FatalIncludeError(
208
+ "cannot load %r as %r" % (href, parse)
209
+ )
210
+ node = _include(node, loader, href, max_depth - 1, {href} | _parent_hrefs)
211
+ if e.tail:
212
+ node.tail = (node.tail or "") + e.tail
213
+ if parent is None:
214
+ return node # replaced the root node!
215
+ parent.replace(e, node)
216
+ elif parse == "text":
217
+ text = load_include(href, parse, encoding=e.get("encoding"))
218
+ if text is None:
219
+ raise FatalIncludeError(
220
+ "cannot load %r as %r" % (href, parse)
221
+ )
222
+ predecessor = e.getprevious()
223
+ if predecessor is not None:
224
+ predecessor.tail = (predecessor.tail or "") + text
225
+ elif parent is None:
226
+ return text # replaced the root node!
227
+ else:
228
+ parent.text = (parent.text or "") + text + (e.tail or "")
229
+ parent.remove(e)
230
+ else:
231
+ raise FatalIncludeError(
232
+ "unknown parse type in xi:include tag (%r)" % parse
233
+ )
234
+ elif e.tag == XINCLUDE_FALLBACK:
235
+ parent = e.getparent()
236
+ if parent is not None and parent.tag != XINCLUDE_INCLUDE:
237
+ raise FatalIncludeError(
238
+ "xi:fallback tag must be child of xi:include (%r)" % e.tag
239
+ )
240
+ else:
241
+ raise FatalIncludeError(
242
+ "Invalid element found in XInclude namespace (%r)" % e.tag
243
+ )
244
+ return elem
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/__init__.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # this is a package
2
+
3
+ __version__ = "6.0.2"
4
+
5
+
6
+ def get_include():
7
+ """
8
+ Returns a list of header include paths (for lxml itself, libxml2
9
+ and libxslt) needed to compile C code against lxml if it was built
10
+ with statically linked libraries.
11
+ """
12
+ import os
13
+ lxml_path = __path__[0]
14
+ include_path = os.path.join(lxml_path, 'includes')
15
+ includes = [include_path, lxml_path]
16
+
17
+ for name in os.listdir(include_path):
18
+ path = os.path.join(include_path, name)
19
+ if os.path.isdir(path):
20
+ includes.append(path)
21
+
22
+ return includes
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/_elementpath.py ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # cython: language_level=3
2
+
3
+ #
4
+ # ElementTree
5
+ # $Id: ElementPath.py 3375 2008-02-13 08:05:08Z fredrik $
6
+ #
7
+ # limited xpath support for element trees
8
+ #
9
+ # history:
10
+ # 2003-05-23 fl created
11
+ # 2003-05-28 fl added support for // etc
12
+ # 2003-08-27 fl fixed parsing of periods in element names
13
+ # 2007-09-10 fl new selection engine
14
+ # 2007-09-12 fl fixed parent selector
15
+ # 2007-09-13 fl added iterfind; changed findall to return a list
16
+ # 2007-11-30 fl added namespaces support
17
+ # 2009-10-30 fl added child element value filter
18
+ #
19
+ # Copyright (c) 2003-2009 by Fredrik Lundh. All rights reserved.
20
+ #
21
+ # fredrik@pythonware.com
22
+ # http://www.pythonware.com
23
+ #
24
+ # --------------------------------------------------------------------
25
+ # The ElementTree toolkit is
26
+ #
27
+ # Copyright (c) 1999-2009 by Fredrik Lundh
28
+ #
29
+ # By obtaining, using, and/or copying this software and/or its
30
+ # associated documentation, you agree that you have read, understood,
31
+ # and will comply with the following terms and conditions:
32
+ #
33
+ # Permission to use, copy, modify, and distribute this software and
34
+ # its associated documentation for any purpose and without fee is
35
+ # hereby granted, provided that the above copyright notice appears in
36
+ # all copies, and that both that copyright notice and this permission
37
+ # notice appear in supporting documentation, and that the name of
38
+ # Secret Labs AB or the author not be used in advertising or publicity
39
+ # pertaining to distribution of the software without specific, written
40
+ # prior permission.
41
+ #
42
+ # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
43
+ # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
44
+ # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
45
+ # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
46
+ # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
47
+ # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48
+ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
49
+ # OF THIS SOFTWARE.
50
+ # --------------------------------------------------------------------
51
+
52
+ ##
53
+ # Implementation module for XPath support. There's usually no reason
54
+ # to import this module directly; the <b>ElementTree</b> does this for
55
+ # you, if needed.
56
+ ##
57
+
58
+
59
+ import re
60
+
61
+ xpath_tokenizer_re = re.compile(
62
+ "("
63
+ "'[^']*'|\"[^\"]*\"|"
64
+ "::|"
65
+ "//?|"
66
+ r"\.\.|"
67
+ r"\(\)|"
68
+ r"[/.*:\[\]\(\)@=])|"
69
+ r"((?:\{[^}]+\})?[^/\[\]\(\)@=\s]+)|"
70
+ r"\s+"
71
+ )
72
+
73
+ def xpath_tokenizer(pattern, namespaces=None, with_prefixes=True):
74
+ # ElementTree uses '', lxml used None originally.
75
+ default_namespace = (namespaces.get(None) or namespaces.get('')) if namespaces else None
76
+ parsing_attribute = False
77
+ for token in xpath_tokenizer_re.findall(pattern):
78
+ ttype, tag = token
79
+ if tag and tag[0] != "{":
80
+ if ":" in tag and with_prefixes:
81
+ prefix, uri = tag.split(":", 1)
82
+ try:
83
+ if not namespaces:
84
+ raise KeyError
85
+ yield ttype, "{%s}%s" % (namespaces[prefix], uri)
86
+ except KeyError:
87
+ raise SyntaxError("prefix %r not found in prefix map" % prefix)
88
+ elif tag.isdecimal():
89
+ yield token # index
90
+ elif default_namespace and not parsing_attribute:
91
+ yield ttype, "{%s}%s" % (default_namespace, tag)
92
+ else:
93
+ yield token
94
+ parsing_attribute = False
95
+ else:
96
+ yield token
97
+ parsing_attribute = ttype == '@'
98
+
99
+
100
+ def prepare_child(next, token):
101
+ tag = token[1]
102
+ def select(result):
103
+ for elem in result:
104
+ yield from elem.iterchildren(tag)
105
+ return select
106
+
107
+ def prepare_star(next, token):
108
+ def select(result):
109
+ for elem in result:
110
+ yield from elem.iterchildren('*')
111
+ return select
112
+
113
+ def prepare_self(next, token):
114
+ def select(result):
115
+ return result
116
+ return select
117
+
118
+ def prepare_descendant(next, token):
119
+ token = next()
120
+ if token[0] == "*":
121
+ tag = "*"
122
+ elif not token[0]:
123
+ tag = token[1]
124
+ else:
125
+ raise SyntaxError("invalid descendant")
126
+ def select(result):
127
+ for elem in result:
128
+ yield from elem.iterdescendants(tag)
129
+ return select
130
+
131
+ def prepare_parent(next, token):
132
+ def select(result):
133
+ for elem in result:
134
+ parent = elem.getparent()
135
+ if parent is not None:
136
+ yield parent
137
+ return select
138
+
139
+ def prepare_predicate(next, token):
140
+ # FIXME: replace with real parser!!! refs:
141
+ # http://effbot.org/zone/simple-iterator-parser.htm
142
+ # http://javascript.crockford.com/tdop/tdop.html
143
+ signature = ''
144
+ predicate = []
145
+ while 1:
146
+ token = next()
147
+ if token[0] == "]":
148
+ break
149
+ if token == ('', ''):
150
+ # ignore whitespace
151
+ continue
152
+ if token[0] and token[0][:1] in "'\"":
153
+ token = "'", token[0][1:-1]
154
+ signature += token[0] or "-"
155
+ predicate.append(token[1])
156
+
157
+ # use signature to determine predicate type
158
+ if signature == "@-":
159
+ # [@attribute] predicate
160
+ key = predicate[1]
161
+ def select(result):
162
+ for elem in result:
163
+ if elem.get(key) is not None:
164
+ yield elem
165
+ return select
166
+ if signature == "@-='":
167
+ # [@attribute='value']
168
+ key = predicate[1]
169
+ value = predicate[-1]
170
+ def select(result):
171
+ for elem in result:
172
+ if elem.get(key) == value:
173
+ yield elem
174
+ return select
175
+ if signature == "-" and not re.match(r"-?\d+$", predicate[0]):
176
+ # [tag]
177
+ tag = predicate[0]
178
+ def select(result):
179
+ for elem in result:
180
+ for _ in elem.iterchildren(tag):
181
+ yield elem
182
+ break
183
+ return select
184
+ if signature == ".='" or (signature == "-='" and not re.match(r"-?\d+$", predicate[0])):
185
+ # [.='value'] or [tag='value']
186
+ tag = predicate[0]
187
+ value = predicate[-1]
188
+ if tag:
189
+ def select(result):
190
+ for elem in result:
191
+ for e in elem.iterchildren(tag):
192
+ if "".join(e.itertext()) == value:
193
+ yield elem
194
+ break
195
+ else:
196
+ def select(result):
197
+ for elem in result:
198
+ if "".join(elem.itertext()) == value:
199
+ yield elem
200
+ return select
201
+ if signature == "-" or signature == "-()" or signature == "-()-":
202
+ # [index] or [last()] or [last()-index]
203
+ if signature == "-":
204
+ # [index]
205
+ index = int(predicate[0]) - 1
206
+ if index < 0:
207
+ if index == -1:
208
+ raise SyntaxError(
209
+ "indices in path predicates are 1-based, not 0-based")
210
+ else:
211
+ raise SyntaxError("path index >= 1 expected")
212
+ else:
213
+ if predicate[0] != "last":
214
+ raise SyntaxError("unsupported function")
215
+ if signature == "-()-":
216
+ try:
217
+ index = int(predicate[2]) - 1
218
+ except ValueError:
219
+ raise SyntaxError("unsupported expression")
220
+ else:
221
+ index = -1
222
+ def select(result):
223
+ for elem in result:
224
+ parent = elem.getparent()
225
+ if parent is None:
226
+ continue
227
+ try:
228
+ # FIXME: what if the selector is "*" ?
229
+ elems = list(parent.iterchildren(elem.tag))
230
+ if elems[index] is elem:
231
+ yield elem
232
+ except IndexError:
233
+ pass
234
+ return select
235
+ raise SyntaxError("invalid predicate")
236
+
237
+ ops = {
238
+ "": prepare_child,
239
+ "*": prepare_star,
240
+ ".": prepare_self,
241
+ "..": prepare_parent,
242
+ "//": prepare_descendant,
243
+ "[": prepare_predicate,
244
+ }
245
+
246
+
247
+ # --------------------------------------------------------------------
248
+
249
+ _cache = {}
250
+
251
+
252
+ def _build_path_iterator(path, namespaces, with_prefixes=True):
253
+ """compile selector pattern"""
254
+ if path[-1:] == "/":
255
+ path += "*" # implicit all (FIXME: keep this?)
256
+
257
+ cache_key = (path,)
258
+ if namespaces:
259
+ # lxml originally used None for the default namespace but ElementTree uses the
260
+ # more convenient (all-strings-dict) empty string, so we support both here,
261
+ # preferring the more convenient '', as long as they aren't ambiguous.
262
+ if None in namespaces:
263
+ if '' in namespaces and namespaces[None] != namespaces['']:
264
+ raise ValueError("Ambiguous default namespace provided: %r versus %r" % (
265
+ namespaces[None], namespaces['']))
266
+ cache_key += (namespaces[None],) + tuple(sorted(
267
+ item for item in namespaces.items() if item[0] is not None))
268
+ else:
269
+ cache_key += tuple(sorted(namespaces.items()))
270
+
271
+ try:
272
+ return _cache[cache_key]
273
+ except KeyError:
274
+ pass
275
+ if len(_cache) > 100:
276
+ _cache.clear()
277
+
278
+ if path[:1] == "/":
279
+ raise SyntaxError("cannot use absolute path on element")
280
+ stream = iter(xpath_tokenizer(path, namespaces, with_prefixes=with_prefixes))
281
+ try:
282
+ _next = stream.next
283
+ except AttributeError:
284
+ # Python 3
285
+ _next = stream.__next__
286
+ try:
287
+ token = _next()
288
+ except StopIteration:
289
+ raise SyntaxError("empty path expression")
290
+ selector = []
291
+ while 1:
292
+ try:
293
+ selector.append(ops[token[0]](_next, token))
294
+ except StopIteration:
295
+ raise SyntaxError("invalid path")
296
+ try:
297
+ token = _next()
298
+ if token[0] == "/":
299
+ token = _next()
300
+ except StopIteration:
301
+ break
302
+ _cache[cache_key] = selector
303
+ return selector
304
+
305
+
306
+ ##
307
+ # Iterate over the matching nodes
308
+
309
+ def iterfind(elem, path, namespaces=None, with_prefixes=True):
310
+ selector = _build_path_iterator(path, namespaces, with_prefixes=with_prefixes)
311
+ result = iter((elem,))
312
+ for select in selector:
313
+ result = select(result)
314
+ return result
315
+
316
+
317
+ ##
318
+ # Find first matching object.
319
+
320
+ def find(elem, path, namespaces=None, with_prefixes=True):
321
+ it = iterfind(elem, path, namespaces, with_prefixes=with_prefixes)
322
+ try:
323
+ return next(it)
324
+ except StopIteration:
325
+ return None
326
+
327
+
328
+ ##
329
+ # Find all matching objects.
330
+
331
+ def findall(elem, path, namespaces=None, with_prefixes=True):
332
+ return list(iterfind(elem, path, namespaces))
333
+
334
+
335
+ ##
336
+ # Find text for first matching object.
337
+
338
+ def findtext(elem, path, default=None, namespaces=None, with_prefixes=True):
339
+ el = find(elem, path, namespaces, with_prefixes=with_prefixes)
340
+ if el is None:
341
+ return default
342
+ else:
343
+ return el.text or ''
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/apihelpers.pxi ADDED
@@ -0,0 +1,1801 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Private/public helper functions for API functions
2
+
3
+ from lxml.includes cimport uri
4
+
5
+
6
+ cdef void displayNode(xmlNode* c_node, indent) noexcept:
7
+ # to help with debugging
8
+ cdef xmlNode* c_child
9
+ try:
10
+ print(indent * ' ', <long>c_node)
11
+ c_child = c_node.children
12
+ while c_child is not NULL:
13
+ displayNode(c_child, indent + 1)
14
+ c_child = c_child.next
15
+ finally:
16
+ return # swallow any exceptions
17
+
18
+ cdef inline bint _isHtmlDocument(_Element element) except -1:
19
+ cdef xmlNode* c_node = element._c_node
20
+ return (
21
+ c_node is not NULL and c_node.doc is not NULL and
22
+ c_node.doc.properties & tree.XML_DOC_HTML != 0
23
+ )
24
+
25
+ cdef inline int _assertValidNode(_Element element) except -1:
26
+ assert element._c_node is not NULL, "invalid Element proxy at %s" % id(element)
27
+
28
+ cdef inline int _assertValidDoc(_Document doc) except -1:
29
+ assert doc._c_doc is not NULL, "invalid Document proxy at %s" % id(doc)
30
+
31
+ cdef _Document _documentOrRaise(object input):
32
+ """Call this to get the document of a _Document, _ElementTree or _Element
33
+ object, or to raise an exception if it can't be determined.
34
+
35
+ Should be used in all API functions for consistency.
36
+ """
37
+ cdef _Document doc
38
+ if isinstance(input, _ElementTree):
39
+ if (<_ElementTree>input)._context_node is not None:
40
+ doc = (<_ElementTree>input)._context_node._doc
41
+ else:
42
+ doc = None
43
+ elif isinstance(input, _Element):
44
+ doc = (<_Element>input)._doc
45
+ elif isinstance(input, _Document):
46
+ doc = <_Document>input
47
+ else:
48
+ raise TypeError, f"Invalid input object: {python._fqtypename(input).decode('utf8')}"
49
+ if doc is None:
50
+ raise ValueError, f"Input object has no document: {python._fqtypename(input).decode('utf8')}"
51
+ _assertValidDoc(doc)
52
+ return doc
53
+
54
+ cdef _Element _rootNodeOrRaise(object input):
55
+ """Call this to get the root node of a _Document, _ElementTree or
56
+ _Element object, or to raise an exception if it can't be determined.
57
+
58
+ Should be used in all API functions for consistency.
59
+ """
60
+ cdef _Element node
61
+ if isinstance(input, _ElementTree):
62
+ node = (<_ElementTree>input)._context_node
63
+ elif isinstance(input, _Element):
64
+ node = <_Element>input
65
+ elif isinstance(input, _Document):
66
+ node = (<_Document>input).getroot()
67
+ else:
68
+ raise TypeError, f"Invalid input object: {python._fqtypename(input).decode('utf8')}"
69
+ if (node is None or not node._c_node or
70
+ node._c_node.type != tree.XML_ELEMENT_NODE):
71
+ raise ValueError, f"Input object is not an XML element: {python._fqtypename(input).decode('utf8')}"
72
+ _assertValidNode(node)
73
+ return node
74
+
75
+ cdef bint _isAncestorOrSame(xmlNode* c_ancestor, xmlNode* c_node) noexcept:
76
+ while c_node:
77
+ if c_node is c_ancestor:
78
+ return True
79
+ c_node = c_node.parent
80
+ return False
81
+
82
+ cdef _Element _makeElement(tag, xmlDoc* c_doc, _Document doc,
83
+ _BaseParser parser, text, tail, attrib, nsmap,
84
+ dict extra_attrs):
85
+ """Create a new element and initialize text content, namespaces and
86
+ attributes.
87
+
88
+ This helper function will reuse as much of the existing document as
89
+ possible:
90
+
91
+ If 'parser' is None, the parser will be inherited from 'doc' or the
92
+ default parser will be used.
93
+
94
+ If 'doc' is None, 'c_doc' is used to create a new _Document and the new
95
+ element is made its root node.
96
+
97
+ If 'c_doc' is also NULL, a new xmlDoc will be created.
98
+ """
99
+ cdef xmlNode* c_node
100
+ if doc is not None:
101
+ c_doc = doc._c_doc
102
+ ns_utf, name_utf = _getNsTag(tag)
103
+ if parser is not None and parser._for_html:
104
+ _htmlTagValidOrRaise(name_utf)
105
+ if c_doc is NULL:
106
+ c_doc = _newHTMLDoc()
107
+ else:
108
+ _tagValidOrRaise(name_utf)
109
+ if c_doc is NULL:
110
+ c_doc = _newXMLDoc()
111
+ c_node = _createElement(c_doc, name_utf)
112
+ if c_node is NULL:
113
+ if doc is None and c_doc is not NULL:
114
+ tree.xmlFreeDoc(c_doc)
115
+ raise MemoryError()
116
+ try:
117
+ if doc is None:
118
+ tree.xmlDocSetRootElement(c_doc, c_node)
119
+ doc = _documentFactory(c_doc, parser)
120
+ if text is not None:
121
+ _setNodeText(c_node, text)
122
+ if tail is not None:
123
+ _setTailText(c_node, tail)
124
+ # add namespaces to node if necessary
125
+ _setNodeNamespaces(c_node, doc, ns_utf, nsmap)
126
+ _initNodeAttributes(c_node, doc, attrib, extra_attrs)
127
+ return _elementFactory(doc, c_node)
128
+ except:
129
+ # free allocated c_node/c_doc unless Python does it for us
130
+ if c_node.doc is not c_doc:
131
+ # node not yet in document => will not be freed by document
132
+ if tail is not None:
133
+ _removeText(c_node.next) # tail
134
+ tree.xmlFreeNode(c_node)
135
+ if doc is None:
136
+ # c_doc will not be freed by doc
137
+ tree.xmlFreeDoc(c_doc)
138
+ raise
139
+
140
+ cdef int _initNewElement(_Element element, bint is_html, name_utf, ns_utf,
141
+ _BaseParser parser, attrib, nsmap, dict extra_attrs) except -1:
142
+ """Initialise a new Element object.
143
+
144
+ This is used when users instantiate a Python Element subclass
145
+ directly, without it being mapped to an existing XML node.
146
+ """
147
+ cdef xmlDoc* c_doc
148
+ cdef xmlNode* c_node
149
+ cdef _Document doc
150
+ if is_html:
151
+ _htmlTagValidOrRaise(name_utf)
152
+ c_doc = _newHTMLDoc()
153
+ else:
154
+ _tagValidOrRaise(name_utf)
155
+ c_doc = _newXMLDoc()
156
+ c_node = _createElement(c_doc, name_utf)
157
+ if c_node is NULL:
158
+ if c_doc is not NULL:
159
+ tree.xmlFreeDoc(c_doc)
160
+ raise MemoryError()
161
+ tree.xmlDocSetRootElement(c_doc, c_node)
162
+ doc = _documentFactory(c_doc, parser)
163
+ # add namespaces to node if necessary
164
+ _setNodeNamespaces(c_node, doc, ns_utf, nsmap)
165
+ _initNodeAttributes(c_node, doc, attrib, extra_attrs)
166
+ _registerProxy(element, doc, c_node)
167
+ element._init()
168
+ return 0
169
+
170
+ cdef _Element _makeSubElement(_Element parent, tag, text, tail,
171
+ attrib, nsmap, dict extra_attrs):
172
+ """Create a new child element and initialize text content, namespaces and
173
+ attributes.
174
+ """
175
+ cdef xmlNode* c_node
176
+ cdef xmlDoc* c_doc
177
+ if parent is None or parent._doc is None:
178
+ return None
179
+ _assertValidNode(parent)
180
+ ns_utf, name_utf = _getNsTag(tag)
181
+ c_doc = parent._doc._c_doc
182
+
183
+ if parent._doc._parser is not None and parent._doc._parser._for_html:
184
+ _htmlTagValidOrRaise(name_utf)
185
+ else:
186
+ _tagValidOrRaise(name_utf)
187
+
188
+ c_node = _createElement(c_doc, name_utf)
189
+ if c_node is NULL:
190
+ raise MemoryError()
191
+ tree.xmlAddChild(parent._c_node, c_node)
192
+
193
+ try:
194
+ if text is not None:
195
+ _setNodeText(c_node, text)
196
+ if tail is not None:
197
+ _setTailText(c_node, tail)
198
+
199
+ # add namespaces to node if necessary
200
+ _setNodeNamespaces(c_node, parent._doc, ns_utf, nsmap)
201
+ _initNodeAttributes(c_node, parent._doc, attrib, extra_attrs)
202
+ return _elementFactory(parent._doc, c_node)
203
+ except:
204
+ # make sure we clean up in case of an error
205
+ _removeNode(parent._doc, c_node)
206
+ raise
207
+
208
+
209
+ cdef int _setNodeNamespaces(xmlNode* c_node, _Document doc,
210
+ object node_ns_utf, object nsmap) except -1:
211
+ """Lookup current namespace prefixes, then set namespace structure for
212
+ node (if 'node_ns_utf' was provided) and register new ns-prefix mappings.
213
+
214
+ 'node_ns_utf' should only be passed for a newly created node.
215
+ """
216
+ cdef xmlNs* c_ns
217
+ cdef list nsdefs
218
+
219
+ if nsmap:
220
+ for prefix, href in _iter_nsmap(nsmap):
221
+ href_utf = _utf8(href)
222
+ _uriValidOrRaise(href_utf)
223
+ c_href = _xcstr(href_utf)
224
+ if prefix is not None:
225
+ prefix_utf = _utf8(prefix)
226
+ _prefixValidOrRaise(prefix_utf)
227
+ c_prefix = _xcstr(prefix_utf)
228
+ else:
229
+ c_prefix = <const_xmlChar*>NULL
230
+ # add namespace with prefix if it is not already known
231
+ c_ns = tree.xmlSearchNs(doc._c_doc, c_node, c_prefix)
232
+ if c_ns is NULL or \
233
+ c_ns.href is NULL or \
234
+ tree.xmlStrcmp(c_ns.href, c_href) != 0:
235
+ c_ns = tree.xmlNewNs(c_node, c_href, c_prefix)
236
+ if href_utf == node_ns_utf:
237
+ tree.xmlSetNs(c_node, c_ns)
238
+ node_ns_utf = None
239
+
240
+ if node_ns_utf is not None:
241
+ _uriValidOrRaise(node_ns_utf)
242
+ doc._setNodeNs(c_node, _xcstr(node_ns_utf))
243
+ return 0
244
+
245
+
246
+ cdef dict _build_nsmap(xmlNode* c_node):
247
+ """
248
+ Namespace prefix->URI mapping known in the context of this Element.
249
+ This includes all namespace declarations of the parents.
250
+ """
251
+ cdef xmlNs* c_ns
252
+ nsmap = {}
253
+ while c_node is not NULL and c_node.type == tree.XML_ELEMENT_NODE:
254
+ c_ns = c_node.nsDef
255
+ while c_ns is not NULL:
256
+ if c_ns.prefix or c_ns.href:
257
+ prefix = funicodeOrNone(c_ns.prefix)
258
+ if prefix not in nsmap:
259
+ nsmap[prefix] = funicodeOrNone(c_ns.href)
260
+ c_ns = c_ns.next
261
+ c_node = c_node.parent
262
+ return nsmap
263
+
264
+
265
+ cdef _iter_nsmap(nsmap):
266
+ """
267
+ Create a reproducibly ordered iterable from an nsmap mapping.
268
+ Tries to preserve an existing order and sorts if it assumes no order.
269
+
270
+ The difference to _iter_attrib() is that None doesn't sort with strings
271
+ in Py3.x.
272
+ """
273
+ if isinstance(nsmap, dict):
274
+ # dicts are insertion-ordered in Py3.6+ => keep the user provided order.
275
+ return nsmap.items()
276
+ if len(nsmap) <= 1:
277
+ return nsmap.items()
278
+ # nsmap will usually be a plain unordered dict => avoid type checking overhead
279
+ if type(nsmap) is not dict and isinstance(nsmap, OrderedDict):
280
+ return nsmap.items() # keep existing order
281
+ if None not in nsmap:
282
+ return sorted(nsmap.items())
283
+
284
+ # Move the default namespace to the end. This makes sure libxml2
285
+ # prefers a prefix if the ns is defined redundantly on the same
286
+ # element. That way, users can work around a problem themselves
287
+ # where default namespace attributes on non-default namespaced
288
+ # elements serialise without prefix (i.e. into the non-default
289
+ # namespace).
290
+ default_ns = nsmap[None]
291
+ nsdefs = [(k, v) for k, v in nsmap.items() if k is not None]
292
+ nsdefs.sort()
293
+ nsdefs.append((None, default_ns))
294
+ return nsdefs
295
+
296
+
297
+ cdef _iter_attrib(attrib):
298
+ """
299
+ Create a reproducibly ordered iterable from an attrib mapping.
300
+ Tries to preserve an existing order and sorts if it assumes no order.
301
+ """
302
+ # dicts are insertion-ordered in Py3.6+ => keep the user provided order.
303
+ if isinstance(attrib, (dict, _Attrib, OrderedDict)):
304
+ return attrib.items()
305
+ # assume it's an unordered mapping of some kind
306
+ return sorted(attrib.items())
307
+
308
+
309
+ cdef _initNodeAttributes(xmlNode* c_node, _Document doc, attrib, dict extra):
310
+ """Initialise the attributes of an element node.
311
+ """
312
+ cdef bint is_html
313
+ cdef xmlNs* c_ns
314
+ if attrib is not None and not hasattr(attrib, 'items'):
315
+ raise TypeError, f"Invalid attribute dictionary: {python._fqtypename(attrib).decode('utf8')}"
316
+ if not attrib and not extra:
317
+ return # nothing to do
318
+ is_html = doc._parser._for_html
319
+ seen = set()
320
+ if extra:
321
+ for name, value in extra.items():
322
+ _addAttributeToNode(c_node, doc, is_html, name, value, seen)
323
+ if attrib:
324
+ for name, value in _iter_attrib(attrib):
325
+ _addAttributeToNode(c_node, doc, is_html, name, value, seen)
326
+
327
+
328
+ cdef int _addAttributeToNode(xmlNode* c_node, _Document doc, bint is_html,
329
+ name, value, set seen_tags) except -1:
330
+ ns_utf, name_utf = tag = _getNsTag(name)
331
+ if tag in seen_tags:
332
+ return 0
333
+ seen_tags.add(tag)
334
+ if not is_html:
335
+ _attributeValidOrRaise(name_utf)
336
+ value_utf = _utf8(value)
337
+ if ns_utf is None:
338
+ tree.xmlNewProp(c_node, _xcstr(name_utf), _xcstr(value_utf))
339
+ else:
340
+ _uriValidOrRaise(ns_utf)
341
+ c_ns = doc._findOrBuildNodeNs(c_node, _xcstr(ns_utf), NULL, 1)
342
+ tree.xmlNewNsProp(c_node, c_ns,
343
+ _xcstr(name_utf), _xcstr(value_utf))
344
+ return 0
345
+
346
+
347
+ ctypedef struct _ns_node_ref:
348
+ xmlNs* ns
349
+ xmlNode* node
350
+
351
+
352
+ cdef int _collectNsDefs(xmlNode* c_element, _ns_node_ref **_c_ns_list,
353
+ size_t *_c_ns_list_len, size_t *_c_ns_list_size) except -1:
354
+ c_ns_list = _c_ns_list[0]
355
+ cdef size_t c_ns_list_len = _c_ns_list_len[0]
356
+ cdef size_t c_ns_list_size = _c_ns_list_size[0]
357
+
358
+ c_nsdef = c_element.nsDef
359
+ while c_nsdef is not NULL:
360
+ if c_ns_list_len >= c_ns_list_size:
361
+ if c_ns_list is NULL:
362
+ c_ns_list_size = 20
363
+ else:
364
+ c_ns_list_size *= 2
365
+ c_nsref_ptr = <_ns_node_ref*> python.lxml_realloc(
366
+ c_ns_list, c_ns_list_size, sizeof(_ns_node_ref))
367
+ if c_nsref_ptr is NULL:
368
+ if c_ns_list is not NULL:
369
+ python.lxml_free(c_ns_list)
370
+ _c_ns_list[0] = NULL
371
+ raise MemoryError()
372
+ c_ns_list = c_nsref_ptr
373
+
374
+ c_ns_list[c_ns_list_len] = _ns_node_ref(c_nsdef, c_element)
375
+ c_ns_list_len += 1
376
+ c_nsdef = c_nsdef.next
377
+
378
+ _c_ns_list_size[0] = c_ns_list_size
379
+ _c_ns_list_len[0] = c_ns_list_len
380
+ _c_ns_list[0] = c_ns_list
381
+
382
+
383
+ cdef int _removeUnusedNamespaceDeclarations(xmlNode* c_element, set prefixes_to_keep) except -1:
384
+ """Remove any namespace declarations from a subtree that are not used by
385
+ any of its elements (or attributes).
386
+
387
+ If a 'prefixes_to_keep' is provided, it must be a set of prefixes.
388
+ Any corresponding namespace mappings will not be removed as part of the cleanup.
389
+ """
390
+ cdef xmlNode* c_node
391
+ cdef _ns_node_ref* c_ns_list = NULL
392
+ cdef size_t c_ns_list_size = 0
393
+ cdef size_t c_ns_list_len = 0
394
+ cdef size_t i
395
+
396
+ if c_element.parent and c_element.parent.type == tree.XML_DOCUMENT_NODE:
397
+ # include declarations on the document node
398
+ _collectNsDefs(c_element.parent, &c_ns_list, &c_ns_list_len, &c_ns_list_size)
399
+
400
+ tree.BEGIN_FOR_EACH_ELEMENT_FROM(c_element, c_element, 1)
401
+ # collect all new namespace declarations into the ns list
402
+ if c_element.nsDef:
403
+ _collectNsDefs(c_element, &c_ns_list, &c_ns_list_len, &c_ns_list_size)
404
+
405
+ # remove all namespace declarations from the list that are referenced
406
+ if c_ns_list_len and c_element.type == tree.XML_ELEMENT_NODE:
407
+ c_node = c_element
408
+ while c_node and c_ns_list_len:
409
+ if c_node.ns:
410
+ for i in range(c_ns_list_len):
411
+ if c_node.ns is c_ns_list[i].ns:
412
+ c_ns_list_len -= 1
413
+ c_ns_list[i] = c_ns_list[c_ns_list_len]
414
+ #c_ns_list[c_ns_list_len] = _ns_node_ref(NULL, NULL)
415
+ break
416
+ if c_node is c_element:
417
+ # continue with attributes
418
+ c_node = <xmlNode*>c_element.properties
419
+ else:
420
+ c_node = c_node.next
421
+ tree.END_FOR_EACH_ELEMENT_FROM(c_element)
422
+
423
+ if c_ns_list is NULL:
424
+ return 0
425
+
426
+ # free all namespace declarations that remained in the list,
427
+ # except for those we should keep explicitly
428
+ cdef xmlNs* c_nsdef
429
+ for i in range(c_ns_list_len):
430
+ if prefixes_to_keep is not None:
431
+ if c_ns_list[i].ns.prefix and c_ns_list[i].ns.prefix in prefixes_to_keep:
432
+ continue
433
+ c_node = c_ns_list[i].node
434
+ c_nsdef = c_node.nsDef
435
+ if c_nsdef is c_ns_list[i].ns:
436
+ c_node.nsDef = c_node.nsDef.next
437
+ else:
438
+ while c_nsdef.next is not c_ns_list[i].ns:
439
+ c_nsdef = c_nsdef.next
440
+ c_nsdef.next = c_nsdef.next.next
441
+ tree.xmlFreeNs(c_ns_list[i].ns)
442
+
443
+ if c_ns_list is not NULL:
444
+ python.lxml_free(c_ns_list)
445
+ return 0
446
+
447
+ cdef xmlNs* _searchNsByHref(xmlNode* c_node, const_xmlChar* c_href, bint is_attribute) noexcept:
448
+ """Search a namespace declaration that covers a node (element or
449
+ attribute).
450
+
451
+ For attributes, try to find a prefixed namespace declaration
452
+ instead of the default namespaces. This helps in supporting
453
+ round-trips for attributes on elements with a different namespace.
454
+ """
455
+ cdef xmlNs* c_ns
456
+ cdef xmlNs* c_default_ns = NULL
457
+ cdef xmlNode* c_element
458
+ if c_href is NULL or c_node is NULL or c_node.type == tree.XML_ENTITY_REF_NODE:
459
+ return NULL
460
+ if tree.xmlStrcmp(c_href, tree.XML_XML_NAMESPACE) == 0:
461
+ # no special cases here, let libxml2 handle this
462
+ return tree.xmlSearchNsByHref(c_node.doc, c_node, c_href)
463
+ if c_node.type == tree.XML_ATTRIBUTE_NODE:
464
+ is_attribute = 1
465
+ while c_node is not NULL and c_node.type != tree.XML_ELEMENT_NODE:
466
+ c_node = c_node.parent
467
+ c_element = c_node
468
+ while c_node is not NULL:
469
+ if c_node.type == tree.XML_ELEMENT_NODE:
470
+ c_ns = c_node.nsDef
471
+ while c_ns is not NULL:
472
+ if c_ns.href is not NULL and tree.xmlStrcmp(c_href, c_ns.href) == 0:
473
+ if c_ns.prefix is NULL and is_attribute:
474
+ # for attributes, continue searching a named
475
+ # prefix, but keep the first default namespace
476
+ # declaration that we found
477
+ if c_default_ns is NULL:
478
+ c_default_ns = c_ns
479
+ elif tree.xmlSearchNs(
480
+ c_element.doc, c_element, c_ns.prefix) is c_ns:
481
+ # start node is in namespace scope => found!
482
+ return c_ns
483
+ c_ns = c_ns.next
484
+ if c_node is not c_element and c_node.ns is not NULL:
485
+ # optimise: the node may have the namespace itself
486
+ c_ns = c_node.ns
487
+ if c_ns.href is not NULL and tree.xmlStrcmp(c_href, c_ns.href) == 0:
488
+ if c_ns.prefix is NULL and is_attribute:
489
+ # for attributes, continue searching a named
490
+ # prefix, but keep the first default namespace
491
+ # declaration that we found
492
+ if c_default_ns is NULL:
493
+ c_default_ns = c_ns
494
+ elif tree.xmlSearchNs(
495
+ c_element.doc, c_element, c_ns.prefix) is c_ns:
496
+ # start node is in namespace scope => found!
497
+ return c_ns
498
+ c_node = c_node.parent
499
+ # nothing found => use a matching default namespace or fail
500
+ if c_default_ns is not NULL:
501
+ if tree.xmlSearchNs(c_element.doc, c_element, NULL) is c_default_ns:
502
+ return c_default_ns
503
+ return NULL
504
+
505
+ cdef int _replaceNodeByChildren(_Document doc, xmlNode* c_node) except -1:
506
+ # NOTE: this does not deallocate the node, just unlink it!
507
+ cdef xmlNode* c_parent
508
+ cdef xmlNode* c_child
509
+ if c_node.children is NULL:
510
+ tree.xmlUnlinkNode(c_node)
511
+ return 0
512
+
513
+ c_parent = c_node.parent
514
+ # fix parent links of children
515
+ c_child = c_node.children
516
+ while c_child is not NULL:
517
+ c_child.parent = c_parent
518
+ c_child = c_child.next
519
+
520
+ # fix namespace references of children if their parent's namespace
521
+ # declarations get lost
522
+ if c_node.nsDef is not NULL:
523
+ c_child = c_node.children
524
+ while c_child is not NULL:
525
+ moveNodeToDocument(doc, doc._c_doc, c_child)
526
+ c_child = c_child.next
527
+
528
+ # fix sibling links to/from child slice
529
+ if c_node.prev is NULL:
530
+ c_parent.children = c_node.children
531
+ else:
532
+ c_node.prev.next = c_node.children
533
+ c_node.children.prev = c_node.prev
534
+ if c_node.next is NULL:
535
+ c_parent.last = c_node.last
536
+ else:
537
+ c_node.next.prev = c_node.last
538
+ c_node.last.next = c_node.next
539
+
540
+ # unlink c_node
541
+ c_node.children = c_node.last = NULL
542
+ c_node.parent = c_node.next = c_node.prev = NULL
543
+ return 0
544
+
545
+ cdef unicode _attributeValue(xmlNode* c_element, xmlAttr* c_attrib_node):
546
+ c_href = _getNs(<xmlNode*>c_attrib_node)
547
+ value = tree.xmlGetNsProp(c_element, c_attrib_node.name, c_href)
548
+ try:
549
+ result = funicode(value)
550
+ finally:
551
+ tree.xmlFree(value)
552
+ return result
553
+
554
+ cdef unicode _attributeValueFromNsName(xmlNode* c_element,
555
+ const_xmlChar* c_href, const_xmlChar* c_name):
556
+ c_result = tree.xmlGetNsProp(c_element, c_name, c_href)
557
+ if c_result is NULL:
558
+ return None
559
+ try:
560
+ result = funicode(c_result)
561
+ finally:
562
+ tree.xmlFree(c_result)
563
+ return result
564
+
565
+ cdef object _getNodeAttributeValue(xmlNode* c_node, key, default):
566
+ ns, tag = _getNsTag(key)
567
+ c_href = <const_xmlChar*>NULL if ns is None else _xcstr(ns)
568
+ c_result = tree.xmlGetNsProp(c_node, _xcstr(tag), c_href)
569
+ if c_result is NULL:
570
+ # XXX free namespace that is not in use..?
571
+ return default
572
+ try:
573
+ result = funicode(c_result)
574
+ finally:
575
+ tree.xmlFree(c_result)
576
+ return result
577
+
578
+ cdef inline object _getAttributeValue(_Element element, key, default):
579
+ return _getNodeAttributeValue(element._c_node, key, default)
580
+
581
+ cdef int _setAttributeValue(_Element element, key, value) except -1:
582
+ cdef const_xmlChar* c_value
583
+ cdef xmlNs* c_ns
584
+ ns, tag = _getNsTag(key)
585
+ is_html = element._doc._parser._for_html
586
+ if not is_html:
587
+ _attributeValidOrRaise(tag)
588
+ c_tag = _xcstr(tag)
589
+ if value is None and is_html:
590
+ c_value = NULL
591
+ else:
592
+ if isinstance(value, QName):
593
+ value = _resolveQNameText(element, value)
594
+ else:
595
+ value = _utf8(value)
596
+ c_value = _xcstr(value)
597
+ if ns is None:
598
+ c_ns = NULL
599
+ else:
600
+ c_ns = element._doc._findOrBuildNodeNs(element._c_node, _xcstr(ns), NULL, 1)
601
+ tree.xmlSetNsProp(element._c_node, c_ns, c_tag, c_value)
602
+ return 0
603
+
604
+ cdef int _delAttribute(_Element element, key) except -1:
605
+ ns, tag = _getNsTag(key)
606
+ c_href = <const_xmlChar*>NULL if ns is None else _xcstr(ns)
607
+ if _delAttributeFromNsName(element._c_node, c_href, _xcstr(tag)):
608
+ raise KeyError, key
609
+ return 0
610
+
611
+ cdef int _delAttributeFromNsName(xmlNode* c_node, const_xmlChar* c_href, const_xmlChar* c_name) noexcept:
612
+ c_attr = tree.xmlHasNsProp(c_node, c_name, c_href)
613
+ if c_attr is NULL:
614
+ # XXX free namespace that is not in use..?
615
+ return -1
616
+ tree.xmlRemoveProp(c_attr)
617
+ return 0
618
+
619
+ cdef list _collectAttributes(xmlNode* c_node, int collecttype):
620
+ """Collect all attributes of a node in a list. Depending on collecttype,
621
+ it collects either the name (1), the value (2) or the name-value tuples.
622
+ """
623
+ cdef Py_ssize_t count
624
+ c_attr = c_node.properties
625
+ count = 0
626
+ while c_attr is not NULL:
627
+ if c_attr.type == tree.XML_ATTRIBUTE_NODE:
628
+ count += 1
629
+ c_attr = c_attr.next
630
+
631
+ if not count:
632
+ return []
633
+
634
+ attributes = [None] * count
635
+ c_attr = c_node.properties
636
+ count = 0
637
+ while c_attr is not NULL:
638
+ if c_attr.type == tree.XML_ATTRIBUTE_NODE:
639
+ if collecttype == 1:
640
+ item = _namespacedName(<xmlNode*>c_attr)
641
+ elif collecttype == 2:
642
+ item = _attributeValue(c_node, c_attr)
643
+ else:
644
+ item = (_namespacedName(<xmlNode*>c_attr),
645
+ _attributeValue(c_node, c_attr))
646
+ attributes[count] = item
647
+ count += 1
648
+ c_attr = c_attr.next
649
+ return attributes
650
+
651
+ cdef object __RE_XML_ENCODING = re.compile(
652
+ r'^(<\?xml[^>]+)\s+encoding\s*=\s*["\'][^"\']*["\'](\s*\?>|)', re.U)
653
+
654
+ cdef object __REPLACE_XML_ENCODING = __RE_XML_ENCODING.sub
655
+ cdef object __HAS_XML_ENCODING = __RE_XML_ENCODING.match
656
+
657
+ cdef object _stripEncodingDeclaration(object xml_string):
658
+ # this is a hack to remove the XML encoding declaration from unicode
659
+ return __REPLACE_XML_ENCODING(r'\g<1>\g<2>', xml_string)
660
+
661
+ cdef bint _hasEncodingDeclaration(object xml_string) except -1:
662
+ # check if a (unicode) string has an XML encoding declaration
663
+ return __HAS_XML_ENCODING(xml_string) is not None
664
+
665
+ cdef inline bint _hasText(xmlNode* c_node) noexcept:
666
+ return c_node is not NULL and _textNodeOrSkip(c_node.children) is not NULL
667
+
668
+ cdef inline bint _hasTail(xmlNode* c_node) noexcept:
669
+ return c_node is not NULL and _textNodeOrSkip(c_node.next) is not NULL
670
+
671
+ cdef inline bint _hasNonWhitespaceTail(xmlNode* c_node) except -1:
672
+ return _hasNonWhitespaceText(c_node, tail=True)
673
+
674
+ cdef bint _hasNonWhitespaceText(xmlNode* c_node, bint tail=False) except -1:
675
+ c_text_node = c_node and _textNodeOrSkip(c_node.next if tail else c_node.children)
676
+ if c_text_node is NULL:
677
+ return False
678
+ while c_text_node is not NULL:
679
+ if c_text_node.content[0] != c'\0' and not _collectText(c_text_node).isspace():
680
+ return True
681
+ c_text_node = _textNodeOrSkip(c_text_node.next)
682
+ return False
683
+
684
+ cdef unicode _collectText(xmlNode* c_node):
685
+ """Collect all text nodes and return them as a unicode string.
686
+
687
+ Start collecting at c_node.
688
+
689
+ If there was no text to collect, return None
690
+ """
691
+ cdef Py_ssize_t scount
692
+ cdef xmlChar* c_text
693
+ cdef xmlNode* c_node_cur
694
+ # check for multiple text nodes
695
+ scount = 0
696
+ c_text = NULL
697
+ c_node_cur = c_node = _textNodeOrSkip(c_node)
698
+ while c_node_cur is not NULL:
699
+ if c_node_cur.content[0] != c'\0':
700
+ c_text = c_node_cur.content
701
+ scount += 1
702
+ c_node_cur = _textNodeOrSkip(c_node_cur.next)
703
+
704
+ # handle two most common cases first
705
+ if c_text is NULL:
706
+ return '' if scount > 0 else None
707
+ if scount == 1:
708
+ return funicode(c_text)
709
+
710
+ # the rest is not performance critical anymore
711
+ result = b''
712
+ while c_node is not NULL:
713
+ result += <unsigned char*>c_node.content
714
+ c_node = _textNodeOrSkip(c_node.next)
715
+ return funicode(<const_xmlChar*><unsigned char*>result)
716
+
717
+ cdef void _removeText(xmlNode* c_node) noexcept:
718
+ """Remove all text nodes.
719
+
720
+ Start removing at c_node.
721
+ """
722
+ cdef xmlNode* c_next
723
+ c_node = _textNodeOrSkip(c_node)
724
+ while c_node is not NULL:
725
+ c_next = _textNodeOrSkip(c_node.next)
726
+ tree.xmlUnlinkNode(c_node)
727
+ tree.xmlFreeNode(c_node)
728
+ c_node = c_next
729
+
730
+ cdef xmlNode* _createTextNode(xmlDoc* doc, value) except NULL:
731
+ cdef xmlNode* c_text_node
732
+ if isinstance(value, CDATA):
733
+ c_text_node = tree.xmlNewCDataBlock(
734
+ doc, _xcstr((<CDATA>value)._utf8_data),
735
+ python.PyBytes_GET_SIZE((<CDATA>value)._utf8_data))
736
+ else:
737
+ text = _utf8(value)
738
+ c_text_node = tree.xmlNewDocText(doc, _xcstr(text))
739
+ if not c_text_node:
740
+ raise MemoryError()
741
+ return c_text_node
742
+
743
+ cdef int _setNodeText(xmlNode* c_node, value) except -1:
744
+ # remove all text nodes at the start first
745
+ _removeText(c_node.children)
746
+ if value is None:
747
+ return 0
748
+ # now add new text node with value at start
749
+ c_text_node = _createTextNode(c_node.doc, value)
750
+ if c_node.children is NULL:
751
+ tree.xmlAddChild(c_node, c_text_node)
752
+ else:
753
+ tree.xmlAddPrevSibling(c_node.children, c_text_node)
754
+ return 0
755
+
756
+ cdef int _setTailText(xmlNode* c_node, value) except -1:
757
+ # remove all text nodes at the start first
758
+ _removeText(c_node.next)
759
+ if value is None:
760
+ return 0
761
+ # now append new text node with value
762
+ c_text_node = _createTextNode(c_node.doc, value)
763
+ tree.xmlAddNextSibling(c_node, c_text_node)
764
+ return 0
765
+
766
+ cdef bytes _resolveQNameText(_Element element, value):
767
+ cdef xmlNs* c_ns
768
+ ns, tag = _getNsTag(value)
769
+ if ns is None:
770
+ return tag
771
+ else:
772
+ c_ns = element._doc._findOrBuildNodeNs(
773
+ element._c_node, _xcstr(ns), NULL, 0)
774
+ return python.PyBytes_FromFormat('%s:%s', c_ns.prefix, _cstr(tag))
775
+
776
+ cdef inline bint _hasChild(xmlNode* c_node) noexcept:
777
+ return c_node is not NULL and _findChildForwards(c_node, 0) is not NULL
778
+
779
+ cdef inline Py_ssize_t _countElements(xmlNode* c_node) noexcept:
780
+ "Counts the elements within the following siblings and the node itself."
781
+ cdef Py_ssize_t count
782
+ count = 0
783
+ while c_node is not NULL:
784
+ if _isElement(c_node):
785
+ count += 1
786
+ c_node = c_node.next
787
+ return count
788
+
789
+ cdef int _findChildSlice(
790
+ slice sliceobject, xmlNode* c_parent,
791
+ xmlNode** c_start_node, Py_ssize_t* c_step, Py_ssize_t* c_length) except -1:
792
+ """Resolve a children slice.
793
+
794
+ Returns the start node, step size and the slice length in the
795
+ pointer arguments.
796
+ """
797
+ cdef Py_ssize_t start = 0, stop = 0, childcount
798
+ childcount = _countElements(c_parent.children)
799
+ if childcount == 0:
800
+ c_start_node[0] = NULL
801
+ c_length[0] = 0
802
+ if sliceobject.step is None:
803
+ c_step[0] = 1
804
+ else:
805
+ python._PyEval_SliceIndex(sliceobject.step, c_step)
806
+ return 0
807
+ python.PySlice_GetIndicesEx(
808
+ sliceobject, childcount, &start, &stop, c_step, c_length)
809
+ if start > childcount // 2:
810
+ c_start_node[0] = _findChildBackwards(c_parent, childcount - start - 1)
811
+ else:
812
+ c_start_node[0] = _findChild(c_parent, start)
813
+ return 0
814
+
815
+ cdef bint _isFullSlice(slice sliceobject) except -1:
816
+ """Conservative guess if this slice is a full slice as in ``s[:]``.
817
+ """
818
+ cdef Py_ssize_t step = 0
819
+ if sliceobject is None:
820
+ return 0
821
+ if sliceobject.start is None and \
822
+ sliceobject.stop is None:
823
+ if sliceobject.step is None:
824
+ return 1
825
+ python._PyEval_SliceIndex(sliceobject.step, &step)
826
+ if step == 1:
827
+ return 1
828
+ return 0
829
+ return 0
830
+
831
+ cdef _collectChildren(_Element element):
832
+ cdef xmlNode* c_node
833
+ cdef list result = []
834
+ c_node = element._c_node.children
835
+ if c_node is not NULL:
836
+ if not _isElement(c_node):
837
+ c_node = _nextElement(c_node)
838
+ while c_node is not NULL:
839
+ result.append(_elementFactory(element._doc, c_node))
840
+ c_node = _nextElement(c_node)
841
+ return result
842
+
843
+ cdef inline xmlNode* _findChild(xmlNode* c_node, Py_ssize_t index) noexcept:
844
+ if index < 0:
845
+ return _findChildBackwards(c_node, -index - 1)
846
+ else:
847
+ return _findChildForwards(c_node, index)
848
+
849
+ cdef inline xmlNode* _findChildForwards(xmlNode* c_node, Py_ssize_t index) noexcept:
850
+ """Return child element of c_node with index, or return NULL if not found.
851
+ """
852
+ cdef xmlNode* c_child
853
+ cdef Py_ssize_t c
854
+ c_child = c_node.children
855
+ c = 0
856
+ while c_child is not NULL:
857
+ if _isElement(c_child):
858
+ if c == index:
859
+ return c_child
860
+ c += 1
861
+ c_child = c_child.next
862
+ return NULL
863
+
864
+ cdef inline xmlNode* _findChildBackwards(xmlNode* c_node, Py_ssize_t index) noexcept:
865
+ """Return child element of c_node with index, or return NULL if not found.
866
+ Search from the end.
867
+ """
868
+ cdef xmlNode* c_child
869
+ cdef Py_ssize_t c
870
+ c_child = c_node.last
871
+ c = 0
872
+ while c_child is not NULL:
873
+ if _isElement(c_child):
874
+ if c == index:
875
+ return c_child
876
+ c += 1
877
+ c_child = c_child.prev
878
+ return NULL
879
+
880
+ cdef inline xmlNode* _textNodeOrSkip(xmlNode* c_node) noexcept nogil:
881
+ """Return the node if it's a text node. Skip over ignorable nodes in a
882
+ series of text nodes. Return NULL if a non-ignorable node is found.
883
+
884
+ This is used to skip over XInclude nodes when collecting adjacent text
885
+ nodes.
886
+ """
887
+ while c_node is not NULL:
888
+ if c_node.type == tree.XML_TEXT_NODE or \
889
+ c_node.type == tree.XML_CDATA_SECTION_NODE:
890
+ return c_node
891
+ elif c_node.type == tree.XML_XINCLUDE_START or \
892
+ c_node.type == tree.XML_XINCLUDE_END:
893
+ c_node = c_node.next
894
+ else:
895
+ return NULL
896
+ return NULL
897
+
898
+ cdef inline xmlNode* _nextElement(xmlNode* c_node) noexcept:
899
+ """Given a node, find the next sibling that is an element.
900
+ """
901
+ if c_node is NULL:
902
+ return NULL
903
+ c_node = c_node.next
904
+ while c_node is not NULL:
905
+ if _isElement(c_node):
906
+ return c_node
907
+ c_node = c_node.next
908
+ return NULL
909
+
910
+ cdef inline xmlNode* _previousElement(xmlNode* c_node) noexcept:
911
+ """Given a node, find the next sibling that is an element.
912
+ """
913
+ if c_node is NULL:
914
+ return NULL
915
+ c_node = c_node.prev
916
+ while c_node is not NULL:
917
+ if _isElement(c_node):
918
+ return c_node
919
+ c_node = c_node.prev
920
+ return NULL
921
+
922
+ cdef inline xmlNode* _parentElement(xmlNode* c_node) noexcept:
923
+ "Given a node, find the parent element."
924
+ if c_node is NULL or not _isElement(c_node):
925
+ return NULL
926
+ c_node = c_node.parent
927
+ if c_node is NULL or not _isElement(c_node):
928
+ return NULL
929
+ return c_node
930
+
931
+ cdef inline bint _tagMatches(xmlNode* c_node, const_xmlChar* c_href, const_xmlChar* c_name) noexcept:
932
+ """Tests if the node matches namespace URI and tag name.
933
+
934
+ A node matches if it matches both c_href and c_name.
935
+
936
+ A node matches c_href if any of the following is true:
937
+ * c_href is NULL
938
+ * its namespace is NULL and c_href is the empty string
939
+ * its namespace string equals the c_href string
940
+
941
+ A node matches c_name if any of the following is true:
942
+ * c_name is NULL
943
+ * its name string equals the c_name string
944
+ """
945
+ if c_node is NULL:
946
+ return 0
947
+ if c_node.type != tree.XML_ELEMENT_NODE:
948
+ # not an element, only succeed if we match everything
949
+ return c_name is NULL and c_href is NULL
950
+ if c_name is NULL:
951
+ if c_href is NULL:
952
+ # always match
953
+ return 1
954
+ else:
955
+ c_node_href = _getNs(c_node)
956
+ if c_node_href is NULL:
957
+ return c_href[0] == c'\0'
958
+ else:
959
+ return tree.xmlStrcmp(c_node_href, c_href) == 0
960
+ elif c_href is NULL:
961
+ if _getNs(c_node) is not NULL:
962
+ return 0
963
+ return c_node.name == c_name or tree.xmlStrcmp(c_node.name, c_name) == 0
964
+ elif c_node.name == c_name or tree.xmlStrcmp(c_node.name, c_name) == 0:
965
+ c_node_href = _getNs(c_node)
966
+ if c_node_href is NULL:
967
+ return c_href[0] == c'\0'
968
+ else:
969
+ return tree.xmlStrcmp(c_node_href, c_href) == 0
970
+ else:
971
+ return 0
972
+
973
+ cdef inline bint _tagMatchesExactly(xmlNode* c_node, qname* c_qname) noexcept:
974
+ """Tests if the node matches namespace URI and tag name.
975
+
976
+ This differs from _tagMatches() in that it does not consider a
977
+ NULL value in qname.href a wildcard, and that it expects the c_name
978
+ to be taken from the doc dict, i.e. it only compares the names by
979
+ address.
980
+
981
+ A node matches if it matches both href and c_name of the qname.
982
+
983
+ A node matches c_href if any of the following is true:
984
+ * its namespace is NULL and c_href is the empty string
985
+ * its namespace string equals the c_href string
986
+
987
+ A node matches c_name if any of the following is true:
988
+ * c_name is NULL
989
+ * its name string points to the same address (!) as c_name
990
+ """
991
+ return _nsTagMatchesExactly(_getNs(c_node), c_node.name, c_qname)
992
+
993
+ cdef inline bint _nsTagMatchesExactly(const_xmlChar* c_node_href,
994
+ const_xmlChar* c_node_name,
995
+ qname* c_qname) noexcept:
996
+ """Tests if name and namespace URI match those of c_qname.
997
+
998
+ This differs from _tagMatches() in that it does not consider a
999
+ NULL value in qname.href a wildcard, and that it expects the c_name
1000
+ to be taken from the doc dict, i.e. it only compares the names by
1001
+ address.
1002
+
1003
+ A node matches if it matches both href and c_name of the qname.
1004
+
1005
+ A node matches c_href if any of the following is true:
1006
+ * its namespace is NULL and c_href is the empty string
1007
+ * its namespace string equals the c_href string
1008
+
1009
+ A node matches c_name if any of the following is true:
1010
+ * c_name is NULL
1011
+ * its name string points to the same address (!) as c_name
1012
+ """
1013
+ cdef char* c_href
1014
+ if c_qname.c_name is not NULL and c_qname.c_name is not c_node_name:
1015
+ return 0
1016
+ if c_qname.href is NULL:
1017
+ return 1
1018
+ c_href = python.__cstr(c_qname.href)
1019
+ if c_href[0] == b'\0':
1020
+ return c_node_href is NULL or c_node_href[0] == b'\0'
1021
+ elif c_node_href is NULL:
1022
+ return 0
1023
+ else:
1024
+ return tree.xmlStrcmp(<const_xmlChar*>c_href, c_node_href) == 0
1025
+
1026
+ cdef Py_ssize_t _mapTagsToQnameMatchArray(xmlDoc* c_doc, list ns_tags,
1027
+ qname* c_ns_tags, bint force_into_dict) except -1:
1028
+ """Map a sequence of (name, namespace) pairs to a qname array for efficient
1029
+ matching with _tagMatchesExactly() above.
1030
+
1031
+ Note that each qname struct in the array owns its href byte string object
1032
+ if it is not NULL.
1033
+ """
1034
+ cdef Py_ssize_t count = 0, i, c_tag_len
1035
+ cdef bytes ns, tag
1036
+ cdef const_xmlChar* c_tag
1037
+
1038
+ for ns, tag in ns_tags:
1039
+ if tag is None:
1040
+ c_tag = <const_xmlChar*> NULL
1041
+ else:
1042
+ c_tag_len = len(tag)
1043
+ if c_tag_len > limits.INT_MAX:
1044
+ # too long, not in the dict => not in the document
1045
+ continue
1046
+ elif force_into_dict:
1047
+ c_tag = tree.xmlDictLookup(c_doc.dict, _xcstr(tag), <int> c_tag_len)
1048
+ if c_tag is NULL:
1049
+ # clean up before raising the error
1050
+ for i in xrange(count):
1051
+ cpython.ref.Py_XDECREF(c_ns_tags[i].href)
1052
+ raise MemoryError()
1053
+ else:
1054
+ c_tag = tree.xmlDictExists(c_doc.dict, _xcstr(tag), <int> c_tag_len)
1055
+ if c_tag is NULL:
1056
+ # not in the dict => not in the document
1057
+ continue
1058
+
1059
+ c_ns_tags[count].c_name = c_tag
1060
+ if ns is None:
1061
+ c_ns_tags[count].href = NULL
1062
+ else:
1063
+ cpython.ref.Py_INCREF(ns) # keep an owned reference!
1064
+ c_ns_tags[count].href = <python.PyObject*>ns
1065
+ count += 1
1066
+ return count
1067
+
1068
+ cdef int _removeNode(_Document doc, xmlNode* c_node) except -1:
1069
+ """Unlink and free a node and subnodes if possible. Otherwise, make sure
1070
+ it's self-contained.
1071
+ """
1072
+ cdef xmlNode* c_next
1073
+ c_next = c_node.next
1074
+ tree.xmlUnlinkNode(c_node)
1075
+ _moveTail(c_next, c_node)
1076
+ if not attemptDeallocation(c_node):
1077
+ # make namespaces absolute
1078
+ moveNodeToDocument(doc, c_node.doc, c_node)
1079
+ return 0
1080
+
1081
+ cdef int _removeSiblings(xmlNode* c_element, tree.xmlElementType node_type, bint with_tail) except -1:
1082
+ cdef xmlNode* c_node
1083
+ cdef xmlNode* c_next
1084
+ c_node = c_element.next
1085
+ while c_node is not NULL:
1086
+ c_next = _nextElement(c_node)
1087
+ if c_node.type == node_type:
1088
+ if with_tail:
1089
+ _removeText(c_node.next)
1090
+ tree.xmlUnlinkNode(c_node)
1091
+ attemptDeallocation(c_node)
1092
+ c_node = c_next
1093
+ c_node = c_element.prev
1094
+ while c_node is not NULL:
1095
+ c_next = _previousElement(c_node)
1096
+ if c_node.type == node_type:
1097
+ if with_tail:
1098
+ _removeText(c_node.next)
1099
+ tree.xmlUnlinkNode(c_node)
1100
+ attemptDeallocation(c_node)
1101
+ c_node = c_next
1102
+ return 0
1103
+
1104
+ cdef void _moveTail(xmlNode* c_tail, xmlNode* c_target) noexcept:
1105
+ cdef xmlNode* c_next
1106
+ # tail support: look for any text nodes trailing this node and
1107
+ # move them too
1108
+ c_tail = _textNodeOrSkip(c_tail)
1109
+ while c_tail is not NULL:
1110
+ c_next = _textNodeOrSkip(c_tail.next)
1111
+ c_target = tree.xmlAddNextSibling(c_target, c_tail)
1112
+ c_tail = c_next
1113
+
1114
+ cdef int _copyTail(xmlNode* c_tail, xmlNode* c_target) except -1:
1115
+ cdef xmlNode* c_new_tail
1116
+ # tail copying support: look for any text nodes trailing this node and
1117
+ # copy it to the target node
1118
+ c_tail = _textNodeOrSkip(c_tail)
1119
+ while c_tail is not NULL:
1120
+ if c_target.doc is not c_tail.doc:
1121
+ c_new_tail = tree.xmlDocCopyNode(c_tail, c_target.doc, 0)
1122
+ else:
1123
+ c_new_tail = tree.xmlCopyNode(c_tail, 0)
1124
+ if c_new_tail is NULL:
1125
+ raise MemoryError()
1126
+ c_target = tree.xmlAddNextSibling(c_target, c_new_tail)
1127
+ c_tail = _textNodeOrSkip(c_tail.next)
1128
+ return 0
1129
+
1130
+ cdef int _copyNonElementSiblings(xmlNode* c_node, xmlNode* c_target) except -1:
1131
+ cdef xmlNode* c_copy
1132
+ cdef xmlNode* c_sibling = c_node
1133
+ while c_sibling.prev != NULL and \
1134
+ (c_sibling.prev.type == tree.XML_PI_NODE or
1135
+ c_sibling.prev.type == tree.XML_COMMENT_NODE or
1136
+ c_sibling.prev.type == tree.XML_DTD_NODE):
1137
+ c_sibling = c_sibling.prev
1138
+ while c_sibling != c_node:
1139
+ if c_sibling.type == tree.XML_DTD_NODE:
1140
+ c_copy = <xmlNode*>_copyDtd(<tree.xmlDtd*>c_sibling)
1141
+ if c_sibling == <xmlNode*>c_node.doc.intSubset:
1142
+ c_target.doc.intSubset = <tree.xmlDtd*>c_copy
1143
+ else: # c_sibling == c_node.doc.extSubset
1144
+ c_target.doc.extSubset = <tree.xmlDtd*>c_copy
1145
+ else:
1146
+ c_copy = tree.xmlDocCopyNode(c_sibling, c_target.doc, 1)
1147
+ if c_copy is NULL:
1148
+ raise MemoryError()
1149
+ tree.xmlAddPrevSibling(c_target, c_copy)
1150
+ c_sibling = c_sibling.next
1151
+ while c_sibling.next != NULL and \
1152
+ (c_sibling.next.type == tree.XML_PI_NODE or
1153
+ c_sibling.next.type == tree.XML_COMMENT_NODE):
1154
+ c_sibling = c_sibling.next
1155
+ c_copy = tree.xmlDocCopyNode(c_sibling, c_target.doc, 1)
1156
+ if c_copy is NULL:
1157
+ raise MemoryError()
1158
+ tree.xmlAddNextSibling(c_target, c_copy)
1159
+
1160
+ cdef int _deleteSlice(_Document doc, xmlNode* c_node,
1161
+ Py_ssize_t count, Py_ssize_t step) except -1:
1162
+ """Delete slice, ``count`` items starting with ``c_node`` with a step
1163
+ width of ``step``.
1164
+ """
1165
+ cdef xmlNode* c_next
1166
+ cdef Py_ssize_t c, i
1167
+ cdef _node_to_node_function next_element
1168
+ if c_node is NULL:
1169
+ return 0
1170
+ if step > 0:
1171
+ next_element = _nextElement
1172
+ else:
1173
+ step = -step
1174
+ next_element = _previousElement
1175
+ # now start deleting nodes
1176
+ c = 0
1177
+ c_next = c_node
1178
+ while c_node is not NULL and c < count:
1179
+ for i in range(step):
1180
+ c_next = next_element(c_next)
1181
+ if c_next is NULL:
1182
+ break
1183
+ _removeNode(doc, c_node)
1184
+ c += 1
1185
+ c_node = c_next
1186
+ return 0
1187
+
1188
+ cdef int _replaceSlice(_Element parent, xmlNode* c_node,
1189
+ Py_ssize_t slicelength, Py_ssize_t step,
1190
+ bint left_to_right, elements) except -1:
1191
+ """Replace the slice of ``count`` elements starting at ``c_node`` with
1192
+ positive step width ``step`` by the Elements in ``elements``. The
1193
+ direction is given by the boolean argument ``left_to_right``.
1194
+
1195
+ ``c_node`` may be NULL to indicate the end of the children list.
1196
+ """
1197
+ cdef xmlNode* c_orig_neighbour
1198
+ cdef xmlNode* c_next
1199
+ cdef xmlDoc* c_source_doc
1200
+ cdef _Element element
1201
+ cdef Py_ssize_t seqlength, i, c
1202
+ cdef _node_to_node_function next_element
1203
+ assert step > 0
1204
+ if left_to_right:
1205
+ next_element = _nextElement
1206
+ else:
1207
+ next_element = _previousElement
1208
+
1209
+ if not isinstance(elements, (list, tuple)):
1210
+ elements = list(elements)
1211
+
1212
+ if step != 1 or not left_to_right:
1213
+ # *replacing* children stepwise with list => check size!
1214
+ seqlength = len(elements)
1215
+ if seqlength != slicelength:
1216
+ raise ValueError, f"attempt to assign sequence of size {seqlength} " \
1217
+ f"to extended slice of size {slicelength}"
1218
+
1219
+ if c_node is NULL:
1220
+ # no children yet => add all elements straight away
1221
+ if left_to_right:
1222
+ for element in elements:
1223
+ assert element is not None, "Node must not be None"
1224
+ _appendChild(parent, element)
1225
+ else:
1226
+ for element in elements:
1227
+ assert element is not None, "Node must not be None"
1228
+ _prependChild(parent, element)
1229
+ return 0
1230
+
1231
+ # remove the elements first as some might be re-added
1232
+ if left_to_right:
1233
+ # L->R, remember left neighbour
1234
+ c_orig_neighbour = _previousElement(c_node)
1235
+ else:
1236
+ # R->L, remember right neighbour
1237
+ c_orig_neighbour = _nextElement(c_node)
1238
+
1239
+ # We remove the original slice elements one by one. Since we hold
1240
+ # a Python reference to all elements that we will insert, it is
1241
+ # safe to let _removeNode() try (and fail) to free them even if
1242
+ # the element itself or one of its descendents will be reinserted.
1243
+ c = 0
1244
+ c_next = c_node
1245
+ while c_node is not NULL and c < slicelength:
1246
+ for i in range(step):
1247
+ c_next = next_element(c_next)
1248
+ if c_next is NULL:
1249
+ break
1250
+ _removeNode(parent._doc, c_node)
1251
+ c += 1
1252
+ c_node = c_next
1253
+
1254
+ # make sure each element is inserted only once
1255
+ elements = iter(elements)
1256
+
1257
+ # find the first node right of the new insertion point
1258
+ if left_to_right:
1259
+ if c_orig_neighbour is not NULL:
1260
+ c_node = next_element(c_orig_neighbour)
1261
+ else:
1262
+ # before the first element
1263
+ c_node = _findChildForwards(parent._c_node, 0)
1264
+ elif c_orig_neighbour is NULL:
1265
+ # at the end, but reversed stepping
1266
+ # append one element and go to the next insertion point
1267
+ for element in elements:
1268
+ assert element is not None, "Node must not be None"
1269
+ _appendChild(parent, element)
1270
+ c_node = element._c_node
1271
+ if slicelength > 0:
1272
+ slicelength -= 1
1273
+ for i in range(1, step):
1274
+ c_node = next_element(c_node)
1275
+ if c_node is NULL:
1276
+ break
1277
+ break
1278
+ else:
1279
+ c_node = c_orig_neighbour
1280
+
1281
+ if left_to_right:
1282
+ # adjust step size after removing slice as we are not stepping
1283
+ # over the newly inserted elements
1284
+ step -= 1
1285
+
1286
+ # now insert elements where we removed them
1287
+ if c_node is not NULL:
1288
+ for element in elements:
1289
+ assert element is not None, "Node must not be None"
1290
+ _assertValidNode(element)
1291
+ # move element and tail over
1292
+ c_source_doc = element._c_node.doc
1293
+ c_next = element._c_node.next
1294
+ tree.xmlAddPrevSibling(c_node, element._c_node)
1295
+ _moveTail(c_next, element._c_node)
1296
+
1297
+ # integrate element into new document
1298
+ moveNodeToDocument(parent._doc, c_source_doc, element._c_node)
1299
+
1300
+ # stop at the end of the slice
1301
+ if slicelength > 0:
1302
+ slicelength -= 1
1303
+ for i in range(step):
1304
+ c_node = next_element(c_node)
1305
+ if c_node is NULL:
1306
+ break
1307
+ if c_node is NULL:
1308
+ break
1309
+ else:
1310
+ # everything inserted
1311
+ return 0
1312
+
1313
+ # append the remaining elements at the respective end
1314
+ if left_to_right:
1315
+ for element in elements:
1316
+ assert element is not None, "Node must not be None"
1317
+ _assertValidNode(element)
1318
+ _appendChild(parent, element)
1319
+ else:
1320
+ for element in elements:
1321
+ assert element is not None, "Node must not be None"
1322
+ _assertValidNode(element)
1323
+ _prependChild(parent, element)
1324
+
1325
+ return 0
1326
+
1327
+
1328
+ cdef int _linkChild(xmlNode* c_parent, xmlNode* c_node) except -1:
1329
+ """Adaptation of 'xmlAddChild()' that deep-fix the document links iteratively.
1330
+ """
1331
+ assert _isElement(c_node)
1332
+ c_node.parent = c_parent
1333
+ if c_parent.children is NULL:
1334
+ c_parent.children = c_parent.last = c_node
1335
+ else:
1336
+ c_node.prev = c_parent.last
1337
+ c_parent.last.next = c_node
1338
+ c_parent.last = c_node
1339
+
1340
+ _setTreeDoc(c_node, c_parent.doc)
1341
+ return 0
1342
+
1343
+
1344
+ cdef int _appendChild(_Element parent, _Element child) except -1:
1345
+ """Append a new child to a parent element.
1346
+ """
1347
+ c_node = child._c_node
1348
+ c_source_doc = c_node.doc
1349
+ # prevent cycles
1350
+ if _isAncestorOrSame(c_node, parent._c_node):
1351
+ raise ValueError("cannot append parent to itself")
1352
+ # store possible text node
1353
+ c_next = c_node.next
1354
+ # move node itself
1355
+ tree.xmlUnlinkNode(c_node)
1356
+ # do not call xmlAddChild() here since it would deep-traverse the tree
1357
+ _linkChild(parent._c_node, c_node)
1358
+ _moveTail(c_next, c_node)
1359
+ # uh oh, elements may be pointing to different doc when
1360
+ # parent element has moved; change them too..
1361
+ moveNodeToDocument(parent._doc, c_source_doc, c_node)
1362
+ return 0
1363
+
1364
+ cdef int _prependChild(_Element parent, _Element child) except -1:
1365
+ """Prepend a new child to a parent element.
1366
+ """
1367
+ c_node = child._c_node
1368
+ c_source_doc = c_node.doc
1369
+ # prevent cycles
1370
+ if _isAncestorOrSame(c_node, parent._c_node):
1371
+ raise ValueError("cannot append parent to itself")
1372
+ # store possible text node
1373
+ c_next = c_node.next
1374
+ # move node itself
1375
+ c_child = _findChildForwards(parent._c_node, 0)
1376
+ if c_child is NULL:
1377
+ tree.xmlUnlinkNode(c_node)
1378
+ # do not call xmlAddChild() here since it would deep-traverse the tree
1379
+ _linkChild(parent._c_node, c_node)
1380
+ else:
1381
+ tree.xmlAddPrevSibling(c_child, c_node)
1382
+ _moveTail(c_next, c_node)
1383
+ # uh oh, elements may be pointing to different doc when
1384
+ # parent element has moved; change them too..
1385
+ moveNodeToDocument(parent._doc, c_source_doc, c_node)
1386
+ return 0
1387
+
1388
+ cdef int _appendSibling(_Element element, _Element sibling) except -1:
1389
+ """Add a new sibling behind an element.
1390
+ """
1391
+ return _addSibling(element, sibling, as_next=True)
1392
+
1393
+ cdef int _prependSibling(_Element element, _Element sibling) except -1:
1394
+ """Add a new sibling before an element.
1395
+ """
1396
+ return _addSibling(element, sibling, as_next=False)
1397
+
1398
+ cdef int _addSibling(_Element element, _Element sibling, bint as_next) except -1:
1399
+ c_node = sibling._c_node
1400
+ c_source_doc = c_node.doc
1401
+ # prevent cycles
1402
+ if _isAncestorOrSame(c_node, element._c_node):
1403
+ if element._c_node is c_node:
1404
+ return 0 # nothing to do
1405
+ raise ValueError("cannot add ancestor as sibling, please break cycle first")
1406
+ # store possible text node
1407
+ c_next = c_node.next
1408
+ # move node itself
1409
+ if as_next:
1410
+ # must insert after any tail text
1411
+ c_next_node = _nextElement(element._c_node)
1412
+ if c_next_node is NULL:
1413
+ c_next_node = element._c_node
1414
+ while c_next_node.next:
1415
+ c_next_node = c_next_node.next
1416
+ tree.xmlAddNextSibling(c_next_node, c_node)
1417
+ else:
1418
+ tree.xmlAddPrevSibling(c_next_node, c_node)
1419
+ else:
1420
+ tree.xmlAddPrevSibling(element._c_node, c_node)
1421
+ _moveTail(c_next, c_node)
1422
+ # uh oh, elements may be pointing to different doc when
1423
+ # parent element has moved; change them too..
1424
+ moveNodeToDocument(element._doc, c_source_doc, c_node)
1425
+ return 0
1426
+
1427
+ cdef inline bint isutf8(const_xmlChar* s) noexcept:
1428
+ cdef xmlChar c = s[0]
1429
+ while c != c'\0':
1430
+ if c & 0x80:
1431
+ return True
1432
+ s += 1
1433
+ c = s[0]
1434
+ return False
1435
+
1436
+ cdef bint isutf8l(const_xmlChar* s, size_t length) noexcept:
1437
+ """
1438
+ Search for non-ASCII characters in the string, knowing its length in advance.
1439
+ """
1440
+ cdef unsigned int i
1441
+ cdef unsigned long non_ascii_mask
1442
+ cdef const unsigned long *lptr = <const unsigned long*> s
1443
+
1444
+ cdef const unsigned long *end = lptr + length // sizeof(unsigned long)
1445
+ if length >= sizeof(non_ascii_mask):
1446
+ # Build constant 0x80808080... mask (and let the C compiler fold it).
1447
+ non_ascii_mask = 0
1448
+ for i in range(sizeof(non_ascii_mask) // 2):
1449
+ non_ascii_mask = (non_ascii_mask << 16) | 0x8080
1450
+
1451
+ # Advance to long-aligned character before we start reading longs.
1452
+ while (<size_t>s) % sizeof(unsigned long) and s < <const_xmlChar *>end:
1453
+ if s[0] & 0x80:
1454
+ return True
1455
+ s += 1
1456
+
1457
+ # Read one long at a time
1458
+ lptr = <const unsigned long*> s
1459
+ while lptr < end:
1460
+ if lptr[0] & non_ascii_mask:
1461
+ return True
1462
+ lptr += 1
1463
+ s = <const_xmlChar *>lptr
1464
+
1465
+ while s < (<const_xmlChar *>end + length % sizeof(unsigned long)):
1466
+ if s[0] & 0x80:
1467
+ return True
1468
+ s += 1
1469
+
1470
+ return False
1471
+
1472
+ cdef int _is_valid_xml_ascii(bytes pystring) except -1:
1473
+ """Check if a string is XML ascii content."""
1474
+ cdef signed char ch
1475
+ # When ch is a *signed* char, non-ascii characters are negative integers
1476
+ # and xmlIsChar_ch does not accept them.
1477
+ for ch in pystring:
1478
+ if not tree.xmlIsChar_ch(ch):
1479
+ return 0
1480
+ return 1
1481
+
1482
+ cdef bint _is_valid_xml_utf8(bytes pystring) except -1:
1483
+ """Check if a string is like valid UTF-8 XML content."""
1484
+ cdef const_xmlChar* s = _xcstr(pystring)
1485
+ cdef const_xmlChar* c_end = s + len(pystring)
1486
+ cdef unsigned long next3 = 0
1487
+ if s < c_end - 2:
1488
+ next3 = (s[0] << 8) | (s[1])
1489
+
1490
+ while s < c_end - 2:
1491
+ next3 = 0x00ffffff & ((next3 << 8) | s[2])
1492
+ if s[0] & 0x80:
1493
+ # 0xefbfbe and 0xefbfbf are utf-8 encodings of
1494
+ # forbidden characters \ufffe and \uffff
1495
+ if next3 == 0x00efbfbe or next3 == 0x00efbfbf:
1496
+ return 0
1497
+ # 0xeda080 and 0xedbfbf are utf-8 encodings of
1498
+ # \ud800 and \udfff. Anything between them (inclusive)
1499
+ # is forbidden, because they are surrogate blocks in utf-16.
1500
+ if 0x00eda080 <= next3 <= 0x00edbfbf:
1501
+ return 0
1502
+ elif not tree.xmlIsChar_ch(s[0]):
1503
+ return 0 # invalid ascii char
1504
+ s += 1
1505
+
1506
+ while s < c_end:
1507
+ if not s[0] & 0x80 and not tree.xmlIsChar_ch(s[0]):
1508
+ return 0 # invalid ascii char
1509
+ s += 1
1510
+
1511
+ return 1
1512
+
1513
+ cdef inline unicode funicodeOrNone(const_xmlChar* s):
1514
+ return funicode(s) if s is not NULL else None
1515
+
1516
+ cdef inline unicode funicodeOrEmpty(const_xmlChar* s):
1517
+ return funicode(s) if s is not NULL else ''
1518
+
1519
+ cdef unicode funicode(const_xmlChar* s):
1520
+ return s.decode('UTF-8')
1521
+
1522
+ cdef bytes _utf8(object s):
1523
+ """Test if a string is valid user input and encode it to UTF-8.
1524
+ Reject all bytes/unicode input that contains non-XML characters.
1525
+ Reject all bytes input that contains non-ASCII characters.
1526
+ """
1527
+ cdef int valid
1528
+ cdef bytes utf8_string
1529
+ if isinstance(s, unicode):
1530
+ utf8_string = (<unicode>s).encode('utf8')
1531
+ valid = _is_valid_xml_utf8(utf8_string)
1532
+ elif isinstance(s, (bytes, bytearray)):
1533
+ utf8_string = s if type(s) is bytes else bytes(s)
1534
+ valid = _is_valid_xml_ascii(utf8_string)
1535
+ else:
1536
+ raise TypeError("Argument must be bytes or unicode, got '%.200s'" % type(s).__name__)
1537
+ if not valid:
1538
+ raise ValueError(
1539
+ "All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters")
1540
+ return utf8_string
1541
+
1542
+
1543
+ cdef bytes _utf8orNone(object s):
1544
+ return _utf8(s) if s is not None else None
1545
+
1546
+
1547
+ cdef enum:
1548
+ NO_FILE_PATH = 0
1549
+ ABS_UNIX_FILE_PATH = 1
1550
+ ABS_WIN_FILE_PATH = 2
1551
+ REL_FILE_PATH = 3
1552
+
1553
+
1554
+ cdef bint _isFilePath(const_xmlChar* c_path) noexcept:
1555
+ "simple heuristic to see if a path is a filename"
1556
+ cdef xmlChar c
1557
+ # test if it looks like an absolute Unix path or a Windows network path
1558
+ if c_path[0] == c'/':
1559
+ return ABS_UNIX_FILE_PATH
1560
+
1561
+ # test if it looks like an absolute Windows path or URL
1562
+ if c'a' <= c_path[0] <= c'z' or c'A' <= c_path[0] <= c'Z':
1563
+ c_path += 1
1564
+ if c_path[0] == c':' and c_path[1] in b'\0\\':
1565
+ return ABS_WIN_FILE_PATH # C: or C:\...
1566
+
1567
+ # test if it looks like a URL with scheme://
1568
+ while c'a' <= c_path[0] <= c'z' or c'A' <= c_path[0] <= c'Z':
1569
+ c_path += 1
1570
+ if c_path[0] == c':' and c_path[1] == c'/' and c_path[2] == c'/':
1571
+ return NO_FILE_PATH
1572
+
1573
+ # assume it's a relative path
1574
+ return REL_FILE_PATH
1575
+
1576
+
1577
+ cdef object _getFSPathOrObject(object obj):
1578
+ """
1579
+ Get the __fspath__ attribute of an object if it exists.
1580
+ Otherwise, the original object is returned.
1581
+ """
1582
+ if _isString(obj):
1583
+ return obj
1584
+ try:
1585
+ return python.PyOS_FSPath(obj)
1586
+ except TypeError:
1587
+ return obj
1588
+
1589
+
1590
+ cdef object _encodeFilename(object filename):
1591
+ """Make sure a filename is 8-bit encoded (or None).
1592
+ """
1593
+ if filename is None:
1594
+ return None
1595
+ elif isinstance(filename, bytes):
1596
+ return filename
1597
+ elif isinstance(filename, unicode):
1598
+ filename8 = (<unicode>filename).encode('utf8')
1599
+ if _isFilePath(<unsigned char*>filename8):
1600
+ try:
1601
+ return python.PyUnicode_AsEncodedString(
1602
+ filename, _C_FILENAME_ENCODING, NULL)
1603
+ except UnicodeEncodeError:
1604
+ pass
1605
+ return filename8
1606
+ else:
1607
+ raise TypeError("Argument must be string or unicode.")
1608
+
1609
+ cdef object _decodeFilename(const_xmlChar* c_path):
1610
+ """Make the filename a unicode string if we are in Py3.
1611
+ """
1612
+ return _decodeFilenameWithLength(c_path, tree.xmlStrlen(c_path))
1613
+
1614
+ cdef object _decodeFilenameWithLength(const_xmlChar* c_path, size_t c_len):
1615
+ """Make the filename a unicode string if we are in Py3.
1616
+ """
1617
+ if _isFilePath(c_path):
1618
+ try:
1619
+ return python.PyUnicode_Decode(
1620
+ <const_char*>c_path, c_len, _C_FILENAME_ENCODING, NULL)
1621
+ except UnicodeDecodeError:
1622
+ pass
1623
+ try:
1624
+ return (<unsigned char*>c_path)[:c_len].decode('UTF-8')
1625
+ except UnicodeDecodeError:
1626
+ # this is a stupid fallback, but it might still work...
1627
+ return (<unsigned char*>c_path)[:c_len].decode('latin-1', 'replace')
1628
+
1629
+ cdef object _encodeFilenameUTF8(object filename):
1630
+ """Recode filename as UTF-8. Tries ASCII, local filesystem encoding and
1631
+ UTF-8 as source encoding.
1632
+ """
1633
+ cdef char* c_filename
1634
+ if filename is None:
1635
+ return None
1636
+ elif isinstance(filename, bytes):
1637
+ if not isutf8l(<bytes>filename, len(<bytes>filename)):
1638
+ # plain ASCII!
1639
+ return filename
1640
+ c_filename = _cstr(<bytes>filename)
1641
+ try:
1642
+ # try to decode with default encoding
1643
+ filename = python.PyUnicode_Decode(
1644
+ c_filename, len(<bytes>filename),
1645
+ _C_FILENAME_ENCODING, NULL)
1646
+ except UnicodeDecodeError as decode_exc:
1647
+ try:
1648
+ # try if it's proper UTF-8
1649
+ (<bytes>filename).decode('utf8')
1650
+ return filename
1651
+ except UnicodeDecodeError:
1652
+ raise decode_exc # otherwise re-raise original exception
1653
+ if isinstance(filename, unicode):
1654
+ return (<unicode>filename).encode('utf8')
1655
+ else:
1656
+ raise TypeError("Argument must be string or unicode.")
1657
+
1658
+ cdef tuple _getNsTag(tag):
1659
+ """Given a tag, find namespace URI and tag name.
1660
+ Return None for NS uri if no namespace URI provided.
1661
+ """
1662
+ return __getNsTag(tag, 0)
1663
+
1664
+ cdef tuple _getNsTagWithEmptyNs(tag):
1665
+ """Given a tag, find namespace URI and tag name. Return None for NS uri
1666
+ if no namespace URI provided, or the empty string if namespace
1667
+ part is '{}'.
1668
+ """
1669
+ return __getNsTag(tag, 1)
1670
+
1671
+ cdef tuple __getNsTag(tag, bint empty_ns):
1672
+ cdef char* c_tag
1673
+ cdef char* c_ns_end
1674
+ cdef Py_ssize_t taglen
1675
+ cdef Py_ssize_t nslen
1676
+ cdef bytes ns = None
1677
+ # _isString() is much faster than isinstance()
1678
+ if not _isString(tag) and isinstance(tag, QName):
1679
+ tag = (<QName>tag).text
1680
+ tag = _utf8(tag)
1681
+ c_tag = _cstr(tag)
1682
+ if c_tag[0] == c'{':
1683
+ c_tag += 1
1684
+ c_ns_end = cstring_h.strchr(c_tag, c'}')
1685
+ if c_ns_end is NULL:
1686
+ raise ValueError, "Invalid tag name"
1687
+ nslen = c_ns_end - c_tag
1688
+ taglen = python.PyBytes_GET_SIZE(tag) - nslen - 2
1689
+ if taglen == 0:
1690
+ raise ValueError, "Empty tag name"
1691
+ if nslen > 0:
1692
+ ns = <bytes>c_tag[:nslen]
1693
+ elif empty_ns:
1694
+ ns = b''
1695
+ tag = <bytes>c_ns_end[1:taglen+1]
1696
+ elif python.PyBytes_GET_SIZE(tag) == 0:
1697
+ raise ValueError, "Empty tag name"
1698
+ return ns, tag
1699
+
1700
+ cdef inline int _pyXmlNameIsValid(name_utf8):
1701
+ return _xmlNameIsValid(_xcstr(name_utf8)) and b':' not in name_utf8
1702
+
1703
+ cdef inline int _pyHtmlNameIsValid(name_utf8):
1704
+ return _htmlNameIsValid(_xcstr(name_utf8))
1705
+
1706
+ cdef inline int _xmlNameIsValid(const_xmlChar* c_name) noexcept:
1707
+ return tree.xmlValidateNameValue(c_name)
1708
+
1709
+ cdef int _htmlNameIsValid(const_xmlChar* c_name) noexcept:
1710
+ if c_name is NULL or c_name[0] == c'\0':
1711
+ return 0
1712
+ while c_name[0] != c'\0':
1713
+ if c_name[0] in b'&<>/"\'\t\n\x0B\x0C\r ':
1714
+ return 0
1715
+ c_name += 1
1716
+ return 1
1717
+
1718
+ cdef bint _characterReferenceIsValid(const_xmlChar* c_name) noexcept:
1719
+ cdef bint is_hex
1720
+ if c_name[0] == c'x':
1721
+ c_name += 1
1722
+ is_hex = 1
1723
+ else:
1724
+ is_hex = 0
1725
+ if c_name[0] == c'\0':
1726
+ return 0
1727
+ while c_name[0] != c'\0':
1728
+ if c_name[0] < c'0' or c_name[0] > c'9':
1729
+ if not is_hex:
1730
+ return 0
1731
+ if not (c'a' <= c_name[0] <= c'f'):
1732
+ if not (c'A' <= c_name[0] <= c'F'):
1733
+ return 0
1734
+ c_name += 1
1735
+ return 1
1736
+
1737
+ cdef int _tagValidOrRaise(tag_utf) except -1:
1738
+ if not _pyXmlNameIsValid(tag_utf):
1739
+ raise ValueError(f"Invalid tag name {(<bytes>tag_utf).decode('utf8')!r}")
1740
+ return 0
1741
+
1742
+ cdef int _htmlTagValidOrRaise(tag_utf) except -1:
1743
+ if not _pyHtmlNameIsValid(tag_utf):
1744
+ raise ValueError(f"Invalid HTML tag name {(<bytes>tag_utf).decode('utf8')!r}")
1745
+ return 0
1746
+
1747
+ cdef int _attributeValidOrRaise(name_utf) except -1:
1748
+ if not _pyXmlNameIsValid(name_utf):
1749
+ raise ValueError(f"Invalid attribute name {(<bytes>name_utf).decode('utf8')!r}")
1750
+ return 0
1751
+
1752
+ cdef int _prefixValidOrRaise(tag_utf) except -1:
1753
+ if not _pyXmlNameIsValid(tag_utf):
1754
+ raise ValueError(f"Invalid namespace prefix {(<bytes>tag_utf).decode('utf8')!r}")
1755
+ return 0
1756
+
1757
+ cdef int _uriValidOrRaise(uri_utf) except -1:
1758
+ cdef uri.xmlURI* c_uri = uri.xmlParseURI(_cstr(uri_utf))
1759
+ if c_uri is NULL:
1760
+ raise ValueError(f"Invalid namespace URI {(<bytes>uri_utf).decode('utf8')!r}")
1761
+ uri.xmlFreeURI(c_uri)
1762
+ return 0
1763
+
1764
+ cdef inline unicode _namespacedName(xmlNode* c_node):
1765
+ return _namespacedNameFromNsName(_getNs(c_node), c_node.name)
1766
+
1767
+
1768
+ cdef unicode _namespacedNameFromNsName(const_xmlChar* c_href, const_xmlChar* c_name):
1769
+ name = funicode(c_name)
1770
+ if c_href is NULL:
1771
+ return name
1772
+ href = funicode(c_href)
1773
+ return f"{{{href}}}{name}"
1774
+
1775
+
1776
+ cdef _getFilenameForFile(source):
1777
+ """Given a Python File or Gzip object, give filename back.
1778
+
1779
+ Returns None if not a file object.
1780
+ """
1781
+ # urllib2 provides a geturl() method
1782
+ try:
1783
+ return source.geturl()
1784
+ except:
1785
+ pass
1786
+ # file instances have a name attribute
1787
+ try:
1788
+ filename = source.name
1789
+ if _isString(filename):
1790
+ return os_path_abspath(filename)
1791
+ except:
1792
+ pass
1793
+ # gzip file instances have a filename attribute (before Py3k)
1794
+ try:
1795
+ filename = source.filename
1796
+ if _isString(filename):
1797
+ return os_path_abspath(filename)
1798
+ except:
1799
+ pass
1800
+ # can't determine filename
1801
+ return None
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/builder.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # cython: language_level=2
2
+
3
+ #
4
+ # Element generator factory by Fredrik Lundh.
5
+ #
6
+ # Source:
7
+ # http://online.effbot.org/2006_11_01_archive.htm#et-builder
8
+ # http://effbot.python-hosting.com/file/stuff/sandbox/elementlib/builder.py
9
+ #
10
+ # --------------------------------------------------------------------
11
+ # The ElementTree toolkit is
12
+ #
13
+ # Copyright (c) 1999-2004 by Fredrik Lundh
14
+ #
15
+ # By obtaining, using, and/or copying this software and/or its
16
+ # associated documentation, you agree that you have read, understood,
17
+ # and will comply with the following terms and conditions:
18
+ #
19
+ # Permission to use, copy, modify, and distribute this software and
20
+ # its associated documentation for any purpose and without fee is
21
+ # hereby granted, provided that the above copyright notice appears in
22
+ # all copies, and that both that copyright notice and this permission
23
+ # notice appear in supporting documentation, and that the name of
24
+ # Secret Labs AB or the author not be used in advertising or publicity
25
+ # pertaining to distribution of the software without specific, written
26
+ # prior permission.
27
+ #
28
+ # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
29
+ # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
30
+ # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
31
+ # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
32
+ # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
33
+ # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
34
+ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
35
+ # OF THIS SOFTWARE.
36
+ # --------------------------------------------------------------------
37
+
38
+ """
39
+ The ``E`` Element factory for generating XML documents.
40
+ """
41
+
42
+
43
+ import lxml.etree as ET
44
+ _QName = ET.QName
45
+
46
+ from functools import partial
47
+
48
+ try:
49
+ from types import GenericAlias as _GenericAlias
50
+ except ImportError:
51
+ # Python 3.8 - we only need this as return value from "__class_getitem__"
52
+ def _GenericAlias(cls, item):
53
+ return f"{cls.__name__}[{item.__name__}]"
54
+
55
+ try:
56
+ basestring
57
+ except NameError:
58
+ basestring = str
59
+
60
+ try:
61
+ unicode
62
+ except NameError:
63
+ unicode = str
64
+
65
+
66
+ class ElementMaker:
67
+ """Element generator factory.
68
+
69
+ Unlike the ordinary Element factory, the E factory allows you to pass in
70
+ more than just a tag and some optional attributes; you can also pass in
71
+ text and other elements. The text is added as either text or tail
72
+ attributes, and elements are inserted at the right spot. Some small
73
+ examples::
74
+
75
+ >>> from lxml import etree as ET
76
+ >>> from lxml.builder import E
77
+
78
+ >>> ET.tostring(E("tag"))
79
+ '<tag/>'
80
+ >>> ET.tostring(E("tag", "text"))
81
+ '<tag>text</tag>'
82
+ >>> ET.tostring(E("tag", "text", key="value"))
83
+ '<tag key="value">text</tag>'
84
+ >>> ET.tostring(E("tag", E("subtag", "text"), "tail"))
85
+ '<tag><subtag>text</subtag>tail</tag>'
86
+
87
+ For simple tags, the factory also allows you to write ``E.tag(...)`` instead
88
+ of ``E('tag', ...)``::
89
+
90
+ >>> ET.tostring(E.tag())
91
+ '<tag/>'
92
+ >>> ET.tostring(E.tag("text"))
93
+ '<tag>text</tag>'
94
+ >>> ET.tostring(E.tag(E.subtag("text"), "tail"))
95
+ '<tag><subtag>text</subtag>tail</tag>'
96
+
97
+ Here's a somewhat larger example; this shows how to generate HTML
98
+ documents, using a mix of prepared factory functions for inline elements,
99
+ nested ``E.tag`` calls, and embedded XHTML fragments::
100
+
101
+ # some common inline elements
102
+ A = E.a
103
+ I = E.i
104
+ B = E.b
105
+
106
+ def CLASS(v):
107
+ # helper function, 'class' is a reserved word
108
+ return {'class': v}
109
+
110
+ page = (
111
+ E.html(
112
+ E.head(
113
+ E.title("This is a sample document")
114
+ ),
115
+ E.body(
116
+ E.h1("Hello!", CLASS("title")),
117
+ E.p("This is a paragraph with ", B("bold"), " text in it!"),
118
+ E.p("This is another paragraph, with a ",
119
+ A("link", href="http://www.python.org"), "."),
120
+ E.p("Here are some reserved characters: <spam&egg>."),
121
+ ET.XML("<p>And finally, here is an embedded XHTML fragment.</p>"),
122
+ )
123
+ )
124
+ )
125
+
126
+ print ET.tostring(page)
127
+
128
+ Here's a prettyprinted version of the output from the above script::
129
+
130
+ <html>
131
+ <head>
132
+ <title>This is a sample document</title>
133
+ </head>
134
+ <body>
135
+ <h1 class="title">Hello!</h1>
136
+ <p>This is a paragraph with <b>bold</b> text in it!</p>
137
+ <p>This is another paragraph, with <a href="http://www.python.org">link</a>.</p>
138
+ <p>Here are some reserved characters: &lt;spam&amp;egg&gt;.</p>
139
+ <p>And finally, here is an embedded XHTML fragment.</p>
140
+ </body>
141
+ </html>
142
+
143
+ For namespace support, you can pass a namespace map (``nsmap``)
144
+ and/or a specific target ``namespace`` to the ElementMaker class::
145
+
146
+ >>> E = ElementMaker(namespace="http://my.ns/")
147
+ >>> print(ET.tostring( E.test ))
148
+ <test xmlns="http://my.ns/"/>
149
+
150
+ >>> E = ElementMaker(namespace="http://my.ns/", nsmap={'p':'http://my.ns/'})
151
+ >>> print(ET.tostring( E.test ))
152
+ <p:test xmlns:p="http://my.ns/"/>
153
+ """
154
+
155
+ def __init__(self, typemap=None,
156
+ namespace=None, nsmap=None, makeelement=None):
157
+ self._namespace = '{' + namespace + '}' if namespace is not None else None
158
+ self._nsmap = dict(nsmap) if nsmap else None
159
+
160
+ assert makeelement is None or callable(makeelement)
161
+ self._makeelement = makeelement if makeelement is not None else ET.Element
162
+
163
+ # initialize the default type map functions for this element factory
164
+ typemap = dict(typemap) if typemap else {}
165
+
166
+ def add_text(elem, item):
167
+ try:
168
+ last_child = elem[-1]
169
+ except IndexError:
170
+ elem.text = (elem.text or "") + item
171
+ else:
172
+ last_child.tail = (last_child.tail or "") + item
173
+
174
+ def add_cdata(elem, cdata):
175
+ if elem.text:
176
+ raise ValueError("Can't add a CDATA section. Element already has some text: %r" % elem.text)
177
+ elem.text = cdata
178
+
179
+ if str not in typemap:
180
+ typemap[str] = add_text
181
+ if unicode not in typemap:
182
+ typemap[unicode] = add_text
183
+ if ET.CDATA not in typemap:
184
+ typemap[ET.CDATA] = add_cdata
185
+
186
+ def add_dict(elem, item):
187
+ attrib = elem.attrib
188
+ for k, v in item.items():
189
+ if isinstance(v, basestring):
190
+ attrib[k] = v
191
+ else:
192
+ attrib[k] = typemap[type(v)](None, v)
193
+
194
+ if dict not in typemap:
195
+ typemap[dict] = add_dict
196
+
197
+ self._typemap = typemap
198
+
199
+ def __call__(self, tag, *children, **attrib):
200
+ typemap = self._typemap
201
+
202
+ # We'll usually get a 'str', and the compiled type check is very fast.
203
+ if not isinstance(tag, str) and isinstance(tag, _QName):
204
+ # A QName is explicitly qualified, do not look at self._namespace.
205
+ tag = tag.text
206
+ elif self._namespace is not None and tag[0] != '{':
207
+ tag = self._namespace + tag
208
+ elem = self._makeelement(tag, nsmap=self._nsmap)
209
+ if attrib:
210
+ typemap[dict](elem, attrib)
211
+
212
+ for item in children:
213
+ if callable(item):
214
+ item = item()
215
+ t = typemap.get(type(item))
216
+ if t is None:
217
+ if ET.iselement(item):
218
+ elem.append(item)
219
+ continue
220
+ for basetype in type(item).__mro__:
221
+ # See if the typemap knows of any of this type's bases.
222
+ t = typemap.get(basetype)
223
+ if t is not None:
224
+ break
225
+ else:
226
+ raise TypeError("bad argument type: %s(%r)" %
227
+ (type(item).__name__, item))
228
+ v = t(elem, item)
229
+ if v:
230
+ typemap.get(type(v))(elem, v)
231
+
232
+ return elem
233
+
234
+ def __getattr__(self, tag):
235
+ return partial(self, tag)
236
+
237
+ # Allow subscripting ElementMaker in type annotions (PEP 560)
238
+ def __class_getitem__(cls, item):
239
+ return _GenericAlias(cls, item)
240
+
241
+
242
+ # create factory object
243
+ E = ElementMaker()
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/classlookup.pxi ADDED
@@ -0,0 +1,580 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configurable Element class lookup
2
+
3
+ ################################################################################
4
+ # Custom Element classes
5
+
6
+ cdef public class ElementBase(_Element) [ type LxmlElementBaseType,
7
+ object LxmlElementBase ]:
8
+ """ElementBase(*children, attrib=None, nsmap=None, **_extra)
9
+
10
+ The public Element class. All custom Element classes must inherit
11
+ from this one. To create an Element, use the `Element()` factory.
12
+
13
+ BIG FAT WARNING: Subclasses *must not* override __init__ or
14
+ __new__ as it is absolutely undefined when these objects will be
15
+ created or destroyed. All persistent state of Elements must be
16
+ stored in the underlying XML. If you really need to initialize
17
+ the object after creation, you can implement an ``_init(self)``
18
+ method that will be called directly after object creation.
19
+
20
+ Subclasses of this class can be instantiated to create a new
21
+ Element. By default, the tag name will be the class name and the
22
+ namespace will be empty. You can modify this with the following
23
+ class attributes:
24
+
25
+ * TAG - the tag name, possibly containing a namespace in Clark
26
+ notation
27
+
28
+ * NAMESPACE - the default namespace URI, unless provided as part
29
+ of the TAG attribute.
30
+
31
+ * HTML - flag if the class is an HTML tag, as opposed to an XML
32
+ tag. This only applies to un-namespaced tags and defaults to
33
+ false (i.e. XML).
34
+
35
+ * PARSER - the parser that provides the configuration for the
36
+ newly created document. Providing an HTML parser here will
37
+ default to creating an HTML element.
38
+
39
+ In user code, the latter three are commonly inherited in class
40
+ hierarchies that implement a common namespace.
41
+ """
42
+ def __init__(self, *children, attrib=None, nsmap=None, **_extra):
43
+ """ElementBase(*children, attrib=None, nsmap=None, **_extra)
44
+ """
45
+ cdef bint is_html = 0
46
+ cdef _BaseParser parser
47
+ cdef _Element last_child
48
+ # don't use normal attribute access as it might be overridden
49
+ _getattr = object.__getattribute__
50
+ try:
51
+ namespace = _utf8(_getattr(self, 'NAMESPACE'))
52
+ except AttributeError:
53
+ namespace = None
54
+ try:
55
+ ns, tag = _getNsTag(_getattr(self, 'TAG'))
56
+ if ns is not None:
57
+ namespace = ns
58
+ except AttributeError:
59
+ tag = _utf8(_getattr(_getattr(self, '__class__'), '__name__'))
60
+ if b'.' in tag:
61
+ tag = tag.split(b'.')[-1]
62
+ try:
63
+ parser = _getattr(self, 'PARSER')
64
+ except AttributeError:
65
+ parser = None
66
+ for child in children:
67
+ if isinstance(child, _Element):
68
+ parser = (<_Element>child)._doc._parser
69
+ break
70
+ if isinstance(parser, HTMLParser):
71
+ is_html = 1
72
+ if namespace is None:
73
+ try:
74
+ is_html = _getattr(self, 'HTML')
75
+ except AttributeError:
76
+ pass
77
+ _initNewElement(self, is_html, tag, namespace, parser,
78
+ attrib, nsmap, _extra)
79
+ last_child = None
80
+ for child in children:
81
+ if _isString(child):
82
+ if last_child is None:
83
+ _setNodeText(self._c_node,
84
+ (_collectText(self._c_node.children) or '') + child)
85
+ else:
86
+ _setTailText(last_child._c_node,
87
+ (_collectText(last_child._c_node.next) or '') + child)
88
+ elif isinstance(child, _Element):
89
+ last_child = child
90
+ _appendChild(self, last_child)
91
+ elif isinstance(child, type) and issubclass(child, ElementBase):
92
+ last_child = child()
93
+ _appendChild(self, last_child)
94
+ else:
95
+ raise TypeError, f"Invalid child type: {type(child)!r}"
96
+
97
+ cdef class CommentBase(_Comment):
98
+ """All custom Comment classes must inherit from this one.
99
+
100
+ To create an XML Comment instance, use the ``Comment()`` factory.
101
+
102
+ Subclasses *must not* override __init__ or __new__ as it is
103
+ absolutely undefined when these objects will be created or
104
+ destroyed. All persistent state of Comments must be stored in the
105
+ underlying XML. If you really need to initialize the object after
106
+ creation, you can implement an ``_init(self)`` method that will be
107
+ called after object creation.
108
+ """
109
+ def __init__(self, text):
110
+ # copied from Comment() factory
111
+ cdef _Document doc
112
+ cdef xmlDoc* c_doc
113
+ if text is None:
114
+ text = b''
115
+ else:
116
+ text = _utf8(text)
117
+ c_doc = _newXMLDoc()
118
+ doc = _documentFactory(c_doc, None)
119
+ self._c_node = _createComment(c_doc, _xcstr(text))
120
+ if self._c_node is NULL:
121
+ raise MemoryError()
122
+ tree.xmlAddChild(<xmlNode*>c_doc, self._c_node)
123
+ _registerProxy(self, doc, self._c_node)
124
+ self._init()
125
+
126
+ cdef class PIBase(_ProcessingInstruction):
127
+ """All custom Processing Instruction classes must inherit from this one.
128
+
129
+ To create an XML ProcessingInstruction instance, use the ``PI()``
130
+ factory.
131
+
132
+ Subclasses *must not* override __init__ or __new__ as it is
133
+ absolutely undefined when these objects will be created or
134
+ destroyed. All persistent state of PIs must be stored in the
135
+ underlying XML. If you really need to initialize the object after
136
+ creation, you can implement an ``_init(self)`` method that will be
137
+ called after object creation.
138
+ """
139
+ def __init__(self, target, text=None):
140
+ # copied from PI() factory
141
+ cdef _Document doc
142
+ cdef xmlDoc* c_doc
143
+ target = _utf8(target)
144
+ if text is None:
145
+ text = b''
146
+ else:
147
+ text = _utf8(text)
148
+ c_doc = _newXMLDoc()
149
+ doc = _documentFactory(c_doc, None)
150
+ self._c_node = _createPI(c_doc, _xcstr(target), _xcstr(text))
151
+ if self._c_node is NULL:
152
+ raise MemoryError()
153
+ tree.xmlAddChild(<xmlNode*>c_doc, self._c_node)
154
+ _registerProxy(self, doc, self._c_node)
155
+ self._init()
156
+
157
+ cdef class EntityBase(_Entity):
158
+ """All custom Entity classes must inherit from this one.
159
+
160
+ To create an XML Entity instance, use the ``Entity()`` factory.
161
+
162
+ Subclasses *must not* override __init__ or __new__ as it is
163
+ absolutely undefined when these objects will be created or
164
+ destroyed. All persistent state of Entities must be stored in the
165
+ underlying XML. If you really need to initialize the object after
166
+ creation, you can implement an ``_init(self)`` method that will be
167
+ called after object creation.
168
+ """
169
+ def __init__(self, name):
170
+ cdef _Document doc
171
+ cdef xmlDoc* c_doc
172
+ name_utf = _utf8(name)
173
+ c_name = _xcstr(name_utf)
174
+ if c_name[0] == c'#':
175
+ if not _characterReferenceIsValid(c_name + 1):
176
+ raise ValueError, f"Invalid character reference: '{name}'"
177
+ elif not _xmlNameIsValid(c_name):
178
+ raise ValueError, f"Invalid entity reference: '{name}'"
179
+ c_doc = _newXMLDoc()
180
+ doc = _documentFactory(c_doc, None)
181
+ self._c_node = _createEntity(c_doc, c_name)
182
+ if self._c_node is NULL:
183
+ raise MemoryError()
184
+ tree.xmlAddChild(<xmlNode*>c_doc, self._c_node)
185
+ _registerProxy(self, doc, self._c_node)
186
+ self._init()
187
+
188
+
189
+ cdef int _validateNodeClass(xmlNode* c_node, cls) except -1:
190
+ if c_node.type == tree.XML_ELEMENT_NODE:
191
+ expected = ElementBase
192
+ elif c_node.type == tree.XML_COMMENT_NODE:
193
+ expected = CommentBase
194
+ elif c_node.type == tree.XML_ENTITY_REF_NODE:
195
+ expected = EntityBase
196
+ elif c_node.type == tree.XML_PI_NODE:
197
+ expected = PIBase
198
+ else:
199
+ assert False, f"Unknown node type: {c_node.type}"
200
+
201
+ if not (isinstance(cls, type) and issubclass(cls, expected)):
202
+ raise TypeError(
203
+ f"result of class lookup must be subclass of {type(expected)}, got {type(cls)}")
204
+ return 0
205
+
206
+
207
+ ################################################################################
208
+ # Element class lookup
209
+
210
+ ctypedef public object (*_element_class_lookup_function)(object, _Document, xmlNode*)
211
+
212
+ # class to store element class lookup functions
213
+ cdef public class ElementClassLookup [ type LxmlElementClassLookupType,
214
+ object LxmlElementClassLookup ]:
215
+ """ElementClassLookup(self)
216
+ Superclass of Element class lookups.
217
+ """
218
+ cdef _element_class_lookup_function _lookup_function
219
+
220
+
221
+ cdef public class FallbackElementClassLookup(ElementClassLookup) \
222
+ [ type LxmlFallbackElementClassLookupType,
223
+ object LxmlFallbackElementClassLookup ]:
224
+ """FallbackElementClassLookup(self, fallback=None)
225
+
226
+ Superclass of Element class lookups with additional fallback.
227
+ """
228
+ cdef readonly ElementClassLookup fallback
229
+ cdef _element_class_lookup_function _fallback_function
230
+ def __cinit__(self):
231
+ # fall back to default lookup
232
+ self._fallback_function = _lookupDefaultElementClass
233
+
234
+ def __init__(self, ElementClassLookup fallback=None):
235
+ if fallback is not None:
236
+ self._setFallback(fallback)
237
+ else:
238
+ self._fallback_function = _lookupDefaultElementClass
239
+
240
+ cdef void _setFallback(self, ElementClassLookup lookup):
241
+ """Sets the fallback scheme for this lookup method.
242
+ """
243
+ self.fallback = lookup
244
+ self._fallback_function = lookup._lookup_function
245
+ if self._fallback_function is NULL:
246
+ self._fallback_function = _lookupDefaultElementClass
247
+
248
+ def set_fallback(self, ElementClassLookup lookup not None):
249
+ """set_fallback(self, lookup)
250
+
251
+ Sets the fallback scheme for this lookup method.
252
+ """
253
+ self._setFallback(lookup)
254
+
255
+ cdef inline object _callLookupFallback(FallbackElementClassLookup lookup,
256
+ _Document doc, xmlNode* c_node):
257
+ return lookup._fallback_function(lookup.fallback, doc, c_node)
258
+
259
+
260
+ ################################################################################
261
+ # default lookup scheme
262
+
263
+ cdef class ElementDefaultClassLookup(ElementClassLookup):
264
+ """ElementDefaultClassLookup(self, element=None, comment=None, pi=None, entity=None)
265
+ Element class lookup scheme that always returns the default Element
266
+ class.
267
+
268
+ The keyword arguments ``element``, ``comment``, ``pi`` and ``entity``
269
+ accept the respective Element classes.
270
+ """
271
+ cdef readonly object element_class
272
+ cdef readonly object comment_class
273
+ cdef readonly object pi_class
274
+ cdef readonly object entity_class
275
+ def __cinit__(self):
276
+ self._lookup_function = _lookupDefaultElementClass
277
+
278
+ def __init__(self, element=None, comment=None, pi=None, entity=None):
279
+ if element is None:
280
+ self.element_class = _Element
281
+ elif issubclass(element, ElementBase):
282
+ self.element_class = element
283
+ else:
284
+ raise TypeError, "element class must be subclass of ElementBase"
285
+
286
+ if comment is None:
287
+ self.comment_class = _Comment
288
+ elif issubclass(comment, CommentBase):
289
+ self.comment_class = comment
290
+ else:
291
+ raise TypeError, "comment class must be subclass of CommentBase"
292
+
293
+ if entity is None:
294
+ self.entity_class = _Entity
295
+ elif issubclass(entity, EntityBase):
296
+ self.entity_class = entity
297
+ else:
298
+ raise TypeError, "Entity class must be subclass of EntityBase"
299
+
300
+ if pi is None:
301
+ self.pi_class = None # special case, see below
302
+ elif issubclass(pi, PIBase):
303
+ self.pi_class = pi
304
+ else:
305
+ raise TypeError, "PI class must be subclass of PIBase"
306
+
307
+ cdef object _lookupDefaultElementClass(state, _Document _doc, xmlNode* c_node):
308
+ "Trivial class lookup function that always returns the default class."
309
+ if c_node.type == tree.XML_ELEMENT_NODE:
310
+ if state is not None:
311
+ return (<ElementDefaultClassLookup>state).element_class
312
+ else:
313
+ return _Element
314
+ elif c_node.type == tree.XML_COMMENT_NODE:
315
+ if state is not None:
316
+ return (<ElementDefaultClassLookup>state).comment_class
317
+ else:
318
+ return _Comment
319
+ elif c_node.type == tree.XML_ENTITY_REF_NODE:
320
+ if state is not None:
321
+ return (<ElementDefaultClassLookup>state).entity_class
322
+ else:
323
+ return _Entity
324
+ elif c_node.type == tree.XML_PI_NODE:
325
+ if state is None or (<ElementDefaultClassLookup>state).pi_class is None:
326
+ # special case XSLT-PI
327
+ if c_node.name is not NULL and c_node.content is not NULL:
328
+ if tree.xmlStrcmp(c_node.name, <unsigned char*>"xml-stylesheet") == 0:
329
+ if tree.xmlStrstr(c_node.content, <unsigned char*>"text/xsl") is not NULL or \
330
+ tree.xmlStrstr(c_node.content, <unsigned char*>"text/xml") is not NULL:
331
+ return _XSLTProcessingInstruction
332
+ return _ProcessingInstruction
333
+ else:
334
+ return (<ElementDefaultClassLookup>state).pi_class
335
+ else:
336
+ assert False, f"Unknown node type: {c_node.type}"
337
+
338
+
339
+ ################################################################################
340
+ # attribute based lookup scheme
341
+
342
+ cdef class AttributeBasedElementClassLookup(FallbackElementClassLookup):
343
+ """AttributeBasedElementClassLookup(self, attribute_name, class_mapping, fallback=None)
344
+ Checks an attribute of an Element and looks up the value in a
345
+ class dictionary.
346
+
347
+ Arguments:
348
+ - attribute name - '{ns}name' style string
349
+ - class mapping - Python dict mapping attribute values to Element classes
350
+ - fallback - optional fallback lookup mechanism
351
+
352
+ A None key in the class mapping will be checked if the attribute is
353
+ missing.
354
+ """
355
+ cdef object _class_mapping
356
+ cdef tuple _pytag
357
+ cdef const_xmlChar* _c_ns
358
+ cdef const_xmlChar* _c_name
359
+ def __cinit__(self):
360
+ self._lookup_function = _attribute_class_lookup
361
+
362
+ def __init__(self, attribute_name, class_mapping,
363
+ ElementClassLookup fallback=None):
364
+ self._pytag = _getNsTag(attribute_name)
365
+ ns, name = self._pytag
366
+ if ns is None:
367
+ self._c_ns = NULL
368
+ else:
369
+ self._c_ns = _xcstr(ns)
370
+ self._c_name = _xcstr(name)
371
+ self._class_mapping = dict(class_mapping)
372
+
373
+ FallbackElementClassLookup.__init__(self, fallback)
374
+
375
+ cdef object _attribute_class_lookup(state, _Document doc, xmlNode* c_node):
376
+ cdef AttributeBasedElementClassLookup lookup
377
+ cdef python.PyObject* dict_result
378
+
379
+ lookup = <AttributeBasedElementClassLookup>state
380
+ if c_node.type == tree.XML_ELEMENT_NODE:
381
+ value = _attributeValueFromNsName(
382
+ c_node, lookup._c_ns, lookup._c_name)
383
+ dict_result = python.PyDict_GetItem(lookup._class_mapping, value)
384
+ if dict_result is not NULL:
385
+ cls = <object>dict_result
386
+ _validateNodeClass(c_node, cls)
387
+ return cls
388
+ return _callLookupFallback(lookup, doc, c_node)
389
+
390
+
391
+ ################################################################################
392
+ # per-parser lookup scheme
393
+
394
+ cdef class ParserBasedElementClassLookup(FallbackElementClassLookup):
395
+ """ParserBasedElementClassLookup(self, fallback=None)
396
+ Element class lookup based on the XML parser.
397
+ """
398
+ def __cinit__(self):
399
+ self._lookup_function = _parser_class_lookup
400
+
401
+ cdef object _parser_class_lookup(state, _Document doc, xmlNode* c_node):
402
+ if doc._parser._class_lookup is not None:
403
+ return doc._parser._class_lookup._lookup_function(
404
+ doc._parser._class_lookup, doc, c_node)
405
+ return _callLookupFallback(<FallbackElementClassLookup>state, doc, c_node)
406
+
407
+
408
+ ################################################################################
409
+ # custom class lookup based on node type, namespace, name
410
+
411
+ cdef class CustomElementClassLookup(FallbackElementClassLookup):
412
+ """CustomElementClassLookup(self, fallback=None)
413
+ Element class lookup based on a subclass method.
414
+
415
+ You can inherit from this class and override the method::
416
+
417
+ lookup(self, type, doc, namespace, name)
418
+
419
+ to lookup the element class for a node. Arguments of the method:
420
+ * type: one of 'element', 'comment', 'PI', 'entity'
421
+ * doc: document that the node is in
422
+ * namespace: namespace URI of the node (or None for comments/PIs/entities)
423
+ * name: name of the element/entity, None for comments, target for PIs
424
+
425
+ If you return None from this method, the fallback will be called.
426
+ """
427
+ def __cinit__(self):
428
+ self._lookup_function = _custom_class_lookup
429
+
430
+ def lookup(self, type, doc, namespace, name):
431
+ "lookup(self, type, doc, namespace, name)"
432
+ return None
433
+
434
+ cdef object _custom_class_lookup(state, _Document doc, xmlNode* c_node):
435
+ cdef CustomElementClassLookup lookup
436
+
437
+ lookup = <CustomElementClassLookup>state
438
+
439
+ if c_node.type == tree.XML_ELEMENT_NODE:
440
+ element_type = "element"
441
+ elif c_node.type == tree.XML_COMMENT_NODE:
442
+ element_type = "comment"
443
+ elif c_node.type == tree.XML_PI_NODE:
444
+ element_type = "PI"
445
+ elif c_node.type == tree.XML_ENTITY_REF_NODE:
446
+ element_type = "entity"
447
+ else:
448
+ element_type = "element"
449
+ if c_node.name is NULL:
450
+ name = None
451
+ else:
452
+ name = funicode(c_node.name)
453
+ c_str = tree._getNs(c_node)
454
+ ns = funicode(c_str) if c_str is not NULL else None
455
+
456
+ cls = lookup.lookup(element_type, doc, ns, name)
457
+ if cls is not None:
458
+ _validateNodeClass(c_node, cls)
459
+ return cls
460
+ return _callLookupFallback(lookup, doc, c_node)
461
+
462
+
463
+ ################################################################################
464
+ # read-only tree based class lookup
465
+
466
+ cdef class PythonElementClassLookup(FallbackElementClassLookup):
467
+ """PythonElementClassLookup(self, fallback=None)
468
+ Element class lookup based on a subclass method.
469
+
470
+ This class lookup scheme allows access to the entire XML tree in
471
+ read-only mode. To use it, re-implement the ``lookup(self, doc,
472
+ root)`` method in a subclass::
473
+
474
+ from lxml import etree, pyclasslookup
475
+
476
+ class MyElementClass(etree.ElementBase):
477
+ honkey = True
478
+
479
+ class MyLookup(pyclasslookup.PythonElementClassLookup):
480
+ def lookup(self, doc, root):
481
+ if root.tag == "sometag":
482
+ return MyElementClass
483
+ else:
484
+ for child in root:
485
+ if child.tag == "someothertag":
486
+ return MyElementClass
487
+ # delegate to default
488
+ return None
489
+
490
+ If you return None from this method, the fallback will be called.
491
+
492
+ The first argument is the opaque document instance that contains
493
+ the Element. The second argument is a lightweight Element proxy
494
+ implementation that is only valid during the lookup. Do not try
495
+ to keep a reference to it. Once the lookup is done, the proxy
496
+ will be invalid.
497
+
498
+ Also, you cannot wrap such a read-only Element in an ElementTree,
499
+ and you must take care not to keep a reference to them outside of
500
+ the `lookup()` method.
501
+
502
+ Note that the API of the Element objects is not complete. It is
503
+ purely read-only and does not support all features of the normal
504
+ `lxml.etree` API (such as XPath, extended slicing or some
505
+ iteration methods).
506
+
507
+ See https://lxml.de/element_classes.html
508
+ """
509
+ def __cinit__(self):
510
+ self._lookup_function = _python_class_lookup
511
+
512
+ def lookup(self, doc, element):
513
+ """lookup(self, doc, element)
514
+
515
+ Override this method to implement your own lookup scheme.
516
+ """
517
+ return None
518
+
519
+ cdef object _python_class_lookup(state, _Document doc, tree.xmlNode* c_node):
520
+ cdef PythonElementClassLookup lookup
521
+ cdef _ReadOnlyProxy proxy
522
+ lookup = <PythonElementClassLookup>state
523
+
524
+ proxy = _newReadOnlyProxy(None, c_node)
525
+ cls = lookup.lookup(doc, proxy)
526
+ _freeReadOnlyProxies(proxy)
527
+
528
+ if cls is not None:
529
+ _validateNodeClass(c_node, cls)
530
+ return cls
531
+ return _callLookupFallback(lookup, doc, c_node)
532
+
533
+ ################################################################################
534
+ # Global setup
535
+
536
+ cdef _element_class_lookup_function LOOKUP_ELEMENT_CLASS
537
+ cdef object ELEMENT_CLASS_LOOKUP_STATE
538
+
539
+ cdef void _setElementClassLookupFunction(
540
+ _element_class_lookup_function function, object state):
541
+ global LOOKUP_ELEMENT_CLASS, ELEMENT_CLASS_LOOKUP_STATE
542
+ if function is NULL:
543
+ state = DEFAULT_ELEMENT_CLASS_LOOKUP
544
+ function = DEFAULT_ELEMENT_CLASS_LOOKUP._lookup_function
545
+
546
+ ELEMENT_CLASS_LOOKUP_STATE = state
547
+ LOOKUP_ELEMENT_CLASS = function
548
+
549
+ def set_element_class_lookup(ElementClassLookup lookup = None):
550
+ """set_element_class_lookup(lookup = None)
551
+
552
+ Set the global element class lookup method.
553
+
554
+ This defines the main entry point for looking up element implementations.
555
+ The standard implementation uses the :class:`ParserBasedElementClassLookup`
556
+ to delegate to different lookup schemes for each parser.
557
+
558
+ .. warning::
559
+
560
+ This should only be changed by applications, not by library packages.
561
+ In most cases, parser specific lookups should be preferred,
562
+ which can be configured via
563
+ :meth:`~lxml.etree.XMLParser.set_element_class_lookup`
564
+ (and the same for HTML parsers).
565
+
566
+ Globally replacing the element class lookup by something other than a
567
+ :class:`ParserBasedElementClassLookup` will prevent parser specific lookup
568
+ schemes from working. Several tools rely on parser specific lookups,
569
+ including :mod:`lxml.html` and :mod:`lxml.objectify`.
570
+ """
571
+ if lookup is None or lookup._lookup_function is NULL:
572
+ _setElementClassLookupFunction(NULL, None)
573
+ else:
574
+ _setElementClassLookupFunction(lookup._lookup_function, lookup)
575
+
576
+ # default setup: parser delegation
577
+ cdef ParserBasedElementClassLookup DEFAULT_ELEMENT_CLASS_LOOKUP
578
+ DEFAULT_ELEMENT_CLASS_LOOKUP = ParserBasedElementClassLookup()
579
+
580
+ set_element_class_lookup(DEFAULT_ELEMENT_CLASS_LOOKUP)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/cleanup.pxi ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # functions for tree cleanup and removing elements from subtrees
2
+
3
+ def cleanup_namespaces(tree_or_element, top_nsmap=None, keep_ns_prefixes=None):
4
+ """cleanup_namespaces(tree_or_element, top_nsmap=None, keep_ns_prefixes=None)
5
+
6
+ Remove all namespace declarations from a subtree that are not used
7
+ by any of the elements or attributes in that tree.
8
+
9
+ If a 'top_nsmap' is provided, it must be a mapping from prefixes
10
+ to namespace URIs. These namespaces will be declared on the top
11
+ element of the subtree before running the cleanup, which allows
12
+ moving namespace declarations to the top of the tree.
13
+
14
+ If a 'keep_ns_prefixes' is provided, it must be a list of prefixes.
15
+ These prefixes will not be removed as part of the cleanup.
16
+ """
17
+ element = _rootNodeOrRaise(tree_or_element)
18
+ c_element = element._c_node
19
+
20
+ if top_nsmap:
21
+ doc = element._doc
22
+ # declare namespaces from nsmap, then apply them to the subtree
23
+ _setNodeNamespaces(c_element, doc, None, top_nsmap)
24
+ moveNodeToDocument(doc, c_element.doc, c_element)
25
+
26
+ keep_ns_prefixes = (
27
+ set([_utf8(prefix) for prefix in keep_ns_prefixes])
28
+ if keep_ns_prefixes else None)
29
+
30
+ _removeUnusedNamespaceDeclarations(c_element, keep_ns_prefixes)
31
+
32
+
33
+ def strip_attributes(tree_or_element, *attribute_names):
34
+ """strip_attributes(tree_or_element, *attribute_names)
35
+
36
+ Delete all attributes with the provided attribute names from an
37
+ Element (or ElementTree) and its descendants.
38
+
39
+ Attribute names can contain wildcards as in `_Element.iter`.
40
+
41
+ Example usage::
42
+
43
+ strip_attributes(root_element,
44
+ 'simpleattr',
45
+ '{http://some/ns}attrname',
46
+ '{http://other/ns}*')
47
+ """
48
+ cdef _MultiTagMatcher matcher
49
+ element = _rootNodeOrRaise(tree_or_element)
50
+ if not attribute_names:
51
+ return
52
+
53
+ matcher = _MultiTagMatcher.__new__(_MultiTagMatcher, attribute_names)
54
+ matcher.cacheTags(element._doc)
55
+ if matcher.rejectsAllAttributes():
56
+ return
57
+ _strip_attributes(element._c_node, matcher)
58
+
59
+
60
+ cdef _strip_attributes(xmlNode* c_node, _MultiTagMatcher matcher):
61
+ cdef xmlAttr* c_attr
62
+ cdef xmlAttr* c_next_attr
63
+ tree.BEGIN_FOR_EACH_ELEMENT_FROM(c_node, c_node, 1)
64
+ if c_node.type == tree.XML_ELEMENT_NODE:
65
+ c_attr = c_node.properties
66
+ while c_attr is not NULL:
67
+ c_next_attr = c_attr.next
68
+ if matcher.matchesAttribute(c_attr):
69
+ tree.xmlRemoveProp(c_attr)
70
+ c_attr = c_next_attr
71
+ tree.END_FOR_EACH_ELEMENT_FROM(c_node)
72
+
73
+
74
+ def strip_elements(tree_or_element, *tag_names, bint with_tail=True):
75
+ """strip_elements(tree_or_element, *tag_names, with_tail=True)
76
+
77
+ Delete all elements with the provided tag names from a tree or
78
+ subtree. This will remove the elements and their entire subtree,
79
+ including all their attributes, text content and descendants. It
80
+ will also remove the tail text of the element unless you
81
+ explicitly set the ``with_tail`` keyword argument option to False.
82
+
83
+ Tag names can contain wildcards as in `_Element.iter`.
84
+
85
+ Note that this will not delete the element (or ElementTree root
86
+ element) that you passed even if it matches. It will only treat
87
+ its descendants. If you want to include the root element, check
88
+ its tag name directly before even calling this function.
89
+
90
+ Example usage::
91
+
92
+ strip_elements(some_element,
93
+ 'simpletagname', # non-namespaced tag
94
+ '{http://some/ns}tagname', # namespaced tag
95
+ '{http://some/other/ns}*' # any tag from a namespace
96
+ lxml.etree.Comment # comments
97
+ )
98
+ """
99
+ cdef _MultiTagMatcher matcher
100
+ doc = _documentOrRaise(tree_or_element)
101
+ element = _rootNodeOrRaise(tree_or_element)
102
+ if not tag_names:
103
+ return
104
+
105
+ matcher = _MultiTagMatcher.__new__(_MultiTagMatcher, tag_names)
106
+ matcher.cacheTags(doc)
107
+ if matcher.rejectsAll():
108
+ return
109
+
110
+ if isinstance(tree_or_element, _ElementTree):
111
+ # include PIs and comments next to the root node
112
+ if matcher.matchesType(tree.XML_COMMENT_NODE):
113
+ _removeSiblings(element._c_node, tree.XML_COMMENT_NODE, with_tail)
114
+ if matcher.matchesType(tree.XML_PI_NODE):
115
+ _removeSiblings(element._c_node, tree.XML_PI_NODE, with_tail)
116
+ _strip_elements(doc, element._c_node, matcher, with_tail)
117
+
118
+ cdef _strip_elements(_Document doc, xmlNode* c_node, _MultiTagMatcher matcher,
119
+ bint with_tail):
120
+ cdef xmlNode* c_child
121
+ cdef xmlNode* c_next
122
+
123
+ tree.BEGIN_FOR_EACH_ELEMENT_FROM(c_node, c_node, 1)
124
+ if c_node.type == tree.XML_ELEMENT_NODE:
125
+ # we run through the children here to prevent any problems
126
+ # with the tree iteration which would occur if we unlinked the
127
+ # c_node itself
128
+ c_child = _findChildForwards(c_node, 0)
129
+ while c_child is not NULL:
130
+ c_next = _nextElement(c_child)
131
+ if matcher.matches(c_child):
132
+ if c_child.type == tree.XML_ELEMENT_NODE:
133
+ if not with_tail:
134
+ tree.xmlUnlinkNode(c_child)
135
+ _removeNode(doc, c_child)
136
+ else:
137
+ if with_tail:
138
+ _removeText(c_child.next)
139
+ tree.xmlUnlinkNode(c_child)
140
+ attemptDeallocation(c_child)
141
+ c_child = c_next
142
+ tree.END_FOR_EACH_ELEMENT_FROM(c_node)
143
+
144
+
145
+ def strip_tags(tree_or_element, *tag_names):
146
+ """strip_tags(tree_or_element, *tag_names)
147
+
148
+ Delete all elements with the provided tag names from a tree or
149
+ subtree. This will remove the elements and their attributes, but
150
+ *not* their text/tail content or descendants. Instead, it will
151
+ merge the text content and children of the element into its
152
+ parent.
153
+
154
+ Tag names can contain wildcards as in `_Element.iter`.
155
+
156
+ Note that this will not delete the element (or ElementTree root
157
+ element) that you passed even if it matches. It will only treat
158
+ its descendants.
159
+
160
+ Example usage::
161
+
162
+ strip_tags(some_element,
163
+ 'simpletagname', # non-namespaced tag
164
+ '{http://some/ns}tagname', # namespaced tag
165
+ '{http://some/other/ns}*' # any tag from a namespace
166
+ Comment # comments (including their text!)
167
+ )
168
+ """
169
+ cdef _MultiTagMatcher matcher
170
+ doc = _documentOrRaise(tree_or_element)
171
+ element = _rootNodeOrRaise(tree_or_element)
172
+ if not tag_names:
173
+ return
174
+
175
+ matcher = _MultiTagMatcher.__new__(_MultiTagMatcher, tag_names)
176
+ matcher.cacheTags(doc)
177
+ if matcher.rejectsAll():
178
+ return
179
+
180
+ if isinstance(tree_or_element, _ElementTree):
181
+ # include PIs and comments next to the root node
182
+ if matcher.matchesType(tree.XML_COMMENT_NODE):
183
+ _removeSiblings(element._c_node, tree.XML_COMMENT_NODE, 0)
184
+ if matcher.matchesType(tree.XML_PI_NODE):
185
+ _removeSiblings(element._c_node, tree.XML_PI_NODE, 0)
186
+ _strip_tags(doc, element._c_node, matcher)
187
+
188
+ cdef _strip_tags(_Document doc, xmlNode* c_node, _MultiTagMatcher matcher):
189
+ cdef xmlNode* c_child
190
+ cdef xmlNode* c_next
191
+
192
+ tree.BEGIN_FOR_EACH_ELEMENT_FROM(c_node, c_node, 1)
193
+ if c_node.type == tree.XML_ELEMENT_NODE:
194
+ # we run through the children here to prevent any problems
195
+ # with the tree iteration which would occur if we unlinked the
196
+ # c_node itself
197
+ c_child = _findChildForwards(c_node, 0)
198
+ while c_child is not NULL:
199
+ if not matcher.matches(c_child):
200
+ c_child = _nextElement(c_child)
201
+ continue
202
+ if c_child.type == tree.XML_ELEMENT_NODE:
203
+ c_next = _findChildForwards(c_child, 0) or _nextElement(c_child)
204
+ _replaceNodeByChildren(doc, c_child)
205
+ if not attemptDeallocation(c_child):
206
+ if c_child.nsDef is not NULL:
207
+ # make namespaces absolute
208
+ moveNodeToDocument(doc, doc._c_doc, c_child)
209
+ c_child = c_next
210
+ else:
211
+ c_next = _nextElement(c_child)
212
+ tree.xmlUnlinkNode(c_child)
213
+ attemptDeallocation(c_child)
214
+ c_child = c_next
215
+ tree.END_FOR_EACH_ELEMENT_FROM(c_node)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/cssselect.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """CSS Selectors based on XPath.
2
+
3
+ This module supports selecting XML/HTML tags based on CSS selectors.
4
+ See the `CSSSelector` class for details.
5
+
6
+ This is a thin wrapper around cssselect 0.7 or later.
7
+ """
8
+
9
+
10
+ from . import etree
11
+ try:
12
+ import cssselect as external_cssselect
13
+ except ImportError:
14
+ raise ImportError(
15
+ 'cssselect does not seem to be installed. '
16
+ 'See https://pypi.org/project/cssselect/')
17
+
18
+
19
+ SelectorSyntaxError = external_cssselect.SelectorSyntaxError
20
+ ExpressionError = external_cssselect.ExpressionError
21
+ SelectorError = external_cssselect.SelectorError
22
+
23
+
24
+ __all__ = ['SelectorSyntaxError', 'ExpressionError', 'SelectorError',
25
+ 'CSSSelector']
26
+
27
+
28
+ class LxmlTranslator(external_cssselect.GenericTranslator):
29
+ """
30
+ A custom CSS selector to XPath translator with lxml-specific extensions.
31
+ """
32
+ def xpath_contains_function(self, xpath, function):
33
+ # Defined there, removed in later drafts:
34
+ # http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors
35
+ if function.argument_types() not in (['STRING'], ['IDENT']):
36
+ raise ExpressionError(
37
+ "Expected a single string or ident for :contains(), got %r"
38
+ % function.arguments)
39
+ value = function.arguments[0].value
40
+ return xpath.add_condition(
41
+ 'contains(__lxml_internal_css:lower-case(string(.)), %s)'
42
+ % self.xpath_literal(value.lower()))
43
+
44
+
45
+ class LxmlHTMLTranslator(LxmlTranslator, external_cssselect.HTMLTranslator):
46
+ """
47
+ lxml extensions + HTML support.
48
+ """
49
+
50
+
51
+ def _make_lower_case(context, s):
52
+ return s.lower()
53
+
54
+ ns = etree.FunctionNamespace('http://codespeak.net/lxml/css/')
55
+ ns.prefix = '__lxml_internal_css'
56
+ ns['lower-case'] = _make_lower_case
57
+
58
+
59
+ class CSSSelector(etree.XPath):
60
+ """A CSS selector.
61
+
62
+ Usage::
63
+
64
+ >>> from lxml import etree, cssselect
65
+ >>> select = cssselect.CSSSelector("a tag > child")
66
+
67
+ >>> root = etree.XML("<a><b><c/><tag><child>TEXT</child></tag></b></a>")
68
+ >>> [ el.tag for el in select(root) ]
69
+ ['child']
70
+
71
+ To use CSS namespaces, you need to pass a prefix-to-namespace
72
+ mapping as ``namespaces`` keyword argument::
73
+
74
+ >>> rdfns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
75
+ >>> select_ns = cssselect.CSSSelector('root > rdf|Description',
76
+ ... namespaces={'rdf': rdfns})
77
+
78
+ >>> rdf = etree.XML((
79
+ ... '<root xmlns:rdf="%s">'
80
+ ... '<rdf:Description>blah</rdf:Description>'
81
+ ... '</root>') % rdfns)
82
+ >>> [(el.tag, el.text) for el in select_ns(rdf)]
83
+ [('{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description', 'blah')]
84
+
85
+ """
86
+ def __init__(self, css, namespaces=None, translator='xml'):
87
+ if translator == 'xml':
88
+ translator = LxmlTranslator()
89
+ elif translator == 'html':
90
+ translator = LxmlHTMLTranslator()
91
+ elif translator == 'xhtml':
92
+ translator = LxmlHTMLTranslator(xhtml=True)
93
+ path = translator.css_to_xpath(css)
94
+ super().__init__(path, namespaces=namespaces)
95
+ self.css = css
96
+
97
+ def __repr__(self):
98
+ return '<%s %x for %r>' % (
99
+ self.__class__.__name__,
100
+ abs(id(self)),
101
+ self.css)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/doctestcompare.py ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ lxml-based doctest output comparison.
3
+
4
+ Note: normally, you should just import the `lxml.usedoctest` and
5
+ `lxml.html.usedoctest` modules from within a doctest, instead of this
6
+ one::
7
+
8
+ >>> import lxml.usedoctest # for XML output
9
+
10
+ >>> import lxml.html.usedoctest # for HTML output
11
+
12
+ To use this module directly, you must call ``lxmldoctest.install()``,
13
+ which will cause doctest to use this in all subsequent calls.
14
+
15
+ This changes the way output is checked and comparisons are made for
16
+ XML or HTML-like content.
17
+
18
+ XML or HTML content is noticed because the example starts with ``<``
19
+ (it's HTML if it starts with ``<html``). You can also use the
20
+ ``PARSE_HTML`` and ``PARSE_XML`` flags to force parsing.
21
+
22
+ Some rough wildcard-like things are allowed. Whitespace is generally
23
+ ignored (except in attributes). In text (attributes and text in the
24
+ body) you can use ``...`` as a wildcard. In an example it also
25
+ matches any trailing tags in the element, though it does not match
26
+ leading tags. You may create a tag ``<any>`` or include an ``any``
27
+ attribute in the tag. An ``any`` tag matches any tag, while the
28
+ attribute matches any and all attributes.
29
+
30
+ When a match fails, the reformatted example and gotten text is
31
+ displayed (indented), and a rough diff-like output is given. Anything
32
+ marked with ``+`` is in the output but wasn't supposed to be, and
33
+ similarly ``-`` means its in the example but wasn't in the output.
34
+
35
+ You can disable parsing on one line with ``# doctest:+NOPARSE_MARKUP``
36
+ """
37
+
38
+ from lxml import etree
39
+ import sys
40
+ import re
41
+ import doctest
42
+ try:
43
+ from html import escape as html_escape
44
+ except ImportError:
45
+ from cgi import escape as html_escape
46
+
47
+ __all__ = ['PARSE_HTML', 'PARSE_XML', 'NOPARSE_MARKUP', 'LXMLOutputChecker',
48
+ 'LHTMLOutputChecker', 'install', 'temp_install']
49
+
50
+ PARSE_HTML = doctest.register_optionflag('PARSE_HTML')
51
+ PARSE_XML = doctest.register_optionflag('PARSE_XML')
52
+ NOPARSE_MARKUP = doctest.register_optionflag('NOPARSE_MARKUP')
53
+
54
+ OutputChecker = doctest.OutputChecker
55
+
56
+ def strip(v):
57
+ if v is None:
58
+ return None
59
+ else:
60
+ return v.strip()
61
+
62
+ def norm_whitespace(v):
63
+ return _norm_whitespace_re.sub(' ', v)
64
+
65
+ _html_parser = etree.HTMLParser(recover=False, remove_blank_text=True)
66
+
67
+ def html_fromstring(html):
68
+ return etree.fromstring(html, _html_parser)
69
+
70
+ # We use this to distinguish repr()s from elements:
71
+ _repr_re = re.compile(r'^<[^>]+ (at|object) ')
72
+ _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')
73
+
74
+ class LXMLOutputChecker(OutputChecker):
75
+
76
+ empty_tags = (
77
+ 'param', 'img', 'area', 'br', 'basefont', 'input',
78
+ 'base', 'meta', 'link', 'col')
79
+
80
+ def get_default_parser(self):
81
+ return etree.XML
82
+
83
+ def check_output(self, want, got, optionflags):
84
+ alt_self = getattr(self, '_temp_override_self', None)
85
+ if alt_self is not None:
86
+ super_method = self._temp_call_super_check_output
87
+ self = alt_self
88
+ else:
89
+ super_method = OutputChecker.check_output
90
+ parser = self.get_parser(want, got, optionflags)
91
+ if not parser:
92
+ return super_method(
93
+ self, want, got, optionflags)
94
+ try:
95
+ want_doc = parser(want)
96
+ except etree.XMLSyntaxError:
97
+ return False
98
+ try:
99
+ got_doc = parser(got)
100
+ except etree.XMLSyntaxError:
101
+ return False
102
+ return self.compare_docs(want_doc, got_doc)
103
+
104
+ def get_parser(self, want, got, optionflags):
105
+ parser = None
106
+ if NOPARSE_MARKUP & optionflags:
107
+ return None
108
+ if PARSE_HTML & optionflags:
109
+ parser = html_fromstring
110
+ elif PARSE_XML & optionflags:
111
+ parser = etree.XML
112
+ elif (want.strip().lower().startswith('<html')
113
+ and got.strip().startswith('<html')):
114
+ parser = html_fromstring
115
+ elif (self._looks_like_markup(want)
116
+ and self._looks_like_markup(got)):
117
+ parser = self.get_default_parser()
118
+ return parser
119
+
120
+ def _looks_like_markup(self, s):
121
+ s = s.strip()
122
+ return (s.startswith('<')
123
+ and not _repr_re.search(s))
124
+
125
+ def compare_docs(self, want, got):
126
+ if not self.tag_compare(want.tag, got.tag):
127
+ return False
128
+ if not self.text_compare(want.text, got.text, True):
129
+ return False
130
+ if not self.text_compare(want.tail, got.tail, True):
131
+ return False
132
+ if 'any' not in want.attrib:
133
+ want_keys = sorted(want.attrib.keys())
134
+ got_keys = sorted(got.attrib.keys())
135
+ if want_keys != got_keys:
136
+ return False
137
+ for key in want_keys:
138
+ if not self.text_compare(want.attrib[key], got.attrib[key], False):
139
+ return False
140
+ if want.text != '...' or len(want):
141
+ want_children = list(want)
142
+ got_children = list(got)
143
+ while want_children or got_children:
144
+ if not want_children or not got_children:
145
+ return False
146
+ want_first = want_children.pop(0)
147
+ got_first = got_children.pop(0)
148
+ if not self.compare_docs(want_first, got_first):
149
+ return False
150
+ if not got_children and want_first.tail == '...':
151
+ break
152
+ return True
153
+
154
+ def text_compare(self, want, got, strip):
155
+ want = want or ''
156
+ got = got or ''
157
+ if strip:
158
+ want = norm_whitespace(want).strip()
159
+ got = norm_whitespace(got).strip()
160
+ want = '^%s$' % re.escape(want)
161
+ want = want.replace(r'\.\.\.', '.*')
162
+ if re.search(want, got):
163
+ return True
164
+ else:
165
+ return False
166
+
167
+ def tag_compare(self, want, got):
168
+ if want == 'any':
169
+ return True
170
+ if (not isinstance(want, (str, bytes))
171
+ or not isinstance(got, (str, bytes))):
172
+ return want == got
173
+ want = want or ''
174
+ got = got or ''
175
+ if want.startswith('{...}'):
176
+ # Ellipsis on the namespace
177
+ return want.split('}')[-1] == got.split('}')[-1]
178
+ else:
179
+ return want == got
180
+
181
+ def output_difference(self, example, got, optionflags):
182
+ want = example.want
183
+ parser = self.get_parser(want, got, optionflags)
184
+ errors = []
185
+ if parser is not None:
186
+ try:
187
+ want_doc = parser(want)
188
+ except etree.XMLSyntaxError:
189
+ e = sys.exc_info()[1]
190
+ errors.append('In example: %s' % e)
191
+ try:
192
+ got_doc = parser(got)
193
+ except etree.XMLSyntaxError:
194
+ e = sys.exc_info()[1]
195
+ errors.append('In actual output: %s' % e)
196
+ if parser is None or errors:
197
+ value = OutputChecker.output_difference(
198
+ self, example, got, optionflags)
199
+ if errors:
200
+ errors.append(value)
201
+ return '\n'.join(errors)
202
+ else:
203
+ return value
204
+ html = parser is html_fromstring
205
+ diff_parts = ['Expected:',
206
+ self.format_doc(want_doc, html, 2),
207
+ 'Got:',
208
+ self.format_doc(got_doc, html, 2),
209
+ 'Diff:',
210
+ self.collect_diff(want_doc, got_doc, html, 2)]
211
+ return '\n'.join(diff_parts)
212
+
213
+ def html_empty_tag(self, el, html=True):
214
+ if not html:
215
+ return False
216
+ if el.tag not in self.empty_tags:
217
+ return False
218
+ if el.text or len(el):
219
+ # This shouldn't happen (contents in an empty tag)
220
+ return False
221
+ return True
222
+
223
+ def format_doc(self, doc, html, indent, prefix=''):
224
+ parts = []
225
+ if not len(doc):
226
+ # No children...
227
+ parts.append(' '*indent)
228
+ parts.append(prefix)
229
+ parts.append(self.format_tag(doc))
230
+ if not self.html_empty_tag(doc, html):
231
+ if strip(doc.text):
232
+ parts.append(self.format_text(doc.text))
233
+ parts.append(self.format_end_tag(doc))
234
+ if strip(doc.tail):
235
+ parts.append(self.format_text(doc.tail))
236
+ parts.append('\n')
237
+ return ''.join(parts)
238
+ parts.append(' '*indent)
239
+ parts.append(prefix)
240
+ parts.append(self.format_tag(doc))
241
+ if not self.html_empty_tag(doc, html):
242
+ parts.append('\n')
243
+ if strip(doc.text):
244
+ parts.append(' '*indent)
245
+ parts.append(self.format_text(doc.text))
246
+ parts.append('\n')
247
+ for el in doc:
248
+ parts.append(self.format_doc(el, html, indent+2))
249
+ parts.append(' '*indent)
250
+ parts.append(self.format_end_tag(doc))
251
+ parts.append('\n')
252
+ if strip(doc.tail):
253
+ parts.append(' '*indent)
254
+ parts.append(self.format_text(doc.tail))
255
+ parts.append('\n')
256
+ return ''.join(parts)
257
+
258
+ def format_text(self, text, strip=True):
259
+ if text is None:
260
+ return ''
261
+ if strip:
262
+ text = text.strip()
263
+ return html_escape(text, 1)
264
+
265
+ def format_tag(self, el):
266
+ attrs = []
267
+ if isinstance(el, etree.CommentBase):
268
+ # FIXME: probably PIs should be handled specially too?
269
+ return '<!--'
270
+ for name, value in sorted(el.attrib.items()):
271
+ attrs.append('%s="%s"' % (name, self.format_text(value, False)))
272
+ if not attrs:
273
+ return '<%s>' % el.tag
274
+ return '<%s %s>' % (el.tag, ' '.join(attrs))
275
+
276
+ def format_end_tag(self, el):
277
+ if isinstance(el, etree.CommentBase):
278
+ # FIXME: probably PIs should be handled specially too?
279
+ return '-->'
280
+ return '</%s>' % el.tag
281
+
282
+ def collect_diff(self, want, got, html, indent):
283
+ parts = []
284
+ if not len(want) and not len(got):
285
+ parts.append(' '*indent)
286
+ parts.append(self.collect_diff_tag(want, got))
287
+ if not self.html_empty_tag(got, html):
288
+ parts.append(self.collect_diff_text(want.text, got.text))
289
+ parts.append(self.collect_diff_end_tag(want, got))
290
+ parts.append(self.collect_diff_text(want.tail, got.tail))
291
+ parts.append('\n')
292
+ return ''.join(parts)
293
+ parts.append(' '*indent)
294
+ parts.append(self.collect_diff_tag(want, got))
295
+ parts.append('\n')
296
+ if strip(want.text) or strip(got.text):
297
+ parts.append(' '*indent)
298
+ parts.append(self.collect_diff_text(want.text, got.text))
299
+ parts.append('\n')
300
+ want_children = list(want)
301
+ got_children = list(got)
302
+ while want_children or got_children:
303
+ if not want_children:
304
+ parts.append(self.format_doc(got_children.pop(0), html, indent+2, '+'))
305
+ continue
306
+ if not got_children:
307
+ parts.append(self.format_doc(want_children.pop(0), html, indent+2, '-'))
308
+ continue
309
+ parts.append(self.collect_diff(
310
+ want_children.pop(0), got_children.pop(0), html, indent+2))
311
+ parts.append(' '*indent)
312
+ parts.append(self.collect_diff_end_tag(want, got))
313
+ parts.append('\n')
314
+ if strip(want.tail) or strip(got.tail):
315
+ parts.append(' '*indent)
316
+ parts.append(self.collect_diff_text(want.tail, got.tail))
317
+ parts.append('\n')
318
+ return ''.join(parts)
319
+
320
+ def collect_diff_tag(self, want, got):
321
+ if not self.tag_compare(want.tag, got.tag):
322
+ tag = '%s (got: %s)' % (want.tag, got.tag)
323
+ else:
324
+ tag = got.tag
325
+ attrs = []
326
+ any = want.tag == 'any' or 'any' in want.attrib
327
+ for name, value in sorted(got.attrib.items()):
328
+ if name not in want.attrib and not any:
329
+ attrs.append('+%s="%s"' % (name, self.format_text(value, False)))
330
+ else:
331
+ if name in want.attrib:
332
+ text = self.collect_diff_text(want.attrib[name], value, False)
333
+ else:
334
+ text = self.format_text(value, False)
335
+ attrs.append('%s="%s"' % (name, text))
336
+ if not any:
337
+ for name, value in sorted(want.attrib.items()):
338
+ if name in got.attrib:
339
+ continue
340
+ attrs.append('-%s="%s"' % (name, self.format_text(value, False)))
341
+ if attrs:
342
+ tag = '<%s %s>' % (tag, ' '.join(attrs))
343
+ else:
344
+ tag = '<%s>' % tag
345
+ return tag
346
+
347
+ def collect_diff_end_tag(self, want, got):
348
+ if want.tag != got.tag:
349
+ tag = '%s (got: %s)' % (want.tag, got.tag)
350
+ else:
351
+ tag = got.tag
352
+ return '</%s>' % tag
353
+
354
+ def collect_diff_text(self, want, got, strip=True):
355
+ if self.text_compare(want, got, strip):
356
+ if not got:
357
+ return ''
358
+ return self.format_text(got, strip)
359
+ text = '%s (got: %s)' % (want, got)
360
+ return self.format_text(text, strip)
361
+
362
+ class LHTMLOutputChecker(LXMLOutputChecker):
363
+ def get_default_parser(self):
364
+ return html_fromstring
365
+
366
+ def install(html=False):
367
+ """
368
+ Install doctestcompare for all future doctests.
369
+
370
+ If html is true, then by default the HTML parser will be used;
371
+ otherwise the XML parser is used.
372
+ """
373
+ if html:
374
+ doctest.OutputChecker = LHTMLOutputChecker
375
+ else:
376
+ doctest.OutputChecker = LXMLOutputChecker
377
+
378
+ def temp_install(html=False, del_module=None):
379
+ """
380
+ Use this *inside* a doctest to enable this checker for this
381
+ doctest only.
382
+
383
+ If html is true, then by default the HTML parser will be used;
384
+ otherwise the XML parser is used.
385
+ """
386
+ if html:
387
+ Checker = LHTMLOutputChecker
388
+ else:
389
+ Checker = LXMLOutputChecker
390
+ frame = _find_doctest_frame()
391
+ dt_self = frame.f_locals['self']
392
+ checker = Checker()
393
+ old_checker = dt_self._checker
394
+ dt_self._checker = checker
395
+ # The unfortunate thing is that there is a local variable 'check'
396
+ # in the function that runs the doctests, that is a bound method
397
+ # into the output checker. We have to update that. We can't
398
+ # modify the frame, so we have to modify the object in place. The
399
+ # only way to do this is to actually change the func_code
400
+ # attribute of the method. We change it, and then wait for
401
+ # __record_outcome to be run, which signals the end of the __run
402
+ # method, at which point we restore the previous check_output
403
+ # implementation.
404
+ check_func = frame.f_locals['check'].__func__
405
+ checker_check_func = checker.check_output.__func__
406
+ # Because we can't patch up func_globals, this is the only global
407
+ # in check_output that we care about:
408
+ doctest.etree = etree
409
+ _RestoreChecker(dt_self, old_checker, checker,
410
+ check_func, checker_check_func,
411
+ del_module)
412
+
413
+ class _RestoreChecker:
414
+ def __init__(self, dt_self, old_checker, new_checker, check_func, clone_func,
415
+ del_module):
416
+ self.dt_self = dt_self
417
+ self.checker = old_checker
418
+ self.checker._temp_call_super_check_output = self.call_super
419
+ self.checker._temp_override_self = new_checker
420
+ self.check_func = check_func
421
+ self.clone_func = clone_func
422
+ self.del_module = del_module
423
+ self.install_clone()
424
+ self.install_dt_self()
425
+ def install_clone(self):
426
+ self.func_code = self.check_func.__code__
427
+ self.func_globals = self.check_func.__globals__
428
+ self.check_func.__code__ = self.clone_func.__code__
429
+ def uninstall_clone(self):
430
+ self.check_func.__code__ = self.func_code
431
+ def install_dt_self(self):
432
+ self.prev_func = self.dt_self._DocTestRunner__record_outcome
433
+ self.dt_self._DocTestRunner__record_outcome = self
434
+ def uninstall_dt_self(self):
435
+ self.dt_self._DocTestRunner__record_outcome = self.prev_func
436
+ def uninstall_module(self):
437
+ if self.del_module:
438
+ import sys
439
+ del sys.modules[self.del_module]
440
+ if '.' in self.del_module:
441
+ package, module = self.del_module.rsplit('.', 1)
442
+ package_mod = sys.modules[package]
443
+ delattr(package_mod, module)
444
+ def __call__(self, *args, **kw):
445
+ self.uninstall_clone()
446
+ self.uninstall_dt_self()
447
+ del self.checker._temp_override_self
448
+ del self.checker._temp_call_super_check_output
449
+ result = self.prev_func(*args, **kw)
450
+ self.uninstall_module()
451
+ return result
452
+ def call_super(self, *args, **kw):
453
+ self.uninstall_clone()
454
+ try:
455
+ return self.check_func(*args, **kw)
456
+ finally:
457
+ self.install_clone()
458
+
459
+ def _find_doctest_frame():
460
+ import sys
461
+ frame = sys._getframe(1)
462
+ while frame:
463
+ l = frame.f_locals
464
+ if 'BOOM' in l:
465
+ # Sign of doctest
466
+ return frame
467
+ frame = frame.f_back
468
+ raise LookupError(
469
+ "Could not find doctest (only use this function *inside* a doctest)")
470
+
471
+ __test__ = {
472
+ 'basic': '''
473
+ >>> temp_install()
474
+ >>> print """<xml a="1" b="2">stuff</xml>"""
475
+ <xml b="2" a="1">...</xml>
476
+ >>> print """<xml xmlns="http://example.com"><tag attr="bar" /></xml>"""
477
+ <xml xmlns="...">
478
+ <tag attr="..." />
479
+ </xml>
480
+ >>> print """<xml>blahblahblah<foo /></xml>""" # doctest: +NOPARSE_MARKUP, +ELLIPSIS
481
+ <xml>...foo /></xml>
482
+ '''}
483
+
484
+ if __name__ == '__main__':
485
+ import doctest
486
+ doctest.testmod()
487
+
488
+
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/etree.h ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Generated by Cython 3.1.4 */
2
+
3
+ #ifndef __PYX_HAVE__lxml__etree
4
+ #define __PYX_HAVE__lxml__etree
5
+
6
+ #include "Python.h"
7
+ struct LxmlDocument;
8
+ struct LxmlElement;
9
+ struct LxmlElementTree;
10
+ struct LxmlElementTagMatcher;
11
+ struct LxmlElementIterator;
12
+ struct LxmlElementBase;
13
+ struct LxmlElementClassLookup;
14
+ struct LxmlFallbackElementClassLookup;
15
+
16
+ /* "lxml/etree.pyx":451
17
+ *
18
+ * # type of a function that steps from node to node
19
+ * ctypedef public xmlNode* (*_node_to_node_function)(xmlNode*) # <<<<<<<<<<<<<<
20
+ *
21
+ *
22
+ */
23
+ typedef xmlNode *(*_node_to_node_function)(xmlNode *);
24
+
25
+ /* "lxml/etree.pyx":465
26
+ * # Public Python API
27
+ *
28
+ * @cython.final # <<<<<<<<<<<<<<
29
+ * @cython.freelist(8)
30
+ * cdef public class _Document [ type LxmlDocumentType, object LxmlDocument ]:
31
+ */
32
+ struct LxmlDocument {
33
+ PyObject_HEAD
34
+ struct __pyx_vtabstruct_4lxml_5etree__Document *__pyx_vtab;
35
+ int _ns_counter;
36
+ PyObject *_prefix_tail;
37
+ xmlDoc *_c_doc;
38
+ struct __pyx_obj_4lxml_5etree__BaseParser *_parser;
39
+ };
40
+
41
+ /* "lxml/etree.pyx":817
42
+ *
43
+ *
44
+ * @cython.no_gc_clear # <<<<<<<<<<<<<<
45
+ * cdef public class _Element [ type LxmlElementType, object LxmlElement ]:
46
+ * """Element class.
47
+ */
48
+ struct LxmlElement {
49
+ PyObject_HEAD
50
+ struct LxmlDocument *_doc;
51
+ xmlNode *_c_node;
52
+ PyObject *_tag;
53
+ };
54
+
55
+ /* "lxml/etree.pyx":1991
56
+ *
57
+ *
58
+ * cdef public class _ElementTree [ type LxmlElementTreeType, # <<<<<<<<<<<<<<
59
+ * object LxmlElementTree ]:
60
+ * cdef _Document _doc
61
+ */
62
+ struct LxmlElementTree {
63
+ PyObject_HEAD
64
+ struct __pyx_vtabstruct_4lxml_5etree__ElementTree *__pyx_vtab;
65
+ struct LxmlDocument *_doc;
66
+ struct LxmlElement *_context_node;
67
+ };
68
+
69
+ /* "lxml/etree.pyx":2765
70
+ *
71
+ *
72
+ * cdef public class _ElementTagMatcher [ object LxmlElementTagMatcher, # <<<<<<<<<<<<<<
73
+ * type LxmlElementTagMatcherType ]:
74
+ * """
75
+ */
76
+ struct LxmlElementTagMatcher {
77
+ PyObject_HEAD
78
+ struct __pyx_vtabstruct_4lxml_5etree__ElementTagMatcher *__pyx_vtab;
79
+ PyObject *_pystrings;
80
+ int _node_type;
81
+ char *_href;
82
+ char *_name;
83
+ };
84
+
85
+ /* "lxml/etree.pyx":2796
86
+ * self._name = NULL
87
+ *
88
+ * cdef public class _ElementIterator(_ElementTagMatcher) [ # <<<<<<<<<<<<<<
89
+ * object LxmlElementIterator, type LxmlElementIteratorType ]:
90
+ * """
91
+ */
92
+ struct LxmlElementIterator {
93
+ struct LxmlElementTagMatcher __pyx_base;
94
+ struct LxmlElement *_node;
95
+ _node_to_node_function _next_element;
96
+ };
97
+
98
+ /* "src/lxml/classlookup.pxi":6
99
+ * # Custom Element classes
100
+ *
101
+ * cdef public class ElementBase(_Element) [ type LxmlElementBaseType, # <<<<<<<<<<<<<<
102
+ * object LxmlElementBase ]:
103
+ * """ElementBase(*children, attrib=None, nsmap=None, **_extra)
104
+ */
105
+ struct LxmlElementBase {
106
+ struct LxmlElement __pyx_base;
107
+ };
108
+
109
+ /* "src/lxml/classlookup.pxi":210
110
+ * # Element class lookup
111
+ *
112
+ * ctypedef public object (*_element_class_lookup_function)(object, _Document, xmlNode*) # <<<<<<<<<<<<<<
113
+ *
114
+ * # class to store element class lookup functions
115
+ */
116
+ typedef PyObject *(*_element_class_lookup_function)(PyObject *, struct LxmlDocument *, xmlNode *);
117
+
118
+ /* "src/lxml/classlookup.pxi":213
119
+ *
120
+ * # class to store element class lookup functions
121
+ * cdef public class ElementClassLookup [ type LxmlElementClassLookupType, # <<<<<<<<<<<<<<
122
+ * object LxmlElementClassLookup ]:
123
+ * """ElementClassLookup(self)
124
+ */
125
+ struct LxmlElementClassLookup {
126
+ PyObject_HEAD
127
+ _element_class_lookup_function _lookup_function;
128
+ };
129
+
130
+ /* "src/lxml/classlookup.pxi":221
131
+ *
132
+ *
133
+ * cdef public class FallbackElementClassLookup(ElementClassLookup) \ # <<<<<<<<<<<<<<
134
+ * [ type LxmlFallbackElementClassLookupType,
135
+ * object LxmlFallbackElementClassLookup ]:
136
+ */
137
+ struct LxmlFallbackElementClassLookup {
138
+ struct LxmlElementClassLookup __pyx_base;
139
+ struct __pyx_vtabstruct_4lxml_5etree_FallbackElementClassLookup *__pyx_vtab;
140
+ struct LxmlElementClassLookup *fallback;
141
+ _element_class_lookup_function _fallback_function;
142
+ };
143
+
144
+ #ifndef __PYX_HAVE_API__lxml__etree
145
+
146
+ #ifdef CYTHON_EXTERN_C
147
+ #undef __PYX_EXTERN_C
148
+ #define __PYX_EXTERN_C CYTHON_EXTERN_C
149
+ #elif defined(__PYX_EXTERN_C)
150
+ #ifdef _MSC_VER
151
+ #pragma message ("Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.")
152
+ #else
153
+ #warning Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.
154
+ #endif
155
+ #else
156
+ #ifdef __cplusplus
157
+ #define __PYX_EXTERN_C extern "C"
158
+ #else
159
+ #define __PYX_EXTERN_C extern
160
+ #endif
161
+ #endif
162
+
163
+ #ifndef DL_IMPORT
164
+ #define DL_IMPORT(_T) _T
165
+ #endif
166
+
167
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlDocumentType;
168
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementType;
169
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementTreeType;
170
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementTagMatcherType;
171
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementIteratorType;
172
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementBaseType;
173
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementClassLookupType;
174
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlFallbackElementClassLookupType;
175
+
176
+ __PYX_EXTERN_C struct LxmlElement *deepcopyNodeToDocument(struct LxmlDocument *, xmlNode *);
177
+ __PYX_EXTERN_C struct LxmlElementTree *elementTreeFactory(struct LxmlElement *);
178
+ __PYX_EXTERN_C struct LxmlElementTree *newElementTree(struct LxmlElement *, PyObject *);
179
+ __PYX_EXTERN_C struct LxmlElementTree *adoptExternalDocument(xmlDoc *, PyObject *, int);
180
+ __PYX_EXTERN_C struct LxmlElement *elementFactory(struct LxmlDocument *, xmlNode *);
181
+ __PYX_EXTERN_C struct LxmlElement *makeElement(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *);
182
+ __PYX_EXTERN_C struct LxmlElement *makeSubElement(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *);
183
+ __PYX_EXTERN_C void setElementClassLookupFunction(_element_class_lookup_function, PyObject *);
184
+ __PYX_EXTERN_C PyObject *lookupDefaultElementClass(PyObject *, PyObject *, xmlNode *);
185
+ __PYX_EXTERN_C PyObject *lookupNamespaceElementClass(PyObject *, PyObject *, xmlNode *);
186
+ __PYX_EXTERN_C PyObject *callLookupFallback(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *);
187
+ __PYX_EXTERN_C int tagMatches(xmlNode *, const xmlChar *, const xmlChar *);
188
+ __PYX_EXTERN_C struct LxmlDocument *documentOrRaise(PyObject *);
189
+ __PYX_EXTERN_C struct LxmlElement *rootNodeOrRaise(PyObject *);
190
+ __PYX_EXTERN_C int hasText(xmlNode *);
191
+ __PYX_EXTERN_C int hasTail(xmlNode *);
192
+ __PYX_EXTERN_C PyObject *textOf(xmlNode *);
193
+ __PYX_EXTERN_C PyObject *tailOf(xmlNode *);
194
+ __PYX_EXTERN_C int setNodeText(xmlNode *, PyObject *);
195
+ __PYX_EXTERN_C int setTailText(xmlNode *, PyObject *);
196
+ __PYX_EXTERN_C PyObject *attributeValue(xmlNode *, xmlAttr *);
197
+ __PYX_EXTERN_C PyObject *attributeValueFromNsName(xmlNode *, const xmlChar *, const xmlChar *);
198
+ __PYX_EXTERN_C PyObject *getAttributeValue(struct LxmlElement *, PyObject *, PyObject *);
199
+ __PYX_EXTERN_C PyObject *iterattributes(struct LxmlElement *, int);
200
+ __PYX_EXTERN_C PyObject *collectAttributes(xmlNode *, int);
201
+ __PYX_EXTERN_C int setAttributeValue(struct LxmlElement *, PyObject *, PyObject *);
202
+ __PYX_EXTERN_C int delAttribute(struct LxmlElement *, PyObject *);
203
+ __PYX_EXTERN_C int delAttributeFromNsName(xmlNode *, const xmlChar *, const xmlChar *);
204
+ __PYX_EXTERN_C int hasChild(xmlNode *);
205
+ __PYX_EXTERN_C xmlNode *findChild(xmlNode *, Py_ssize_t);
206
+ __PYX_EXTERN_C xmlNode *findChildForwards(xmlNode *, Py_ssize_t);
207
+ __PYX_EXTERN_C xmlNode *findChildBackwards(xmlNode *, Py_ssize_t);
208
+ __PYX_EXTERN_C xmlNode *nextElement(xmlNode *);
209
+ __PYX_EXTERN_C xmlNode *previousElement(xmlNode *);
210
+ __PYX_EXTERN_C void appendChild(struct LxmlElement *, struct LxmlElement *);
211
+ __PYX_EXTERN_C int appendChildToElement(struct LxmlElement *, struct LxmlElement *);
212
+ __PYX_EXTERN_C PyObject *pyunicode(const xmlChar *);
213
+ __PYX_EXTERN_C PyObject *utf8(PyObject *);
214
+ __PYX_EXTERN_C PyObject *getNsTag(PyObject *);
215
+ __PYX_EXTERN_C PyObject *getNsTagWithEmptyNs(PyObject *);
216
+ __PYX_EXTERN_C PyObject *namespacedName(xmlNode *);
217
+ __PYX_EXTERN_C PyObject *namespacedNameFromNsName(const xmlChar *, const xmlChar *);
218
+ __PYX_EXTERN_C void iteratorStoreNext(struct LxmlElementIterator *, struct LxmlElement *);
219
+ __PYX_EXTERN_C void initTagMatch(struct LxmlElementTagMatcher *, PyObject *);
220
+ __PYX_EXTERN_C xmlNs *findOrBuildNodeNsPrefix(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *);
221
+
222
+ #endif /* !__PYX_HAVE_API__lxml__etree */
223
+
224
+ /* WARNING: the interface of the module init function changed in CPython 3.5. */
225
+ /* It now returns a PyModuleDef instance instead of a PyModule instance. */
226
+
227
+ /* WARNING: Use PyImport_AppendInittab("etree", PyInit_etree) instead of calling PyInit_etree directly from Python 3.5 */
228
+ PyMODINIT_FUNC PyInit_etree(void);
229
+
230
+ #if PY_VERSION_HEX >= 0x03050000 && (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || (defined(__cplusplus) && __cplusplus >= 201402L))
231
+ #if defined(__cplusplus) && __cplusplus >= 201402L
232
+ [[deprecated("Use PyImport_AppendInittab(\"etree\", PyInit_etree) instead of calling PyInit_etree directly.")]] inline
233
+ #elif defined(__GNUC__) || defined(__clang__)
234
+ __attribute__ ((__deprecated__("Use PyImport_AppendInittab(\"etree\", PyInit_etree) instead of calling PyInit_etree directly."), __unused__)) __inline__
235
+ #elif defined(_MSC_VER)
236
+ __declspec(deprecated("Use PyImport_AppendInittab(\"etree\", PyInit_etree) instead of calling PyInit_etree directly.")) __inline
237
+ #endif
238
+ static PyObject* __PYX_WARN_IF_PyInit_etree_INIT_CALLED(PyObject* res) {
239
+ return res;
240
+ }
241
+ #define PyInit_etree() __PYX_WARN_IF_PyInit_etree_INIT_CALLED(PyInit_etree())
242
+ #endif
243
+
244
+ #endif /* !__PYX_HAVE__lxml__etree */
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/etree.pyx ADDED
The diff for this file is too large to render. See raw diff
 
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/etree_api.h ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Generated by Cython 3.1.4 */
2
+
3
+ #ifndef __PYX_HAVE_API__lxml__etree
4
+ #define __PYX_HAVE_API__lxml__etree
5
+ #ifdef __MINGW64__
6
+ #define MS_WIN64
7
+ #endif
8
+ #include "Python.h"
9
+ #include "etree.h"
10
+
11
+ static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_deepcopyNodeToDocument)(struct LxmlDocument *, xmlNode *) = 0;
12
+ #define deepcopyNodeToDocument __pyx_api_f_4lxml_5etree_deepcopyNodeToDocument
13
+ static struct LxmlElementTree *(*__pyx_api_f_4lxml_5etree_elementTreeFactory)(struct LxmlElement *) = 0;
14
+ #define elementTreeFactory __pyx_api_f_4lxml_5etree_elementTreeFactory
15
+ static struct LxmlElementTree *(*__pyx_api_f_4lxml_5etree_newElementTree)(struct LxmlElement *, PyObject *) = 0;
16
+ #define newElementTree __pyx_api_f_4lxml_5etree_newElementTree
17
+ static struct LxmlElementTree *(*__pyx_api_f_4lxml_5etree_adoptExternalDocument)(xmlDoc *, PyObject *, int) = 0;
18
+ #define adoptExternalDocument __pyx_api_f_4lxml_5etree_adoptExternalDocument
19
+ static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_elementFactory)(struct LxmlDocument *, xmlNode *) = 0;
20
+ #define elementFactory __pyx_api_f_4lxml_5etree_elementFactory
21
+ static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_makeElement)(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *) = 0;
22
+ #define makeElement __pyx_api_f_4lxml_5etree_makeElement
23
+ static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_makeSubElement)(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *) = 0;
24
+ #define makeSubElement __pyx_api_f_4lxml_5etree_makeSubElement
25
+ static void (*__pyx_api_f_4lxml_5etree_setElementClassLookupFunction)(_element_class_lookup_function, PyObject *) = 0;
26
+ #define setElementClassLookupFunction __pyx_api_f_4lxml_5etree_setElementClassLookupFunction
27
+ static PyObject *(*__pyx_api_f_4lxml_5etree_lookupDefaultElementClass)(PyObject *, PyObject *, xmlNode *) = 0;
28
+ #define lookupDefaultElementClass __pyx_api_f_4lxml_5etree_lookupDefaultElementClass
29
+ static PyObject *(*__pyx_api_f_4lxml_5etree_lookupNamespaceElementClass)(PyObject *, PyObject *, xmlNode *) = 0;
30
+ #define lookupNamespaceElementClass __pyx_api_f_4lxml_5etree_lookupNamespaceElementClass
31
+ static PyObject *(*__pyx_api_f_4lxml_5etree_callLookupFallback)(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *) = 0;
32
+ #define callLookupFallback __pyx_api_f_4lxml_5etree_callLookupFallback
33
+ static int (*__pyx_api_f_4lxml_5etree_tagMatches)(xmlNode *, const xmlChar *, const xmlChar *) = 0;
34
+ #define tagMatches __pyx_api_f_4lxml_5etree_tagMatches
35
+ static struct LxmlDocument *(*__pyx_api_f_4lxml_5etree_documentOrRaise)(PyObject *) = 0;
36
+ #define documentOrRaise __pyx_api_f_4lxml_5etree_documentOrRaise
37
+ static struct LxmlElement *(*__pyx_api_f_4lxml_5etree_rootNodeOrRaise)(PyObject *) = 0;
38
+ #define rootNodeOrRaise __pyx_api_f_4lxml_5etree_rootNodeOrRaise
39
+ static int (*__pyx_api_f_4lxml_5etree_hasText)(xmlNode *) = 0;
40
+ #define hasText __pyx_api_f_4lxml_5etree_hasText
41
+ static int (*__pyx_api_f_4lxml_5etree_hasTail)(xmlNode *) = 0;
42
+ #define hasTail __pyx_api_f_4lxml_5etree_hasTail
43
+ static PyObject *(*__pyx_api_f_4lxml_5etree_textOf)(xmlNode *) = 0;
44
+ #define textOf __pyx_api_f_4lxml_5etree_textOf
45
+ static PyObject *(*__pyx_api_f_4lxml_5etree_tailOf)(xmlNode *) = 0;
46
+ #define tailOf __pyx_api_f_4lxml_5etree_tailOf
47
+ static int (*__pyx_api_f_4lxml_5etree_setNodeText)(xmlNode *, PyObject *) = 0;
48
+ #define setNodeText __pyx_api_f_4lxml_5etree_setNodeText
49
+ static int (*__pyx_api_f_4lxml_5etree_setTailText)(xmlNode *, PyObject *) = 0;
50
+ #define setTailText __pyx_api_f_4lxml_5etree_setTailText
51
+ static PyObject *(*__pyx_api_f_4lxml_5etree_attributeValue)(xmlNode *, xmlAttr *) = 0;
52
+ #define attributeValue __pyx_api_f_4lxml_5etree_attributeValue
53
+ static PyObject *(*__pyx_api_f_4lxml_5etree_attributeValueFromNsName)(xmlNode *, const xmlChar *, const xmlChar *) = 0;
54
+ #define attributeValueFromNsName __pyx_api_f_4lxml_5etree_attributeValueFromNsName
55
+ static PyObject *(*__pyx_api_f_4lxml_5etree_getAttributeValue)(struct LxmlElement *, PyObject *, PyObject *) = 0;
56
+ #define getAttributeValue __pyx_api_f_4lxml_5etree_getAttributeValue
57
+ static PyObject *(*__pyx_api_f_4lxml_5etree_iterattributes)(struct LxmlElement *, int) = 0;
58
+ #define iterattributes __pyx_api_f_4lxml_5etree_iterattributes
59
+ static PyObject *(*__pyx_api_f_4lxml_5etree_collectAttributes)(xmlNode *, int) = 0;
60
+ #define collectAttributes __pyx_api_f_4lxml_5etree_collectAttributes
61
+ static int (*__pyx_api_f_4lxml_5etree_setAttributeValue)(struct LxmlElement *, PyObject *, PyObject *) = 0;
62
+ #define setAttributeValue __pyx_api_f_4lxml_5etree_setAttributeValue
63
+ static int (*__pyx_api_f_4lxml_5etree_delAttribute)(struct LxmlElement *, PyObject *) = 0;
64
+ #define delAttribute __pyx_api_f_4lxml_5etree_delAttribute
65
+ static int (*__pyx_api_f_4lxml_5etree_delAttributeFromNsName)(xmlNode *, const xmlChar *, const xmlChar *) = 0;
66
+ #define delAttributeFromNsName __pyx_api_f_4lxml_5etree_delAttributeFromNsName
67
+ static int (*__pyx_api_f_4lxml_5etree_hasChild)(xmlNode *) = 0;
68
+ #define hasChild __pyx_api_f_4lxml_5etree_hasChild
69
+ static xmlNode *(*__pyx_api_f_4lxml_5etree_findChild)(xmlNode *, Py_ssize_t) = 0;
70
+ #define findChild __pyx_api_f_4lxml_5etree_findChild
71
+ static xmlNode *(*__pyx_api_f_4lxml_5etree_findChildForwards)(xmlNode *, Py_ssize_t) = 0;
72
+ #define findChildForwards __pyx_api_f_4lxml_5etree_findChildForwards
73
+ static xmlNode *(*__pyx_api_f_4lxml_5etree_findChildBackwards)(xmlNode *, Py_ssize_t) = 0;
74
+ #define findChildBackwards __pyx_api_f_4lxml_5etree_findChildBackwards
75
+ static xmlNode *(*__pyx_api_f_4lxml_5etree_nextElement)(xmlNode *) = 0;
76
+ #define nextElement __pyx_api_f_4lxml_5etree_nextElement
77
+ static xmlNode *(*__pyx_api_f_4lxml_5etree_previousElement)(xmlNode *) = 0;
78
+ #define previousElement __pyx_api_f_4lxml_5etree_previousElement
79
+ static void (*__pyx_api_f_4lxml_5etree_appendChild)(struct LxmlElement *, struct LxmlElement *) = 0;
80
+ #define appendChild __pyx_api_f_4lxml_5etree_appendChild
81
+ static int (*__pyx_api_f_4lxml_5etree_appendChildToElement)(struct LxmlElement *, struct LxmlElement *) = 0;
82
+ #define appendChildToElement __pyx_api_f_4lxml_5etree_appendChildToElement
83
+ static PyObject *(*__pyx_api_f_4lxml_5etree_pyunicode)(const xmlChar *) = 0;
84
+ #define pyunicode __pyx_api_f_4lxml_5etree_pyunicode
85
+ static PyObject *(*__pyx_api_f_4lxml_5etree_utf8)(PyObject *) = 0;
86
+ #define utf8 __pyx_api_f_4lxml_5etree_utf8
87
+ static PyObject *(*__pyx_api_f_4lxml_5etree_getNsTag)(PyObject *) = 0;
88
+ #define getNsTag __pyx_api_f_4lxml_5etree_getNsTag
89
+ static PyObject *(*__pyx_api_f_4lxml_5etree_getNsTagWithEmptyNs)(PyObject *) = 0;
90
+ #define getNsTagWithEmptyNs __pyx_api_f_4lxml_5etree_getNsTagWithEmptyNs
91
+ static PyObject *(*__pyx_api_f_4lxml_5etree_namespacedName)(xmlNode *) = 0;
92
+ #define namespacedName __pyx_api_f_4lxml_5etree_namespacedName
93
+ static PyObject *(*__pyx_api_f_4lxml_5etree_namespacedNameFromNsName)(const xmlChar *, const xmlChar *) = 0;
94
+ #define namespacedNameFromNsName __pyx_api_f_4lxml_5etree_namespacedNameFromNsName
95
+ static void (*__pyx_api_f_4lxml_5etree_iteratorStoreNext)(struct LxmlElementIterator *, struct LxmlElement *) = 0;
96
+ #define iteratorStoreNext __pyx_api_f_4lxml_5etree_iteratorStoreNext
97
+ static void (*__pyx_api_f_4lxml_5etree_initTagMatch)(struct LxmlElementTagMatcher *, PyObject *) = 0;
98
+ #define initTagMatch __pyx_api_f_4lxml_5etree_initTagMatch
99
+ static xmlNs *(*__pyx_api_f_4lxml_5etree_findOrBuildNodeNsPrefix)(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *) = 0;
100
+ #define findOrBuildNodeNsPrefix __pyx_api_f_4lxml_5etree_findOrBuildNodeNsPrefix
101
+ static int __Pyx_ImportFunction_3_1_4(PyObject *module, const char *funcname, void (**f)(void), const char *sig);
102
+
103
+ #ifndef __PYX_HAVE_RT_ImportFunction_3_1_4
104
+ #define __PYX_HAVE_RT_ImportFunction_3_1_4
105
+ static int __Pyx_ImportFunction_3_1_4(PyObject *module, const char *funcname, void (**f)(void), const char *sig) {
106
+ PyObject *d = 0;
107
+ PyObject *cobj = 0;
108
+ union {
109
+ void (*fp)(void);
110
+ void *p;
111
+ } tmp;
112
+ d = PyObject_GetAttrString(module, "__pyx_capi__");
113
+ if (!d)
114
+ goto bad;
115
+ #if (defined(Py_LIMITED_API) && Py_LIMITED_API >= 0x030d0000) || (!defined(Py_LIMITED_API) && PY_VERSION_HEX >= 0x030d0000)
116
+ PyDict_GetItemStringRef(d, funcname, &cobj);
117
+ #else
118
+ cobj = PyDict_GetItemString(d, funcname);
119
+ Py_XINCREF(cobj);
120
+ #endif
121
+ if (!cobj) {
122
+ PyErr_Format(PyExc_ImportError,
123
+ "%.200s does not export expected C function %.200s",
124
+ PyModule_GetName(module), funcname);
125
+ goto bad;
126
+ }
127
+ if (!PyCapsule_IsValid(cobj, sig)) {
128
+ PyErr_Format(PyExc_TypeError,
129
+ "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
130
+ PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj));
131
+ goto bad;
132
+ }
133
+ tmp.p = PyCapsule_GetPointer(cobj, sig);
134
+ *f = tmp.fp;
135
+ if (!(*f))
136
+ goto bad;
137
+ Py_DECREF(d);
138
+ Py_DECREF(cobj);
139
+ return 0;
140
+ bad:
141
+ Py_XDECREF(d);
142
+ Py_XDECREF(cobj);
143
+ return -1;
144
+ }
145
+ #endif
146
+
147
+
148
+ static int import_lxml__etree(void) {
149
+ PyObject *module = 0;
150
+ module = PyImport_ImportModule("lxml.etree");
151
+ if (!module) goto bad;
152
+ if (__Pyx_ImportFunction_3_1_4(module, "deepcopyNodeToDocument", (void (**)(void))&__pyx_api_f_4lxml_5etree_deepcopyNodeToDocument, "struct LxmlElement *(struct LxmlDocument *, xmlNode *)") < 0) goto bad;
153
+ if (__Pyx_ImportFunction_3_1_4(module, "elementTreeFactory", (void (**)(void))&__pyx_api_f_4lxml_5etree_elementTreeFactory, "struct LxmlElementTree *(struct LxmlElement *)") < 0) goto bad;
154
+ if (__Pyx_ImportFunction_3_1_4(module, "newElementTree", (void (**)(void))&__pyx_api_f_4lxml_5etree_newElementTree, "struct LxmlElementTree *(struct LxmlElement *, PyObject *)") < 0) goto bad;
155
+ if (__Pyx_ImportFunction_3_1_4(module, "adoptExternalDocument", (void (**)(void))&__pyx_api_f_4lxml_5etree_adoptExternalDocument, "struct LxmlElementTree *(xmlDoc *, PyObject *, int)") < 0) goto bad;
156
+ if (__Pyx_ImportFunction_3_1_4(module, "elementFactory", (void (**)(void))&__pyx_api_f_4lxml_5etree_elementFactory, "struct LxmlElement *(struct LxmlDocument *, xmlNode *)") < 0) goto bad;
157
+ if (__Pyx_ImportFunction_3_1_4(module, "makeElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_makeElement, "struct LxmlElement *(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *)") < 0) goto bad;
158
+ if (__Pyx_ImportFunction_3_1_4(module, "makeSubElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_makeSubElement, "struct LxmlElement *(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *)") < 0) goto bad;
159
+ if (__Pyx_ImportFunction_3_1_4(module, "setElementClassLookupFunction", (void (**)(void))&__pyx_api_f_4lxml_5etree_setElementClassLookupFunction, "void (_element_class_lookup_function, PyObject *)") < 0) goto bad;
160
+ if (__Pyx_ImportFunction_3_1_4(module, "lookupDefaultElementClass", (void (**)(void))&__pyx_api_f_4lxml_5etree_lookupDefaultElementClass, "PyObject *(PyObject *, PyObject *, xmlNode *)") < 0) goto bad;
161
+ if (__Pyx_ImportFunction_3_1_4(module, "lookupNamespaceElementClass", (void (**)(void))&__pyx_api_f_4lxml_5etree_lookupNamespaceElementClass, "PyObject *(PyObject *, PyObject *, xmlNode *)") < 0) goto bad;
162
+ if (__Pyx_ImportFunction_3_1_4(module, "callLookupFallback", (void (**)(void))&__pyx_api_f_4lxml_5etree_callLookupFallback, "PyObject *(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *)") < 0) goto bad;
163
+ if (__Pyx_ImportFunction_3_1_4(module, "tagMatches", (void (**)(void))&__pyx_api_f_4lxml_5etree_tagMatches, "int (xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad;
164
+ if (__Pyx_ImportFunction_3_1_4(module, "documentOrRaise", (void (**)(void))&__pyx_api_f_4lxml_5etree_documentOrRaise, "struct LxmlDocument *(PyObject *)") < 0) goto bad;
165
+ if (__Pyx_ImportFunction_3_1_4(module, "rootNodeOrRaise", (void (**)(void))&__pyx_api_f_4lxml_5etree_rootNodeOrRaise, "struct LxmlElement *(PyObject *)") < 0) goto bad;
166
+ if (__Pyx_ImportFunction_3_1_4(module, "hasText", (void (**)(void))&__pyx_api_f_4lxml_5etree_hasText, "int (xmlNode *)") < 0) goto bad;
167
+ if (__Pyx_ImportFunction_3_1_4(module, "hasTail", (void (**)(void))&__pyx_api_f_4lxml_5etree_hasTail, "int (xmlNode *)") < 0) goto bad;
168
+ if (__Pyx_ImportFunction_3_1_4(module, "textOf", (void (**)(void))&__pyx_api_f_4lxml_5etree_textOf, "PyObject *(xmlNode *)") < 0) goto bad;
169
+ if (__Pyx_ImportFunction_3_1_4(module, "tailOf", (void (**)(void))&__pyx_api_f_4lxml_5etree_tailOf, "PyObject *(xmlNode *)") < 0) goto bad;
170
+ if (__Pyx_ImportFunction_3_1_4(module, "setNodeText", (void (**)(void))&__pyx_api_f_4lxml_5etree_setNodeText, "int (xmlNode *, PyObject *)") < 0) goto bad;
171
+ if (__Pyx_ImportFunction_3_1_4(module, "setTailText", (void (**)(void))&__pyx_api_f_4lxml_5etree_setTailText, "int (xmlNode *, PyObject *)") < 0) goto bad;
172
+ if (__Pyx_ImportFunction_3_1_4(module, "attributeValue", (void (**)(void))&__pyx_api_f_4lxml_5etree_attributeValue, "PyObject *(xmlNode *, xmlAttr *)") < 0) goto bad;
173
+ if (__Pyx_ImportFunction_3_1_4(module, "attributeValueFromNsName", (void (**)(void))&__pyx_api_f_4lxml_5etree_attributeValueFromNsName, "PyObject *(xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad;
174
+ if (__Pyx_ImportFunction_3_1_4(module, "getAttributeValue", (void (**)(void))&__pyx_api_f_4lxml_5etree_getAttributeValue, "PyObject *(struct LxmlElement *, PyObject *, PyObject *)") < 0) goto bad;
175
+ if (__Pyx_ImportFunction_3_1_4(module, "iterattributes", (void (**)(void))&__pyx_api_f_4lxml_5etree_iterattributes, "PyObject *(struct LxmlElement *, int)") < 0) goto bad;
176
+ if (__Pyx_ImportFunction_3_1_4(module, "collectAttributes", (void (**)(void))&__pyx_api_f_4lxml_5etree_collectAttributes, "PyObject *(xmlNode *, int)") < 0) goto bad;
177
+ if (__Pyx_ImportFunction_3_1_4(module, "setAttributeValue", (void (**)(void))&__pyx_api_f_4lxml_5etree_setAttributeValue, "int (struct LxmlElement *, PyObject *, PyObject *)") < 0) goto bad;
178
+ if (__Pyx_ImportFunction_3_1_4(module, "delAttribute", (void (**)(void))&__pyx_api_f_4lxml_5etree_delAttribute, "int (struct LxmlElement *, PyObject *)") < 0) goto bad;
179
+ if (__Pyx_ImportFunction_3_1_4(module, "delAttributeFromNsName", (void (**)(void))&__pyx_api_f_4lxml_5etree_delAttributeFromNsName, "int (xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad;
180
+ if (__Pyx_ImportFunction_3_1_4(module, "hasChild", (void (**)(void))&__pyx_api_f_4lxml_5etree_hasChild, "int (xmlNode *)") < 0) goto bad;
181
+ if (__Pyx_ImportFunction_3_1_4(module, "findChild", (void (**)(void))&__pyx_api_f_4lxml_5etree_findChild, "xmlNode *(xmlNode *, Py_ssize_t)") < 0) goto bad;
182
+ if (__Pyx_ImportFunction_3_1_4(module, "findChildForwards", (void (**)(void))&__pyx_api_f_4lxml_5etree_findChildForwards, "xmlNode *(xmlNode *, Py_ssize_t)") < 0) goto bad;
183
+ if (__Pyx_ImportFunction_3_1_4(module, "findChildBackwards", (void (**)(void))&__pyx_api_f_4lxml_5etree_findChildBackwards, "xmlNode *(xmlNode *, Py_ssize_t)") < 0) goto bad;
184
+ if (__Pyx_ImportFunction_3_1_4(module, "nextElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_nextElement, "xmlNode *(xmlNode *)") < 0) goto bad;
185
+ if (__Pyx_ImportFunction_3_1_4(module, "previousElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_previousElement, "xmlNode *(xmlNode *)") < 0) goto bad;
186
+ if (__Pyx_ImportFunction_3_1_4(module, "appendChild", (void (**)(void))&__pyx_api_f_4lxml_5etree_appendChild, "void (struct LxmlElement *, struct LxmlElement *)") < 0) goto bad;
187
+ if (__Pyx_ImportFunction_3_1_4(module, "appendChildToElement", (void (**)(void))&__pyx_api_f_4lxml_5etree_appendChildToElement, "int (struct LxmlElement *, struct LxmlElement *)") < 0) goto bad;
188
+ if (__Pyx_ImportFunction_3_1_4(module, "pyunicode", (void (**)(void))&__pyx_api_f_4lxml_5etree_pyunicode, "PyObject *(const xmlChar *)") < 0) goto bad;
189
+ if (__Pyx_ImportFunction_3_1_4(module, "utf8", (void (**)(void))&__pyx_api_f_4lxml_5etree_utf8, "PyObject *(PyObject *)") < 0) goto bad;
190
+ if (__Pyx_ImportFunction_3_1_4(module, "getNsTag", (void (**)(void))&__pyx_api_f_4lxml_5etree_getNsTag, "PyObject *(PyObject *)") < 0) goto bad;
191
+ if (__Pyx_ImportFunction_3_1_4(module, "getNsTagWithEmptyNs", (void (**)(void))&__pyx_api_f_4lxml_5etree_getNsTagWithEmptyNs, "PyObject *(PyObject *)") < 0) goto bad;
192
+ if (__Pyx_ImportFunction_3_1_4(module, "namespacedName", (void (**)(void))&__pyx_api_f_4lxml_5etree_namespacedName, "PyObject *(xmlNode *)") < 0) goto bad;
193
+ if (__Pyx_ImportFunction_3_1_4(module, "namespacedNameFromNsName", (void (**)(void))&__pyx_api_f_4lxml_5etree_namespacedNameFromNsName, "PyObject *(const xmlChar *, const xmlChar *)") < 0) goto bad;
194
+ if (__Pyx_ImportFunction_3_1_4(module, "iteratorStoreNext", (void (**)(void))&__pyx_api_f_4lxml_5etree_iteratorStoreNext, "void (struct LxmlElementIterator *, struct LxmlElement *)") < 0) goto bad;
195
+ if (__Pyx_ImportFunction_3_1_4(module, "initTagMatch", (void (**)(void))&__pyx_api_f_4lxml_5etree_initTagMatch, "void (struct LxmlElementTagMatcher *, PyObject *)") < 0) goto bad;
196
+ if (__Pyx_ImportFunction_3_1_4(module, "findOrBuildNodeNsPrefix", (void (**)(void))&__pyx_api_f_4lxml_5etree_findOrBuildNodeNsPrefix, "xmlNs *(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *)") < 0) goto bad;
197
+ Py_DECREF(module); module = 0;
198
+ return 0;
199
+ bad:
200
+ Py_XDECREF(module);
201
+ return -1;
202
+ }
203
+
204
+ #endif /* !__PYX_HAVE_API__lxml__etree */
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/extensions.pxi ADDED
@@ -0,0 +1,830 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # support for extension functions in XPath and XSLT
2
+
3
+ cdef class XPathError(LxmlError):
4
+ """Base class of all XPath errors.
5
+ """
6
+
7
+ cdef class XPathEvalError(XPathError):
8
+ """Error during XPath evaluation.
9
+ """
10
+
11
+ cdef class XPathFunctionError(XPathEvalError):
12
+ """Internal error looking up an XPath extension function.
13
+ """
14
+
15
+ cdef class XPathResultError(XPathEvalError):
16
+ """Error handling an XPath result.
17
+ """
18
+
19
+
20
+ # forward declarations
21
+
22
+ ctypedef int (*_register_function)(void* ctxt, name_utf, ns_uri_utf)
23
+ cdef class _ExsltRegExp
24
+
25
+ ################################################################################
26
+ # Base class for XSLT and XPath evaluation contexts: functions, namespaces, ...
27
+
28
+ @cython.internal
29
+ cdef class _BaseContext:
30
+ cdef xpath.xmlXPathContext* _xpathCtxt
31
+ cdef _Document _doc
32
+ cdef dict _extensions
33
+ cdef list _namespaces
34
+ cdef list _global_namespaces
35
+ cdef dict _utf_refs
36
+ cdef dict _function_cache
37
+ cdef dict _eval_context_dict
38
+ cdef bint _build_smart_strings
39
+ # for exception handling and temporary reference keeping:
40
+ cdef _TempStore _temp_refs
41
+ cdef set _temp_documents
42
+ cdef _ExceptionContext _exc
43
+ cdef _ErrorLog _error_log
44
+
45
+ def __init__(self, namespaces, extensions, error_log, enable_regexp,
46
+ build_smart_strings):
47
+ cdef _ExsltRegExp _regexp
48
+ cdef dict new_extensions
49
+ cdef list ns
50
+ self._utf_refs = {}
51
+ self._global_namespaces = []
52
+ self._function_cache = {}
53
+ self._eval_context_dict = None
54
+ self._error_log = error_log
55
+
56
+ if extensions is not None:
57
+ # convert extensions to UTF-8
58
+ if isinstance(extensions, dict):
59
+ extensions = (extensions,)
60
+ # format: [ {(ns, name):function} ] -> {(ns_utf, name_utf):function}
61
+ new_extensions = {}
62
+ for extension in extensions:
63
+ for (ns_uri, name), function in extension.items():
64
+ if name is None:
65
+ raise ValueError, "extensions must have non empty names"
66
+ ns_utf = self._to_utf(ns_uri)
67
+ name_utf = self._to_utf(name)
68
+ new_extensions[(ns_utf, name_utf)] = function
69
+ extensions = new_extensions or None
70
+
71
+ if namespaces is not None:
72
+ if isinstance(namespaces, dict):
73
+ namespaces = namespaces.items()
74
+ if namespaces:
75
+ ns = []
76
+ for prefix, ns_uri in namespaces:
77
+ if prefix is None or not prefix:
78
+ raise TypeError, \
79
+ "empty namespace prefix is not supported in XPath"
80
+ if ns_uri is None or not ns_uri:
81
+ raise TypeError, \
82
+ "setting default namespace is not supported in XPath"
83
+ prefix_utf = self._to_utf(prefix)
84
+ ns_uri_utf = self._to_utf(ns_uri)
85
+ ns.append( (prefix_utf, ns_uri_utf) )
86
+ namespaces = ns
87
+ else:
88
+ namespaces = None
89
+
90
+ self._doc = None
91
+ self._exc = _ExceptionContext()
92
+ self._extensions = extensions
93
+ self._namespaces = namespaces
94
+ self._temp_refs = _TempStore()
95
+ self._temp_documents = set()
96
+ self._build_smart_strings = build_smart_strings
97
+
98
+ if enable_regexp:
99
+ _regexp = _ExsltRegExp()
100
+ _regexp._register_in_context(self)
101
+
102
+ cdef _BaseContext _copy(self):
103
+ cdef _BaseContext context
104
+ if self._namespaces is not None:
105
+ namespaces = self._namespaces[:]
106
+ else:
107
+ namespaces = None
108
+ context = self.__class__(namespaces, None, self._error_log, False,
109
+ self._build_smart_strings)
110
+ if self._extensions is not None:
111
+ context._extensions = self._extensions.copy()
112
+ return context
113
+
114
+ cdef bytes _to_utf(self, s):
115
+ "Convert to UTF-8 and keep a reference to the encoded string"
116
+ cdef python.PyObject* dict_result
117
+ if s is None:
118
+ return None
119
+ dict_result = python.PyDict_GetItem(self._utf_refs, s)
120
+ if dict_result is not NULL:
121
+ return <bytes>dict_result
122
+ utf = _utf8(s)
123
+ self._utf_refs[s] = utf
124
+ if python.IS_PYPY:
125
+ # use C level refs, PyPy refs are not enough!
126
+ python.Py_INCREF(utf)
127
+ return utf
128
+
129
+ cdef void _set_xpath_context(self, xpath.xmlXPathContext* xpathCtxt) noexcept:
130
+ self._xpathCtxt = xpathCtxt
131
+ xpathCtxt.userData = <void*>self
132
+ # Need a cast here because older libxml2 releases do not use 'const' in the functype.
133
+ xpathCtxt.error = <xmlerror.xmlStructuredErrorFunc> _receiveXPathError
134
+
135
+ @cython.final
136
+ cdef _register_context(self, _Document doc):
137
+ self._doc = doc
138
+ self._exc.clear()
139
+
140
+ @cython.final
141
+ cdef _cleanup_context(self):
142
+ #xpath.xmlXPathRegisteredNsCleanup(self._xpathCtxt)
143
+ #self.unregisterGlobalNamespaces()
144
+ if python.IS_PYPY:
145
+ # clean up double refs in PyPy (see "_to_utf()" method)
146
+ for ref in self._utf_refs.itervalues():
147
+ python.Py_DECREF(ref)
148
+ self._utf_refs.clear()
149
+ self._eval_context_dict = None
150
+ self._doc = None
151
+
152
+ @cython.final
153
+ cdef _release_context(self):
154
+ if self._xpathCtxt is not NULL:
155
+ self._xpathCtxt.userData = NULL
156
+ self._xpathCtxt = NULL
157
+
158
+ # namespaces (internal UTF-8 methods with leading '_')
159
+
160
+ cdef addNamespace(self, prefix, ns_uri):
161
+ cdef list namespaces
162
+ if prefix is None:
163
+ raise TypeError, "empty prefix is not supported in XPath"
164
+ prefix_utf = self._to_utf(prefix)
165
+ ns_uri_utf = self._to_utf(ns_uri)
166
+ new_item = (prefix_utf, ns_uri_utf)
167
+ if self._namespaces is None:
168
+ self._namespaces = [new_item]
169
+ else:
170
+ namespaces = []
171
+ for item in self._namespaces:
172
+ if item[0] == prefix_utf:
173
+ item = new_item
174
+ new_item = None
175
+ namespaces.append(item)
176
+ if new_item is not None:
177
+ namespaces.append(new_item)
178
+ self._namespaces = namespaces
179
+ if self._xpathCtxt is not NULL:
180
+ xpath.xmlXPathRegisterNs(
181
+ self._xpathCtxt, _xcstr(prefix_utf), _xcstr(ns_uri_utf))
182
+
183
+ cdef registerNamespace(self, prefix, ns_uri):
184
+ if prefix is None:
185
+ raise TypeError, "empty prefix is not supported in XPath"
186
+ prefix_utf = self._to_utf(prefix)
187
+ ns_uri_utf = self._to_utf(ns_uri)
188
+ self._global_namespaces.append(prefix_utf)
189
+ xpath.xmlXPathRegisterNs(self._xpathCtxt,
190
+ _xcstr(prefix_utf), _xcstr(ns_uri_utf))
191
+
192
+ cdef registerLocalNamespaces(self):
193
+ if self._namespaces is None:
194
+ return
195
+ for prefix_utf, ns_uri_utf in self._namespaces:
196
+ xpath.xmlXPathRegisterNs(
197
+ self._xpathCtxt, _xcstr(prefix_utf), _xcstr(ns_uri_utf))
198
+
199
+ cdef registerGlobalNamespaces(self):
200
+ cdef list ns_prefixes = _find_all_extension_prefixes()
201
+ if python.PyList_GET_SIZE(ns_prefixes) > 0:
202
+ for prefix_utf, ns_uri_utf in ns_prefixes:
203
+ self._global_namespaces.append(prefix_utf)
204
+ xpath.xmlXPathRegisterNs(
205
+ self._xpathCtxt, _xcstr(prefix_utf), _xcstr(ns_uri_utf))
206
+
207
+ cdef unregisterGlobalNamespaces(self):
208
+ if python.PyList_GET_SIZE(self._global_namespaces) > 0:
209
+ for prefix_utf in self._global_namespaces:
210
+ xpath.xmlXPathRegisterNs(self._xpathCtxt,
211
+ _xcstr(prefix_utf), NULL)
212
+ del self._global_namespaces[:]
213
+
214
+ cdef void _unregisterNamespace(self, prefix_utf) noexcept:
215
+ xpath.xmlXPathRegisterNs(self._xpathCtxt,
216
+ _xcstr(prefix_utf), NULL)
217
+
218
+ # extension functions
219
+
220
+ cdef int _addLocalExtensionFunction(self, ns_utf, name_utf, function) except -1:
221
+ if self._extensions is None:
222
+ self._extensions = {}
223
+ self._extensions[(ns_utf, name_utf)] = function
224
+ return 0
225
+
226
+ cdef registerGlobalFunctions(self, void* ctxt,
227
+ _register_function reg_func):
228
+ cdef python.PyObject* dict_result
229
+ cdef dict d
230
+ for ns_utf, ns_functions in __FUNCTION_NAMESPACE_REGISTRIES.iteritems():
231
+ dict_result = python.PyDict_GetItem(
232
+ self._function_cache, ns_utf)
233
+ if dict_result is not NULL:
234
+ d = <dict>dict_result
235
+ else:
236
+ d = {}
237
+ self._function_cache[ns_utf] = d
238
+ for name_utf, function in ns_functions.iteritems():
239
+ d[name_utf] = function
240
+ reg_func(ctxt, name_utf, ns_utf)
241
+
242
+ cdef registerLocalFunctions(self, void* ctxt,
243
+ _register_function reg_func):
244
+ cdef python.PyObject* dict_result
245
+ cdef dict d
246
+ if self._extensions is None:
247
+ return # done
248
+ last_ns = None
249
+ d = None
250
+ for (ns_utf, name_utf), function in self._extensions.iteritems():
251
+ if ns_utf is not last_ns or d is None:
252
+ last_ns = ns_utf
253
+ dict_result = python.PyDict_GetItem(
254
+ self._function_cache, ns_utf)
255
+ if dict_result is not NULL:
256
+ d = <dict>dict_result
257
+ else:
258
+ d = {}
259
+ self._function_cache[ns_utf] = d
260
+ d[name_utf] = function
261
+ reg_func(ctxt, name_utf, ns_utf)
262
+
263
+ cdef unregisterAllFunctions(self, void* ctxt,
264
+ _register_function unreg_func):
265
+ for ns_utf, functions in self._function_cache.iteritems():
266
+ for name_utf in functions:
267
+ unreg_func(ctxt, name_utf, ns_utf)
268
+
269
+ cdef unregisterGlobalFunctions(self, void* ctxt,
270
+ _register_function unreg_func):
271
+ for ns_utf, functions in self._function_cache.items():
272
+ for name_utf in functions:
273
+ if self._extensions is None or \
274
+ (ns_utf, name_utf) not in self._extensions:
275
+ unreg_func(ctxt, name_utf, ns_utf)
276
+
277
+ @cython.final
278
+ cdef _find_cached_function(self, const_xmlChar* c_ns_uri, const_xmlChar* c_name):
279
+ """Lookup an extension function in the cache and return it.
280
+
281
+ Parameters: c_ns_uri may be NULL, c_name must not be NULL
282
+ """
283
+ cdef python.PyObject* c_dict
284
+ cdef python.PyObject* dict_result
285
+ c_dict = python.PyDict_GetItem(
286
+ self._function_cache, None if c_ns_uri is NULL else c_ns_uri)
287
+ if c_dict is not NULL:
288
+ dict_result = python.PyDict_GetItem(
289
+ <object>c_dict, <unsigned char*>c_name)
290
+ if dict_result is not NULL:
291
+ return <object>dict_result
292
+ return None
293
+
294
+ # Python access to the XPath context for extension functions
295
+
296
+ @property
297
+ def context_node(self):
298
+ cdef xmlNode* c_node
299
+ if self._xpathCtxt is NULL:
300
+ raise XPathError, \
301
+ "XPath context is only usable during the evaluation"
302
+ c_node = self._xpathCtxt.node
303
+ if c_node is NULL:
304
+ raise XPathError, "no context node"
305
+ if c_node.doc != self._xpathCtxt.doc:
306
+ raise XPathError, \
307
+ "document-external context nodes are not supported"
308
+ if self._doc is None:
309
+ raise XPathError, "document context is missing"
310
+ return _elementFactory(self._doc, c_node)
311
+
312
+ @property
313
+ def eval_context(self):
314
+ if self._eval_context_dict is None:
315
+ self._eval_context_dict = {}
316
+ return self._eval_context_dict
317
+
318
+ # Python reference keeping during XPath function evaluation
319
+
320
+ @cython.final
321
+ cdef _release_temp_refs(self):
322
+ "Free temporarily referenced objects from this context."
323
+ self._temp_refs.clear()
324
+ self._temp_documents.clear()
325
+
326
+ @cython.final
327
+ cdef _hold(self, obj):
328
+ """A way to temporarily hold references to nodes in the evaluator.
329
+
330
+ This is needed because otherwise nodes created in XPath extension
331
+ functions would be reference counted too soon, during the XPath
332
+ evaluation. This is most important in the case of exceptions.
333
+ """
334
+ cdef _Element element
335
+ if isinstance(obj, _Element):
336
+ self._temp_refs.add(obj)
337
+ self._temp_documents.add((<_Element>obj)._doc)
338
+ return
339
+ elif _isString(obj) or not python.PySequence_Check(obj):
340
+ return
341
+ for o in obj:
342
+ if isinstance(o, _Element):
343
+ #print "Holding element:", <int>element._c_node
344
+ self._temp_refs.add(o)
345
+ #print "Holding document:", <int>element._doc._c_doc
346
+ self._temp_documents.add((<_Element>o)._doc)
347
+
348
+ @cython.final
349
+ cdef _Document _findDocumentForNode(self, xmlNode* c_node):
350
+ """If an XPath expression returns an element from a different
351
+ document than the current context document, we call this to
352
+ see if it was possibly created by an extension and is a known
353
+ document instance.
354
+ """
355
+ cdef _Document doc
356
+ for doc in self._temp_documents:
357
+ if doc is not None and doc._c_doc is c_node.doc:
358
+ return doc
359
+ return None
360
+
361
+
362
+ # libxml2 keeps these error messages in a static array in its code
363
+ # and doesn't give us access to them ...
364
+
365
+ cdef tuple LIBXML2_XPATH_ERROR_MESSAGES = (
366
+ b"Ok",
367
+ b"Number encoding",
368
+ b"Unfinished literal",
369
+ b"Start of literal",
370
+ b"Expected $ for variable reference",
371
+ b"Undefined variable",
372
+ b"Invalid predicate",
373
+ b"Invalid expression",
374
+ b"Missing closing curly brace",
375
+ b"Unregistered function",
376
+ b"Invalid operand",
377
+ b"Invalid type",
378
+ b"Invalid number of arguments",
379
+ b"Invalid context size",
380
+ b"Invalid context position",
381
+ b"Memory allocation error",
382
+ b"Syntax error",
383
+ b"Resource error",
384
+ b"Sub resource error",
385
+ b"Undefined namespace prefix",
386
+ b"Encoding error",
387
+ b"Char out of XML range",
388
+ b"Invalid or incomplete context",
389
+ b"Stack usage error",
390
+ b"Forbidden variable\n",
391
+ b"?? Unknown error ??\n",
392
+ )
393
+
394
+ cdef void _forwardXPathError(void* c_ctxt, const xmlerror.xmlError* c_error) noexcept with gil:
395
+ cdef xmlerror.xmlError error
396
+ cdef int xpath_code
397
+ if c_error.message is not NULL:
398
+ error.message = c_error.message
399
+ else:
400
+ xpath_code = c_error.code - xmlerror.XML_XPATH_EXPRESSION_OK
401
+ if 0 <= xpath_code < len(LIBXML2_XPATH_ERROR_MESSAGES):
402
+ error.message = _cstr(LIBXML2_XPATH_ERROR_MESSAGES[xpath_code])
403
+ else:
404
+ error.message = b"unknown error"
405
+ error.domain = c_error.domain
406
+ error.code = c_error.code
407
+ error.level = c_error.level
408
+ error.line = c_error.line
409
+ error.int2 = c_error.int1 # column
410
+ error.file = c_error.file
411
+ error.node = NULL
412
+
413
+ (<_BaseContext>c_ctxt)._error_log._receive(&error)
414
+
415
+ cdef void _receiveXPathError(void* c_context, const xmlerror.xmlError* error) noexcept nogil:
416
+ if not __DEBUG:
417
+ return
418
+ if c_context is NULL:
419
+ _forwardError(NULL, error)
420
+ else:
421
+ _forwardXPathError(c_context, error)
422
+
423
+
424
+ def Extension(module, function_mapping=None, *, ns=None):
425
+ """Extension(module, function_mapping=None, ns=None)
426
+
427
+ Build a dictionary of extension functions from the functions
428
+ defined in a module or the methods of an object.
429
+
430
+ As second argument, you can pass an additional mapping of
431
+ attribute names to XPath function names, or a list of function
432
+ names that should be taken.
433
+
434
+ The ``ns`` keyword argument accepts a namespace URI for the XPath
435
+ functions.
436
+ """
437
+ cdef dict functions = {}
438
+ if isinstance(function_mapping, dict):
439
+ for function_name, xpath_name in function_mapping.items():
440
+ functions[(ns, xpath_name)] = getattr(module, function_name)
441
+ else:
442
+ if function_mapping is None:
443
+ function_mapping = [ name for name in dir(module)
444
+ if not name.startswith('_') ]
445
+ for function_name in function_mapping:
446
+ functions[(ns, function_name)] = getattr(module, function_name)
447
+ return functions
448
+
449
+ ################################################################################
450
+ # EXSLT regexp implementation
451
+
452
+ @cython.final
453
+ @cython.internal
454
+ cdef class _ExsltRegExp:
455
+ cdef dict _compile_map
456
+ def __cinit__(self):
457
+ self._compile_map = {}
458
+
459
+ cdef _make_string(self, value):
460
+ if _isString(value):
461
+ return value
462
+ elif isinstance(value, list):
463
+ # node set: take recursive text concatenation of first element
464
+ if python.PyList_GET_SIZE(value) == 0:
465
+ return ''
466
+ firstnode = value[0]
467
+ if _isString(firstnode):
468
+ return firstnode
469
+ elif isinstance(firstnode, _Element):
470
+ c_text = tree.xmlNodeGetContent((<_Element>firstnode)._c_node)
471
+ if c_text is NULL:
472
+ raise MemoryError()
473
+ try:
474
+ return funicode(c_text)
475
+ finally:
476
+ tree.xmlFree(c_text)
477
+ else:
478
+ return unicode(firstnode)
479
+ else:
480
+ return unicode(value)
481
+
482
+ cdef _compile(self, rexp, ignore_case):
483
+ cdef python.PyObject* c_result
484
+ rexp = self._make_string(rexp)
485
+ key = (rexp, ignore_case)
486
+ c_result = python.PyDict_GetItem(self._compile_map, key)
487
+ if c_result is not NULL:
488
+ return <object>c_result
489
+ py_flags = re.UNICODE
490
+ if ignore_case:
491
+ py_flags = py_flags | re.IGNORECASE
492
+ rexp_compiled = re.compile(rexp, py_flags)
493
+ self._compile_map[key] = rexp_compiled
494
+ return rexp_compiled
495
+
496
+ def test(self, ctxt, s, rexp, flags=''):
497
+ flags = self._make_string(flags)
498
+ s = self._make_string(s)
499
+ rexpc = self._compile(rexp, 'i' in flags)
500
+ if rexpc.search(s) is None:
501
+ return False
502
+ else:
503
+ return True
504
+
505
+ def match(self, ctxt, s, rexp, flags=''):
506
+ cdef list result_list
507
+ flags = self._make_string(flags)
508
+ s = self._make_string(s)
509
+ rexpc = self._compile(rexp, 'i' in flags)
510
+ if 'g' in flags:
511
+ results = rexpc.findall(s)
512
+ if not results:
513
+ return ()
514
+ else:
515
+ result = rexpc.search(s)
516
+ if not result:
517
+ return ()
518
+ results = [ result.group() ]
519
+ results.extend( result.groups('') )
520
+ result_list = []
521
+ root = Element('matches')
522
+ for s_match in results:
523
+ if python.PyTuple_CheckExact(s_match):
524
+ s_match = ''.join(s_match)
525
+ elem = SubElement(root, 'match')
526
+ elem.text = s_match
527
+ result_list.append(elem)
528
+ return result_list
529
+
530
+ def replace(self, ctxt, s, rexp, flags, replacement):
531
+ replacement = self._make_string(replacement)
532
+ flags = self._make_string(flags)
533
+ s = self._make_string(s)
534
+ rexpc = self._compile(rexp, 'i' in flags)
535
+ count: object = 0 if 'g' in flags else 1
536
+ return rexpc.sub(replacement, s, count)
537
+
538
+ cdef _register_in_context(self, _BaseContext context):
539
+ ns = b"http://exslt.org/regular-expressions"
540
+ context._addLocalExtensionFunction(ns, b"test", self.test)
541
+ context._addLocalExtensionFunction(ns, b"match", self.match)
542
+ context._addLocalExtensionFunction(ns, b"replace", self.replace)
543
+
544
+
545
+ ################################################################################
546
+ # helper functions
547
+
548
+ cdef xpath.xmlXPathObject* _wrapXPathObject(object obj, _Document doc,
549
+ _BaseContext context) except NULL:
550
+ cdef xpath.xmlNodeSet* resultSet
551
+ cdef _Element fake_node = None
552
+ cdef xmlNode* c_node
553
+
554
+ if isinstance(obj, unicode):
555
+ obj = _utf8(obj)
556
+ if isinstance(obj, bytes):
557
+ # libxml2 copies the string value
558
+ return xpath.xmlXPathNewCString(_cstr(obj))
559
+ if isinstance(obj, bool):
560
+ return xpath.xmlXPathNewBoolean(obj)
561
+ if python.PyNumber_Check(obj):
562
+ return xpath.xmlXPathNewFloat(obj)
563
+ if obj is None:
564
+ resultSet = xpath.xmlXPathNodeSetCreate(NULL)
565
+ elif isinstance(obj, _Element):
566
+ resultSet = xpath.xmlXPathNodeSetCreate((<_Element>obj)._c_node)
567
+ elif python.PySequence_Check(obj):
568
+ resultSet = xpath.xmlXPathNodeSetCreate(NULL)
569
+ try:
570
+ for value in obj:
571
+ if isinstance(value, _Element):
572
+ if context is not None:
573
+ context._hold(value)
574
+ xpath.xmlXPathNodeSetAdd(resultSet, (<_Element>value)._c_node)
575
+ else:
576
+ if context is None or doc is None:
577
+ raise XPathResultError, \
578
+ f"Non-Element values not supported at this point - got {value!r}"
579
+ # support strings by appending text nodes to an Element
580
+ if isinstance(value, unicode):
581
+ value = _utf8(value)
582
+ if isinstance(value, bytes):
583
+ if fake_node is None:
584
+ fake_node = _makeElement("text-root", NULL, doc, None,
585
+ None, None, None, None, None)
586
+ context._hold(fake_node)
587
+ else:
588
+ # append a comment node to keep the text nodes separate
589
+ c_node = tree.xmlNewDocComment(doc._c_doc, <unsigned char*>"")
590
+ if c_node is NULL:
591
+ raise MemoryError()
592
+ tree.xmlAddChild(fake_node._c_node, c_node)
593
+ context._hold(value)
594
+ c_node = tree.xmlNewDocText(doc._c_doc, _xcstr(value))
595
+ if c_node is NULL:
596
+ raise MemoryError()
597
+ tree.xmlAddChild(fake_node._c_node, c_node)
598
+ xpath.xmlXPathNodeSetAdd(resultSet, c_node)
599
+ else:
600
+ raise XPathResultError, \
601
+ f"This is not a supported node-set result: {value!r}"
602
+ except:
603
+ xpath.xmlXPathFreeNodeSet(resultSet)
604
+ raise
605
+ else:
606
+ raise XPathResultError, f"Unknown return type: {python._fqtypename(obj).decode('utf8')}"
607
+ return xpath.xmlXPathWrapNodeSet(resultSet)
608
+
609
+ cdef object _unwrapXPathObject(xpath.xmlXPathObject* xpathObj,
610
+ _Document doc, _BaseContext context):
611
+ if xpathObj.type == xpath.XPATH_UNDEFINED:
612
+ raise XPathResultError, "Undefined xpath result"
613
+ elif xpathObj.type == xpath.XPATH_NODESET:
614
+ return _createNodeSetResult(xpathObj, doc, context)
615
+ elif xpathObj.type == xpath.XPATH_BOOLEAN:
616
+ return xpathObj.boolval
617
+ elif xpathObj.type == xpath.XPATH_NUMBER:
618
+ return xpathObj.floatval
619
+ elif xpathObj.type == xpath.XPATH_STRING:
620
+ stringval = funicode(xpathObj.stringval)
621
+ if context._build_smart_strings:
622
+ stringval = _elementStringResultFactory(
623
+ stringval, None, None, False)
624
+ return stringval
625
+ elif xpathObj.type == xpath.XPATH_POINT:
626
+ raise NotImplementedError, "XPATH_POINT"
627
+ elif xpathObj.type == xpath.XPATH_RANGE:
628
+ raise NotImplementedError, "XPATH_RANGE"
629
+ elif xpathObj.type == xpath.XPATH_LOCATIONSET:
630
+ raise NotImplementedError, "XPATH_LOCATIONSET"
631
+ elif xpathObj.type == xpath.XPATH_USERS:
632
+ raise NotImplementedError, "XPATH_USERS"
633
+ elif xpathObj.type == xpath.XPATH_XSLT_TREE:
634
+ return _createNodeSetResult(xpathObj, doc, context)
635
+ else:
636
+ raise XPathResultError, f"Unknown xpath result {xpathObj.type}"
637
+
638
+ cdef object _createNodeSetResult(xpath.xmlXPathObject* xpathObj, _Document doc,
639
+ _BaseContext context):
640
+ cdef xmlNode* c_node
641
+ cdef int i
642
+ cdef list result
643
+ result = []
644
+ if xpathObj.nodesetval is NULL:
645
+ return result
646
+ for i in range(xpathObj.nodesetval.nodeNr):
647
+ c_node = xpathObj.nodesetval.nodeTab[i]
648
+ _unpackNodeSetEntry(result, c_node, doc, context,
649
+ xpathObj.type == xpath.XPATH_XSLT_TREE)
650
+ return result
651
+
652
+ cdef _unpackNodeSetEntry(list results, xmlNode* c_node, _Document doc,
653
+ _BaseContext context, bint is_fragment):
654
+ cdef xmlNode* c_child
655
+ if _isElement(c_node):
656
+ if c_node.doc != doc._c_doc and c_node.doc._private is NULL:
657
+ # XXX: works, but maybe not always the right thing to do?
658
+ # XPath: only runs when extensions create or copy trees
659
+ # -> we store Python refs to these, so that is OK
660
+ # XSLT: can it leak when merging trees from multiple sources?
661
+ c_node = tree.xmlDocCopyNode(c_node, doc._c_doc, 1)
662
+ # FIXME: call _instantiateElementFromXPath() instead?
663
+ results.append(
664
+ _fakeDocElementFactory(doc, c_node))
665
+ elif c_node.type == tree.XML_TEXT_NODE or \
666
+ c_node.type == tree.XML_CDATA_SECTION_NODE or \
667
+ c_node.type == tree.XML_ATTRIBUTE_NODE:
668
+ results.append(
669
+ _buildElementStringResult(doc, c_node, context))
670
+ elif c_node.type == tree.XML_NAMESPACE_DECL:
671
+ results.append( (funicodeOrNone((<xmlNs*>c_node).prefix),
672
+ funicodeOrNone((<xmlNs*>c_node).href)) )
673
+ elif c_node.type == tree.XML_DOCUMENT_NODE or \
674
+ c_node.type == tree.XML_HTML_DOCUMENT_NODE:
675
+ # ignored for everything but result tree fragments
676
+ if is_fragment:
677
+ c_child = c_node.children
678
+ while c_child is not NULL:
679
+ _unpackNodeSetEntry(results, c_child, doc, context, 0)
680
+ c_child = c_child.next
681
+ elif c_node.type == tree.XML_XINCLUDE_START or \
682
+ c_node.type == tree.XML_XINCLUDE_END:
683
+ pass
684
+ else:
685
+ raise NotImplementedError, \
686
+ f"Not yet implemented result node type: {c_node.type}"
687
+
688
+ cdef void _freeXPathObject(xpath.xmlXPathObject* xpathObj) noexcept:
689
+ """Free the XPath object, but *never* free the *content* of node sets.
690
+ Python dealloc will do that for us.
691
+ """
692
+ if xpathObj.nodesetval is not NULL:
693
+ xpath.xmlXPathFreeNodeSet(xpathObj.nodesetval)
694
+ xpathObj.nodesetval = NULL
695
+ xpath.xmlXPathFreeObject(xpathObj)
696
+
697
+ cdef _Element _instantiateElementFromXPath(xmlNode* c_node, _Document doc,
698
+ _BaseContext context):
699
+ # NOTE: this may copy the element - only call this when it can't leak
700
+ if c_node.doc != doc._c_doc and c_node.doc._private is NULL:
701
+ # not from the context document and not from a fake document
702
+ # either => may still be from a known document, e.g. one
703
+ # created by an extension function
704
+ node_doc = context._findDocumentForNode(c_node)
705
+ if node_doc is None:
706
+ # not from a known document at all! => can only make a
707
+ # safety copy here
708
+ c_node = tree.xmlDocCopyNode(c_node, doc._c_doc, 1)
709
+ else:
710
+ doc = node_doc
711
+ return _fakeDocElementFactory(doc, c_node)
712
+
713
+ ################################################################################
714
+ # special str/unicode subclasses
715
+
716
+ @cython.final
717
+ cdef class _ElementUnicodeResult(unicode):
718
+ cdef _Element _parent
719
+ cdef readonly object attrname
720
+ cdef readonly bint is_tail
721
+
722
+ def getparent(self):
723
+ return self._parent
724
+
725
+ @property
726
+ def is_text(self):
727
+ return self._parent is not None and not (self.is_tail or self.attrname is not None)
728
+
729
+ @property
730
+ def is_attribute(self):
731
+ return self.attrname is not None
732
+
733
+ cdef object _elementStringResultFactory(string_value, _Element parent,
734
+ attrname, bint is_tail):
735
+ result = _ElementUnicodeResult(string_value)
736
+ result._parent = parent
737
+ result.is_tail = is_tail
738
+ result.attrname = attrname
739
+ return result
740
+
741
+ cdef object _buildElementStringResult(_Document doc, xmlNode* c_node,
742
+ _BaseContext context):
743
+ cdef _Element parent = None
744
+ cdef object attrname = None
745
+ cdef xmlNode* c_element
746
+ cdef bint is_tail
747
+
748
+ if c_node.type == tree.XML_ATTRIBUTE_NODE:
749
+ attrname = _namespacedName(c_node)
750
+ is_tail = 0
751
+ s = tree.xmlNodeGetContent(c_node)
752
+ try:
753
+ value = funicode(s)
754
+ finally:
755
+ tree.xmlFree(s)
756
+ c_element = NULL
757
+ else:
758
+ #assert c_node.type == tree.XML_TEXT_NODE or c_node.type == tree.XML_CDATA_SECTION_NODE, "invalid node type"
759
+ # may be tail text or normal text
760
+ value = funicode(c_node.content)
761
+ c_element = _previousElement(c_node)
762
+ is_tail = c_element is not NULL
763
+
764
+ if not context._build_smart_strings:
765
+ return value
766
+
767
+ if c_element is NULL:
768
+ # non-tail text or attribute text
769
+ c_element = c_node.parent
770
+ while c_element is not NULL and not _isElement(c_element):
771
+ c_element = c_element.parent
772
+
773
+ if c_element is not NULL:
774
+ parent = _instantiateElementFromXPath(c_element, doc, context)
775
+
776
+ return _elementStringResultFactory(
777
+ value, parent, attrname, is_tail)
778
+
779
+ ################################################################################
780
+ # callbacks for XPath/XSLT extension functions
781
+
782
+ cdef void _extension_function_call(_BaseContext context, function,
783
+ xpath.xmlXPathParserContext* ctxt, int nargs) noexcept:
784
+ cdef _Document doc
785
+ cdef xpath.xmlXPathObject* obj
786
+ cdef list args
787
+ cdef int i
788
+ doc = context._doc
789
+ try:
790
+ args = []
791
+ for i in range(nargs):
792
+ obj = xpath.valuePop(ctxt)
793
+ o = _unwrapXPathObject(obj, doc, context)
794
+ _freeXPathObject(obj)
795
+ args.append(o)
796
+ args.reverse()
797
+
798
+ res = function(context, *args)
799
+ # wrap result for XPath consumption
800
+ obj = _wrapXPathObject(res, doc, context)
801
+ # prevent Python from deallocating elements handed to libxml2
802
+ context._hold(res)
803
+ xpath.valuePush(ctxt, obj)
804
+ except:
805
+ xpath.xmlXPathErr(ctxt, xpath.XPATH_EXPR_ERROR)
806
+ context._exc._store_raised()
807
+ finally:
808
+ return # swallow any further exceptions
809
+
810
+ # lookup the function by name and call it
811
+
812
+ cdef void _xpath_function_call(xpath.xmlXPathParserContext* ctxt,
813
+ int nargs) noexcept with gil:
814
+ cdef _BaseContext context
815
+ cdef xpath.xmlXPathContext* rctxt = ctxt.context
816
+ context = <_BaseContext> rctxt.userData
817
+ try:
818
+ function = context._find_cached_function(rctxt.functionURI, rctxt.function)
819
+ if function is not None:
820
+ _extension_function_call(context, function, ctxt, nargs)
821
+ else:
822
+ xpath.xmlXPathErr(ctxt, xpath.XPATH_UNKNOWN_FUNC_ERROR)
823
+ context._exc._store_exception(XPathFunctionError(
824
+ f"XPath function '{_namespacedNameFromNsName(rctxt.functionURI, rctxt.function)}' not found"))
825
+ except:
826
+ # may not be the right error, but we need to tell libxml2 *something*
827
+ xpath.xmlXPathErr(ctxt, xpath.XPATH_UNKNOWN_FUNC_ERROR)
828
+ context._exc._store_raised()
829
+ finally:
830
+ return # swallow any further exceptions
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/lxml.etree.h ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Generated by Cython 3.1.4 */
2
+
3
+ #ifndef __PYX_HAVE__lxml__etree
4
+ #define __PYX_HAVE__lxml__etree
5
+
6
+ #include "Python.h"
7
+ struct LxmlDocument;
8
+ struct LxmlElement;
9
+ struct LxmlElementTree;
10
+ struct LxmlElementTagMatcher;
11
+ struct LxmlElementIterator;
12
+ struct LxmlElementBase;
13
+ struct LxmlElementClassLookup;
14
+ struct LxmlFallbackElementClassLookup;
15
+
16
+ /* "lxml/etree.pyx":451
17
+ *
18
+ * # type of a function that steps from node to node
19
+ * ctypedef public xmlNode* (*_node_to_node_function)(xmlNode*) # <<<<<<<<<<<<<<
20
+ *
21
+ *
22
+ */
23
+ typedef xmlNode *(*_node_to_node_function)(xmlNode *);
24
+
25
+ /* "lxml/etree.pyx":465
26
+ * # Public Python API
27
+ *
28
+ * @cython.final # <<<<<<<<<<<<<<
29
+ * @cython.freelist(8)
30
+ * cdef public class _Document [ type LxmlDocumentType, object LxmlDocument ]:
31
+ */
32
+ struct LxmlDocument {
33
+ PyObject_HEAD
34
+ struct __pyx_vtabstruct_4lxml_5etree__Document *__pyx_vtab;
35
+ int _ns_counter;
36
+ PyObject *_prefix_tail;
37
+ xmlDoc *_c_doc;
38
+ struct __pyx_obj_4lxml_5etree__BaseParser *_parser;
39
+ };
40
+
41
+ /* "lxml/etree.pyx":817
42
+ *
43
+ *
44
+ * @cython.no_gc_clear # <<<<<<<<<<<<<<
45
+ * cdef public class _Element [ type LxmlElementType, object LxmlElement ]:
46
+ * """Element class.
47
+ */
48
+ struct LxmlElement {
49
+ PyObject_HEAD
50
+ struct LxmlDocument *_doc;
51
+ xmlNode *_c_node;
52
+ PyObject *_tag;
53
+ };
54
+
55
+ /* "lxml/etree.pyx":1991
56
+ *
57
+ *
58
+ * cdef public class _ElementTree [ type LxmlElementTreeType, # <<<<<<<<<<<<<<
59
+ * object LxmlElementTree ]:
60
+ * cdef _Document _doc
61
+ */
62
+ struct LxmlElementTree {
63
+ PyObject_HEAD
64
+ struct __pyx_vtabstruct_4lxml_5etree__ElementTree *__pyx_vtab;
65
+ struct LxmlDocument *_doc;
66
+ struct LxmlElement *_context_node;
67
+ };
68
+
69
+ /* "lxml/etree.pyx":2765
70
+ *
71
+ *
72
+ * cdef public class _ElementTagMatcher [ object LxmlElementTagMatcher, # <<<<<<<<<<<<<<
73
+ * type LxmlElementTagMatcherType ]:
74
+ * """
75
+ */
76
+ struct LxmlElementTagMatcher {
77
+ PyObject_HEAD
78
+ struct __pyx_vtabstruct_4lxml_5etree__ElementTagMatcher *__pyx_vtab;
79
+ PyObject *_pystrings;
80
+ int _node_type;
81
+ char *_href;
82
+ char *_name;
83
+ };
84
+
85
+ /* "lxml/etree.pyx":2796
86
+ * self._name = NULL
87
+ *
88
+ * cdef public class _ElementIterator(_ElementTagMatcher) [ # <<<<<<<<<<<<<<
89
+ * object LxmlElementIterator, type LxmlElementIteratorType ]:
90
+ * """
91
+ */
92
+ struct LxmlElementIterator {
93
+ struct LxmlElementTagMatcher __pyx_base;
94
+ struct LxmlElement *_node;
95
+ _node_to_node_function _next_element;
96
+ };
97
+
98
+ /* "src/lxml/classlookup.pxi":6
99
+ * # Custom Element classes
100
+ *
101
+ * cdef public class ElementBase(_Element) [ type LxmlElementBaseType, # <<<<<<<<<<<<<<
102
+ * object LxmlElementBase ]:
103
+ * """ElementBase(*children, attrib=None, nsmap=None, **_extra)
104
+ */
105
+ struct LxmlElementBase {
106
+ struct LxmlElement __pyx_base;
107
+ };
108
+
109
+ /* "src/lxml/classlookup.pxi":210
110
+ * # Element class lookup
111
+ *
112
+ * ctypedef public object (*_element_class_lookup_function)(object, _Document, xmlNode*) # <<<<<<<<<<<<<<
113
+ *
114
+ * # class to store element class lookup functions
115
+ */
116
+ typedef PyObject *(*_element_class_lookup_function)(PyObject *, struct LxmlDocument *, xmlNode *);
117
+
118
+ /* "src/lxml/classlookup.pxi":213
119
+ *
120
+ * # class to store element class lookup functions
121
+ * cdef public class ElementClassLookup [ type LxmlElementClassLookupType, # <<<<<<<<<<<<<<
122
+ * object LxmlElementClassLookup ]:
123
+ * """ElementClassLookup(self)
124
+ */
125
+ struct LxmlElementClassLookup {
126
+ PyObject_HEAD
127
+ _element_class_lookup_function _lookup_function;
128
+ };
129
+
130
+ /* "src/lxml/classlookup.pxi":221
131
+ *
132
+ *
133
+ * cdef public class FallbackElementClassLookup(ElementClassLookup) \ # <<<<<<<<<<<<<<
134
+ * [ type LxmlFallbackElementClassLookupType,
135
+ * object LxmlFallbackElementClassLookup ]:
136
+ */
137
+ struct LxmlFallbackElementClassLookup {
138
+ struct LxmlElementClassLookup __pyx_base;
139
+ struct __pyx_vtabstruct_4lxml_5etree_FallbackElementClassLookup *__pyx_vtab;
140
+ struct LxmlElementClassLookup *fallback;
141
+ _element_class_lookup_function _fallback_function;
142
+ };
143
+
144
+ #ifndef __PYX_HAVE_API__lxml__etree
145
+
146
+ #ifdef CYTHON_EXTERN_C
147
+ #undef __PYX_EXTERN_C
148
+ #define __PYX_EXTERN_C CYTHON_EXTERN_C
149
+ #elif defined(__PYX_EXTERN_C)
150
+ #ifdef _MSC_VER
151
+ #pragma message ("Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.")
152
+ #else
153
+ #warning Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.
154
+ #endif
155
+ #else
156
+ #ifdef __cplusplus
157
+ #define __PYX_EXTERN_C extern "C"
158
+ #else
159
+ #define __PYX_EXTERN_C extern
160
+ #endif
161
+ #endif
162
+
163
+ #ifndef DL_IMPORT
164
+ #define DL_IMPORT(_T) _T
165
+ #endif
166
+
167
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlDocumentType;
168
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementType;
169
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementTreeType;
170
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementTagMatcherType;
171
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementIteratorType;
172
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementBaseType;
173
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlElementClassLookupType;
174
+ __PYX_EXTERN_C DL_IMPORT(PyTypeObject) LxmlFallbackElementClassLookupType;
175
+
176
+ __PYX_EXTERN_C struct LxmlElement *deepcopyNodeToDocument(struct LxmlDocument *, xmlNode *);
177
+ __PYX_EXTERN_C struct LxmlElementTree *elementTreeFactory(struct LxmlElement *);
178
+ __PYX_EXTERN_C struct LxmlElementTree *newElementTree(struct LxmlElement *, PyObject *);
179
+ __PYX_EXTERN_C struct LxmlElementTree *adoptExternalDocument(xmlDoc *, PyObject *, int);
180
+ __PYX_EXTERN_C struct LxmlElement *elementFactory(struct LxmlDocument *, xmlNode *);
181
+ __PYX_EXTERN_C struct LxmlElement *makeElement(PyObject *, struct LxmlDocument *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *);
182
+ __PYX_EXTERN_C struct LxmlElement *makeSubElement(struct LxmlElement *, PyObject *, PyObject *, PyObject *, PyObject *, PyObject *);
183
+ __PYX_EXTERN_C void setElementClassLookupFunction(_element_class_lookup_function, PyObject *);
184
+ __PYX_EXTERN_C PyObject *lookupDefaultElementClass(PyObject *, PyObject *, xmlNode *);
185
+ __PYX_EXTERN_C PyObject *lookupNamespaceElementClass(PyObject *, PyObject *, xmlNode *);
186
+ __PYX_EXTERN_C PyObject *callLookupFallback(struct LxmlFallbackElementClassLookup *, struct LxmlDocument *, xmlNode *);
187
+ __PYX_EXTERN_C int tagMatches(xmlNode *, const xmlChar *, const xmlChar *);
188
+ __PYX_EXTERN_C struct LxmlDocument *documentOrRaise(PyObject *);
189
+ __PYX_EXTERN_C struct LxmlElement *rootNodeOrRaise(PyObject *);
190
+ __PYX_EXTERN_C int hasText(xmlNode *);
191
+ __PYX_EXTERN_C int hasTail(xmlNode *);
192
+ __PYX_EXTERN_C PyObject *textOf(xmlNode *);
193
+ __PYX_EXTERN_C PyObject *tailOf(xmlNode *);
194
+ __PYX_EXTERN_C int setNodeText(xmlNode *, PyObject *);
195
+ __PYX_EXTERN_C int setTailText(xmlNode *, PyObject *);
196
+ __PYX_EXTERN_C PyObject *attributeValue(xmlNode *, xmlAttr *);
197
+ __PYX_EXTERN_C PyObject *attributeValueFromNsName(xmlNode *, const xmlChar *, const xmlChar *);
198
+ __PYX_EXTERN_C PyObject *getAttributeValue(struct LxmlElement *, PyObject *, PyObject *);
199
+ __PYX_EXTERN_C PyObject *iterattributes(struct LxmlElement *, int);
200
+ __PYX_EXTERN_C PyObject *collectAttributes(xmlNode *, int);
201
+ __PYX_EXTERN_C int setAttributeValue(struct LxmlElement *, PyObject *, PyObject *);
202
+ __PYX_EXTERN_C int delAttribute(struct LxmlElement *, PyObject *);
203
+ __PYX_EXTERN_C int delAttributeFromNsName(xmlNode *, const xmlChar *, const xmlChar *);
204
+ __PYX_EXTERN_C int hasChild(xmlNode *);
205
+ __PYX_EXTERN_C xmlNode *findChild(xmlNode *, Py_ssize_t);
206
+ __PYX_EXTERN_C xmlNode *findChildForwards(xmlNode *, Py_ssize_t);
207
+ __PYX_EXTERN_C xmlNode *findChildBackwards(xmlNode *, Py_ssize_t);
208
+ __PYX_EXTERN_C xmlNode *nextElement(xmlNode *);
209
+ __PYX_EXTERN_C xmlNode *previousElement(xmlNode *);
210
+ __PYX_EXTERN_C void appendChild(struct LxmlElement *, struct LxmlElement *);
211
+ __PYX_EXTERN_C int appendChildToElement(struct LxmlElement *, struct LxmlElement *);
212
+ __PYX_EXTERN_C PyObject *pyunicode(const xmlChar *);
213
+ __PYX_EXTERN_C PyObject *utf8(PyObject *);
214
+ __PYX_EXTERN_C PyObject *getNsTag(PyObject *);
215
+ __PYX_EXTERN_C PyObject *getNsTagWithEmptyNs(PyObject *);
216
+ __PYX_EXTERN_C PyObject *namespacedName(xmlNode *);
217
+ __PYX_EXTERN_C PyObject *namespacedNameFromNsName(const xmlChar *, const xmlChar *);
218
+ __PYX_EXTERN_C void iteratorStoreNext(struct LxmlElementIterator *, struct LxmlElement *);
219
+ __PYX_EXTERN_C void initTagMatch(struct LxmlElementTagMatcher *, PyObject *);
220
+ __PYX_EXTERN_C xmlNs *findOrBuildNodeNsPrefix(struct LxmlDocument *, xmlNode *, const xmlChar *, const xmlChar *);
221
+
222
+ #endif /* !__PYX_HAVE_API__lxml__etree */
223
+
224
+ /* WARNING: the interface of the module init function changed in CPython 3.5. */
225
+ /* It now returns a PyModuleDef instance instead of a PyModule instance. */
226
+
227
+ /* WARNING: Use PyImport_AppendInittab("etree", PyInit_etree) instead of calling PyInit_etree directly from Python 3.5 */
228
+ PyMODINIT_FUNC PyInit_etree(void);
229
+
230
+ #if PY_VERSION_HEX >= 0x03050000 && (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || (defined(__cplusplus) && __cplusplus >= 201402L))
231
+ #if defined(__cplusplus) && __cplusplus >= 201402L
232
+ [[deprecated("Use PyImport_AppendInittab(\"etree\", PyInit_etree) instead of calling PyInit_etree directly.")]] inline
233
+ #elif defined(__GNUC__) || defined(__clang__)
234
+ __attribute__ ((__deprecated__("Use PyImport_AppendInittab(\"etree\", PyInit_etree) instead of calling PyInit_etree directly."), __unused__)) __inline__
235
+ #elif defined(_MSC_VER)
236
+ __declspec(deprecated("Use PyImport_AppendInittab(\"etree\", PyInit_etree) instead of calling PyInit_etree directly.")) __inline
237
+ #endif
238
+ static PyObject* __PYX_WARN_IF_PyInit_etree_INIT_CALLED(PyObject* res) {
239
+ return res;
240
+ }
241
+ #define PyInit_etree() __PYX_WARN_IF_PyInit_etree_INIT_CALLED(PyInit_etree())
242
+ #endif
243
+
244
+ #endif /* !__PYX_HAVE__lxml__etree */
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/objectpath.pxi ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ################################################################################
2
+ # ObjectPath
3
+
4
+ ctypedef struct _ObjectPath:
5
+ const_xmlChar* href
6
+ const_xmlChar* name
7
+ Py_ssize_t index
8
+
9
+
10
+ cdef object _NO_DEFAULT = object()
11
+
12
+
13
+ cdef class ObjectPath:
14
+ """ObjectPath(path)
15
+ Immutable object that represents a compiled object path.
16
+
17
+ Example for a path: 'root.child[1].{other}child[25]'
18
+ """
19
+ cdef readonly object find
20
+ cdef list _path
21
+ cdef object _path_str
22
+ cdef _ObjectPath* _c_path
23
+ cdef Py_ssize_t _path_len
24
+ def __init__(self, path):
25
+ if python._isString(path):
26
+ self._path = _parse_object_path_string(path)
27
+ self._path_str = path
28
+ else:
29
+ self._path = _parse_object_path_list(path)
30
+ self._path_str = '.'.join(path)
31
+ self._path_len = len(self._path)
32
+ self._c_path = _build_object_path_segments(self._path)
33
+ self.find = self.__call__
34
+
35
+ def __dealloc__(self):
36
+ if self._c_path is not NULL:
37
+ python.lxml_free(self._c_path)
38
+
39
+ def __str__(self):
40
+ return self._path_str
41
+
42
+ def __call__(self, _Element root not None, *_default):
43
+ """Follow the attribute path in the object structure and return the
44
+ target attribute value.
45
+
46
+ If it it not found, either returns a default value (if one was passed
47
+ as second argument) or raises AttributeError.
48
+ """
49
+ if _default:
50
+ if len(_default) > 1:
51
+ raise TypeError, "invalid number of arguments: needs one or two"
52
+ default = _default[0]
53
+ else:
54
+ default = _NO_DEFAULT
55
+ return _find_object_path(root, self._c_path, self._path_len, default)
56
+
57
+ def hasattr(self, _Element root not None):
58
+ "hasattr(self, root)"
59
+ try:
60
+ _find_object_path(root, self._c_path, self._path_len, _NO_DEFAULT)
61
+ except AttributeError:
62
+ return False
63
+ return True
64
+
65
+ def setattr(self, _Element root not None, value):
66
+ """setattr(self, root, value)
67
+
68
+ Set the value of the target element in a subtree.
69
+
70
+ If any of the children on the path does not exist, it is created.
71
+ """
72
+ _create_object_path(root, self._c_path, self._path_len, 1, value)
73
+
74
+ def addattr(self, _Element root not None, value):
75
+ """addattr(self, root, value)
76
+
77
+ Append a value to the target element in a subtree.
78
+
79
+ If any of the children on the path does not exist, it is created.
80
+ """
81
+ _create_object_path(root, self._c_path, self._path_len, 0, value)
82
+
83
+
84
+ cdef object __MATCH_PATH_SEGMENT = re.compile(
85
+ r"(\.?)\s*(?:\{([^}]*)\})?\s*([^.{}\[\]\s]+)\s*(?:\[\s*([-0-9]+)\s*\])?",
86
+ re.U).match
87
+
88
+ cdef tuple _RELATIVE_PATH_SEGMENT = (None, None, 0)
89
+
90
+
91
+ cdef list _parse_object_path_string(_path):
92
+ """Parse object path string into a (ns, name, index) list.
93
+ """
94
+ cdef bint has_dot
95
+ cdef unicode path
96
+ new_path = []
97
+ if isinstance(_path, bytes):
98
+ path = (<bytes>_path).decode('ascii')
99
+ elif type(_path) is not unicode:
100
+ path = unicode(_path)
101
+ else:
102
+ path = _path
103
+ path = path.strip()
104
+ if path == '.':
105
+ return [_RELATIVE_PATH_SEGMENT]
106
+ path_pos = 0
107
+ while path:
108
+ match = __MATCH_PATH_SEGMENT(path, path_pos)
109
+ if match is None:
110
+ break
111
+
112
+ dot, ns, name, index = match.groups()
113
+ index = int(index) if index else 0
114
+ has_dot = dot == '.'
115
+ if not new_path:
116
+ if has_dot:
117
+ # path '.child' => ignore root
118
+ new_path.append(_RELATIVE_PATH_SEGMENT)
119
+ elif index:
120
+ raise ValueError, "index not allowed on root node"
121
+ elif not has_dot:
122
+ raise ValueError, "invalid path"
123
+ if ns is not None:
124
+ ns = python.PyUnicode_AsUTF8String(ns)
125
+ name = python.PyUnicode_AsUTF8String(name)
126
+ new_path.append( (ns, name, index) )
127
+
128
+ path_pos = match.end()
129
+ if not new_path or len(path) > path_pos:
130
+ raise ValueError, "invalid path"
131
+ return new_path
132
+
133
+
134
+ cdef list _parse_object_path_list(path):
135
+ """Parse object path sequence into a (ns, name, index) list.
136
+ """
137
+ new_path = []
138
+ for item in path:
139
+ item = item.strip()
140
+ if not new_path and item == '':
141
+ # path '.child' => ignore root
142
+ ns = name = None
143
+ index = 0
144
+ else:
145
+ ns, name = cetree.getNsTag(item)
146
+ c_name = _xcstr(name)
147
+ index_pos = tree.xmlStrchr(c_name, c'[')
148
+ if index_pos is NULL:
149
+ index = 0
150
+ else:
151
+ index_end = tree.xmlStrchr(index_pos + 1, c']')
152
+ if index_end is NULL:
153
+ raise ValueError, "index must be enclosed in []"
154
+ index = int(index_pos[1:index_end - index_pos])
155
+ if not new_path and index != 0:
156
+ raise ValueError, "index not allowed on root node"
157
+ name = <bytes>c_name[:index_pos - c_name]
158
+ new_path.append( (ns, name, index) )
159
+ if not new_path:
160
+ raise ValueError, "invalid path"
161
+ return new_path
162
+
163
+
164
+ cdef _ObjectPath* _build_object_path_segments(list path_list) except NULL:
165
+ cdef _ObjectPath* c_path
166
+ cdef _ObjectPath* c_path_segments
167
+ c_path_segments = <_ObjectPath*>python.lxml_malloc(len(path_list), sizeof(_ObjectPath))
168
+ if c_path_segments is NULL:
169
+ raise MemoryError()
170
+ c_path = c_path_segments
171
+ for href, name, index in path_list:
172
+ c_path[0].href = _xcstr(href) if href is not None else NULL
173
+ c_path[0].name = _xcstr(name) if name is not None else NULL
174
+ c_path[0].index = index
175
+ c_path += 1
176
+ return c_path_segments
177
+
178
+
179
+ cdef _find_object_path(_Element root, _ObjectPath* c_path, Py_ssize_t c_path_len, default_value):
180
+ """Follow the path to find the target element.
181
+ """
182
+ cdef tree.xmlNode* c_node
183
+ cdef Py_ssize_t c_index
184
+ c_node = root._c_node
185
+ c_name = c_path[0].name
186
+ c_href = c_path[0].href
187
+ if c_href is NULL or c_href[0] == c'\0':
188
+ c_href = tree._getNs(c_node)
189
+ if not cetree.tagMatches(c_node, c_href, c_name):
190
+ if default_value is not _NO_DEFAULT:
191
+ return default_value
192
+ else:
193
+ raise ValueError(
194
+ f"root element does not match: need {cetree.namespacedNameFromNsName(c_href, c_name)}, got {root.tag}")
195
+
196
+ while c_node is not NULL:
197
+ c_path_len -= 1
198
+ if c_path_len <= 0:
199
+ break
200
+
201
+ c_path += 1
202
+ if c_path[0].href is not NULL:
203
+ c_href = c_path[0].href # otherwise: keep parent namespace
204
+ c_name = tree.xmlDictExists(c_node.doc.dict, c_path[0].name, -1)
205
+ if c_name is NULL:
206
+ c_name = c_path[0].name
207
+ c_node = NULL
208
+ break
209
+ c_index = c_path[0].index
210
+ c_node = c_node.last if c_index < 0 else c_node.children
211
+ c_node = _findFollowingSibling(c_node, c_href, c_name, c_index)
212
+
213
+ if c_node is not NULL:
214
+ return cetree.elementFactory(root._doc, c_node)
215
+ elif default_value is not _NO_DEFAULT:
216
+ return default_value
217
+ else:
218
+ tag = cetree.namespacedNameFromNsName(c_href, c_name)
219
+ raise AttributeError, f"no such child: {tag}"
220
+
221
+
222
+ cdef _create_object_path(_Element root, _ObjectPath* c_path,
223
+ Py_ssize_t c_path_len, int replace, value):
224
+ """Follow the path to find the target element, build the missing children
225
+ as needed and set the target element to 'value'. If replace is true, an
226
+ existing value is replaced, otherwise the new value is added.
227
+ """
228
+ cdef _Element child
229
+ cdef tree.xmlNode* c_node
230
+ cdef tree.xmlNode* c_child
231
+ cdef Py_ssize_t c_index
232
+ if c_path_len == 1:
233
+ raise TypeError, "cannot update root node"
234
+
235
+ c_node = root._c_node
236
+ c_name = c_path[0].name
237
+ c_href = c_path[0].href
238
+ if c_href is NULL or c_href[0] == c'\0':
239
+ c_href = tree._getNs(c_node)
240
+ if not cetree.tagMatches(c_node, c_href, c_name):
241
+ raise ValueError(
242
+ f"root element does not match: need {cetree.namespacedNameFromNsName(c_href, c_name)}, got {root.tag}")
243
+
244
+ while c_path_len > 1:
245
+ c_path_len -= 1
246
+ c_path += 1
247
+ if c_path[0].href is not NULL:
248
+ c_href = c_path[0].href # otherwise: keep parent namespace
249
+ c_index = c_path[0].index
250
+ c_name = tree.xmlDictExists(c_node.doc.dict, c_path[0].name, -1)
251
+ if c_name is NULL:
252
+ c_name = c_path[0].name
253
+ c_child = NULL
254
+ else:
255
+ c_child = c_node.last if c_index < 0 else c_node.children
256
+ c_child = _findFollowingSibling(c_child, c_href, c_name, c_index)
257
+
258
+ if c_child is not NULL:
259
+ c_node = c_child
260
+ elif c_index != 0:
261
+ raise TypeError, "creating indexed path attributes is not supported"
262
+ elif c_path_len == 1:
263
+ _appendValue(cetree.elementFactory(root._doc, c_node),
264
+ cetree.namespacedNameFromNsName(c_href, c_name),
265
+ value)
266
+ return
267
+ else:
268
+ child = cetree.makeSubElement(
269
+ cetree.elementFactory(root._doc, c_node),
270
+ cetree.namespacedNameFromNsName(c_href, c_name),
271
+ None, None, None, None)
272
+ c_node = child._c_node
273
+
274
+ # if we get here, the entire path was already there
275
+ if replace:
276
+ element = cetree.elementFactory(root._doc, c_node)
277
+ _replaceElement(element, value)
278
+ else:
279
+ _appendValue(cetree.elementFactory(root._doc, c_node.parent),
280
+ cetree.namespacedName(c_node), value)
281
+
282
+
283
+ cdef list _build_descendant_paths(tree.xmlNode* c_node, prefix_string):
284
+ """Returns a list of all descendant paths.
285
+ """
286
+ cdef list path, path_list
287
+ tag = cetree.namespacedName(c_node)
288
+ if prefix_string:
289
+ if prefix_string[-1] != '.':
290
+ prefix_string += '.'
291
+ prefix_string = prefix_string + tag
292
+ else:
293
+ prefix_string = tag
294
+ path = [prefix_string]
295
+ path_list = []
296
+ _recursive_build_descendant_paths(c_node, path, path_list)
297
+ return path_list
298
+
299
+
300
+ cdef int _recursive_build_descendant_paths(tree.xmlNode* c_node,
301
+ list path, list path_list) except -1:
302
+ """Fills the list 'path_list' with all descendant paths, initial prefix
303
+ being in the list 'path'.
304
+ """
305
+ cdef tree.xmlNode* c_child
306
+ tags = {}
307
+ path_list.append('.'.join(path))
308
+ c_href = tree._getNs(c_node)
309
+ c_child = c_node.children
310
+ while c_child is not NULL:
311
+ while c_child.type != tree.XML_ELEMENT_NODE:
312
+ c_child = c_child.next
313
+ if c_child is NULL:
314
+ return 0
315
+ if c_href is tree._getNs(c_child):
316
+ tag = pyunicode(c_child.name)
317
+ elif c_href is not NULL and tree._getNs(c_child) is NULL:
318
+ # special case: parent has namespace, child does not
319
+ tag = '{}' + pyunicode(c_child.name)
320
+ else:
321
+ tag = cetree.namespacedName(c_child)
322
+ count = tags.get(tag)
323
+ if count is None:
324
+ tags[tag] = 1
325
+ else:
326
+ tags[tag] = count + 1
327
+ tag += f'[{count}]'
328
+ path.append(tag)
329
+ _recursive_build_descendant_paths(c_child, path, path_list)
330
+ del path[-1]
331
+ c_child = c_child.next
332
+ return 0
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/proxy.pxi ADDED
@@ -0,0 +1,622 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Proxy functions and low level node allocation stuff
2
+
3
+ # Proxies represent elements, their reference is stored in the C
4
+ # structure of the respective node to avoid multiple instantiation of
5
+ # the Python class.
6
+
7
+ @cython.linetrace(False)
8
+ @cython.profile(False)
9
+ cdef inline _Element getProxy(xmlNode* c_node):
10
+ """Get a proxy for a given node.
11
+ """
12
+ #print "getProxy for:", <int>c_node
13
+ if c_node is not NULL and c_node._private is not NULL:
14
+ return <_Element>c_node._private
15
+ else:
16
+ return None
17
+
18
+
19
+ @cython.linetrace(False)
20
+ @cython.profile(False)
21
+ cdef inline bint hasProxy(xmlNode* c_node):
22
+ if c_node._private is NULL:
23
+ return False
24
+ return True
25
+
26
+
27
+ @cython.linetrace(False)
28
+ @cython.profile(False)
29
+ cdef inline int _registerProxy(_Element proxy, _Document doc,
30
+ xmlNode* c_node) except -1:
31
+ """Register a proxy and type for the node it's proxying for.
32
+ """
33
+ #print "registering for:", <int>proxy._c_node
34
+ assert not hasProxy(c_node), "double registering proxy!"
35
+ proxy._doc = doc
36
+ proxy._c_node = c_node
37
+ c_node._private = <void*>proxy
38
+ return 0
39
+
40
+
41
+ @cython.linetrace(False)
42
+ @cython.profile(False)
43
+ cdef inline int _unregisterProxy(_Element proxy) except -1:
44
+ """Unregister a proxy for the node it's proxying for.
45
+ """
46
+ cdef xmlNode* c_node = proxy._c_node
47
+ assert c_node._private is <void*>proxy, "Tried to unregister unknown proxy"
48
+ c_node._private = NULL
49
+ return 0
50
+
51
+
52
+ ################################################################################
53
+ # temporarily make a node the root node of its document
54
+
55
+ cdef xmlDoc* _fakeRootDoc(xmlDoc* c_base_doc, xmlNode* c_node) except NULL:
56
+ return _plainFakeRootDoc(c_base_doc, c_node, 1)
57
+
58
+ cdef xmlDoc* _plainFakeRootDoc(xmlDoc* c_base_doc, xmlNode* c_node,
59
+ bint with_siblings) except NULL:
60
+ # build a temporary document that has the given node as root node
61
+ # note that copy and original must not be modified during its lifetime!!
62
+ # always call _destroyFakeDoc() after use!
63
+ cdef xmlNode* c_child
64
+ cdef xmlNode* c_root
65
+ cdef xmlNode* c_new_root
66
+ cdef xmlDoc* c_doc
67
+ if with_siblings or (c_node.prev is NULL and c_node.next is NULL):
68
+ c_root = tree.xmlDocGetRootElement(c_base_doc)
69
+ if c_root is c_node:
70
+ # already the root node, no siblings
71
+ return c_base_doc
72
+
73
+ c_doc = _copyDoc(c_base_doc, 0) # non recursive!
74
+ c_new_root = tree.xmlDocCopyNode(c_node, c_doc, 2) # non recursive!
75
+ tree.xmlDocSetRootElement(c_doc, c_new_root)
76
+ _copyParentNamespaces(c_node, c_new_root)
77
+
78
+ c_new_root.children = c_node.children
79
+ c_new_root.last = c_node.last
80
+ c_new_root.next = c_new_root.prev = NULL
81
+
82
+ # store original node
83
+ c_doc._private = c_node
84
+
85
+ # divert parent pointers of children
86
+ c_child = c_new_root.children
87
+ while c_child is not NULL:
88
+ c_child.parent = c_new_root
89
+ c_child = c_child.next
90
+
91
+ c_doc.children = c_new_root
92
+ return c_doc
93
+
94
+ cdef void _destroyFakeDoc(xmlDoc* c_base_doc, xmlDoc* c_doc) noexcept:
95
+ # delete a temporary document
96
+ cdef xmlNode* c_child
97
+ cdef xmlNode* c_parent
98
+ cdef xmlNode* c_root
99
+ if c_doc is c_base_doc:
100
+ return
101
+ c_root = tree.xmlDocGetRootElement(c_doc)
102
+
103
+ # restore parent pointers of children
104
+ c_parent = <xmlNode*>c_doc._private
105
+ c_child = c_root.children
106
+ while c_child is not NULL:
107
+ c_child.parent = c_parent
108
+ c_child = c_child.next
109
+
110
+ # prevent recursive removal of children
111
+ c_root.children = c_root.last = NULL
112
+ tree.xmlFreeDoc(c_doc)
113
+
114
+ cdef _Element _fakeDocElementFactory(_Document doc, xmlNode* c_element):
115
+ """Special element factory for cases where we need to create a fake
116
+ root document, but still need to instantiate arbitrary nodes from
117
+ it. If we instantiate the fake root node, things will turn bad
118
+ when it's destroyed.
119
+
120
+ Instead, if we are asked to instantiate the fake root node, we
121
+ instantiate the original node instead.
122
+ """
123
+ if c_element.doc is not doc._c_doc:
124
+ if c_element.doc._private is not NULL:
125
+ if c_element is c_element.doc.children:
126
+ c_element = <xmlNode*>c_element.doc._private
127
+ #assert c_element.type == tree.XML_ELEMENT_NODE
128
+ return _elementFactory(doc, c_element)
129
+
130
+ ################################################################################
131
+ # support for freeing tree elements when proxy objects are destroyed
132
+
133
+ cdef int attemptDeallocation(xmlNode* c_node) noexcept:
134
+ """Attempt deallocation of c_node (or higher up in tree).
135
+ """
136
+ cdef xmlNode* c_top
137
+ # could be we actually aren't referring to the tree at all
138
+ if c_node is NULL:
139
+ #print "not freeing, node is NULL"
140
+ return 0
141
+ c_top = getDeallocationTop(c_node)
142
+ if c_top is not NULL:
143
+ #print "freeing:", c_top.name
144
+ _removeText(c_top.next) # tail
145
+ tree.xmlFreeNode(c_top)
146
+ return 1
147
+ return 0
148
+
149
+ cdef xmlNode* getDeallocationTop(xmlNode* c_node) noexcept:
150
+ """Return the top of the tree that can be deallocated, or NULL.
151
+ """
152
+ cdef xmlNode* c_next
153
+ #print "trying to do deallocating:", c_node.type
154
+ if hasProxy(c_node):
155
+ #print "Not freeing: proxies still exist"
156
+ return NULL
157
+ while c_node.parent is not NULL:
158
+ c_node = c_node.parent
159
+ #print "checking:", c_current.type
160
+ if c_node.type == tree.XML_DOCUMENT_NODE or \
161
+ c_node.type == tree.XML_HTML_DOCUMENT_NODE:
162
+ #print "not freeing: still in doc"
163
+ return NULL
164
+ # if we're still attached to the document, don't deallocate
165
+ if hasProxy(c_node):
166
+ #print "Not freeing: proxies still exist"
167
+ return NULL
168
+ # see whether we have children to deallocate
169
+ if not canDeallocateChildNodes(c_node):
170
+ return NULL
171
+ # see whether we have siblings to deallocate
172
+ c_next = c_node.prev
173
+ while c_next:
174
+ if _isElement(c_next):
175
+ if hasProxy(c_next) or not canDeallocateChildNodes(c_next):
176
+ return NULL
177
+ c_next = c_next.prev
178
+ c_next = c_node.next
179
+ while c_next:
180
+ if _isElement(c_next):
181
+ if hasProxy(c_next) or not canDeallocateChildNodes(c_next):
182
+ return NULL
183
+ c_next = c_next.next
184
+ return c_node
185
+
186
+ cdef int canDeallocateChildNodes(xmlNode* c_parent) noexcept:
187
+ cdef xmlNode* c_node
188
+ c_node = c_parent.children
189
+ tree.BEGIN_FOR_EACH_ELEMENT_FROM(c_parent, c_node, 1)
190
+ if hasProxy(c_node):
191
+ return 0
192
+ tree.END_FOR_EACH_ELEMENT_FROM(c_node)
193
+ return 1
194
+
195
+ ################################################################################
196
+ # fix _Document references and namespaces when a node changes documents
197
+
198
+ cdef void _copyParentNamespaces(xmlNode* c_from_node, xmlNode* c_to_node) noexcept nogil:
199
+ """Copy the namespaces of all ancestors of c_from_node to c_to_node.
200
+ """
201
+ cdef xmlNode* c_parent
202
+ cdef xmlNs* c_ns
203
+ cdef xmlNs* c_new_ns
204
+ cdef int prefix_known
205
+ c_parent = c_from_node.parent
206
+ while c_parent and (tree._isElementOrXInclude(c_parent) or
207
+ c_parent.type == tree.XML_DOCUMENT_NODE):
208
+ c_new_ns = c_parent.nsDef
209
+ while c_new_ns:
210
+ # libxml2 will check if the prefix is already defined
211
+ tree.xmlNewNs(c_to_node, c_new_ns.href, c_new_ns.prefix)
212
+ c_new_ns = c_new_ns.next
213
+ c_parent = c_parent.parent
214
+
215
+
216
+ ctypedef struct _ns_update_map:
217
+ xmlNs* old
218
+ xmlNs* new
219
+
220
+
221
+ ctypedef struct _nscache:
222
+ _ns_update_map* ns_map
223
+ size_t size
224
+ size_t last
225
+
226
+
227
+ cdef int _growNsCache(_nscache* c_ns_cache) except -1:
228
+ cdef _ns_update_map* ns_map_ptr
229
+ if c_ns_cache.size == 0:
230
+ c_ns_cache.size = 20
231
+ else:
232
+ c_ns_cache.size *= 2
233
+ ns_map_ptr = <_ns_update_map*> python.lxml_realloc(
234
+ c_ns_cache.ns_map, c_ns_cache.size, sizeof(_ns_update_map))
235
+ if not ns_map_ptr:
236
+ python.lxml_free(c_ns_cache.ns_map)
237
+ c_ns_cache.ns_map = NULL
238
+ raise MemoryError()
239
+ c_ns_cache.ns_map = ns_map_ptr
240
+ return 0
241
+
242
+
243
+ cdef inline int _appendToNsCache(_nscache* c_ns_cache,
244
+ xmlNs* c_old_ns, xmlNs* c_new_ns) except -1:
245
+ if c_ns_cache.last >= c_ns_cache.size:
246
+ _growNsCache(c_ns_cache)
247
+ c_ns_cache.ns_map[c_ns_cache.last] = _ns_update_map(old=c_old_ns, new=c_new_ns)
248
+ c_ns_cache.last += 1
249
+
250
+
251
+ cdef int _stripRedundantNamespaceDeclarations(xmlNode* c_element, _nscache* c_ns_cache,
252
+ xmlNs** c_del_ns_list) except -1:
253
+ """Removes namespace declarations from an element that are already
254
+ defined in its parents. Does not free the xmlNs's, just prepends
255
+ them to the c_del_ns_list.
256
+ """
257
+ cdef xmlNs* c_ns
258
+ cdef xmlNs* c_ns_next
259
+ cdef xmlNs** c_nsdef
260
+ # use a xmlNs** to handle assignments to "c_element.nsDef" correctly
261
+ c_nsdef = &c_element.nsDef
262
+ while c_nsdef[0] is not NULL:
263
+ c_ns = tree.xmlSearchNsByHref(
264
+ c_element.doc, c_element.parent, c_nsdef[0].href)
265
+ if c_ns is NULL:
266
+ # new namespace href => keep and cache the ns declaration
267
+ _appendToNsCache(c_ns_cache, c_nsdef[0], c_nsdef[0])
268
+ c_nsdef = &c_nsdef[0].next
269
+ else:
270
+ # known namespace href => cache mapping and strip old ns
271
+ _appendToNsCache(c_ns_cache, c_nsdef[0], c_ns)
272
+ # cut out c_nsdef.next and prepend it to garbage chain
273
+ c_ns_next = c_nsdef[0].next
274
+ c_nsdef[0].next = c_del_ns_list[0]
275
+ c_del_ns_list[0] = c_nsdef[0]
276
+ c_nsdef[0] = c_ns_next
277
+ return 0
278
+
279
+
280
+ cdef void _cleanUpFromNamespaceAdaptation(xmlNode* c_start_node,
281
+ _nscache* c_ns_cache, xmlNs* c_del_ns_list) noexcept:
282
+ # Try to recover from exceptions with really bad timing. We were in the middle
283
+ # of ripping out xmlNS-es and likely ran out of memory. Try to fix up the tree
284
+ # by re-adding the original xmlNs declarations (which might still be used in some
285
+ # places).
286
+ if c_ns_cache.ns_map:
287
+ python.lxml_free(c_ns_cache.ns_map)
288
+ if c_del_ns_list:
289
+ if not c_start_node.nsDef:
290
+ c_start_node.nsDef = c_del_ns_list
291
+ else:
292
+ c_ns = c_start_node.nsDef
293
+ while c_ns.next:
294
+ c_ns = c_ns.next
295
+ c_ns.next = c_del_ns_list
296
+
297
+
298
+ cdef int moveNodeToDocument(_Document doc, xmlDoc* c_source_doc,
299
+ xmlNode* c_element) except -1:
300
+ """Fix the xmlNs pointers of a node and its subtree that were moved.
301
+
302
+ Originally copied from libxml2's xmlReconciliateNs(). Expects
303
+ libxml2 doc pointers of node to be correct already, but fixes
304
+ _Document references.
305
+
306
+ For each node in the subtree, we do this:
307
+
308
+ 1) Remove redundant declarations of namespace that are already
309
+ defined in its parents.
310
+
311
+ 2) Replace namespaces that are *not* defined on the node or its
312
+ parents by the equivalent namespace declarations that *are*
313
+ defined on the node or its parents (possibly using a different
314
+ prefix). If a namespace is unknown, declare a new one on the
315
+ node.
316
+
317
+ 3) Reassign the names of tags and attribute from the dict of the
318
+ target document *iff* it is different from the dict used in the
319
+ source subtree.
320
+
321
+ 4) Set the Document reference to the new Document (if different).
322
+ This is done on backtracking to keep the original Document
323
+ alive as long as possible, until all its elements are updated.
324
+
325
+ Note that the namespace declarations are removed from the tree in
326
+ step 1), but freed only after the complete subtree was traversed
327
+ and all occurrences were replaced by tree-internal pointers.
328
+ """
329
+ cdef xmlNode* c_start_node
330
+ cdef xmlNode* c_node
331
+ cdef xmlDoc* c_doc = doc._c_doc
332
+ cdef tree.xmlAttr* c_attr
333
+ cdef char* c_name
334
+ cdef _nscache c_ns_cache = [NULL, 0, 0]
335
+ cdef xmlNs* c_del_ns_list = NULL
336
+ cdef proxy_count = 0
337
+
338
+ if not tree._isElementOrXInclude(c_element):
339
+ return 0
340
+
341
+ c_start_node = c_element
342
+
343
+ tree.BEGIN_FOR_EACH_FROM(c_element, c_element, 1)
344
+ if tree._isElementOrXInclude(c_element):
345
+ if hasProxy(c_element):
346
+ proxy_count += 1
347
+
348
+ # 1) cut out namespaces defined here that are already known by
349
+ # the ancestors
350
+ if c_element.nsDef is not NULL:
351
+ try:
352
+ _stripRedundantNamespaceDeclarations(c_element, &c_ns_cache, &c_del_ns_list)
353
+ except:
354
+ _cleanUpFromNamespaceAdaptation(c_start_node, &c_ns_cache, c_del_ns_list)
355
+ raise
356
+
357
+ # 2) make sure the namespaces of an element and its attributes
358
+ # are declared in this document (i.e. on the node or its parents)
359
+ if c_element.ns is not NULL:
360
+ _fixCNs(doc, c_start_node, c_element, &c_ns_cache, c_del_ns_list)
361
+
362
+ c_node = <xmlNode*>c_element.properties
363
+ while c_node is not NULL:
364
+ if c_node.ns is not NULL:
365
+ _fixCNs(doc, c_start_node, c_node, &c_ns_cache, c_del_ns_list)
366
+ c_node = c_node.next
367
+
368
+ tree.END_FOR_EACH_FROM(c_element)
369
+
370
+ # free now unused namespace declarations
371
+ if c_del_ns_list is not NULL:
372
+ tree.xmlFreeNsList(c_del_ns_list)
373
+
374
+ # cleanup
375
+ if c_ns_cache.ns_map is not NULL:
376
+ python.lxml_free(c_ns_cache.ns_map)
377
+
378
+ # 3) fix the names in the tree if we moved it from a different thread
379
+ if doc._c_doc.dict is not c_source_doc.dict:
380
+ fixThreadDictNames(c_start_node, c_source_doc.dict, doc._c_doc.dict)
381
+
382
+ # 4) fix _Document references
383
+ # (and potentially deallocate the source document)
384
+ if proxy_count > 0:
385
+ if proxy_count == 1 and c_start_node._private is not NULL:
386
+ proxy = getProxy(c_start_node)
387
+ if proxy is not None:
388
+ if proxy._doc is not doc:
389
+ proxy._doc = doc
390
+ else:
391
+ fixElementDocument(c_start_node, doc, proxy_count)
392
+ else:
393
+ fixElementDocument(c_start_node, doc, proxy_count)
394
+
395
+ return 0
396
+
397
+
398
+ cdef void _setTreeDoc(xmlNode* c_node, xmlDoc* c_doc) noexcept:
399
+ """Adaptation of 'xmlSetTreeDoc()' that deep-fixes the document links iteratively.
400
+ It avoids https://gitlab.gnome.org/GNOME/libxml2/issues/42
401
+ """
402
+ tree.BEGIN_FOR_EACH_FROM(c_node, c_node, 1)
403
+ if c_node.type == tree.XML_ELEMENT_NODE:
404
+ c_attr = <tree.xmlAttr*>c_node.properties
405
+ while c_attr:
406
+ if c_attr.atype == tree.XML_ATTRIBUTE_ID:
407
+ tree.xmlRemoveID(c_node.doc, c_attr)
408
+ c_attr.doc = c_doc
409
+ _fixDocChildren(c_attr.children, c_doc)
410
+ c_attr = c_attr.next
411
+ # Set doc link for all nodes, not only elements.
412
+ c_node.doc = c_doc
413
+ tree.END_FOR_EACH_FROM(c_node)
414
+
415
+
416
+ cdef inline void _fixDocChildren(xmlNode* c_child, xmlDoc* c_doc) noexcept:
417
+ while c_child:
418
+ c_child.doc = c_doc
419
+ if c_child.children:
420
+ _fixDocChildren(c_child.children, c_doc)
421
+ c_child = c_child.next
422
+
423
+
424
+ cdef int _fixCNs(_Document doc, xmlNode* c_start_node, xmlNode* c_node,
425
+ _nscache* c_ns_cache, xmlNs* c_del_ns_list) except -1:
426
+ cdef xmlNs* c_ns = NULL
427
+ cdef bint is_prefixed_attr = (c_node.type == tree.XML_ATTRIBUTE_NODE and c_node.ns.prefix)
428
+
429
+ for ns_map in c_ns_cache.ns_map[:c_ns_cache.last]:
430
+ if c_node.ns is ns_map.old:
431
+ if is_prefixed_attr and not ns_map.new.prefix:
432
+ # avoid dropping prefix from attributes
433
+ continue
434
+ c_ns = ns_map.new
435
+ break
436
+
437
+ if c_ns:
438
+ c_node.ns = c_ns
439
+ else:
440
+ # not in cache or not acceptable
441
+ # => find a replacement from this document
442
+ try:
443
+ c_ns = doc._findOrBuildNodeNs(
444
+ c_start_node, c_node.ns.href, c_node.ns.prefix,
445
+ c_node.type == tree.XML_ATTRIBUTE_NODE)
446
+ c_node.ns = c_ns
447
+ _appendToNsCache(c_ns_cache, c_node.ns, c_ns)
448
+ except:
449
+ _cleanUpFromNamespaceAdaptation(c_start_node, c_ns_cache, c_del_ns_list)
450
+ raise
451
+ return 0
452
+
453
+
454
+ cdef int fixElementDocument(xmlNode* c_element, _Document doc,
455
+ size_t proxy_count) except -1:
456
+ cdef xmlNode* c_node = c_element
457
+ cdef _Element proxy = None # init-to-None required due to fake-loop below
458
+ tree.BEGIN_FOR_EACH_FROM(c_element, c_node, 1)
459
+ if c_node._private is not NULL:
460
+ proxy = getProxy(c_node)
461
+ if proxy is not None:
462
+ if proxy._doc is not doc:
463
+ proxy._doc = doc
464
+ proxy_count -= 1
465
+ if proxy_count == 0:
466
+ return 0
467
+ tree.END_FOR_EACH_FROM(c_node)
468
+
469
+
470
+ cdef void fixThreadDictNames(xmlNode* c_element,
471
+ tree.xmlDict* c_src_dict,
472
+ tree.xmlDict* c_dict) noexcept nogil:
473
+ # re-assign the names of tags and attributes
474
+ #
475
+ # this should only be called when the element is based on a
476
+ # different libxml2 tag name dictionary
477
+ if c_element.type == tree.XML_DOCUMENT_NODE or \
478
+ c_element.type == tree.XML_HTML_DOCUMENT_NODE:
479
+ # may define "xml" namespace
480
+ fixThreadDictNsForNode(c_element, c_src_dict, c_dict)
481
+ if c_element.doc.extSubset:
482
+ fixThreadDictNamesForDtd(c_element.doc.extSubset, c_src_dict, c_dict)
483
+ if c_element.doc.intSubset:
484
+ fixThreadDictNamesForDtd(c_element.doc.intSubset, c_src_dict, c_dict)
485
+ c_element = c_element.children
486
+ while c_element is not NULL:
487
+ fixThreadDictNamesForNode(c_element, c_src_dict, c_dict)
488
+ c_element = c_element.next
489
+ elif tree._isElementOrXInclude(c_element):
490
+ fixThreadDictNamesForNode(c_element, c_src_dict, c_dict)
491
+
492
+
493
+ cdef inline void _fixThreadDictPtr(const_xmlChar** c_ptr,
494
+ tree.xmlDict* c_src_dict,
495
+ tree.xmlDict* c_dict) noexcept nogil:
496
+ c_str = c_ptr[0]
497
+ if c_str and c_src_dict and tree.xmlDictOwns(c_src_dict, c_str):
498
+ # return value can be NULL on memory error, but we don't handle that here
499
+ c_str = tree.xmlDictLookup(c_dict, c_str, -1)
500
+ if c_str:
501
+ c_ptr[0] = c_str
502
+
503
+
504
+ cdef void fixThreadDictNamesForNode(xmlNode* c_element,
505
+ tree.xmlDict* c_src_dict,
506
+ tree.xmlDict* c_dict) noexcept nogil:
507
+ cdef xmlNode* c_node = c_element
508
+ tree.BEGIN_FOR_EACH_FROM(c_element, c_node, 1)
509
+ if c_node.type in (tree.XML_ELEMENT_NODE, tree.XML_XINCLUDE_START):
510
+ fixThreadDictNamesForAttributes(
511
+ c_node.properties, c_src_dict, c_dict)
512
+ fixThreadDictNsForNode(c_node, c_src_dict, c_dict)
513
+ _fixThreadDictPtr(&c_node.name, c_src_dict, c_dict)
514
+ elif c_node.type == tree.XML_TEXT_NODE:
515
+ # libxml2's SAX2 parser interns some indentation space
516
+ fixThreadDictContentForNode(c_node, c_src_dict, c_dict)
517
+ elif c_node.type == tree.XML_COMMENT_NODE:
518
+ pass # don't touch c_node.name
519
+ else:
520
+ _fixThreadDictPtr(&c_node.name, c_src_dict, c_dict)
521
+ tree.END_FOR_EACH_FROM(c_node)
522
+
523
+
524
+ cdef inline void fixThreadDictNamesForAttributes(tree.xmlAttr* c_attr,
525
+ tree.xmlDict* c_src_dict,
526
+ tree.xmlDict* c_dict) noexcept nogil:
527
+ cdef xmlNode* c_child
528
+ cdef xmlNode* c_node = <xmlNode*>c_attr
529
+ while c_node is not NULL:
530
+ if c_node.type not in (tree.XML_TEXT_NODE, tree.XML_COMMENT_NODE):
531
+ _fixThreadDictPtr(&c_node.name, c_src_dict, c_dict)
532
+ # libxml2 keeps some (!) attribute values in the dict
533
+ c_child = c_node.children
534
+ while c_child is not NULL:
535
+ fixThreadDictContentForNode(c_child, c_src_dict, c_dict)
536
+ c_child = c_child.next
537
+ c_node = c_node.next
538
+
539
+
540
+ cdef inline void fixThreadDictContentForNode(xmlNode* c_node,
541
+ tree.xmlDict* c_src_dict,
542
+ tree.xmlDict* c_dict) noexcept nogil:
543
+ if c_node.content is not NULL and \
544
+ c_node.content is not <xmlChar*>&c_node.properties:
545
+ if tree.xmlDictOwns(c_src_dict, c_node.content):
546
+ # result can be NULL on memory error, but we don't handle that here
547
+ c_node.content = <xmlChar*>tree.xmlDictLookup(c_dict, c_node.content, -1)
548
+
549
+
550
+ cdef inline void fixThreadDictNsForNode(xmlNode* c_node,
551
+ tree.xmlDict* c_src_dict,
552
+ tree.xmlDict* c_dict) noexcept nogil:
553
+ cdef xmlNs* c_ns = c_node.nsDef
554
+ while c_ns is not NULL:
555
+ _fixThreadDictPtr(&c_ns.href, c_src_dict, c_dict)
556
+ _fixThreadDictPtr(&c_ns.prefix, c_src_dict, c_dict)
557
+ c_ns = c_ns.next
558
+
559
+
560
+ cdef void fixThreadDictNamesForDtd(tree.xmlDtd* c_dtd,
561
+ tree.xmlDict* c_src_dict,
562
+ tree.xmlDict* c_dict) noexcept nogil:
563
+ cdef xmlNode* c_node
564
+ cdef tree.xmlElement* c_element
565
+ cdef tree.xmlAttribute* c_attribute
566
+ cdef tree.xmlEntity* c_entity
567
+
568
+ c_node = c_dtd.children
569
+ while c_node:
570
+ if c_node.type == tree.XML_ELEMENT_DECL:
571
+ c_element = <tree.xmlElement*>c_node
572
+ if c_element.content:
573
+ _fixThreadDictPtr(&c_element.content.name, c_src_dict, c_dict)
574
+ _fixThreadDictPtr(&c_element.content.prefix, c_src_dict, c_dict)
575
+ c_attribute = c_element.attributes
576
+ while c_attribute:
577
+ if tree.LIBXML_VERSION < 21500:
578
+ # libxml2 2.15 no longer stores default values in the dict.
579
+ # See https://gitlab.gnome.org/GNOME/libxml2/-/commit/24628f25
580
+ _fixThreadDictPtr(<const_xmlChar**>&c_attribute.defaultValue, c_src_dict, c_dict)
581
+ _fixThreadDictPtr(&c_attribute.name, c_src_dict, c_dict)
582
+ _fixThreadDictPtr(&c_attribute.prefix, c_src_dict, c_dict)
583
+ _fixThreadDictPtr(&c_attribute.elem, c_src_dict, c_dict)
584
+ c_attribute = c_attribute.nexth
585
+ elif c_node.type == tree.XML_ENTITY_DECL:
586
+ c_entity = <tree.xmlEntity*>c_node
587
+ _fixThreadDictPtr(&c_entity.name, c_src_dict, c_dict)
588
+ _fixThreadDictPtr(&c_entity.ExternalID, c_src_dict, c_dict)
589
+ _fixThreadDictPtr(&c_entity.SystemID, c_src_dict, c_dict)
590
+ _fixThreadDictPtr(<const_xmlChar**>&c_entity.content, c_src_dict, c_dict)
591
+ c_node = c_node.next
592
+
593
+
594
+ ################################################################################
595
+ # adopt an xmlDoc from an external libxml2 document source
596
+
597
+ cdef _Document _adoptForeignDoc(xmlDoc* c_doc, _BaseParser parser=None, bint is_owned=True):
598
+ """Convert and wrap an externally produced xmlDoc for use in lxml.
599
+ Assures that all '_private' pointers are NULL to prevent accidental
600
+ dereference into lxml proxy objects.
601
+ """
602
+ if c_doc is NULL:
603
+ raise ValueError("Illegal document provided: NULL")
604
+ if c_doc.type not in (tree.XML_DOCUMENT_NODE, tree.XML_HTML_DOCUMENT_NODE):
605
+ doc_type = c_doc.type
606
+ if is_owned:
607
+ tree.xmlFreeDoc(c_doc)
608
+ raise ValueError(f"Illegal document provided: expected XML or HTML, found {doc_type}")
609
+
610
+ cdef xmlNode* c_node = <xmlNode*>c_doc
611
+
612
+ if is_owned:
613
+ tree.BEGIN_FOR_EACH_FROM(<xmlNode*>c_doc, c_node, 1)
614
+ c_node._private = NULL
615
+ tree.END_FOR_EACH_FROM(c_node)
616
+ else:
617
+ # create a fresh copy that lxml owns
618
+ c_doc = tree.xmlCopyDoc(c_doc, 1)
619
+ if c_doc is NULL:
620
+ raise MemoryError()
621
+
622
+ return _documentFactory(c_doc, parser)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/public-api.pxi ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Public C API for lxml.etree
2
+
3
+ cdef public api _Element deepcopyNodeToDocument(_Document doc, xmlNode* c_root):
4
+ "Recursively copy the element into the document. doc is not modified."
5
+ cdef xmlNode* c_node
6
+ c_node = _copyNodeToDoc(c_root, doc._c_doc)
7
+ return _elementFactory(doc, c_node)
8
+
9
+ cdef public api _ElementTree elementTreeFactory(_Element context_node):
10
+ _assertValidNode(context_node)
11
+ return newElementTree(context_node, _ElementTree)
12
+
13
+ cdef public api _ElementTree newElementTree(_Element context_node,
14
+ object subclass):
15
+ if <void*>context_node is NULL or context_node is None:
16
+ raise TypeError
17
+ _assertValidNode(context_node)
18
+ return _newElementTree(context_node._doc, context_node, subclass)
19
+
20
+ cdef public api _ElementTree adoptExternalDocument(xmlDoc* c_doc, parser, bint is_owned):
21
+ if c_doc is NULL:
22
+ raise TypeError
23
+ doc = _adoptForeignDoc(c_doc, parser, is_owned)
24
+ return _elementTreeFactory(doc, None)
25
+
26
+ cdef public api _Element elementFactory(_Document doc, xmlNode* c_node):
27
+ if c_node is NULL or doc is None:
28
+ raise TypeError
29
+ return _elementFactory(doc, c_node)
30
+
31
+ cdef public api _Element makeElement(tag, _Document doc, parser,
32
+ text, tail, attrib, nsmap):
33
+ return _makeElement(tag, NULL, doc, parser, text, tail, attrib, nsmap, None)
34
+
35
+ cdef public api _Element makeSubElement(_Element parent, tag, text, tail,
36
+ attrib, nsmap):
37
+ _assertValidNode(parent)
38
+ return _makeSubElement(parent, tag, text, tail, attrib, nsmap, None)
39
+
40
+ cdef public api void setElementClassLookupFunction(
41
+ _element_class_lookup_function function, state):
42
+ _setElementClassLookupFunction(function, state)
43
+
44
+ cdef public api object lookupDefaultElementClass(state, doc, xmlNode* c_node):
45
+ return _lookupDefaultElementClass(state, doc, c_node)
46
+
47
+ cdef public api object lookupNamespaceElementClass(state, doc, xmlNode* c_node):
48
+ return _find_nselement_class(state, doc, c_node)
49
+
50
+ cdef public api object callLookupFallback(FallbackElementClassLookup lookup,
51
+ _Document doc, xmlNode* c_node):
52
+ return _callLookupFallback(lookup, doc, c_node)
53
+
54
+ cdef public api int tagMatches(xmlNode* c_node, const_xmlChar* c_href, const_xmlChar* c_name):
55
+ if c_node is NULL:
56
+ return -1
57
+ return _tagMatches(c_node, c_href, c_name)
58
+
59
+ cdef public api _Document documentOrRaise(object input):
60
+ return _documentOrRaise(input)
61
+
62
+ cdef public api _Element rootNodeOrRaise(object input):
63
+ return _rootNodeOrRaise(input)
64
+
65
+ cdef public api bint hasText(xmlNode* c_node):
66
+ return _hasText(c_node)
67
+
68
+ cdef public api bint hasTail(xmlNode* c_node):
69
+ return _hasTail(c_node)
70
+
71
+ cdef public api unicode textOf(xmlNode* c_node):
72
+ if c_node is NULL:
73
+ return None
74
+ return _collectText(c_node.children)
75
+
76
+ cdef public api unicode tailOf(xmlNode* c_node):
77
+ if c_node is NULL:
78
+ return None
79
+ return _collectText(c_node.next)
80
+
81
+ cdef public api int setNodeText(xmlNode* c_node, text) except -1:
82
+ if c_node is NULL:
83
+ raise ValueError
84
+ return _setNodeText(c_node, text)
85
+
86
+ cdef public api int setTailText(xmlNode* c_node, text) except -1:
87
+ if c_node is NULL:
88
+ raise ValueError
89
+ return _setTailText(c_node, text)
90
+
91
+ cdef public api unicode attributeValue(xmlNode* c_element, xmlAttr* c_attrib_node):
92
+ return _attributeValue(c_element, c_attrib_node)
93
+
94
+ cdef public api unicode attributeValueFromNsName(xmlNode* c_element,
95
+ const_xmlChar* ns, const_xmlChar* name):
96
+ return _attributeValueFromNsName(c_element, ns, name)
97
+
98
+ cdef public api object getAttributeValue(_Element element, key, default):
99
+ _assertValidNode(element)
100
+ return _getAttributeValue(element, key, default)
101
+
102
+ cdef public api object iterattributes(_Element element, int keysvalues):
103
+ _assertValidNode(element)
104
+ return _attributeIteratorFactory(element, keysvalues)
105
+
106
+ cdef public api list collectAttributes(xmlNode* c_element, int keysvalues):
107
+ return _collectAttributes(c_element, keysvalues)
108
+
109
+ cdef public api int setAttributeValue(_Element element, key, value) except -1:
110
+ _assertValidNode(element)
111
+ return _setAttributeValue(element, key, value)
112
+
113
+ cdef public api int delAttribute(_Element element, key) except -1:
114
+ _assertValidNode(element)
115
+ return _delAttribute(element, key)
116
+
117
+ cdef public api int delAttributeFromNsName(tree.xmlNode* c_element,
118
+ const_xmlChar* c_href, const_xmlChar* c_name):
119
+ return _delAttributeFromNsName(c_element, c_href, c_name)
120
+
121
+ cdef public api bint hasChild(xmlNode* c_node):
122
+ return _hasChild(c_node)
123
+
124
+ cdef public api xmlNode* findChild(xmlNode* c_node, Py_ssize_t index):
125
+ return _findChild(c_node, index)
126
+
127
+ cdef public api xmlNode* findChildForwards(xmlNode* c_node, Py_ssize_t index):
128
+ return _findChildForwards(c_node, index)
129
+
130
+ cdef public api xmlNode* findChildBackwards(xmlNode* c_node, Py_ssize_t index):
131
+ return _findChildBackwards(c_node, index)
132
+
133
+ cdef public api xmlNode* nextElement(xmlNode* c_node):
134
+ return _nextElement(c_node)
135
+
136
+ cdef public api xmlNode* previousElement(xmlNode* c_node):
137
+ return _previousElement(c_node)
138
+
139
+ cdef public api void appendChild(_Element parent, _Element child):
140
+ # deprecated, use appendChildToElement() instead!
141
+ _appendChild(parent, child)
142
+
143
+ cdef public api int appendChildToElement(_Element parent, _Element child) except -1:
144
+ return _appendChild(parent, child)
145
+
146
+ cdef public api unicode pyunicode(const_xmlChar* s):
147
+ if s is NULL:
148
+ raise TypeError
149
+ return funicode(s)
150
+
151
+ cdef public api bytes utf8(object s):
152
+ return _utf8(s)
153
+
154
+ cdef public api tuple getNsTag(object tag):
155
+ return _getNsTag(tag)
156
+
157
+ cdef public api tuple getNsTagWithEmptyNs(object tag):
158
+ return _getNsTagWithEmptyNs(tag)
159
+
160
+ cdef public api unicode namespacedName(xmlNode* c_node):
161
+ return _namespacedName(c_node)
162
+
163
+ cdef public api unicode namespacedNameFromNsName(const_xmlChar* href, const_xmlChar* name):
164
+ return _namespacedNameFromNsName(href, name)
165
+
166
+ cdef public api void iteratorStoreNext(_ElementIterator iterator, _Element node):
167
+ # deprecated!
168
+ iterator._storeNext(node)
169
+
170
+ cdef public api void initTagMatch(_ElementTagMatcher matcher, tag):
171
+ # deprecated!
172
+ matcher._initTagMatch(tag)
173
+
174
+ cdef public api tree.xmlNs* findOrBuildNodeNsPrefix(
175
+ _Document doc, xmlNode* c_node, const_xmlChar* href, const_xmlChar* prefix) except NULL:
176
+ if doc is None:
177
+ raise TypeError
178
+ return doc._findOrBuildNodeNs(c_node, href, prefix, 0)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/pyclasslookup.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # dummy module for backwards compatibility
2
+
3
+ from lxml.etree import PythonElementClassLookup
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/relaxng.pxi ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # support for RelaxNG validation
2
+ from lxml.includes cimport relaxng
3
+
4
+ cdef object _rnc2rng
5
+ try:
6
+ import rnc2rng as _rnc2rng
7
+ except ImportError:
8
+ _rnc2rng = None
9
+
10
+
11
+ cdef int _require_rnc2rng() except -1:
12
+ if _rnc2rng is None:
13
+ raise RelaxNGParseError(
14
+ 'compact syntax not supported (please install rnc2rng)')
15
+ return 0
16
+
17
+
18
+ cdef class RelaxNGError(LxmlError):
19
+ """Base class for RelaxNG errors.
20
+ """
21
+
22
+ cdef class RelaxNGParseError(RelaxNGError):
23
+ """Error while parsing an XML document as RelaxNG.
24
+ """
25
+
26
+ cdef class RelaxNGValidateError(RelaxNGError):
27
+ """Error while validating an XML document with a RelaxNG schema.
28
+ """
29
+
30
+
31
+ ################################################################################
32
+ # RelaxNG
33
+
34
+ cdef class RelaxNG(_Validator):
35
+ """RelaxNG(self, etree=None, file=None)
36
+ Turn a document into a Relax NG validator.
37
+
38
+ Either pass a schema as Element or ElementTree, or pass a file or
39
+ filename through the ``file`` keyword argument.
40
+ """
41
+ cdef relaxng.xmlRelaxNG* _c_schema
42
+ def __cinit__(self):
43
+ self._c_schema = NULL
44
+
45
+ def __init__(self, etree=None, *, file=None):
46
+ cdef _Document doc
47
+ cdef _Element root_node
48
+ cdef xmlDoc* fake_c_doc = NULL
49
+ cdef relaxng.xmlRelaxNGParserCtxt* parser_ctxt = NULL
50
+ _Validator.__init__(self)
51
+ if etree is not None:
52
+ doc = _documentOrRaise(etree)
53
+ root_node = _rootNodeOrRaise(etree)
54
+ fake_c_doc = _fakeRootDoc(doc._c_doc, root_node._c_node)
55
+ parser_ctxt = relaxng.xmlRelaxNGNewDocParserCtxt(fake_c_doc)
56
+ elif file is not None:
57
+ if _isString(file):
58
+ if file[-4:].lower() == '.rnc':
59
+ _require_rnc2rng()
60
+ rng_data_utf8 = _utf8(_rnc2rng.dumps(_rnc2rng.load(file)))
61
+ doc = _parseMemoryDocument(rng_data_utf8, parser=None, url=file)
62
+ parser_ctxt = relaxng.xmlRelaxNGNewDocParserCtxt(doc._c_doc)
63
+ else:
64
+ doc = None
65
+ filename = _encodeFilename(file)
66
+ with self._error_log:
67
+ orig_loader = _register_document_loader()
68
+ parser_ctxt = relaxng.xmlRelaxNGNewParserCtxt(_cstr(filename))
69
+ _reset_document_loader(orig_loader)
70
+ elif (_getFilenameForFile(file) or '')[-4:].lower() == '.rnc':
71
+ _require_rnc2rng()
72
+ rng_data_utf8 = _utf8(_rnc2rng.dumps(_rnc2rng.load(file)))
73
+ doc = _parseMemoryDocument(
74
+ rng_data_utf8, parser=None, url=_getFilenameForFile(file))
75
+ parser_ctxt = relaxng.xmlRelaxNGNewDocParserCtxt(doc._c_doc)
76
+ else:
77
+ doc = _parseDocument(file, parser=None, base_url=None)
78
+ parser_ctxt = relaxng.xmlRelaxNGNewDocParserCtxt(doc._c_doc)
79
+ else:
80
+ raise RelaxNGParseError, "No tree or file given"
81
+
82
+ if parser_ctxt is NULL:
83
+ if fake_c_doc is not NULL:
84
+ _destroyFakeDoc(doc._c_doc, fake_c_doc)
85
+ raise RelaxNGParseError(
86
+ self._error_log._buildExceptionMessage(
87
+ "Document is not parsable as Relax NG"),
88
+ self._error_log)
89
+
90
+ # Need a cast here because older libxml2 releases do not use 'const' in the functype.
91
+ relaxng.xmlRelaxNGSetParserStructuredErrors(
92
+ parser_ctxt, <xmlerror.xmlStructuredErrorFunc> _receiveError, <void*>self._error_log)
93
+ _connectGenericErrorLog(self._error_log, xmlerror.XML_FROM_RELAXNGP)
94
+ self._c_schema = relaxng.xmlRelaxNGParse(parser_ctxt)
95
+ _connectGenericErrorLog(None)
96
+
97
+ relaxng.xmlRelaxNGFreeParserCtxt(parser_ctxt)
98
+ if self._c_schema is NULL:
99
+ if fake_c_doc is not NULL:
100
+ _destroyFakeDoc(doc._c_doc, fake_c_doc)
101
+ raise RelaxNGParseError(
102
+ self._error_log._buildExceptionMessage(
103
+ "Document is not valid Relax NG"),
104
+ self._error_log)
105
+ if fake_c_doc is not NULL:
106
+ _destroyFakeDoc(doc._c_doc, fake_c_doc)
107
+
108
+ def __dealloc__(self):
109
+ relaxng.xmlRelaxNGFree(self._c_schema)
110
+
111
+ def __call__(self, etree):
112
+ """__call__(self, etree)
113
+
114
+ Validate doc using Relax NG.
115
+
116
+ Returns true if document is valid, false if not."""
117
+ cdef _Document doc
118
+ cdef _Element root_node
119
+ cdef xmlDoc* c_doc
120
+ cdef relaxng.xmlRelaxNGValidCtxt* valid_ctxt
121
+ cdef int ret
122
+
123
+ assert self._c_schema is not NULL, "RelaxNG instance not initialised"
124
+ doc = _documentOrRaise(etree)
125
+ root_node = _rootNodeOrRaise(etree)
126
+
127
+ valid_ctxt = relaxng.xmlRelaxNGNewValidCtxt(self._c_schema)
128
+ if valid_ctxt is NULL:
129
+ raise MemoryError()
130
+
131
+ try:
132
+ self._error_log.clear()
133
+ # Need a cast here because older libxml2 releases do not use 'const' in the functype.
134
+ relaxng.xmlRelaxNGSetValidStructuredErrors(
135
+ valid_ctxt, <xmlerror.xmlStructuredErrorFunc> _receiveError, <void*>self._error_log)
136
+ _connectGenericErrorLog(self._error_log, xmlerror.XML_FROM_RELAXNGV)
137
+ c_doc = _fakeRootDoc(doc._c_doc, root_node._c_node)
138
+ with nogil:
139
+ ret = relaxng.xmlRelaxNGValidateDoc(valid_ctxt, c_doc)
140
+ _destroyFakeDoc(doc._c_doc, c_doc)
141
+ finally:
142
+ _connectGenericErrorLog(None)
143
+ relaxng.xmlRelaxNGFreeValidCtxt(valid_ctxt)
144
+
145
+ if ret == -1:
146
+ raise RelaxNGValidateError(
147
+ "Internal error in Relax NG validation",
148
+ self._error_log)
149
+ if ret == 0:
150
+ return True
151
+ else:
152
+ return False
153
+
154
+ @classmethod
155
+ def from_rnc_string(cls, src, base_url=None):
156
+ """Parse a RelaxNG schema in compact syntax from a text string
157
+
158
+ Requires the rnc2rng package to be installed.
159
+
160
+ Passing the source URL or file path of the source as 'base_url'
161
+ will enable resolving resource references relative to the source.
162
+ """
163
+ _require_rnc2rng()
164
+ rng_str = utf8(_rnc2rng.dumps(_rnc2rng.loads(src)))
165
+ return cls(_parseMemoryDocument(rng_str, parser=None, url=base_url))
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/sax.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ SAX-based adapter to copy trees from/to the Python standard library.
3
+
4
+ Use the `ElementTreeContentHandler` class to build an ElementTree from
5
+ SAX events.
6
+
7
+ Use the `ElementTreeProducer` class or the `saxify()` function to fire
8
+ the SAX events of an ElementTree against a SAX ContentHandler.
9
+
10
+ See https://lxml.de/sax.html
11
+ """
12
+
13
+
14
+ from xml.sax.handler import ContentHandler
15
+ from lxml import etree
16
+ from lxml.etree import ElementTree, SubElement
17
+ from lxml.etree import Comment, ProcessingInstruction
18
+
19
+ try:
20
+ from types import GenericAlias as _GenericAlias
21
+ except ImportError:
22
+ # Python 3.8 - we only need this as return value from "__class_getitem__"
23
+ def _GenericAlias(cls, item):
24
+ return f"{cls.__name__}[{item.__name__}]"
25
+
26
+
27
+ class SaxError(etree.LxmlError):
28
+ """General SAX error.
29
+ """
30
+
31
+
32
+ def _getNsTag(tag):
33
+ if tag[0] == '{' and '}' in tag:
34
+ return tuple(tag[1:].split('}', 1))
35
+ else:
36
+ return None, tag
37
+
38
+
39
+ class ElementTreeContentHandler(ContentHandler):
40
+ """Build an lxml ElementTree from SAX events.
41
+ """
42
+ def __init__(self, makeelement=None):
43
+ ContentHandler.__init__(self)
44
+ self._root = None
45
+ self._root_siblings = []
46
+ self._element_stack = []
47
+ self._default_ns = None
48
+ self._ns_mapping = { None : [None] }
49
+ self._new_mappings = {}
50
+ if makeelement is None:
51
+ makeelement = etree.Element
52
+ self._makeelement = makeelement
53
+
54
+ def _get_etree(self):
55
+ "Contains the generated ElementTree after parsing is finished."
56
+ return ElementTree(self._root)
57
+
58
+ etree = property(_get_etree, doc=_get_etree.__doc__)
59
+
60
+ def setDocumentLocator(self, locator):
61
+ pass
62
+
63
+ def startDocument(self):
64
+ pass
65
+
66
+ def endDocument(self):
67
+ pass
68
+
69
+ def startPrefixMapping(self, prefix, uri):
70
+ self._new_mappings[prefix] = uri
71
+ try:
72
+ self._ns_mapping[prefix].append(uri)
73
+ except KeyError:
74
+ self._ns_mapping[prefix] = [uri]
75
+ if prefix is None:
76
+ self._default_ns = uri
77
+
78
+ def endPrefixMapping(self, prefix):
79
+ ns_uri_list = self._ns_mapping[prefix]
80
+ ns_uri_list.pop()
81
+ if prefix is None:
82
+ self._default_ns = ns_uri_list[-1]
83
+
84
+ def _buildTag(self, ns_name_tuple):
85
+ ns_uri, local_name = ns_name_tuple
86
+ if ns_uri:
87
+ el_tag = "{%s}%s" % ns_name_tuple
88
+ elif self._default_ns:
89
+ el_tag = "{%s}%s" % (self._default_ns, local_name)
90
+ else:
91
+ el_tag = local_name
92
+ return el_tag
93
+
94
+ def startElementNS(self, ns_name, qname, attributes=None):
95
+ el_name = self._buildTag(ns_name)
96
+ if attributes:
97
+ attrs = {}
98
+ try:
99
+ iter_attributes = attributes.iteritems()
100
+ except AttributeError:
101
+ iter_attributes = attributes.items()
102
+
103
+ for name_tuple, value in iter_attributes:
104
+ if name_tuple[0]:
105
+ attr_name = "{%s}%s" % name_tuple
106
+ else:
107
+ attr_name = name_tuple[1]
108
+ attrs[attr_name] = value
109
+ else:
110
+ attrs = None
111
+
112
+ element_stack = self._element_stack
113
+ if self._root is None:
114
+ element = self._root = \
115
+ self._makeelement(el_name, attrs, self._new_mappings)
116
+ if self._root_siblings and hasattr(element, 'addprevious'):
117
+ for sibling in self._root_siblings:
118
+ element.addprevious(sibling)
119
+ del self._root_siblings[:]
120
+ else:
121
+ element = SubElement(element_stack[-1], el_name,
122
+ attrs, self._new_mappings)
123
+ element_stack.append(element)
124
+
125
+ self._new_mappings.clear()
126
+
127
+ def processingInstruction(self, target, data):
128
+ pi = ProcessingInstruction(target, data)
129
+ if self._root is None:
130
+ self._root_siblings.append(pi)
131
+ else:
132
+ self._element_stack[-1].append(pi)
133
+
134
+ def endElementNS(self, ns_name, qname):
135
+ element = self._element_stack.pop()
136
+ el_tag = self._buildTag(ns_name)
137
+ if el_tag != element.tag:
138
+ raise SaxError("Unexpected element closed: " + el_tag)
139
+
140
+ def startElement(self, name, attributes=None):
141
+ if attributes:
142
+ attributes = {(None, k): v for k, v in attributes.items()}
143
+ self.startElementNS((None, name), name, attributes)
144
+
145
+ def endElement(self, name):
146
+ self.endElementNS((None, name), name)
147
+
148
+ def characters(self, data):
149
+ last_element = self._element_stack[-1]
150
+ try:
151
+ # if there already is a child element, we must append to its tail
152
+ last_element = last_element[-1]
153
+ except IndexError:
154
+ # otherwise: append to the text
155
+ last_element.text = (last_element.text or '') + data
156
+ else:
157
+ last_element.tail = (last_element.tail or '') + data
158
+
159
+ ignorableWhitespace = characters
160
+
161
+ # Allow subscripting sax.ElementTreeContentHandler in type annotions (PEP 560)
162
+ def __class_getitem__(cls, item):
163
+ return _GenericAlias(cls, item)
164
+
165
+
166
+ class ElementTreeProducer:
167
+ """Produces SAX events for an element and children.
168
+ """
169
+ def __init__(self, element_or_tree, content_handler):
170
+ try:
171
+ element = element_or_tree.getroot()
172
+ except AttributeError:
173
+ element = element_or_tree
174
+ self._element = element
175
+ self._content_handler = content_handler
176
+ from xml.sax.xmlreader import AttributesNSImpl as attr_class
177
+ self._attr_class = attr_class
178
+ self._empty_attributes = attr_class({}, {})
179
+
180
+ def saxify(self):
181
+ self._content_handler.startDocument()
182
+
183
+ element = self._element
184
+ if hasattr(element, 'getprevious'):
185
+ siblings = []
186
+ sibling = element.getprevious()
187
+ while getattr(sibling, 'tag', None) is ProcessingInstruction:
188
+ siblings.append(sibling)
189
+ sibling = sibling.getprevious()
190
+ for sibling in siblings[::-1]:
191
+ self._recursive_saxify(sibling, {})
192
+
193
+ self._recursive_saxify(element, {})
194
+
195
+ if hasattr(element, 'getnext'):
196
+ sibling = element.getnext()
197
+ while getattr(sibling, 'tag', None) is ProcessingInstruction:
198
+ self._recursive_saxify(sibling, {})
199
+ sibling = sibling.getnext()
200
+
201
+ self._content_handler.endDocument()
202
+
203
+ def _recursive_saxify(self, element, parent_nsmap):
204
+ content_handler = self._content_handler
205
+ tag = element.tag
206
+ if tag is Comment or tag is ProcessingInstruction:
207
+ if tag is ProcessingInstruction:
208
+ content_handler.processingInstruction(
209
+ element.target, element.text)
210
+ tail = element.tail
211
+ if tail:
212
+ content_handler.characters(tail)
213
+ return
214
+
215
+ element_nsmap = element.nsmap
216
+ new_prefixes = []
217
+ if element_nsmap != parent_nsmap:
218
+ # There have been updates to the namespace
219
+ for prefix, ns_uri in element_nsmap.items():
220
+ if parent_nsmap.get(prefix) != ns_uri:
221
+ new_prefixes.append( (prefix, ns_uri) )
222
+
223
+ attribs = element.items()
224
+ if attribs:
225
+ attr_values = {}
226
+ attr_qnames = {}
227
+ for attr_ns_name, value in attribs:
228
+ attr_ns_tuple = _getNsTag(attr_ns_name)
229
+ attr_values[attr_ns_tuple] = value
230
+ attr_qnames[attr_ns_tuple] = self._build_qname(
231
+ attr_ns_tuple[0], attr_ns_tuple[1], element_nsmap,
232
+ preferred_prefix=None, is_attribute=True)
233
+ sax_attributes = self._attr_class(attr_values, attr_qnames)
234
+ else:
235
+ sax_attributes = self._empty_attributes
236
+
237
+ ns_uri, local_name = _getNsTag(tag)
238
+ qname = self._build_qname(
239
+ ns_uri, local_name, element_nsmap, element.prefix, is_attribute=False)
240
+
241
+ for prefix, uri in new_prefixes:
242
+ content_handler.startPrefixMapping(prefix, uri)
243
+ content_handler.startElementNS(
244
+ (ns_uri, local_name), qname, sax_attributes)
245
+ text = element.text
246
+ if text:
247
+ content_handler.characters(text)
248
+ for child in element:
249
+ self._recursive_saxify(child, element_nsmap)
250
+ content_handler.endElementNS((ns_uri, local_name), qname)
251
+ for prefix, uri in new_prefixes:
252
+ content_handler.endPrefixMapping(prefix)
253
+ tail = element.tail
254
+ if tail:
255
+ content_handler.characters(tail)
256
+
257
+ def _build_qname(self, ns_uri, local_name, nsmap, preferred_prefix, is_attribute):
258
+ if ns_uri is None:
259
+ return local_name
260
+
261
+ if not is_attribute and nsmap.get(preferred_prefix) == ns_uri:
262
+ prefix = preferred_prefix
263
+ else:
264
+ # Pick the first matching prefix, in alphabetical order.
265
+ candidates = [
266
+ pfx for (pfx, uri) in nsmap.items()
267
+ if pfx is not None and uri == ns_uri
268
+ ]
269
+ prefix = (
270
+ candidates[0] if len(candidates) == 1
271
+ else min(candidates) if candidates
272
+ else None
273
+ )
274
+
275
+ if prefix is None:
276
+ # Default namespace
277
+ return local_name
278
+ return prefix + ':' + local_name
279
+
280
+
281
+ def saxify(element_or_tree, content_handler):
282
+ """One-shot helper to generate SAX events from an XML tree and fire
283
+ them against a SAX ContentHandler.
284
+ """
285
+ return ElementTreeProducer(element_or_tree, content_handler).saxify()
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/schematron.pxi ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # support for Schematron validation
2
+ from lxml.includes cimport schematron
3
+
4
+
5
+ cdef class SchematronError(LxmlError):
6
+ """Base class of all Schematron errors.
7
+ """
8
+
9
+ cdef class SchematronParseError(SchematronError):
10
+ """Error while parsing an XML document as Schematron schema.
11
+ """
12
+
13
+ cdef class SchematronValidateError(SchematronError):
14
+ """Error while validating an XML document with a Schematron schema.
15
+ """
16
+
17
+
18
+ ################################################################################
19
+ # Schematron
20
+
21
+ cdef class Schematron(_Validator):
22
+ """Schematron(self, etree=None, file=None)
23
+ A Schematron validator.
24
+
25
+ Pass a root Element or an ElementTree to turn it into a validator.
26
+ Alternatively, pass a filename as keyword argument 'file' to parse from
27
+ the file system.
28
+
29
+ Schematron is a less well known, but very powerful schema language. The main
30
+ idea is to use the capabilities of XPath to put restrictions on the structure
31
+ and the content of XML documents. Here is a simple example::
32
+
33
+ >>> schematron = Schematron(XML('''
34
+ ... <schema xmlns="http://www.ascc.net/xml/schematron" >
35
+ ... <pattern name="id is the only permitted attribute name">
36
+ ... <rule context="*">
37
+ ... <report test="@*[not(name()='id')]">Attribute
38
+ ... <name path="@*[not(name()='id')]"/> is forbidden<name/>
39
+ ... </report>
40
+ ... </rule>
41
+ ... </pattern>
42
+ ... </schema>
43
+ ... '''))
44
+
45
+ >>> xml = XML('''
46
+ ... <AAA name="aaa">
47
+ ... <BBB id="bbb"/>
48
+ ... <CCC color="ccc"/>
49
+ ... </AAA>
50
+ ... ''')
51
+
52
+ >>> schematron.validate(xml)
53
+ 0
54
+
55
+ >>> xml = XML('''
56
+ ... <AAA id="aaa">
57
+ ... <BBB id="bbb"/>
58
+ ... <CCC/>
59
+ ... </AAA>
60
+ ... ''')
61
+
62
+ >>> schematron.validate(xml)
63
+ 1
64
+
65
+ Schematron was added to libxml2 in version 2.6.21. Before version 2.6.32,
66
+ however, Schematron lacked support for error reporting other than to stderr.
67
+ This version is therefore required to retrieve validation warnings and
68
+ errors in lxml.
69
+ """
70
+ cdef schematron.xmlSchematron* _c_schema
71
+ cdef xmlDoc* _c_schema_doc
72
+
73
+ def __init__(self, etree=None, *, file=None):
74
+ cdef _Document doc
75
+ cdef _Element root_node
76
+ cdef xmlNode* c_node
77
+ cdef char* c_href
78
+ cdef schematron.xmlSchematronParserCtxt* parser_ctxt = NULL
79
+ _Validator.__init__(self)
80
+ if not config.ENABLE_SCHEMATRON:
81
+ raise SchematronError, \
82
+ "lxml.etree was compiled without Schematron support."
83
+
84
+ import warnings
85
+ warnings.warn(
86
+ "The (non-ISO) Schematron feature is deprecated and will be removed from libxml2 and lxml. "
87
+ "Use 'lxml.isoschematron' instead.",
88
+ DeprecationWarning,
89
+ )
90
+
91
+ if etree is not None:
92
+ doc = _documentOrRaise(etree)
93
+ root_node = _rootNodeOrRaise(etree)
94
+ self._c_schema_doc = _copyDocRoot(doc._c_doc, root_node._c_node)
95
+ parser_ctxt = schematron.xmlSchematronNewDocParserCtxt(self._c_schema_doc)
96
+ elif file is not None:
97
+ filename = _getFilenameForFile(file)
98
+ if filename is None:
99
+ # XXX assume a string object
100
+ filename = file
101
+ filename = _encodeFilename(filename)
102
+ with self._error_log:
103
+ orig_loader = _register_document_loader()
104
+ parser_ctxt = schematron.xmlSchematronNewParserCtxt(_cstr(filename))
105
+ _reset_document_loader(orig_loader)
106
+ else:
107
+ raise SchematronParseError, "No tree or file given"
108
+
109
+ if parser_ctxt is NULL:
110
+ if self._c_schema_doc is not NULL:
111
+ tree.xmlFreeDoc(self._c_schema_doc)
112
+ self._c_schema_doc = NULL
113
+ raise MemoryError()
114
+
115
+ try:
116
+ with self._error_log:
117
+ orig_loader = _register_document_loader()
118
+ self._c_schema = schematron.xmlSchematronParse(parser_ctxt)
119
+ _reset_document_loader(orig_loader)
120
+ finally:
121
+ schematron.xmlSchematronFreeParserCtxt(parser_ctxt)
122
+
123
+ if self._c_schema is NULL:
124
+ raise SchematronParseError(
125
+ "Document is not a valid Schematron schema",
126
+ self._error_log)
127
+
128
+ def __dealloc__(self):
129
+ schematron.xmlSchematronFree(self._c_schema)
130
+ if self._c_schema_doc is not NULL:
131
+ tree.xmlFreeDoc(self._c_schema_doc)
132
+
133
+ def __call__(self, etree):
134
+ """__call__(self, etree)
135
+
136
+ Validate doc using Schematron.
137
+
138
+ Returns true if document is valid, false if not."""
139
+ cdef _Document doc
140
+ cdef _Element root_node
141
+ cdef xmlDoc* c_doc
142
+ cdef schematron.xmlSchematronValidCtxt* valid_ctxt
143
+ cdef int ret
144
+
145
+ assert self._c_schema is not NULL, "Schematron instance not initialised"
146
+ doc = _documentOrRaise(etree)
147
+ root_node = _rootNodeOrRaise(etree)
148
+
149
+ valid_ctxt = schematron.xmlSchematronNewValidCtxt(
150
+ self._c_schema, schematron.XML_SCHEMATRON_OUT_ERROR)
151
+ if valid_ctxt is NULL:
152
+ raise MemoryError()
153
+
154
+ try:
155
+ self._error_log.clear()
156
+ # Need a cast here because older libxml2 releases do not use 'const' in the functype.
157
+ schematron.xmlSchematronSetValidStructuredErrors(
158
+ valid_ctxt, <xmlerror.xmlStructuredErrorFunc> _receiveError, <void*>self._error_log)
159
+ c_doc = _fakeRootDoc(doc._c_doc, root_node._c_node)
160
+ with nogil:
161
+ ret = schematron.xmlSchematronValidateDoc(valid_ctxt, c_doc)
162
+ _destroyFakeDoc(doc._c_doc, c_doc)
163
+ finally:
164
+ schematron.xmlSchematronFreeValidCtxt(valid_ctxt)
165
+
166
+ if ret == -1:
167
+ raise SchematronValidateError(
168
+ "Internal error in Schematron validation",
169
+ self._error_log)
170
+ if ret == 0:
171
+ return True
172
+ else:
173
+ return False
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/serializer.pxi ADDED
@@ -0,0 +1,1849 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # XML serialization and output functions
2
+
3
+ cdef object GzipFile
4
+ from gzip import GzipFile
5
+
6
+
7
+ cdef class SerialisationError(LxmlError):
8
+ """A libxml2 error that occurred during serialisation.
9
+ """
10
+
11
+
12
+ cdef enum _OutputMethods:
13
+ OUTPUT_METHOD_XML
14
+ OUTPUT_METHOD_HTML
15
+ OUTPUT_METHOD_TEXT
16
+
17
+
18
+ cdef int _findOutputMethod(method) except -1:
19
+ if method is None:
20
+ return OUTPUT_METHOD_XML
21
+ method = method.lower()
22
+ if method == "xml":
23
+ return OUTPUT_METHOD_XML
24
+ if method == "html":
25
+ return OUTPUT_METHOD_HTML
26
+ if method == "text":
27
+ return OUTPUT_METHOD_TEXT
28
+ raise ValueError(f"unknown output method {method!r}")
29
+
30
+
31
+ cdef _textToString(xmlNode* c_node, encoding, bint with_tail):
32
+ cdef bint needs_conversion
33
+ cdef const_xmlChar* c_text
34
+ cdef xmlNode* c_text_node
35
+ cdef tree.xmlBuffer* c_buffer
36
+ cdef int error_result
37
+
38
+ c_buffer = tree.xmlBufferCreate()
39
+ if c_buffer is NULL:
40
+ raise MemoryError()
41
+
42
+ with nogil:
43
+ error_result = tree.xmlNodeBufGetContent(c_buffer, c_node)
44
+ if with_tail:
45
+ c_text_node = _textNodeOrSkip(c_node.next)
46
+ while c_text_node is not NULL:
47
+ tree.xmlBufferWriteChar(c_buffer, <const_char*>c_text_node.content)
48
+ c_text_node = _textNodeOrSkip(c_text_node.next)
49
+ c_text = tree.xmlBufferContent(c_buffer)
50
+
51
+ if error_result < 0 or c_text is NULL:
52
+ tree.xmlBufferFree(c_buffer)
53
+ raise SerialisationError, "Error during serialisation (out of memory?)"
54
+
55
+ try:
56
+ needs_conversion = 0
57
+ if encoding is unicode:
58
+ needs_conversion = 1
59
+ elif encoding is not None:
60
+ # Python prefers lower case encoding names
61
+ encoding = encoding.lower()
62
+ if encoding not in ('utf8', 'utf-8'):
63
+ if encoding == 'ascii':
64
+ if isutf8l(c_text, tree.xmlBufferLength(c_buffer)):
65
+ # will raise a decode error below
66
+ needs_conversion = 1
67
+ else:
68
+ needs_conversion = 1
69
+
70
+ if needs_conversion:
71
+ text = (<const_char*>c_text)[:tree.xmlBufferLength(c_buffer)].decode('utf8')
72
+ if encoding is not unicode:
73
+ encoding = _utf8(encoding)
74
+ text = python.PyUnicode_AsEncodedString(
75
+ text, encoding, 'strict')
76
+ else:
77
+ text = (<unsigned char*>c_text)[:tree.xmlBufferLength(c_buffer)]
78
+ finally:
79
+ tree.xmlBufferFree(c_buffer)
80
+ return text
81
+
82
+
83
+ cdef _tostring(_Element element, encoding, doctype, method,
84
+ bint write_xml_declaration, bint write_complete_document,
85
+ bint pretty_print, bint with_tail, int standalone):
86
+ """Serialize an element to an encoded string representation of its XML
87
+ tree.
88
+ """
89
+ cdef tree.xmlOutputBuffer* c_buffer
90
+ cdef tree.xmlBuf* c_result_buffer
91
+ cdef tree.xmlCharEncodingHandler* enchandler
92
+ cdef const_char* c_enc
93
+ cdef const_xmlChar* c_version
94
+ cdef const_xmlChar* c_doctype
95
+ cdef int c_method
96
+ cdef int error_result
97
+ if element is None:
98
+ return None
99
+ _assertValidNode(element)
100
+ c_method = _findOutputMethod(method)
101
+ if c_method == OUTPUT_METHOD_TEXT:
102
+ return _textToString(element._c_node, encoding, with_tail)
103
+ if encoding is None or encoding is unicode:
104
+ c_enc = NULL
105
+ else:
106
+ encoding = _utf8(encoding)
107
+ c_enc = _cstr(encoding)
108
+ if doctype is None:
109
+ c_doctype = NULL
110
+ else:
111
+ doctype = _utf8(doctype)
112
+ c_doctype = _xcstr(doctype)
113
+ # it is necessary to *and* find the encoding handler *and* use
114
+ # encoding during output
115
+ enchandler = tree.xmlFindCharEncodingHandler(c_enc)
116
+ if enchandler is NULL and c_enc is not NULL:
117
+ if encoding is not None:
118
+ encoding = encoding.decode('UTF-8')
119
+ raise LookupError, f"unknown encoding: '{encoding}'"
120
+ c_buffer = tree.xmlAllocOutputBuffer(enchandler)
121
+ if c_buffer is NULL:
122
+ tree.xmlCharEncCloseFunc(enchandler)
123
+ raise MemoryError()
124
+
125
+ with nogil:
126
+ _writeNodeToBuffer(c_buffer, element._c_node, c_enc, c_doctype, c_method,
127
+ write_xml_declaration, write_complete_document,
128
+ pretty_print, with_tail, standalone)
129
+ tree.xmlOutputBufferFlush(c_buffer)
130
+ if c_buffer.conv is not NULL:
131
+ c_result_buffer = c_buffer.conv
132
+ else:
133
+ c_result_buffer = c_buffer.buffer
134
+
135
+ error_result = c_buffer.error
136
+ if error_result != xmlerror.XML_ERR_OK:
137
+ tree.xmlOutputBufferClose(c_buffer)
138
+ _raiseSerialisationError(error_result)
139
+
140
+ try:
141
+ if encoding is unicode:
142
+ result = (<unsigned char*>tree.xmlBufContent(
143
+ c_result_buffer))[:tree.xmlBufUse(c_result_buffer)].decode('UTF-8')
144
+ else:
145
+ result = <bytes>(<unsigned char*>tree.xmlBufContent(
146
+ c_result_buffer))[:tree.xmlBufUse(c_result_buffer)]
147
+ finally:
148
+ error_result = tree.xmlOutputBufferClose(c_buffer)
149
+ if error_result == -1:
150
+ _raiseSerialisationError(error_result)
151
+ return result
152
+
153
+ cdef bytes _tostringC14N(element_or_tree, bint exclusive, bint with_comments, inclusive_ns_prefixes):
154
+ cdef xmlDoc* c_doc
155
+ cdef xmlChar* c_buffer = NULL
156
+ cdef int byte_count = -1
157
+ cdef bytes result
158
+ cdef _Document doc
159
+ cdef _Element element
160
+ cdef xmlChar **c_inclusive_ns_prefixes
161
+
162
+ if isinstance(element_or_tree, _Element):
163
+ _assertValidNode(<_Element>element_or_tree)
164
+ doc = (<_Element>element_or_tree)._doc
165
+ c_doc = _plainFakeRootDoc(doc._c_doc, (<_Element>element_or_tree)._c_node, 0)
166
+ else:
167
+ doc = _documentOrRaise(element_or_tree)
168
+ _assertValidDoc(doc)
169
+ c_doc = doc._c_doc
170
+
171
+ c_inclusive_ns_prefixes = _convert_ns_prefixes(c_doc.dict, inclusive_ns_prefixes) if inclusive_ns_prefixes else NULL
172
+ try:
173
+ with nogil:
174
+ byte_count = c14n.xmlC14NDocDumpMemory(
175
+ c_doc, NULL, exclusive, c_inclusive_ns_prefixes, with_comments, &c_buffer)
176
+
177
+ finally:
178
+ _destroyFakeDoc(doc._c_doc, c_doc)
179
+ if c_inclusive_ns_prefixes is not NULL:
180
+ python.lxml_free(c_inclusive_ns_prefixes)
181
+
182
+ if byte_count < 0 or c_buffer is NULL:
183
+ if c_buffer is not NULL:
184
+ tree.xmlFree(c_buffer)
185
+ raise C14NError, "C14N failed"
186
+ try:
187
+ result = c_buffer[:byte_count]
188
+ finally:
189
+ tree.xmlFree(c_buffer)
190
+ return result
191
+
192
+ cdef _raiseSerialisationError(int error_result):
193
+ if error_result == xmlerror.XML_ERR_NO_MEMORY:
194
+ raise MemoryError()
195
+ message = ErrorTypes._getName(error_result)
196
+ if message is None:
197
+ message = f"unknown error {error_result}"
198
+ raise SerialisationError, message
199
+
200
+ ############################################################
201
+ # low-level serialisation functions
202
+
203
+ cdef void _writeDoctype(tree.xmlOutputBuffer* c_buffer,
204
+ const_xmlChar* c_doctype) noexcept nogil:
205
+ tree.xmlOutputBufferWrite(c_buffer, tree.xmlStrlen(c_doctype),
206
+ <const_char*>c_doctype)
207
+ tree.xmlOutputBufferWriteString(c_buffer, "\n")
208
+
209
+ cdef void _writeNodeToBuffer(tree.xmlOutputBuffer* c_buffer,
210
+ xmlNode* c_node, const_char* encoding, const_xmlChar* c_doctype,
211
+ int c_method, bint write_xml_declaration,
212
+ bint write_complete_document,
213
+ bint pretty_print, bint with_tail,
214
+ int standalone) noexcept nogil:
215
+ cdef xmlNode* c_nsdecl_node
216
+ cdef xmlDoc* c_doc = c_node.doc
217
+ if write_xml_declaration and c_method == OUTPUT_METHOD_XML:
218
+ _writeDeclarationToBuffer(c_buffer, c_doc.version, encoding, standalone)
219
+
220
+ # comments/processing instructions before doctype declaration
221
+ if write_complete_document and not c_buffer.error and c_doc.intSubset:
222
+ _writePrevSiblings(c_buffer, <xmlNode*>c_doc.intSubset, encoding, pretty_print)
223
+
224
+ if c_doctype:
225
+ _writeDoctype(c_buffer, c_doctype)
226
+ # write internal DTD subset, preceding PIs/comments, etc.
227
+ if write_complete_document and not c_buffer.error:
228
+ if c_doctype is NULL:
229
+ _writeDtdToBuffer(c_buffer, c_doc, c_node.name, c_method, encoding)
230
+ _writePrevSiblings(c_buffer, c_node, encoding, pretty_print)
231
+
232
+ c_nsdecl_node = c_node
233
+ if not c_node.parent or c_node.parent.type != tree.XML_DOCUMENT_NODE:
234
+ # copy the node and add namespaces from parents
235
+ # this is required to make libxml write them
236
+ c_nsdecl_node = tree.xmlCopyNode(c_node, 2)
237
+ if not c_nsdecl_node:
238
+ c_buffer.error = xmlerror.XML_ERR_NO_MEMORY
239
+ return
240
+ _copyParentNamespaces(c_node, c_nsdecl_node)
241
+
242
+ c_nsdecl_node.parent = c_node.parent
243
+ c_nsdecl_node.children = c_node.children
244
+ c_nsdecl_node.last = c_node.last
245
+
246
+ # write node
247
+ if c_method == OUTPUT_METHOD_HTML:
248
+ tree.htmlNodeDumpFormatOutput(
249
+ c_buffer, c_doc, c_nsdecl_node, encoding, pretty_print)
250
+ else:
251
+ tree.xmlNodeDumpOutput(
252
+ c_buffer, c_doc, c_nsdecl_node, 0, pretty_print, encoding)
253
+
254
+ if c_nsdecl_node is not c_node:
255
+ # clean up
256
+ c_nsdecl_node.children = c_nsdecl_node.last = NULL
257
+ tree.xmlFreeNode(c_nsdecl_node)
258
+
259
+ if c_buffer.error:
260
+ return
261
+
262
+ # write tail, trailing comments, etc.
263
+ if with_tail:
264
+ _writeTail(c_buffer, c_node, encoding, c_method, pretty_print)
265
+ if write_complete_document:
266
+ _writeNextSiblings(c_buffer, c_node, encoding, pretty_print)
267
+ if pretty_print:
268
+ tree.xmlOutputBufferWrite(c_buffer, 1, "\n")
269
+
270
+ cdef void _writeDeclarationToBuffer(tree.xmlOutputBuffer* c_buffer,
271
+ const_xmlChar* version, const_char* encoding,
272
+ int standalone) noexcept nogil:
273
+ if version is NULL:
274
+ version = <unsigned char*>"1.0"
275
+ tree.xmlOutputBufferWrite(c_buffer, 15, "<?xml version='")
276
+ tree.xmlOutputBufferWriteString(c_buffer, <const_char*>version)
277
+ tree.xmlOutputBufferWrite(c_buffer, 12, "' encoding='")
278
+ tree.xmlOutputBufferWriteString(c_buffer, encoding)
279
+ if standalone == 0:
280
+ tree.xmlOutputBufferWrite(c_buffer, 20, "' standalone='no'?>\n")
281
+ elif standalone == 1:
282
+ tree.xmlOutputBufferWrite(c_buffer, 21, "' standalone='yes'?>\n")
283
+ else:
284
+ tree.xmlOutputBufferWrite(c_buffer, 4, "'?>\n")
285
+
286
+ cdef void _writeDtdToBuffer(tree.xmlOutputBuffer* c_buffer,
287
+ xmlDoc* c_doc, const_xmlChar* c_root_name,
288
+ int c_method, const_char* encoding) noexcept nogil:
289
+ cdef tree.xmlDtd* c_dtd
290
+ cdef xmlNode* c_node
291
+ cdef char* quotechar
292
+ c_dtd = c_doc.intSubset
293
+ if not c_dtd or not c_dtd.name:
294
+ return
295
+
296
+ # Name in document type declaration must match the root element tag.
297
+ # For XML, case sensitive match, for HTML insensitive.
298
+ if c_method == OUTPUT_METHOD_HTML:
299
+ if tree.xmlStrcasecmp(c_root_name, c_dtd.name) != 0:
300
+ return
301
+ else:
302
+ if tree.xmlStrcmp(c_root_name, c_dtd.name) != 0:
303
+ return
304
+
305
+ tree.xmlOutputBufferWrite(c_buffer, 10, "<!DOCTYPE ")
306
+ tree.xmlOutputBufferWriteString(c_buffer, <const_char*>c_dtd.name)
307
+
308
+ cdef const_xmlChar* public_id = c_dtd.ExternalID
309
+ cdef const_xmlChar* sys_url = c_dtd.SystemID
310
+ if public_id and public_id[0] == b'\0':
311
+ public_id = NULL
312
+ if sys_url and sys_url[0] == b'\0':
313
+ sys_url = NULL
314
+
315
+ if public_id:
316
+ tree.xmlOutputBufferWrite(c_buffer, 9, ' PUBLIC "')
317
+ tree.xmlOutputBufferWriteString(c_buffer, <const_char*>public_id)
318
+ if sys_url:
319
+ tree.xmlOutputBufferWrite(c_buffer, 2, '" ')
320
+ else:
321
+ tree.xmlOutputBufferWrite(c_buffer, 1, '"')
322
+ elif sys_url:
323
+ tree.xmlOutputBufferWrite(c_buffer, 8, ' SYSTEM ')
324
+
325
+ if sys_url:
326
+ if tree.xmlStrchr(sys_url, b'"'):
327
+ quotechar = '\''
328
+ else:
329
+ quotechar = '"'
330
+ tree.xmlOutputBufferWrite(c_buffer, 1, quotechar)
331
+ tree.xmlOutputBufferWriteString(c_buffer, <const_char*>sys_url)
332
+ tree.xmlOutputBufferWrite(c_buffer, 1, quotechar)
333
+
334
+ if (not c_dtd.entities and not c_dtd.elements and
335
+ not c_dtd.attributes and not c_dtd.notations and
336
+ not c_dtd.pentities):
337
+ tree.xmlOutputBufferWrite(c_buffer, 2, '>\n')
338
+ return
339
+
340
+ tree.xmlOutputBufferWrite(c_buffer, 3, ' [\n')
341
+ if c_dtd.notations and not c_buffer.error:
342
+ c_buf = tree.xmlBufferCreate()
343
+ if not c_buf:
344
+ c_buffer.error = xmlerror.XML_ERR_NO_MEMORY
345
+ return
346
+ tree.xmlDumpNotationTable(c_buf, <tree.xmlNotationTable*>c_dtd.notations)
347
+ tree.xmlOutputBufferWrite(
348
+ c_buffer, tree.xmlBufferLength(c_buf),
349
+ <const_char*>tree.xmlBufferContent(c_buf))
350
+ tree.xmlBufferFree(c_buf)
351
+ c_node = c_dtd.children
352
+ while c_node and not c_buffer.error:
353
+ tree.xmlNodeDumpOutput(c_buffer, c_node.doc, c_node, 0, 0, encoding)
354
+ c_node = c_node.next
355
+ tree.xmlOutputBufferWrite(c_buffer, 3, "]>\n")
356
+
357
+ cdef void _writeTail(tree.xmlOutputBuffer* c_buffer, xmlNode* c_node,
358
+ const_char* encoding, int c_method, bint pretty_print) noexcept nogil:
359
+ "Write the element tail."
360
+ c_node = c_node.next
361
+ while c_node and not c_buffer.error and c_node.type in (
362
+ tree.XML_TEXT_NODE, tree.XML_CDATA_SECTION_NODE):
363
+ if c_method == OUTPUT_METHOD_HTML:
364
+ tree.htmlNodeDumpFormatOutput(
365
+ c_buffer, c_node.doc, c_node, encoding, pretty_print)
366
+ else:
367
+ tree.xmlNodeDumpOutput(
368
+ c_buffer, c_node.doc, c_node, 0, pretty_print, encoding)
369
+ c_node = c_node.next
370
+
371
+ cdef void _writePrevSiblings(tree.xmlOutputBuffer* c_buffer, xmlNode* c_node,
372
+ const_char* encoding, bint pretty_print) noexcept nogil:
373
+ cdef xmlNode* c_sibling
374
+ if c_node.parent and _isElement(c_node.parent):
375
+ return
376
+ # we are at a root node, so add PI and comment siblings
377
+ c_sibling = c_node
378
+ while c_sibling.prev and \
379
+ (c_sibling.prev.type == tree.XML_PI_NODE or
380
+ c_sibling.prev.type == tree.XML_COMMENT_NODE):
381
+ c_sibling = c_sibling.prev
382
+ while c_sibling is not c_node and not c_buffer.error:
383
+ tree.xmlNodeDumpOutput(c_buffer, c_node.doc, c_sibling, 0,
384
+ pretty_print, encoding)
385
+ if pretty_print:
386
+ tree.xmlOutputBufferWriteString(c_buffer, "\n")
387
+ c_sibling = c_sibling.next
388
+
389
+ cdef void _writeNextSiblings(tree.xmlOutputBuffer* c_buffer, xmlNode* c_node,
390
+ const_char* encoding, bint pretty_print) noexcept nogil:
391
+ cdef xmlNode* c_sibling
392
+ if c_node.parent and _isElement(c_node.parent):
393
+ return
394
+ # we are at a root node, so add PI and comment siblings
395
+ c_sibling = c_node.next
396
+ while not c_buffer.error and c_sibling and \
397
+ (c_sibling.type == tree.XML_PI_NODE or
398
+ c_sibling.type == tree.XML_COMMENT_NODE):
399
+ if pretty_print:
400
+ tree.xmlOutputBufferWriteString(c_buffer, "\n")
401
+ tree.xmlNodeDumpOutput(c_buffer, c_node.doc, c_sibling, 0,
402
+ pretty_print, encoding)
403
+ c_sibling = c_sibling.next
404
+
405
+
406
+ # copied and adapted from libxml2 (xmlBufAttrSerializeTxtContent())
407
+ cdef _write_attr_string(tree.xmlOutputBuffer* buf, const char *string):
408
+ cdef const char *base
409
+ cdef const char *cur
410
+
411
+ if string == NULL:
412
+ return
413
+
414
+ base = cur = <const char*>string
415
+ while cur[0] != 0:
416
+ if cur[0] == b'\n':
417
+ if base != cur:
418
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
419
+
420
+ tree.xmlOutputBufferWrite(buf, 5, "&#10;")
421
+ cur += 1
422
+ base = cur
423
+
424
+ elif cur[0] == b'\r':
425
+ if base != cur:
426
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
427
+
428
+ tree.xmlOutputBufferWrite(buf, 5, "&#13;")
429
+ cur += 1
430
+ base = cur
431
+
432
+ elif cur[0] == b'\t':
433
+ if base != cur:
434
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
435
+
436
+ tree.xmlOutputBufferWrite(buf, 4, "&#9;")
437
+ cur += 1
438
+ base = cur
439
+
440
+ elif cur[0] == b'"':
441
+ if base != cur:
442
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
443
+
444
+ tree.xmlOutputBufferWrite(buf, 6, "&quot;")
445
+ cur += 1
446
+ base = cur
447
+
448
+ elif cur[0] == b'<':
449
+ if base != cur:
450
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
451
+
452
+ tree.xmlOutputBufferWrite(buf, 4, "&lt;")
453
+ cur += 1
454
+ base = cur
455
+
456
+ elif cur[0] == b'>':
457
+ if base != cur:
458
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
459
+
460
+ tree.xmlOutputBufferWrite(buf, 4, "&gt;")
461
+ cur += 1
462
+ base = cur
463
+ elif cur[0] == b'&':
464
+ if base != cur:
465
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
466
+
467
+ tree.xmlOutputBufferWrite(buf, 5, "&amp;")
468
+ cur += 1
469
+ base = cur
470
+
471
+ else:
472
+ # Leave further encoding and escaping to the buffer encoder.
473
+ cur += 1
474
+
475
+ if base != cur:
476
+ tree.xmlOutputBufferWrite(buf, cur - base, base)
477
+
478
+
479
+ cdef void _write_cdata_section(tree.xmlOutputBuffer* buf, const char* c_data, const char* c_end):
480
+ tree.xmlOutputBufferWrite(buf, 9, "<![CDATA[")
481
+ while c_end - c_data > limits.INT_MAX:
482
+ tree.xmlOutputBufferWrite(buf, limits.INT_MAX, c_data)
483
+ c_data += limits.INT_MAX
484
+ tree.xmlOutputBufferWrite(buf, c_end - c_data, c_data)
485
+ tree.xmlOutputBufferWrite(buf, 3, "]]>")
486
+
487
+
488
+ cdef _write_cdata_string(tree.xmlOutputBuffer* buf, bytes bstring):
489
+ cdef const char* c_data = bstring
490
+ cdef const char* c_end = c_data + len(bstring)
491
+ cdef const char* c_pos = c_data
492
+ cdef bint nothing_written = True
493
+
494
+ while True:
495
+ c_pos = <const char*> cstring_h.memchr(c_pos, b']', c_end - c_pos)
496
+ if not c_pos:
497
+ break
498
+ c_pos += 1
499
+ next_char = c_pos[0]
500
+ c_pos += 1
501
+ if next_char != b']':
502
+ continue
503
+ # Found ']]', c_pos points to next character.
504
+ while c_pos[0] == b']':
505
+ c_pos += 1
506
+ if c_pos[0] != b'>':
507
+ if c_pos == c_end:
508
+ break
509
+ # c_pos[0] is neither ']' nor '>', continue with next character.
510
+ c_pos += 1
511
+ continue
512
+
513
+ # Write section up to ']]' and start next block at trailing '>'.
514
+ _write_cdata_section(buf, c_data, c_pos)
515
+ nothing_written = False
516
+ c_data = c_pos
517
+ c_pos += 1
518
+
519
+ if nothing_written or c_data < c_end:
520
+ _write_cdata_section(buf, c_data, c_end)
521
+
522
+
523
+ ############################################################
524
+ # output to file-like objects
525
+
526
+ cdef object io_open
527
+ from io import open as io_open
528
+
529
+ cdef object gzip
530
+ import gzip
531
+
532
+ cdef object getwriter
533
+ from codecs import getwriter
534
+ cdef object utf8_writer = getwriter('utf8')
535
+
536
+ cdef object contextmanager
537
+ from contextlib import contextmanager
538
+
539
+ cdef object _open_utf8_file
540
+
541
+ @contextmanager
542
+ def _open_utf8_file(file, compression=0):
543
+ file = _getFSPathOrObject(file)
544
+ if _isString(file):
545
+ if compression:
546
+ with gzip.GzipFile(file, mode='wb', compresslevel=compression) as zf:
547
+ yield utf8_writer(zf)
548
+ else:
549
+ with io_open(file, 'w', encoding='utf8') as f:
550
+ yield f
551
+ else:
552
+ if compression:
553
+ with gzip.GzipFile(fileobj=file, mode='wb', compresslevel=compression) as zf:
554
+ yield utf8_writer(zf)
555
+ else:
556
+ yield utf8_writer(file)
557
+
558
+
559
+ @cython.final
560
+ @cython.internal
561
+ cdef class _FilelikeWriter:
562
+ cdef object _filelike
563
+ cdef object _close_filelike
564
+ cdef _ExceptionContext _exc_context
565
+ cdef _ErrorLog error_log
566
+
567
+ def __cinit__(self, filelike, exc_context=None, compression=None, close=False):
568
+ if compression is not None and compression > 0:
569
+ filelike = GzipFile(
570
+ fileobj=filelike, mode='wb', compresslevel=compression)
571
+ self._close_filelike = filelike.close
572
+ elif close:
573
+ self._close_filelike = filelike.close
574
+ self._filelike = filelike
575
+ if exc_context is None:
576
+ self._exc_context = _ExceptionContext()
577
+ else:
578
+ self._exc_context = exc_context
579
+ self.error_log = _ErrorLog()
580
+
581
+ cdef tree.xmlOutputBuffer* _createOutputBuffer(
582
+ self, tree.xmlCharEncodingHandler* enchandler) except NULL:
583
+ cdef tree.xmlOutputBuffer* c_buffer
584
+ c_buffer = tree.xmlOutputBufferCreateIO(
585
+ <tree.xmlOutputWriteCallback>_writeFilelikeWriter, _closeFilelikeWriter,
586
+ <python.PyObject*>self, enchandler)
587
+ if c_buffer is NULL:
588
+ raise IOError, "Could not create I/O writer context."
589
+ return c_buffer
590
+
591
+ cdef int write(self, char* c_buffer, int size) noexcept:
592
+ try:
593
+ if self._filelike is None:
594
+ raise IOError, "File is already closed"
595
+ py_buffer = <bytes>c_buffer[:size]
596
+ self._filelike.write(py_buffer)
597
+ except:
598
+ size = -1
599
+ self._exc_context._store_raised()
600
+ finally:
601
+ return size # and swallow any further exceptions
602
+
603
+ cdef int close(self) noexcept:
604
+ retval = 0
605
+ try:
606
+ if self._close_filelike is not None:
607
+ self._close_filelike()
608
+ # we should not close the file here as we didn't open it
609
+ self._filelike = None
610
+ except:
611
+ retval = -1
612
+ self._exc_context._store_raised()
613
+ finally:
614
+ return retval # and swallow any further exceptions
615
+
616
+ cdef int _writeFilelikeWriter(void* ctxt, char* c_buffer, int length) noexcept:
617
+ return (<_FilelikeWriter>ctxt).write(c_buffer, length)
618
+
619
+ cdef int _closeFilelikeWriter(void* ctxt) noexcept:
620
+ return (<_FilelikeWriter>ctxt).close()
621
+
622
+ cdef _tofilelike(f, _Element element, encoding, doctype, method,
623
+ bint write_xml_declaration, bint write_doctype,
624
+ bint pretty_print, bint with_tail, int standalone,
625
+ int compression):
626
+ cdef _FilelikeWriter writer = None
627
+ cdef tree.xmlOutputBuffer* c_buffer
628
+ cdef tree.xmlCharEncodingHandler* enchandler
629
+ cdef const_char* c_enc
630
+ cdef const_xmlChar* c_doctype
631
+ cdef int error_result
632
+
633
+ c_method = _findOutputMethod(method)
634
+ if c_method == OUTPUT_METHOD_TEXT:
635
+ data = _textToString(element._c_node, encoding, with_tail)
636
+ if compression:
637
+ bytes_out = BytesIO()
638
+ with GzipFile(fileobj=bytes_out, mode='wb', compresslevel=compression) as gzip_file:
639
+ gzip_file.write(data)
640
+ data = bytes_out.getvalue()
641
+ f = _getFSPathOrObject(f)
642
+ if _isString(f):
643
+ filename8 = _encodeFilename(f)
644
+ with open(filename8, 'wb') as f:
645
+ f.write(data)
646
+ else:
647
+ f.write(data)
648
+ return
649
+
650
+ if encoding is None:
651
+ c_enc = NULL
652
+ else:
653
+ encoding = _utf8(encoding)
654
+ c_enc = _cstr(encoding)
655
+ if doctype is None:
656
+ c_doctype = NULL
657
+ else:
658
+ doctype = _utf8(doctype)
659
+ c_doctype = _xcstr(doctype)
660
+
661
+ writer = _create_output_buffer(f, c_enc, compression, &c_buffer, close=False)
662
+ if writer is None:
663
+ with nogil:
664
+ error_result = _serialise_node(
665
+ c_buffer, c_doctype, c_enc, element._c_node, c_method,
666
+ write_xml_declaration, write_doctype, pretty_print, with_tail, standalone)
667
+ else:
668
+ error_result = _serialise_node(
669
+ c_buffer, c_doctype, c_enc, element._c_node, c_method,
670
+ write_xml_declaration, write_doctype, pretty_print, with_tail, standalone)
671
+
672
+ if writer is not None:
673
+ writer._exc_context._raise_if_stored()
674
+ if error_result != xmlerror.XML_ERR_OK:
675
+ _raiseSerialisationError(error_result)
676
+
677
+
678
+ cdef int _serialise_node(tree.xmlOutputBuffer* c_buffer, const_xmlChar* c_doctype,
679
+ const_char* c_enc, xmlNode* c_node, int c_method,
680
+ bint write_xml_declaration, bint write_doctype, bint pretty_print,
681
+ bint with_tail, int standalone) noexcept nogil:
682
+ _writeNodeToBuffer(
683
+ c_buffer, c_node, c_enc, c_doctype, c_method,
684
+ write_xml_declaration, write_doctype, pretty_print, with_tail, standalone)
685
+ error_result = c_buffer.error
686
+ if error_result == xmlerror.XML_ERR_OK:
687
+ error_result = tree.xmlOutputBufferClose(c_buffer)
688
+ if error_result != -1:
689
+ error_result = xmlerror.XML_ERR_OK
690
+ else:
691
+ tree.xmlOutputBufferClose(c_buffer)
692
+ return error_result
693
+
694
+
695
+ cdef _FilelikeWriter _create_output_buffer(
696
+ f, const_char* c_enc, int c_compression,
697
+ tree.xmlOutputBuffer** c_buffer_ret, bint close):
698
+ cdef tree.xmlOutputBuffer* c_buffer
699
+ cdef _FilelikeWriter writer
700
+ cdef bytes filename8
701
+ enchandler = tree.xmlFindCharEncodingHandler(c_enc)
702
+ if enchandler is NULL:
703
+ raise LookupError(
704
+ f"unknown encoding: '{c_enc.decode('UTF-8') if c_enc is not NULL else u''}'")
705
+ try:
706
+ f = _getFSPathOrObject(f)
707
+
708
+ if c_compression and not HAS_ZLIB_COMPRESSION and _isString(f):
709
+ # Let "_FilelikeWriter" fall back to Python's GzipFile.
710
+ f = open(f, mode="wb")
711
+ close = True
712
+
713
+ if _isString(f):
714
+ filename8 = _encodeFilename(f)
715
+ if b'%' in filename8 and (
716
+ # Exclude absolute Windows paths and file:// URLs.
717
+ _isFilePath(<const xmlChar*>filename8) not in (NO_FILE_PATH, ABS_WIN_FILE_PATH)
718
+ or filename8[:7].lower() == b'file://'):
719
+ # A file path (not a URL) containing the '%' URL escape character.
720
+ # libxml2 uses URL-unescaping on these, so escape the path before passing it in.
721
+ filename8 = filename8.replace(b'%', b'%25')
722
+ c_buffer = tree.xmlOutputBufferCreateFilename(
723
+ _cstr(filename8), enchandler, c_compression)
724
+ if c_buffer is NULL:
725
+ python.PyErr_SetFromErrno(IOError) # raises IOError
726
+ writer = None
727
+ elif hasattr(f, 'write'):
728
+ writer = _FilelikeWriter(f, compression=c_compression, close=close)
729
+ c_buffer = writer._createOutputBuffer(enchandler)
730
+ else:
731
+ raise TypeError(
732
+ f"File or filename expected, got '{python._fqtypename(f).decode('UTF-8')}'")
733
+ except:
734
+ tree.xmlCharEncCloseFunc(enchandler)
735
+ raise
736
+ c_buffer_ret[0] = c_buffer
737
+ return writer
738
+
739
+ cdef xmlChar **_convert_ns_prefixes(tree.xmlDict* c_dict, ns_prefixes) except NULL:
740
+ cdef size_t i, num_ns_prefixes = len(ns_prefixes)
741
+ # Need to allocate one extra memory block to handle last NULL entry
742
+ c_ns_prefixes = <xmlChar **>python.lxml_malloc(num_ns_prefixes + 1, sizeof(xmlChar*))
743
+ if not c_ns_prefixes:
744
+ raise MemoryError()
745
+ i = 0
746
+ try:
747
+ for prefix in ns_prefixes:
748
+ prefix_utf = _utf8(prefix)
749
+ c_prefix_len = len(prefix_utf)
750
+ if c_prefix_len > limits.INT_MAX:
751
+ raise ValueError("Prefix too long")
752
+ c_prefix = tree.xmlDictExists(c_dict, _xcstr(prefix_utf), <int> c_prefix_len)
753
+ if c_prefix:
754
+ # unknown prefixes do not need to get serialised
755
+ c_ns_prefixes[i] = <xmlChar*>c_prefix
756
+ i += 1
757
+ except:
758
+ python.lxml_free(c_ns_prefixes)
759
+ raise
760
+
761
+ c_ns_prefixes[i] = NULL # append end marker
762
+ return c_ns_prefixes
763
+
764
+ cdef _tofilelikeC14N(f, _Element element, bint exclusive, bint with_comments,
765
+ int compression, inclusive_ns_prefixes):
766
+ cdef _FilelikeWriter writer = None
767
+ cdef tree.xmlOutputBuffer* c_buffer
768
+ cdef xmlChar **c_inclusive_ns_prefixes = NULL
769
+ cdef char* c_filename
770
+ cdef xmlDoc* c_base_doc
771
+ cdef xmlDoc* c_doc
772
+ cdef int bytes_count, error = 0
773
+
774
+ c_base_doc = element._c_node.doc
775
+ c_doc = _fakeRootDoc(c_base_doc, element._c_node)
776
+ try:
777
+ c_inclusive_ns_prefixes = (
778
+ _convert_ns_prefixes(c_doc.dict, inclusive_ns_prefixes)
779
+ if inclusive_ns_prefixes else NULL)
780
+
781
+ f = _getFSPathOrObject(f)
782
+
783
+ close = False
784
+ if compression and not HAS_ZLIB_COMPRESSION and _isString(f):
785
+ # Let "_FilelikeWriter" fall back to Python's GzipFile.
786
+ f = open(f, mode="wb")
787
+ close = True
788
+
789
+ if _isString(f):
790
+ filename8 = _encodeFilename(f)
791
+ c_filename = _cstr(filename8)
792
+ with nogil:
793
+ error = c14n.xmlC14NDocSave(
794
+ c_doc, NULL, exclusive, c_inclusive_ns_prefixes,
795
+ with_comments, c_filename, compression)
796
+ elif hasattr(f, 'write'):
797
+ writer = _FilelikeWriter(f, compression=compression, close=close)
798
+ c_buffer = writer._createOutputBuffer(NULL)
799
+ try:
800
+ with writer.error_log:
801
+ bytes_count = c14n.xmlC14NDocSaveTo(
802
+ c_doc, NULL, exclusive, c_inclusive_ns_prefixes,
803
+ with_comments, c_buffer)
804
+ finally:
805
+ error = tree.xmlOutputBufferClose(c_buffer)
806
+ if bytes_count < 0:
807
+ error = bytes_count
808
+ elif error != -1:
809
+ error = xmlerror.XML_ERR_OK
810
+ else:
811
+ raise TypeError(f"File or filename expected, got '{python._fqtypename(f).decode('UTF-8')}'")
812
+ finally:
813
+ _destroyFakeDoc(c_base_doc, c_doc)
814
+ if c_inclusive_ns_prefixes is not NULL:
815
+ python.lxml_free(c_inclusive_ns_prefixes)
816
+
817
+ if writer is not None:
818
+ writer._exc_context._raise_if_stored()
819
+
820
+ if error < 0:
821
+ message = "C14N failed"
822
+ if writer is not None:
823
+ errors = writer.error_log
824
+ if len(errors):
825
+ message = errors[0].message
826
+ raise C14NError(message)
827
+
828
+
829
+ # C14N 2.0
830
+
831
+ def canonicalize(xml_data=None, *, out=None, from_file=None, **options):
832
+ """Convert XML to its C14N 2.0 serialised form.
833
+
834
+ If *out* is provided, it must be a file or file-like object that receives
835
+ the serialised canonical XML output (text, not bytes) through its ``.write()``
836
+ method. To write to a file, open it in text mode with encoding "utf-8".
837
+ If *out* is not provided, this function returns the output as text string.
838
+
839
+ Either *xml_data* (an XML string, tree or Element) or *file*
840
+ (a file path or file-like object) must be provided as input.
841
+
842
+ The configuration options are the same as for the ``C14NWriterTarget``.
843
+ """
844
+ if xml_data is None and from_file is None:
845
+ raise ValueError("Either 'xml_data' or 'from_file' must be provided as input")
846
+
847
+ sio = None
848
+ if out is None:
849
+ sio = out = StringIO()
850
+
851
+ target = C14NWriterTarget(out.write, **options)
852
+
853
+ if xml_data is not None and not isinstance(xml_data, basestring):
854
+ _tree_to_target(xml_data, target)
855
+ return sio.getvalue() if sio is not None else None
856
+
857
+ cdef _FeedParser parser = XMLParser(
858
+ target=target,
859
+ attribute_defaults=True,
860
+ collect_ids=False,
861
+ )
862
+
863
+ if xml_data is not None:
864
+ parser.feed(xml_data)
865
+ parser.close()
866
+ elif from_file is not None:
867
+ try:
868
+ _parseDocument(from_file, parser, base_url=None)
869
+ except _TargetParserResult:
870
+ pass
871
+
872
+ return sio.getvalue() if sio is not None else None
873
+
874
+
875
+ cdef _tree_to_target(element, target):
876
+ for event, elem in iterwalk(element, events=('start', 'end', 'start-ns', 'comment', 'pi')):
877
+ text = None
878
+ if event == 'start':
879
+ target.start(elem.tag, elem.attrib)
880
+ text = elem.text
881
+ elif event == 'end':
882
+ target.end(elem.tag)
883
+ text = elem.tail
884
+ elif event == 'start-ns':
885
+ target.start_ns(*elem)
886
+ continue
887
+ elif event == 'comment':
888
+ target.comment(elem.text)
889
+ text = elem.tail
890
+ elif event == 'pi':
891
+ target.pi(elem.target, elem.text)
892
+ text = elem.tail
893
+ if text:
894
+ target.data(text)
895
+ return target.close()
896
+
897
+
898
+ cdef object _looks_like_prefix_name = re.compile(r'^\w+:\w+$', re.UNICODE).match
899
+
900
+
901
+ cdef class C14NWriterTarget:
902
+ """
903
+ Canonicalization writer target for the XMLParser.
904
+
905
+ Serialises parse events to XML C14N 2.0.
906
+
907
+ Configuration options:
908
+
909
+ - *with_comments*: set to true to include comments
910
+ - *strip_text*: set to true to strip whitespace before and after text content
911
+ - *rewrite_prefixes*: set to true to replace namespace prefixes by "n{number}"
912
+ - *qname_aware_tags*: a set of qname aware tag names in which prefixes
913
+ should be replaced in text content
914
+ - *qname_aware_attrs*: a set of qname aware attribute names in which prefixes
915
+ should be replaced in text content
916
+ - *exclude_attrs*: a set of attribute names that should not be serialised
917
+ - *exclude_tags*: a set of tag names that should not be serialised
918
+ """
919
+ cdef object _write
920
+ cdef list _data
921
+ cdef set _qname_aware_tags
922
+ cdef object _find_qname_aware_attrs
923
+ cdef list _declared_ns_stack
924
+ cdef list _ns_stack
925
+ cdef dict _prefix_map
926
+ cdef list _preserve_space
927
+ cdef tuple _pending_start
928
+ cdef set _exclude_tags
929
+ cdef set _exclude_attrs
930
+ cdef Py_ssize_t _ignored_depth
931
+ cdef bint _with_comments
932
+ cdef bint _strip_text
933
+ cdef bint _rewrite_prefixes
934
+ cdef bint _root_seen
935
+ cdef bint _root_done
936
+
937
+ def __init__(self, write, *,
938
+ with_comments=False, strip_text=False, rewrite_prefixes=False,
939
+ qname_aware_tags=None, qname_aware_attrs=None,
940
+ exclude_attrs=None, exclude_tags=None):
941
+ self._write = write
942
+ self._data = []
943
+ self._with_comments = with_comments
944
+ self._strip_text = strip_text
945
+ self._exclude_attrs = set(exclude_attrs) if exclude_attrs else None
946
+ self._exclude_tags = set(exclude_tags) if exclude_tags else None
947
+
948
+ self._rewrite_prefixes = rewrite_prefixes
949
+ if qname_aware_tags:
950
+ self._qname_aware_tags = set(qname_aware_tags)
951
+ else:
952
+ self._qname_aware_tags = None
953
+ if qname_aware_attrs:
954
+ self._find_qname_aware_attrs = set(qname_aware_attrs).intersection
955
+ else:
956
+ self._find_qname_aware_attrs = None
957
+
958
+ # Stack with globally and newly declared namespaces as (uri, prefix) pairs.
959
+ self._declared_ns_stack = [[
960
+ ("http://www.w3.org/XML/1998/namespace", "xml"),
961
+ ]]
962
+ # Stack with user declared namespace prefixes as (uri, prefix) pairs.
963
+ self._ns_stack = []
964
+ if not rewrite_prefixes:
965
+ self._ns_stack.append(_DEFAULT_NAMESPACE_PREFIXES_ITEMS)
966
+ self._ns_stack.append([])
967
+ self._prefix_map = {}
968
+ self._preserve_space = [False]
969
+ self._pending_start = None
970
+ self._ignored_depth = 0
971
+ self._root_seen = False
972
+ self._root_done = False
973
+
974
+ def _iter_namespaces(self, ns_stack):
975
+ for namespaces in reversed(ns_stack):
976
+ if namespaces: # almost no element declares new namespaces
977
+ yield from namespaces
978
+
979
+ cdef _resolve_prefix_name(self, prefixed_name):
980
+ prefix, name = prefixed_name.split(':', 1)
981
+ for uri, p in self._iter_namespaces(self._ns_stack):
982
+ if p == prefix:
983
+ return f'{{{uri}}}{name}'
984
+ raise ValueError(f'Prefix {prefix} of QName "{prefixed_name}" is not declared in scope')
985
+
986
+ cdef _qname(self, qname, uri=None):
987
+ if uri is None:
988
+ uri, tag = qname[1:].rsplit('}', 1) if qname[:1] == '{' else ('', qname)
989
+ else:
990
+ tag = qname
991
+
992
+ prefixes_seen = set()
993
+ for u, prefix in self._iter_namespaces(self._declared_ns_stack):
994
+ if u == uri and prefix not in prefixes_seen:
995
+ return f'{prefix}:{tag}' if prefix else tag, tag, uri
996
+ prefixes_seen.add(prefix)
997
+
998
+ # Not declared yet => add new declaration.
999
+ if self._rewrite_prefixes:
1000
+ if uri in self._prefix_map:
1001
+ prefix = self._prefix_map[uri]
1002
+ else:
1003
+ prefix = self._prefix_map[uri] = f'n{len(self._prefix_map)}'
1004
+ self._declared_ns_stack[-1].append((uri, prefix))
1005
+ return f'{prefix}:{tag}', tag, uri
1006
+
1007
+ if not uri and '' not in prefixes_seen:
1008
+ # No default namespace declared => no prefix needed.
1009
+ return tag, tag, uri
1010
+
1011
+ for u, prefix in self._iter_namespaces(self._ns_stack):
1012
+ if u == uri:
1013
+ self._declared_ns_stack[-1].append((uri, prefix))
1014
+ return f'{prefix}:{tag}' if prefix else tag, tag, uri
1015
+
1016
+ if not uri:
1017
+ # As soon as a default namespace is defined,
1018
+ # anything that has no namespace (and thus, no prefix) goes there.
1019
+ return tag, tag, uri
1020
+
1021
+ raise ValueError(f'Namespace "{uri}" of name "{tag}" is not declared in scope')
1022
+
1023
+ def data(self, data):
1024
+ if not self._ignored_depth:
1025
+ self._data.append(data)
1026
+
1027
+ cdef _flush(self):
1028
+ cdef unicode data = ''.join(self._data)
1029
+ del self._data[:]
1030
+ if self._strip_text and not self._preserve_space[-1]:
1031
+ data = data.strip()
1032
+ if self._pending_start is not None:
1033
+ (tag, attrs, new_namespaces), self._pending_start = self._pending_start, None
1034
+ qname_text = data if ':' in data and _looks_like_prefix_name(data) else None
1035
+ self._start(tag, attrs, new_namespaces, qname_text)
1036
+ if qname_text is not None:
1037
+ return
1038
+ if data and self._root_seen:
1039
+ self._write(_escape_cdata_c14n(data))
1040
+
1041
+ def start_ns(self, prefix, uri):
1042
+ if self._ignored_depth:
1043
+ return
1044
+ # we may have to resolve qnames in text content
1045
+ if self._data:
1046
+ self._flush()
1047
+ self._ns_stack[-1].append((uri, prefix))
1048
+
1049
+ def start(self, tag, attrs):
1050
+ if self._exclude_tags is not None and (
1051
+ self._ignored_depth or tag in self._exclude_tags):
1052
+ self._ignored_depth += 1
1053
+ return
1054
+ if self._data:
1055
+ self._flush()
1056
+
1057
+ new_namespaces = []
1058
+ self._declared_ns_stack.append(new_namespaces)
1059
+
1060
+ if self._qname_aware_tags is not None and tag in self._qname_aware_tags:
1061
+ # Need to parse text first to see if it requires a prefix declaration.
1062
+ self._pending_start = (tag, attrs, new_namespaces)
1063
+ return
1064
+ self._start(tag, attrs, new_namespaces)
1065
+
1066
+ cdef _start(self, tag, attrs, new_namespaces, qname_text=None):
1067
+ if self._exclude_attrs is not None and attrs:
1068
+ attrs = {k: v for k, v in attrs.items() if k not in self._exclude_attrs}
1069
+
1070
+ qnames = {tag, *attrs}
1071
+ resolved_names = {}
1072
+
1073
+ # Resolve prefixes in attribute and tag text.
1074
+ if qname_text is not None:
1075
+ qname = resolved_names[qname_text] = self._resolve_prefix_name(qname_text)
1076
+ qnames.add(qname)
1077
+ if self._find_qname_aware_attrs is not None and attrs:
1078
+ qattrs = self._find_qname_aware_attrs(attrs)
1079
+ if qattrs:
1080
+ for attr_name in qattrs:
1081
+ value = attrs[attr_name]
1082
+ if _looks_like_prefix_name(value):
1083
+ qname = resolved_names[value] = self._resolve_prefix_name(value)
1084
+ qnames.add(qname)
1085
+ else:
1086
+ qattrs = None
1087
+ else:
1088
+ qattrs = None
1089
+
1090
+ # Assign prefixes in lexicographical order of used URIs.
1091
+ parsed_qnames = {n: self._qname(n) for n in sorted(
1092
+ qnames, key=lambda n: n.split('}', 1))}
1093
+
1094
+ # Write namespace declarations in prefix order ...
1095
+ if new_namespaces:
1096
+ attr_list = [
1097
+ ('xmlns:' + prefix if prefix else 'xmlns', uri)
1098
+ for uri, prefix in new_namespaces
1099
+ ]
1100
+ attr_list.sort()
1101
+ else:
1102
+ # almost always empty
1103
+ attr_list = []
1104
+
1105
+ # ... followed by attributes in URI+name order
1106
+ if attrs:
1107
+ for k, v in sorted(attrs.items()):
1108
+ if qattrs is not None and k in qattrs and v in resolved_names:
1109
+ v = parsed_qnames[resolved_names[v]][0]
1110
+ attr_qname, attr_name, uri = parsed_qnames[k]
1111
+ # No prefix for attributes in default ('') namespace.
1112
+ attr_list.append((attr_qname if uri else attr_name, v))
1113
+
1114
+ # Honour xml:space attributes.
1115
+ space_behaviour = attrs.get('{http://www.w3.org/XML/1998/namespace}space')
1116
+ self._preserve_space.append(
1117
+ space_behaviour == 'preserve' if space_behaviour
1118
+ else self._preserve_space[-1])
1119
+
1120
+ # Write the tag.
1121
+ write = self._write
1122
+ write('<' + parsed_qnames[tag][0])
1123
+ if attr_list:
1124
+ write(''.join([f' {k}="{_escape_attrib_c14n(v)}"' for k, v in attr_list]))
1125
+ write('>')
1126
+
1127
+ # Write the resolved qname text content.
1128
+ if qname_text is not None:
1129
+ write(_escape_cdata_c14n(parsed_qnames[resolved_names[qname_text]][0]))
1130
+
1131
+ self._root_seen = True
1132
+ self._ns_stack.append([])
1133
+
1134
+ def end(self, tag):
1135
+ if self._ignored_depth:
1136
+ self._ignored_depth -= 1
1137
+ return
1138
+ if self._data:
1139
+ self._flush()
1140
+ self._write(f'</{self._qname(tag)[0]}>')
1141
+ self._preserve_space.pop()
1142
+ self._root_done = len(self._preserve_space) == 1
1143
+ self._declared_ns_stack.pop()
1144
+ self._ns_stack.pop()
1145
+
1146
+ def comment(self, text):
1147
+ if not self._with_comments:
1148
+ return
1149
+ if self._ignored_depth:
1150
+ return
1151
+ if self._root_done:
1152
+ self._write('\n')
1153
+ elif self._root_seen and self._data:
1154
+ self._flush()
1155
+ self._write(f'<!--{_escape_cdata_c14n(text)}-->')
1156
+ if not self._root_seen:
1157
+ self._write('\n')
1158
+
1159
+ def pi(self, target, data):
1160
+ if self._ignored_depth:
1161
+ return
1162
+ if self._root_done:
1163
+ self._write('\n')
1164
+ elif self._root_seen and self._data:
1165
+ self._flush()
1166
+ self._write(
1167
+ f'<?{target} {_escape_cdata_c14n(data)}?>' if data else f'<?{target}?>')
1168
+ if not self._root_seen:
1169
+ self._write('\n')
1170
+
1171
+ def close(self):
1172
+ return None
1173
+
1174
+
1175
+ cdef _raise_serialization_error(text):
1176
+ raise TypeError("cannot serialize %r (type %s)" % (text, type(text).__name__))
1177
+
1178
+
1179
+ cdef unicode _escape_cdata_c14n(stext):
1180
+ # escape character data
1181
+ cdef unicode text
1182
+ cdef Py_UCS4 ch
1183
+ cdef Py_ssize_t start = 0, pos = 0
1184
+ cdef list substrings = None
1185
+ try:
1186
+ text = unicode(stext)
1187
+ except (TypeError, AttributeError):
1188
+ return _raise_serialization_error(stext)
1189
+
1190
+ for pos, ch in enumerate(text):
1191
+ if ch == '&':
1192
+ escape = '&amp;'
1193
+ elif ch == '<':
1194
+ escape = '&lt;'
1195
+ elif ch == '>':
1196
+ escape = '&gt;'
1197
+ elif ch == '\r':
1198
+ escape = '&#xD;'
1199
+ else:
1200
+ continue
1201
+
1202
+ if substrings is None:
1203
+ substrings = []
1204
+ if pos > start:
1205
+ substrings.append(text[start:pos])
1206
+ substrings.append(escape)
1207
+ start = pos + 1
1208
+
1209
+ if substrings is None:
1210
+ return text
1211
+ if pos >= start:
1212
+ substrings.append(text[start:pos+1])
1213
+ return ''.join(substrings)
1214
+
1215
+
1216
+ cdef unicode _escape_attrib_c14n(stext):
1217
+ # escape attribute value
1218
+ cdef unicode text
1219
+ cdef Py_UCS4 ch
1220
+ cdef Py_ssize_t start = 0, pos = 0
1221
+ cdef list substrings = None
1222
+ try:
1223
+ text = unicode(stext)
1224
+ except (TypeError, AttributeError):
1225
+ return _raise_serialization_error(stext)
1226
+
1227
+ for pos, ch in enumerate(text):
1228
+ if ch == '&':
1229
+ escape = '&amp;'
1230
+ elif ch == '<':
1231
+ escape = '&lt;'
1232
+ elif ch == '"':
1233
+ escape = '&quot;'
1234
+ elif ch == '\t':
1235
+ escape = '&#x9;'
1236
+ elif ch == '\n':
1237
+ escape = '&#xA;'
1238
+ elif ch == '\r':
1239
+ escape = '&#xD;'
1240
+ else:
1241
+ continue
1242
+
1243
+ if substrings is None:
1244
+ substrings = []
1245
+ if pos > start:
1246
+ substrings.append(text[start:pos])
1247
+ substrings.append(escape)
1248
+ start = pos + 1
1249
+
1250
+ if substrings is None:
1251
+ return text
1252
+ if pos >= start:
1253
+ substrings.append(text[start:pos+1])
1254
+ return ''.join(substrings)
1255
+
1256
+
1257
+ # incremental serialisation
1258
+
1259
+ cdef class xmlfile:
1260
+ """xmlfile(self, output_file, encoding=None, compression=None, close=False, buffered=True)
1261
+
1262
+ A simple mechanism for incremental XML serialisation.
1263
+
1264
+ Usage example::
1265
+
1266
+ with xmlfile("somefile.xml", encoding='utf-8') as xf:
1267
+ xf.write_declaration(standalone=True)
1268
+ xf.write_doctype('<!DOCTYPE root SYSTEM "some.dtd">')
1269
+
1270
+ # generate an element (the root element)
1271
+ with xf.element('root'):
1272
+ # write a complete Element into the open root element
1273
+ xf.write(etree.Element('test'))
1274
+
1275
+ # generate and write more Elements, e.g. through iterparse
1276
+ for element in generate_some_elements():
1277
+ # serialise generated elements into the XML file
1278
+ xf.write(element)
1279
+
1280
+ # or write multiple Elements or strings at once
1281
+ xf.write(etree.Element('start'), "text", etree.Element('end'))
1282
+
1283
+ If 'output_file' is a file(-like) object, passing ``close=True`` will
1284
+ close it when exiting the context manager. By default, it is left
1285
+ to the owner to do that. When a file path is used, lxml will take care
1286
+ of opening and closing the file itself. Also, when a compression level
1287
+ is set, lxml will deliberately close the file to make sure all data gets
1288
+ compressed and written.
1289
+
1290
+ Setting ``buffered=False`` will flush the output after each operation,
1291
+ such as opening or closing an ``xf.element()`` block or calling
1292
+ ``xf.write()``. Alternatively, calling ``xf.flush()`` can be used to
1293
+ explicitly flush any pending output when buffering is enabled.
1294
+ """
1295
+ cdef object output_file
1296
+ cdef bytes encoding
1297
+ cdef _IncrementalFileWriter writer
1298
+ cdef _AsyncIncrementalFileWriter async_writer
1299
+ cdef int compresslevel
1300
+ cdef bint close
1301
+ cdef bint buffered
1302
+ cdef int method
1303
+
1304
+ def __init__(self, output_file not None, encoding=None, compression=None,
1305
+ close=False, buffered=True):
1306
+ self.output_file = output_file
1307
+ self.encoding = _utf8orNone(encoding)
1308
+ self.compresslevel = compression or 0
1309
+ self.close = close
1310
+ self.buffered = buffered
1311
+ self.method = OUTPUT_METHOD_XML
1312
+
1313
+ def __enter__(self):
1314
+ assert self.output_file is not None
1315
+ self.writer = _IncrementalFileWriter(
1316
+ self.output_file, self.encoding, self.compresslevel,
1317
+ self.close, self.buffered, self.method)
1318
+ return self.writer
1319
+
1320
+ def __exit__(self, exc_type, exc_val, exc_tb):
1321
+ if self.writer is not None:
1322
+ old_writer, self.writer = self.writer, None
1323
+ raise_on_error = exc_type is None
1324
+ old_writer._close(raise_on_error)
1325
+ if self.close:
1326
+ self.output_file = None
1327
+
1328
+ async def __aenter__(self):
1329
+ assert self.output_file is not None
1330
+ if isinstance(self.output_file, basestring):
1331
+ raise TypeError("Cannot asynchronously write to a plain file")
1332
+ if not hasattr(self.output_file, 'write'):
1333
+ raise TypeError("Output file needs an async .write() method")
1334
+ self.async_writer = _AsyncIncrementalFileWriter(
1335
+ self.output_file, self.encoding, self.compresslevel,
1336
+ self.close, self.buffered, self.method)
1337
+ return self.async_writer
1338
+
1339
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
1340
+ if self.async_writer is not None:
1341
+ old_writer, self.async_writer = self.async_writer, None
1342
+ raise_on_error = exc_type is None
1343
+ await old_writer._close(raise_on_error)
1344
+ if self.close:
1345
+ self.output_file = None
1346
+
1347
+
1348
+ cdef class htmlfile(xmlfile):
1349
+ """htmlfile(self, output_file, encoding=None, compression=None, close=False, buffered=True)
1350
+
1351
+ A simple mechanism for incremental HTML serialisation. Works the same as
1352
+ xmlfile.
1353
+ """
1354
+ def __init__(self, *args, **kwargs):
1355
+ super().__init__(*args, **kwargs)
1356
+ self.method = OUTPUT_METHOD_HTML
1357
+
1358
+
1359
+ cdef enum _IncrementalFileWriterStatus:
1360
+ WRITER_STARTING = 0
1361
+ WRITER_DECL_WRITTEN = 1
1362
+ WRITER_DTD_WRITTEN = 2
1363
+ WRITER_IN_ELEMENT = 3
1364
+ WRITER_FINISHED = 4
1365
+
1366
+
1367
+ @cython.final
1368
+ @cython.internal
1369
+ cdef class _IncrementalFileWriter:
1370
+ cdef tree.xmlOutputBuffer* _c_out
1371
+ cdef bytes _encoding
1372
+ cdef const_char* _c_encoding
1373
+ cdef _FilelikeWriter _target
1374
+ cdef list _element_stack
1375
+ cdef int _status
1376
+ cdef int _method
1377
+ cdef bint _buffered
1378
+
1379
+ def __cinit__(self, outfile, bytes encoding, int compresslevel, bint close,
1380
+ bint buffered, int method):
1381
+ self._status = WRITER_STARTING
1382
+ self._element_stack = []
1383
+ if encoding is None:
1384
+ # We always need a document encoding to make the attribute serialisation
1385
+ # of libxml2 identical to ours.
1386
+ encoding = b'ASCII'
1387
+ self._encoding = encoding
1388
+ self._c_encoding = _cstr(encoding)
1389
+ self._buffered = buffered
1390
+ self._target = _create_output_buffer(
1391
+ outfile, self._c_encoding, compresslevel, &self._c_out, close)
1392
+ self._method = method
1393
+
1394
+ def __dealloc__(self):
1395
+ if self._c_out is not NULL:
1396
+ tree.xmlOutputBufferClose(self._c_out)
1397
+
1398
+ def write_declaration(self, version=None, standalone=None, doctype=None):
1399
+ """write_declaration(self, version=None, standalone=None, doctype=None)
1400
+
1401
+ Write an XML declaration and (optionally) a doctype into the file.
1402
+ """
1403
+ assert self._c_out is not NULL
1404
+ cdef const_xmlChar* c_version
1405
+ cdef int c_standalone
1406
+ if self._method != OUTPUT_METHOD_XML:
1407
+ raise LxmlSyntaxError("only XML documents have declarations")
1408
+ if self._status >= WRITER_DECL_WRITTEN:
1409
+ raise LxmlSyntaxError("XML declaration already written")
1410
+ version = _utf8orNone(version)
1411
+ c_version = _xcstr(version) if version is not None else NULL
1412
+ doctype = _utf8orNone(doctype)
1413
+ if standalone is None:
1414
+ c_standalone = -1
1415
+ else:
1416
+ c_standalone = 1 if standalone else 0
1417
+ _writeDeclarationToBuffer(self._c_out, c_version, self._c_encoding, c_standalone)
1418
+ if doctype is not None:
1419
+ _writeDoctype(self._c_out, _xcstr(doctype))
1420
+ self._status = WRITER_DTD_WRITTEN
1421
+ else:
1422
+ self._status = WRITER_DECL_WRITTEN
1423
+ if not self._buffered:
1424
+ tree.xmlOutputBufferFlush(self._c_out)
1425
+ self._handle_error(self._c_out.error)
1426
+
1427
+ def write_doctype(self, doctype):
1428
+ """write_doctype(self, doctype)
1429
+
1430
+ Writes the given doctype declaration verbatimly into the file.
1431
+ """
1432
+ assert self._c_out is not NULL
1433
+ if doctype is None:
1434
+ return
1435
+ if self._status >= WRITER_DTD_WRITTEN:
1436
+ raise LxmlSyntaxError("DOCTYPE already written or cannot write it here")
1437
+ doctype = _utf8(doctype)
1438
+ _writeDoctype(self._c_out, _xcstr(doctype))
1439
+ self._status = WRITER_DTD_WRITTEN
1440
+ if not self._buffered:
1441
+ tree.xmlOutputBufferFlush(self._c_out)
1442
+ self._handle_error(self._c_out.error)
1443
+
1444
+ def method(self, method):
1445
+ """method(self, method)
1446
+
1447
+ Returns a context manager that overrides and restores the output method.
1448
+ method is one of (None, 'xml', 'html') where None means 'xml'.
1449
+ """
1450
+ assert self._c_out is not NULL
1451
+ c_method = self._method if method is None else _findOutputMethod(method)
1452
+ return _MethodChanger(self, c_method)
1453
+
1454
+ def element(self, tag, attrib=None, nsmap=None, method=None, **_extra):
1455
+ """element(self, tag, attrib=None, nsmap=None, method, **_extra)
1456
+
1457
+ Returns a context manager that writes an opening and closing tag.
1458
+ method is one of (None, 'xml', 'html') where None means 'xml'.
1459
+ """
1460
+ assert self._c_out is not NULL
1461
+ attributes = []
1462
+ if attrib is not None:
1463
+ for name, value in _iter_attrib(attrib):
1464
+ if name not in _extra:
1465
+ ns, name = _getNsTag(name)
1466
+ attributes.append((ns, name, _utf8(value)))
1467
+ if _extra:
1468
+ for name, value in _extra.iteritems():
1469
+ ns, name = _getNsTag(name)
1470
+ attributes.append((ns, name, _utf8(value)))
1471
+ reversed_nsmap = {}
1472
+ if nsmap:
1473
+ for prefix, ns in nsmap.items():
1474
+ if prefix is not None:
1475
+ prefix = _utf8(prefix)
1476
+ _prefixValidOrRaise(prefix)
1477
+ reversed_nsmap[_utf8(ns)] = prefix
1478
+ ns, name = _getNsTag(tag)
1479
+
1480
+ c_method = self._method if method is None else _findOutputMethod(method)
1481
+
1482
+ return _FileWriterElement(self, (ns, name, attributes, reversed_nsmap), c_method)
1483
+
1484
+ cdef _write_qname(self, bytes name, bytes prefix):
1485
+ if prefix: # empty bytes for no prefix (not None to allow sorting)
1486
+ tree.xmlOutputBufferWrite(self._c_out, len(prefix), _cstr(prefix))
1487
+ tree.xmlOutputBufferWrite(self._c_out, 1, ':')
1488
+ tree.xmlOutputBufferWrite(self._c_out, len(name), _cstr(name))
1489
+
1490
+ cdef _write_start_element(self, element_config):
1491
+ if self._status > WRITER_IN_ELEMENT:
1492
+ raise LxmlSyntaxError("cannot append trailing element to complete XML document")
1493
+ ns, name, attributes, nsmap = element_config
1494
+ flat_namespace_map, new_namespaces = self._collect_namespaces(nsmap)
1495
+ prefix = self._find_prefix(ns, flat_namespace_map, new_namespaces)
1496
+ tree.xmlOutputBufferWrite(self._c_out, 1, '<')
1497
+ self._write_qname(name, prefix)
1498
+
1499
+ self._write_attributes_and_namespaces(
1500
+ attributes, flat_namespace_map, new_namespaces)
1501
+
1502
+ tree.xmlOutputBufferWrite(self._c_out, 1, '>')
1503
+ if not self._buffered:
1504
+ tree.xmlOutputBufferFlush(self._c_out)
1505
+ self._handle_error(self._c_out.error)
1506
+
1507
+ self._element_stack.append((ns, name, prefix, flat_namespace_map))
1508
+ self._status = WRITER_IN_ELEMENT
1509
+
1510
+ cdef _write_attributes_and_namespaces(self, list attributes,
1511
+ dict flat_namespace_map,
1512
+ list new_namespaces):
1513
+ if attributes:
1514
+ # _find_prefix() may append to new_namespaces => build them first
1515
+ attributes = [
1516
+ (self._find_prefix(ns, flat_namespace_map, new_namespaces), name, value)
1517
+ for ns, name, value in attributes ]
1518
+ if new_namespaces:
1519
+ new_namespaces.sort()
1520
+ self._write_attributes_list(new_namespaces)
1521
+ if attributes:
1522
+ self._write_attributes_list(attributes)
1523
+
1524
+ cdef _write_attributes_list(self, list attributes):
1525
+ for prefix, name, value in attributes:
1526
+ tree.xmlOutputBufferWrite(self._c_out, 1, ' ')
1527
+ self._write_qname(name, prefix)
1528
+ tree.xmlOutputBufferWrite(self._c_out, 2, '="')
1529
+ _write_attr_string(self._c_out, _cstr(value))
1530
+
1531
+ tree.xmlOutputBufferWrite(self._c_out, 1, '"')
1532
+
1533
+ cdef _write_end_element(self, element_config):
1534
+ if self._status != WRITER_IN_ELEMENT:
1535
+ raise LxmlSyntaxError("not in an element")
1536
+ if not self._element_stack or self._element_stack[-1][:2] != element_config[:2]:
1537
+ raise LxmlSyntaxError("inconsistent exit action in context manager")
1538
+
1539
+ # If previous write operations failed, the context manager exit might still call us.
1540
+ # That is ok, but we stop writing closing tags and handling errors in that case.
1541
+ # For all non-I/O errors, we continue writing closing tags if we can.
1542
+ ok_to_write = self._c_out.error == xmlerror.XML_ERR_OK
1543
+
1544
+ name, prefix = self._element_stack.pop()[1:3]
1545
+ if ok_to_write:
1546
+ tree.xmlOutputBufferWrite(self._c_out, 2, '</')
1547
+ self._write_qname(name, prefix)
1548
+ tree.xmlOutputBufferWrite(self._c_out, 1, '>')
1549
+
1550
+ if not self._element_stack:
1551
+ self._status = WRITER_FINISHED
1552
+ if ok_to_write:
1553
+ if not self._buffered:
1554
+ tree.xmlOutputBufferFlush(self._c_out)
1555
+ self._handle_error(self._c_out.error)
1556
+
1557
+ cdef _find_prefix(self, bytes href, dict flat_namespaces_map, list new_namespaces):
1558
+ if href is None:
1559
+ return None
1560
+ if href in flat_namespaces_map:
1561
+ return flat_namespaces_map[href]
1562
+ # need to create a new prefix
1563
+ prefixes = flat_namespaces_map.values()
1564
+ i = 0
1565
+ while True:
1566
+ prefix = _utf8('ns%d' % i)
1567
+ if prefix not in prefixes:
1568
+ new_namespaces.append((b'xmlns', prefix, href))
1569
+ flat_namespaces_map[href] = prefix
1570
+ return prefix
1571
+ i += 1
1572
+
1573
+ cdef _collect_namespaces(self, dict nsmap):
1574
+ new_namespaces = []
1575
+ flat_namespaces_map = {}
1576
+ for ns, prefix in nsmap.iteritems():
1577
+ flat_namespaces_map[ns] = prefix
1578
+ if prefix is None:
1579
+ # use empty bytes rather than None to allow sorting
1580
+ new_namespaces.append((b'', b'xmlns', ns))
1581
+ else:
1582
+ new_namespaces.append((b'xmlns', prefix, ns))
1583
+ # merge in flat namespace map of parent
1584
+ if self._element_stack:
1585
+ for ns, prefix in (<dict>self._element_stack[-1][-1]).iteritems():
1586
+ if flat_namespaces_map.get(ns) is None:
1587
+ # unknown or empty prefix => prefer a 'real' prefix
1588
+ flat_namespaces_map[ns] = prefix
1589
+ return flat_namespaces_map, new_namespaces
1590
+
1591
+ def write(self, *args, bint with_tail=True, bint pretty_print=False, method=None):
1592
+ """write(self, *args, with_tail=True, pretty_print=False, method=None)
1593
+
1594
+ Write subtrees or strings into the file.
1595
+
1596
+ If method is not None, it should be one of ('html', 'xml', 'text')
1597
+ to temporarily override the output method.
1598
+ """
1599
+ assert self._c_out is not NULL
1600
+ c_method = self._method if method is None else _findOutputMethod(method)
1601
+
1602
+ for content in args:
1603
+ if _isString(content):
1604
+ if self._status != WRITER_IN_ELEMENT:
1605
+ if self._status > WRITER_IN_ELEMENT or content.strip():
1606
+ raise LxmlSyntaxError("not in an element")
1607
+ bstring = _utf8(content)
1608
+ if not bstring:
1609
+ continue
1610
+
1611
+ ns, name, _, _ = self._element_stack[-1]
1612
+ if (c_method == OUTPUT_METHOD_HTML and
1613
+ ns in (None, b'http://www.w3.org/1999/xhtml') and
1614
+ name in (b'script', b'style')):
1615
+ tree.xmlOutputBufferWrite(self._c_out, len(bstring), _cstr(bstring))
1616
+
1617
+ else:
1618
+ tree.xmlOutputBufferWriteEscape(self._c_out, _xcstr(bstring), NULL)
1619
+
1620
+ elif isinstance(content, CDATA):
1621
+ if self._status > WRITER_IN_ELEMENT:
1622
+ raise LxmlSyntaxError("not in an element")
1623
+ _write_cdata_string(self._c_out, (<CDATA>content)._utf8_data)
1624
+
1625
+ elif iselement(content):
1626
+ if self._status > WRITER_IN_ELEMENT:
1627
+ raise LxmlSyntaxError("cannot append trailing element to complete XML document")
1628
+ _writeNodeToBuffer(self._c_out, (<_Element>content)._c_node,
1629
+ self._c_encoding, NULL, c_method,
1630
+ False, False, pretty_print, with_tail, False)
1631
+ if (<_Element>content)._c_node.type == tree.XML_ELEMENT_NODE:
1632
+ if not self._element_stack:
1633
+ self._status = WRITER_FINISHED
1634
+
1635
+ elif content is not None:
1636
+ raise TypeError(
1637
+ f"got invalid input value of type {type(content)}, expected string, CDATA or Element")
1638
+
1639
+ self._handle_error(self._c_out.error)
1640
+
1641
+ if not self._buffered:
1642
+ tree.xmlOutputBufferFlush(self._c_out)
1643
+ self._handle_error(self._c_out.error)
1644
+
1645
+ def flush(self):
1646
+ """flush(self)
1647
+
1648
+ Write any pending content of the current output buffer to the stream.
1649
+ """
1650
+ assert self._c_out is not NULL
1651
+ tree.xmlOutputBufferFlush(self._c_out)
1652
+ self._handle_error(self._c_out.error)
1653
+
1654
+ cdef _close(self, bint raise_on_error):
1655
+ if raise_on_error:
1656
+ if self._status < WRITER_IN_ELEMENT:
1657
+ raise LxmlSyntaxError("no content written")
1658
+ if self._element_stack:
1659
+ raise LxmlSyntaxError("pending open tags on close")
1660
+ error_result = self._c_out.error
1661
+ if error_result == xmlerror.XML_ERR_OK:
1662
+ error_result = tree.xmlOutputBufferClose(self._c_out)
1663
+ if error_result != -1:
1664
+ error_result = xmlerror.XML_ERR_OK
1665
+ else:
1666
+ tree.xmlOutputBufferClose(self._c_out)
1667
+ self._status = WRITER_FINISHED
1668
+ self._c_out = NULL
1669
+ del self._element_stack[:]
1670
+ if raise_on_error:
1671
+ self._handle_error(error_result)
1672
+
1673
+ cdef _handle_error(self, int error_result):
1674
+ if error_result != xmlerror.XML_ERR_OK:
1675
+ if self._target is not None:
1676
+ self._target._exc_context._raise_if_stored()
1677
+ _raiseSerialisationError(error_result)
1678
+
1679
+
1680
+ @cython.final
1681
+ @cython.internal
1682
+ cdef class _AsyncDataWriter:
1683
+ cdef list _data
1684
+ def __cinit__(self):
1685
+ self._data = []
1686
+
1687
+ cdef bytes collect(self):
1688
+ data = b''.join(self._data)
1689
+ del self._data[:]
1690
+ return data
1691
+
1692
+ def write(self, data):
1693
+ self._data.append(data)
1694
+
1695
+ def close(self):
1696
+ pass
1697
+
1698
+
1699
+ @cython.final
1700
+ @cython.internal
1701
+ cdef class _AsyncIncrementalFileWriter:
1702
+ cdef _IncrementalFileWriter _writer
1703
+ cdef _AsyncDataWriter _buffer
1704
+ cdef object _async_outfile
1705
+ cdef int _flush_after_writes
1706
+ cdef bint _should_close
1707
+ cdef bint _buffered
1708
+
1709
+ def __cinit__(self, async_outfile, bytes encoding, int compresslevel, bint close,
1710
+ bint buffered, int method):
1711
+ self._flush_after_writes = 20
1712
+ self._async_outfile = async_outfile
1713
+ self._should_close = close
1714
+ self._buffered = buffered
1715
+ self._buffer = _AsyncDataWriter()
1716
+ self._writer = _IncrementalFileWriter(
1717
+ self._buffer, encoding, compresslevel, close=True, buffered=False, method=method)
1718
+
1719
+ cdef bytes _flush(self):
1720
+ if not self._buffered or len(self._buffer._data) > self._flush_after_writes:
1721
+ return self._buffer.collect()
1722
+ return None
1723
+
1724
+ async def flush(self):
1725
+ self._writer.flush()
1726
+ data = self._buffer.collect()
1727
+ if data:
1728
+ await self._async_outfile.write(data)
1729
+
1730
+ async def write_declaration(self, version=None, standalone=None, doctype=None):
1731
+ self._writer.write_declaration(version, standalone, doctype)
1732
+ data = self._flush()
1733
+ if data:
1734
+ await self._async_outfile.write(data)
1735
+
1736
+ async def write_doctype(self, doctype):
1737
+ self._writer.write_doctype(doctype)
1738
+ data = self._flush()
1739
+ if data:
1740
+ await self._async_outfile.write(data)
1741
+
1742
+ async def write(self, *args, with_tail=True, pretty_print=False, method=None):
1743
+ self._writer.write(*args, with_tail=with_tail, pretty_print=pretty_print, method=method)
1744
+ data = self._flush()
1745
+ if data:
1746
+ await self._async_outfile.write(data)
1747
+
1748
+ def method(self, method):
1749
+ return self._writer.method(method)
1750
+
1751
+ def element(self, tag, attrib=None, nsmap=None, method=None, **_extra):
1752
+ element_writer = self._writer.element(tag, attrib, nsmap, method, **_extra)
1753
+ return _AsyncFileWriterElement(element_writer, self)
1754
+
1755
+ async def _close(self, bint raise_on_error):
1756
+ self._writer._close(raise_on_error)
1757
+ data = self._buffer.collect()
1758
+ if data:
1759
+ await self._async_outfile.write(data)
1760
+ if self._should_close:
1761
+ await self._async_outfile.close()
1762
+
1763
+
1764
+ @cython.final
1765
+ @cython.internal
1766
+ cdef class _AsyncFileWriterElement:
1767
+ cdef _FileWriterElement _element_writer
1768
+ cdef _AsyncIncrementalFileWriter _writer
1769
+
1770
+ def __cinit__(self, _FileWriterElement element_writer not None,
1771
+ _AsyncIncrementalFileWriter writer not None):
1772
+ self._element_writer = element_writer
1773
+ self._writer = writer
1774
+
1775
+ async def __aenter__(self):
1776
+ self._element_writer.__enter__()
1777
+ data = self._writer._flush()
1778
+ if data:
1779
+ await self._writer._async_outfile.write(data)
1780
+
1781
+ async def __aexit__(self, *args):
1782
+ self._element_writer.__exit__(*args)
1783
+ data = self._writer._flush()
1784
+ if data:
1785
+ await self._writer._async_outfile.write(data)
1786
+
1787
+
1788
+ @cython.final
1789
+ @cython.internal
1790
+ @cython.freelist(8)
1791
+ cdef class _FileWriterElement:
1792
+ cdef _IncrementalFileWriter _writer
1793
+ cdef object _element
1794
+ cdef int _new_method
1795
+ cdef int _old_method
1796
+
1797
+ def __cinit__(self, _IncrementalFileWriter writer not None, element_config, int method):
1798
+ self._writer = writer
1799
+ self._element = element_config
1800
+ self._new_method = method
1801
+ self._old_method = writer._method
1802
+
1803
+ def __enter__(self):
1804
+ self._writer._method = self._new_method
1805
+ self._writer._write_start_element(self._element)
1806
+
1807
+ def __exit__(self, exc_type, exc_val, exc_tb):
1808
+ self._writer._write_end_element(self._element)
1809
+ self._writer._method = self._old_method
1810
+
1811
+
1812
+ @cython.final
1813
+ @cython.internal
1814
+ @cython.freelist(8)
1815
+ cdef class _MethodChanger:
1816
+ cdef _IncrementalFileWriter _writer
1817
+ cdef int _new_method
1818
+ cdef int _old_method
1819
+ cdef bint _entered
1820
+ cdef bint _exited
1821
+
1822
+ def __cinit__(self, _IncrementalFileWriter writer not None, int method):
1823
+ self._writer = writer
1824
+ self._new_method = method
1825
+ self._old_method = writer._method
1826
+ self._entered = False
1827
+ self._exited = False
1828
+
1829
+ def __enter__(self):
1830
+ if self._entered:
1831
+ raise LxmlSyntaxError("Inconsistent enter action in context manager")
1832
+ self._writer._method = self._new_method
1833
+ self._entered = True
1834
+
1835
+ def __exit__(self, exc_type, exc_val, exc_tb):
1836
+ if self._exited:
1837
+ raise LxmlSyntaxError("Inconsistent exit action in context manager")
1838
+ if self._writer._method != self._new_method:
1839
+ raise LxmlSyntaxError("Method changed outside of context manager")
1840
+ self._writer._method = self._old_method
1841
+ self._exited = True
1842
+
1843
+ async def __aenter__(self):
1844
+ # for your async convenience
1845
+ return self.__enter__()
1846
+
1847
+ async def __aexit__(self, *args):
1848
+ # for your async convenience
1849
+ return self.__exit__(*args)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xinclude.pxi ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # XInclude processing
2
+
3
+ from lxml.includes cimport xinclude
4
+
5
+
6
+ cdef class XIncludeError(LxmlError):
7
+ """Error during XInclude processing.
8
+ """
9
+
10
+
11
+ cdef class XInclude:
12
+ """XInclude(self)
13
+ XInclude processor.
14
+
15
+ Create an instance and call it on an Element to run XInclude
16
+ processing.
17
+ """
18
+ cdef _ErrorLog _error_log
19
+ def __init__(self):
20
+ self._error_log = _ErrorLog()
21
+
22
+ @property
23
+ def error_log(self):
24
+ assert self._error_log is not None, "XInclude instance not initialised"
25
+ return self._error_log.copy()
26
+
27
+ def __call__(self, _Element node not None):
28
+ "__call__(self, node)"
29
+ # We cannot pass the XML_PARSE_NOXINCNODE option as this would free
30
+ # the XInclude nodes - there may still be Python references to them!
31
+ # Therefore, we allow XInclude nodes to be converted to
32
+ # XML_XINCLUDE_START nodes. XML_XINCLUDE_END nodes are added as
33
+ # siblings. Tree traversal will simply ignore them as they are not
34
+ # typed as elements. The included fragment is added between the two,
35
+ # i.e. as a sibling, which does not conflict with traversal.
36
+ cdef int result
37
+ _assertValidNode(node)
38
+ assert self._error_log is not None, "XInclude processor not initialised"
39
+ if node._doc._parser is not None:
40
+ parse_options = node._doc._parser._parse_options
41
+ context = node._doc._parser._getParserContext()
42
+ c_context = <void*>context
43
+ else:
44
+ parse_options = 0
45
+ context = None
46
+ c_context = NULL
47
+
48
+ self._error_log.connect()
49
+ if tree.LIBXML_VERSION < 20704 or not c_context:
50
+ __GLOBAL_PARSER_CONTEXT.pushImpliedContext(context)
51
+ with nogil:
52
+ orig_loader = _register_document_loader()
53
+ if c_context:
54
+ result = xinclude.xmlXIncludeProcessTreeFlagsData(
55
+ node._c_node, parse_options, c_context)
56
+ else:
57
+ result = xinclude.xmlXIncludeProcessTree(node._c_node)
58
+ _reset_document_loader(orig_loader)
59
+ if tree.LIBXML_VERSION < 20704 or not c_context:
60
+ __GLOBAL_PARSER_CONTEXT.popImpliedContext()
61
+ self._error_log.disconnect()
62
+
63
+ if result == -1:
64
+ raise XIncludeError(
65
+ self._error_log._buildExceptionMessage(
66
+ "XInclude processing failed"),
67
+ self._error_log)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xmlerror.pxi ADDED
@@ -0,0 +1,1662 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DEBUG and error logging
2
+
3
+ from lxml.includes cimport xmlerror
4
+ from lxml cimport cvarargs
5
+
6
+ DEF GLOBAL_ERROR_LOG = "_GlobalErrorLog"
7
+ DEF XSLT_ERROR_LOG = "_XSLTErrorLog"
8
+
9
+ # module level API functions
10
+
11
+ def clear_error_log():
12
+ """clear_error_log()
13
+
14
+ Clear the global error log. Note that this log is already bound to a
15
+ fixed size.
16
+
17
+ Note: since lxml 2.2, the global error log is local to a thread
18
+ and this function will only clear the global error log of the
19
+ current thread.
20
+ """
21
+ _getThreadErrorLog(GLOBAL_ERROR_LOG).clear()
22
+
23
+
24
+ # setup for global log:
25
+
26
+ cdef void _initThreadLogging() noexcept:
27
+ # Disable generic error lines from libxml2.
28
+ _connectGenericErrorLog(None)
29
+
30
+ # Divert XSLT error messages to the global XSLT error log instead of stderr.
31
+ xslt.xsltSetGenericErrorFunc(NULL, <xmlerror.xmlGenericErrorFunc>_receiveXSLTError)
32
+
33
+
34
+ # Logging classes
35
+
36
+ @cython.final
37
+ @cython.freelist(16)
38
+ cdef class _LogEntry:
39
+ """A log message entry from an error log.
40
+
41
+ Attributes:
42
+
43
+ - message: the message text
44
+ - domain: the domain ID (see lxml.etree.ErrorDomains)
45
+ - type: the message type ID (see lxml.etree.ErrorTypes)
46
+ - level: the log level ID (see lxml.etree.ErrorLevels)
47
+ - line: the line at which the message originated (if applicable)
48
+ - column: the character column at which the message originated (if applicable)
49
+ - filename: the name of the file in which the message originated (if applicable)
50
+ - path: the location in which the error was found (if available)
51
+ """
52
+ cdef readonly int domain
53
+ cdef readonly int type
54
+ cdef readonly int level
55
+ cdef readonly long line
56
+ cdef readonly int column
57
+ cdef basestring _message
58
+ cdef basestring _filename
59
+ cdef char* _c_message
60
+ cdef xmlChar* _c_filename
61
+ cdef xmlChar* _c_path
62
+
63
+ def __dealloc__(self):
64
+ tree.xmlFree(self._c_message)
65
+ tree.xmlFree(self._c_filename)
66
+ tree.xmlFree(self._c_path)
67
+
68
+ @cython.final
69
+ cdef int _setError(self, const xmlerror.xmlError* error) except -1:
70
+ self.domain = error.domain
71
+ self.type = error.code
72
+ self.level = <int>error.level
73
+ self.line = <long>error.line
74
+ self.column = error.int2
75
+ self._c_message = NULL
76
+ self._c_filename = NULL
77
+ self._c_path = NULL
78
+ if (error.message is NULL or
79
+ error.message[0] == b'\0' or
80
+ error.message[0] == b'\n' and error.message[1] == b'\0'):
81
+ self._message = "unknown error"
82
+ else:
83
+ self._message = None
84
+ self._c_message = <char*> tree.xmlStrdup(
85
+ <const_xmlChar*> error.message)
86
+ if not self._c_message:
87
+ raise MemoryError()
88
+ if error.file is NULL:
89
+ self._filename = '<string>'
90
+ else:
91
+ self._filename = None
92
+ self._c_filename = tree.xmlStrdup(<const_xmlChar*> error.file)
93
+ if not self._c_filename:
94
+ raise MemoryError()
95
+ if error.node is not NULL:
96
+ self._c_path = tree.xmlGetNodePath(<xmlNode*> error.node)
97
+ c_line = tree.xmlGetLineNo(<xmlNode*> error.node)
98
+ if c_line > limits.INT_MAX:
99
+ self.line = c_line
100
+
101
+ @cython.final
102
+ cdef _setGeneric(self, int domain, int type, int level, long line,
103
+ message, filename):
104
+ self.domain = domain
105
+ self.type = type
106
+ self.level = level
107
+ self.line = line
108
+ self.column = 0
109
+ self._message = message
110
+ self._filename = filename
111
+ self._c_path = NULL
112
+
113
+ def __repr__(self):
114
+ return "%s:%d:%d:%s:%s:%s: %s" % (
115
+ self.filename, self.line, self.column, self.level_name,
116
+ self.domain_name, self.type_name, self.message)
117
+
118
+ @property
119
+ def domain_name(self):
120
+ """The name of the error domain. See lxml.etree.ErrorDomains
121
+ """
122
+ return ErrorDomains._getName(self.domain, "unknown")
123
+
124
+ @property
125
+ def type_name(self):
126
+ """The name of the error type. See lxml.etree.ErrorTypes
127
+ """
128
+ if self.domain == ErrorDomains.RELAXNGV:
129
+ getName = RelaxNGErrorTypes._getName
130
+ else:
131
+ getName = ErrorTypes._getName
132
+ return getName(self.type, "unknown")
133
+
134
+ @property
135
+ def level_name(self):
136
+ """The name of the error level. See lxml.etree.ErrorLevels
137
+ """
138
+ return ErrorLevels._getName(self.level, "unknown")
139
+
140
+ @property
141
+ def message(self):
142
+ """The log message string.
143
+ """
144
+ cdef size_t size
145
+ if self._message is not None:
146
+ return self._message
147
+ if self._c_message is NULL:
148
+ return None
149
+ size = cstring_h.strlen(self._c_message)
150
+ if size > 0 and self._c_message[size-1] == b'\n':
151
+ size -= 1 # strip EOL
152
+ # cannot use funicode() here because the message may contain
153
+ # byte encoded file paths etc.
154
+ try:
155
+ self._message = self._c_message[:size].decode('utf8')
156
+ except UnicodeDecodeError:
157
+ try:
158
+ self._message = self._c_message[:size].decode(
159
+ 'ascii', 'backslashreplace')
160
+ except UnicodeDecodeError:
161
+ self._message = '<undecodable error message>'
162
+ if self._c_message:
163
+ # clean up early
164
+ tree.xmlFree(self._c_message)
165
+ self._c_message = NULL
166
+ return self._message
167
+
168
+ @property
169
+ def filename(self):
170
+ """The file path where the report originated, if any.
171
+ """
172
+ if self._filename is None:
173
+ if self._c_filename is not NULL:
174
+ self._filename = _decodeFilename(self._c_filename)
175
+ # clean up early
176
+ tree.xmlFree(self._c_filename)
177
+ self._c_filename = NULL
178
+ return self._filename
179
+
180
+ @property
181
+ def path(self):
182
+ """The XPath for the node where the error was detected.
183
+ """
184
+ return funicode(self._c_path) if self._c_path is not NULL else None
185
+
186
+
187
+ cdef class _BaseErrorLog:
188
+ cdef _LogEntry _first_error
189
+ cdef readonly object last_error
190
+ def __init__(self, first_error, last_error):
191
+ self._first_error = first_error
192
+ self.last_error = last_error
193
+
194
+ cpdef copy(self):
195
+ return _BaseErrorLog(self._first_error, self.last_error)
196
+
197
+ def __repr__(self):
198
+ return ''
199
+
200
+ cpdef receive(self, _LogEntry entry):
201
+ pass
202
+
203
+ @cython.final
204
+ cdef int _receive(self, const xmlerror.xmlError* error) except -1:
205
+ cdef bint is_error
206
+ cdef _LogEntry entry
207
+ cdef _BaseErrorLog global_log
208
+ entry = _LogEntry.__new__(_LogEntry)
209
+ entry._setError(error)
210
+ is_error = error.level == xmlerror.XML_ERR_ERROR or \
211
+ error.level == xmlerror.XML_ERR_FATAL
212
+ global_log = _getThreadErrorLog(GLOBAL_ERROR_LOG)
213
+ if global_log is not self:
214
+ global_log.receive(entry)
215
+ if is_error:
216
+ global_log.last_error = entry
217
+ self.receive(entry)
218
+ if is_error:
219
+ self.last_error = entry
220
+
221
+ @cython.final
222
+ cdef int _receiveGeneric(self, int domain, int type, int level, long line,
223
+ message, filename) except -1:
224
+ cdef bint is_error
225
+ cdef _LogEntry entry
226
+ cdef _BaseErrorLog global_log
227
+ entry = _LogEntry.__new__(_LogEntry)
228
+ entry._setGeneric(domain, type, level, line, message, filename)
229
+ is_error = level == xmlerror.XML_ERR_ERROR or \
230
+ level == xmlerror.XML_ERR_FATAL
231
+ global_log = _getThreadErrorLog(GLOBAL_ERROR_LOG)
232
+ if global_log is not self:
233
+ global_log.receive(entry)
234
+ if is_error:
235
+ global_log.last_error = entry
236
+ self.receive(entry)
237
+ if is_error:
238
+ self.last_error = entry
239
+
240
+ @cython.final
241
+ cdef _buildParseException(self, exctype, default_message):
242
+ code = xmlerror.XML_ERR_INTERNAL_ERROR
243
+ if self._first_error is None:
244
+ return exctype(default_message, code, 0, 0)
245
+ message = self._first_error.message
246
+ if message:
247
+ code = self._first_error.type
248
+ else:
249
+ message = default_message
250
+ line = self._first_error.line
251
+ column = self._first_error.column
252
+ filename = self._first_error.filename
253
+ if line > 0:
254
+ if column > 0:
255
+ message = f"{message}, line {line}, column {column}"
256
+ else:
257
+ message = f"{message}, line {line}"
258
+ return exctype(message, code, line, column, filename)
259
+
260
+ @cython.final
261
+ cdef _buildExceptionMessage(self, default_message):
262
+ if self._first_error is None:
263
+ return default_message
264
+ if self._first_error.message:
265
+ message = self._first_error.message
266
+ elif default_message is None:
267
+ return None
268
+ else:
269
+ message = default_message
270
+ if self._first_error.line > 0:
271
+ if self._first_error.column > 0:
272
+ message = f"{message}, line {self._first_error.line}, column {self._first_error.column}"
273
+ else:
274
+ message = f"{message}, line {self._first_error.line}"
275
+ return message
276
+
277
+ cdef class _ListErrorLog(_BaseErrorLog):
278
+ "Immutable base version of a list based error log."
279
+ cdef list _entries
280
+ cdef int _offset
281
+ def __init__(self, entries, first_error, last_error):
282
+ if entries:
283
+ if first_error is None:
284
+ first_error = entries[0]
285
+ if last_error is None:
286
+ last_error = entries[-1]
287
+ _BaseErrorLog.__init__(self, first_error, last_error)
288
+ self._entries = entries
289
+
290
+ cpdef copy(self):
291
+ """Creates a shallow copy of this error log. Reuses the list of
292
+ entries.
293
+ """
294
+ cdef _ListErrorLog log = _ListErrorLog(
295
+ self._entries, self._first_error, self.last_error)
296
+ log._offset = self._offset
297
+ return log
298
+
299
+ def __iter__(self):
300
+ entries = self._entries
301
+ if self._offset:
302
+ entries = islice(entries, self._offset)
303
+ return iter(entries)
304
+
305
+ def __repr__(self):
306
+ return '\n'.join([repr(entry) for entry in self])
307
+
308
+ def __getitem__(self, index):
309
+ if self._offset:
310
+ index += self._offset
311
+ return self._entries[index]
312
+
313
+ def __len__(self):
314
+ return len(self._entries) - self._offset
315
+
316
+ def __contains__(self, error_type):
317
+ cdef Py_ssize_t i
318
+ for i, entry in enumerate(self._entries):
319
+ if i < self._offset:
320
+ continue
321
+ if entry.type == error_type:
322
+ return True
323
+ return False
324
+
325
+ def __bool__(self):
326
+ return len(self._entries) > self._offset
327
+
328
+ def filter_domains(self, domains):
329
+ """Filter the errors by the given domains and return a new error log
330
+ containing the matches.
331
+ """
332
+ cdef _LogEntry entry
333
+ if isinstance(domains, int):
334
+ domains = (domains,)
335
+ filtered = [entry for entry in self if entry.domain in domains]
336
+ return _ListErrorLog(filtered, None, None)
337
+
338
+ def filter_types(self, types):
339
+ """filter_types(self, types)
340
+
341
+ Filter the errors by the given types and return a new error
342
+ log containing the matches.
343
+ """
344
+ cdef _LogEntry entry
345
+ if isinstance(types, int):
346
+ types = (types,)
347
+ filtered = [entry for entry in self if entry.type in types]
348
+ return _ListErrorLog(filtered, None, None)
349
+
350
+ def filter_levels(self, levels):
351
+ """filter_levels(self, levels)
352
+
353
+ Filter the errors by the given error levels and return a new
354
+ error log containing the matches.
355
+ """
356
+ cdef _LogEntry entry
357
+ if isinstance(levels, int):
358
+ levels = (levels,)
359
+ filtered = [entry for entry in self if entry.level in levels]
360
+ return _ListErrorLog(filtered, None, None)
361
+
362
+ def filter_from_level(self, level):
363
+ """filter_from_level(self, level)
364
+
365
+ Return a log with all messages of the requested level of worse.
366
+ """
367
+ cdef _LogEntry entry
368
+ filtered = [entry for entry in self if entry.level >= level]
369
+ return _ListErrorLog(filtered, None, None)
370
+
371
+ def filter_from_fatals(self):
372
+ """filter_from_fatals(self)
373
+
374
+ Convenience method to get all fatal error messages.
375
+ """
376
+ return self.filter_from_level(ErrorLevels.FATAL)
377
+
378
+ def filter_from_errors(self):
379
+ """filter_from_errors(self)
380
+
381
+ Convenience method to get all error messages or worse.
382
+ """
383
+ return self.filter_from_level(ErrorLevels.ERROR)
384
+
385
+ def filter_from_warnings(self):
386
+ """filter_from_warnings(self)
387
+
388
+ Convenience method to get all warnings or worse.
389
+ """
390
+ return self.filter_from_level(ErrorLevels.WARNING)
391
+
392
+
393
+ @cython.final
394
+ @cython.internal
395
+ cdef class _ErrorLogContext:
396
+ """
397
+ Error log context for the 'with' statement.
398
+ Stores a reference to the current callbacks to allow for
399
+ recursively stacked log contexts.
400
+ """
401
+ cdef xmlerror.xmlStructuredErrorFunc old_error_func
402
+ cdef void* old_error_context
403
+ cdef xmlerror.xmlGenericErrorFunc old_xslt_error_func
404
+ cdef void* old_xslt_error_context
405
+ cdef _BaseErrorLog old_xslt_error_log
406
+
407
+ cdef int push_error_log(self, _BaseErrorLog log) except -1:
408
+ self.old_error_func = xmlerror.xmlStructuredError
409
+ self.old_error_context = xmlerror.xmlStructuredErrorContext
410
+ xmlerror.xmlSetStructuredErrorFunc(
411
+ <void*>log, <xmlerror.xmlStructuredErrorFunc>_receiveError)
412
+
413
+ # xslt.xsltSetGenericErrorFunc() is not thread-local => keep error log in TLS
414
+ self.old_xslt_error_func = xslt.xsltGenericError
415
+ self.old_xslt_error_context = xslt.xsltGenericErrorContext
416
+ self.old_xslt_error_log = _getThreadErrorLog(XSLT_ERROR_LOG)
417
+ _setThreadErrorLog(XSLT_ERROR_LOG, log)
418
+ xslt.xsltSetGenericErrorFunc(
419
+ NULL, <xmlerror.xmlGenericErrorFunc>_receiveXSLTError)
420
+ return 0
421
+
422
+ cdef int pop_error_log(self) except -1:
423
+ xmlerror.xmlSetStructuredErrorFunc(
424
+ self.old_error_context, self.old_error_func)
425
+ xslt.xsltSetGenericErrorFunc(
426
+ self.old_xslt_error_context, self.old_xslt_error_func)
427
+ _setThreadErrorLog(XSLT_ERROR_LOG, self.old_xslt_error_log)
428
+ self.old_xslt_error_log= None
429
+ return 0
430
+
431
+
432
+ cdef class _ErrorLog(_ListErrorLog):
433
+ cdef list _logContexts
434
+ def __cinit__(self):
435
+ self._logContexts = []
436
+
437
+ def __init__(self):
438
+ _ListErrorLog.__init__(self, [], None, None)
439
+
440
+ @cython.final
441
+ cdef int __enter__(self) except -1:
442
+ return self.connect()
443
+
444
+ def __exit__(self, *args):
445
+ # TODO: make this a cdef function when Cython supports it
446
+ self.disconnect()
447
+
448
+ @cython.final
449
+ cdef int connect(self) except -1:
450
+ self._first_error = None
451
+ del self._entries[:]
452
+
453
+ cdef _ErrorLogContext context = _ErrorLogContext.__new__(_ErrorLogContext)
454
+ context.push_error_log(self)
455
+ self._logContexts.append(context)
456
+ return 0
457
+
458
+ @cython.final
459
+ cdef int disconnect(self) except -1:
460
+ cdef _ErrorLogContext context = self._logContexts.pop()
461
+ context.pop_error_log()
462
+ return 0
463
+
464
+ cpdef clear(self):
465
+ self._first_error = None
466
+ self.last_error = None
467
+ self._offset = 0
468
+ del self._entries[:]
469
+
470
+ cpdef copy(self):
471
+ """Creates a shallow copy of this error log and the list of entries.
472
+ """
473
+ return _ListErrorLog(
474
+ self._entries[self._offset:],
475
+ self._first_error, self.last_error)
476
+
477
+ def __iter__(self):
478
+ return iter(self._entries[self._offset:])
479
+
480
+ cpdef receive(self, _LogEntry entry):
481
+ if self._first_error is None and entry.level >= xmlerror.XML_ERR_ERROR:
482
+ self._first_error = entry
483
+ self._entries.append(entry)
484
+
485
+ cdef class _DomainErrorLog(_ErrorLog):
486
+ def __init__(self, domains):
487
+ _ErrorLog.__init__(self)
488
+ self._accepted_domains = tuple(domains)
489
+
490
+ cpdef receive(self, _LogEntry entry):
491
+ if entry.domain in self._accepted_domains:
492
+ _ErrorLog.receive(self, entry)
493
+
494
+ cdef class _RotatingErrorLog(_ErrorLog):
495
+ cdef int _max_len
496
+ def __init__(self, max_len):
497
+ _ErrorLog.__init__(self)
498
+ self._max_len = max_len
499
+
500
+ cpdef receive(self, _LogEntry entry):
501
+ if self._first_error is None and entry.level >= xmlerror.XML_ERR_ERROR:
502
+ self._first_error = entry
503
+ self._entries.append(entry)
504
+
505
+ if len(self._entries) > self._max_len:
506
+ self._offset += 1
507
+ if self._offset > self._max_len // 3:
508
+ offset = self._offset
509
+ self._offset = 0
510
+ del self._entries[:offset]
511
+
512
+ cdef class PyErrorLog(_BaseErrorLog):
513
+ """PyErrorLog(self, logger_name=None, logger=None)
514
+ A global error log that connects to the Python stdlib logging package.
515
+
516
+ The constructor accepts an optional logger name or a readily
517
+ instantiated logger instance.
518
+
519
+ If you want to change the mapping between libxml2's ErrorLevels and Python
520
+ logging levels, you can modify the level_map dictionary from a subclass.
521
+
522
+ The default mapping is::
523
+
524
+ ErrorLevels.WARNING = logging.WARNING
525
+ ErrorLevels.ERROR = logging.ERROR
526
+ ErrorLevels.FATAL = logging.CRITICAL
527
+
528
+ You can also override the method ``receive()`` that takes a LogEntry
529
+ object and calls ``self.log(log_entry, format_string, arg1, arg2, ...)``
530
+ with appropriate data.
531
+ """
532
+ cdef readonly dict level_map
533
+ cdef object _map_level
534
+ cdef object _log
535
+ def __init__(self, logger_name=None, logger=None):
536
+ _BaseErrorLog.__init__(self, None, None)
537
+ import logging
538
+ self.level_map = {
539
+ ErrorLevels.WARNING : logging.WARNING,
540
+ ErrorLevels.ERROR : logging.ERROR,
541
+ ErrorLevels.FATAL : logging.CRITICAL
542
+ }
543
+ self._map_level = self.level_map.get
544
+ if logger is None:
545
+ if logger_name:
546
+ logger = logging.getLogger(logger_name)
547
+ else:
548
+ logger = logging.getLogger()
549
+ self._log = logger.log
550
+
551
+ cpdef copy(self):
552
+ """Dummy method that returns an empty error log.
553
+ """
554
+ return _ListErrorLog([], None, None)
555
+
556
+ def log(self, log_entry, message, *args):
557
+ """log(self, log_entry, message, *args)
558
+
559
+ Called by the .receive() method to log a _LogEntry instance to
560
+ the Python logging system. This handles the error level
561
+ mapping.
562
+
563
+ In the default implementation, the ``message`` argument
564
+ receives a complete log line, and there are no further
565
+ ``args``. To change the message format, it is best to
566
+ override the .receive() method instead of this one.
567
+ """
568
+ self._log(
569
+ self._map_level(log_entry.level, 0),
570
+ message, *args
571
+ )
572
+
573
+ cpdef receive(self, _LogEntry log_entry):
574
+ """receive(self, log_entry)
575
+
576
+ Receive a _LogEntry instance from the logging system. Calls
577
+ the .log() method with appropriate parameters::
578
+
579
+ self.log(log_entry, repr(log_entry))
580
+
581
+ You can override this method to provide your own log output
582
+ format.
583
+ """
584
+ self.log(log_entry, repr(log_entry))
585
+
586
+ # thread-local, global list log to collect error output messages from
587
+ # libxml2/libxslt
588
+
589
+ cdef _BaseErrorLog __GLOBAL_ERROR_LOG = _RotatingErrorLog(__MAX_LOG_SIZE)
590
+
591
+
592
+ cdef _BaseErrorLog _getThreadErrorLog(name):
593
+ """Retrieve the current error log with name 'name' of this thread."""
594
+ cdef python.PyObject* thread_dict
595
+ thread_dict = python.PyThreadState_GetDict()
596
+ if thread_dict is NULL:
597
+ return __GLOBAL_ERROR_LOG
598
+ try:
599
+ return (<object>thread_dict)[name]
600
+ except KeyError:
601
+ log = (<object>thread_dict)[name] = \
602
+ _RotatingErrorLog(__MAX_LOG_SIZE)
603
+ return log
604
+
605
+
606
+ cdef _setThreadErrorLog(name, _BaseErrorLog log):
607
+ """Set the global error log of this thread."""
608
+ cdef python.PyObject* thread_dict
609
+ thread_dict = python.PyThreadState_GetDict()
610
+ if thread_dict is NULL:
611
+ if name == GLOBAL_ERROR_LOG:
612
+ global __GLOBAL_ERROR_LOG
613
+ __GLOBAL_ERROR_LOG = log
614
+ else:
615
+ (<object>thread_dict)[name] = log
616
+
617
+
618
+ cdef __copyGlobalErrorLog():
619
+ "Helper function for properties in exceptions."
620
+ return _getThreadErrorLog(GLOBAL_ERROR_LOG).copy()
621
+
622
+
623
+ def use_global_python_log(PyErrorLog log not None):
624
+ """use_global_python_log(log)
625
+
626
+ Replace the global error log by an etree.PyErrorLog that uses the
627
+ standard Python logging package.
628
+
629
+ Note that this disables access to the global error log from exceptions.
630
+ Parsers, XSLT etc. will continue to provide their normal local error log.
631
+
632
+ Note: prior to lxml 2.2, this changed the error log globally.
633
+ Since lxml 2.2, the global error log is local to a thread and this
634
+ function will only set the global error log of the current thread.
635
+ """
636
+ _setThreadErrorLog(GLOBAL_ERROR_LOG, log)
637
+
638
+
639
+ # local log functions: forward error to logger object
640
+ cdef void _forwardError(void* c_log_handler, const xmlerror.xmlError* error) noexcept with gil:
641
+ cdef _BaseErrorLog log_handler
642
+ if c_log_handler is not NULL:
643
+ log_handler = <_BaseErrorLog>c_log_handler
644
+ elif error.domain == xmlerror.XML_FROM_XSLT:
645
+ log_handler = _getThreadErrorLog(XSLT_ERROR_LOG)
646
+ else:
647
+ log_handler = _getThreadErrorLog(GLOBAL_ERROR_LOG)
648
+ log_handler._receive(error)
649
+
650
+
651
+ cdef void _receiveError(void* c_log_handler, const xmlerror.xmlError* error) noexcept nogil:
652
+ # no Python objects here, may be called without thread context !
653
+ if __DEBUG:
654
+ _forwardError(c_log_handler, error)
655
+
656
+
657
+ cdef void _receiveXSLTError(void* c_log_handler, char* msg, ...) noexcept nogil:
658
+ # no Python objects here, may be called without thread context !
659
+ cdef cvarargs.va_list args
660
+ cvarargs.va_start(args, msg)
661
+ _receiveGenericError(c_log_handler, xmlerror.XML_FROM_XSLT, msg, args)
662
+ cvarargs.va_end(args)
663
+
664
+ cdef void _receiveRelaxNGParseError(void* c_log_handler, char* msg, ...) noexcept nogil:
665
+ # no Python objects here, may be called without thread context !
666
+ cdef cvarargs.va_list args
667
+ cvarargs.va_start(args, msg)
668
+ _receiveGenericError(c_log_handler, xmlerror.XML_FROM_RELAXNGP, msg, args)
669
+ cvarargs.va_end(args)
670
+
671
+ cdef void _receiveRelaxNGValidationError(void* c_log_handler, char* msg, ...) noexcept nogil:
672
+ # no Python objects here, may be called without thread context !
673
+ cdef cvarargs.va_list args
674
+ cvarargs.va_start(args, msg)
675
+ _receiveGenericError(c_log_handler, xmlerror.XML_FROM_RELAXNGV, msg, args)
676
+ cvarargs.va_end(args)
677
+
678
+ # dummy function: no log output at all
679
+ cdef void _nullGenericErrorFunc(void* ctxt, char* msg, ...) noexcept nogil:
680
+ pass
681
+
682
+
683
+ cdef void _connectGenericErrorLog(log, int c_domain=-1) noexcept:
684
+ cdef xmlerror.xmlGenericErrorFunc error_func = NULL
685
+ c_log = <void*>log
686
+ if c_domain == xmlerror.XML_FROM_XSLT:
687
+ error_func = <xmlerror.xmlGenericErrorFunc>_receiveXSLTError
688
+ elif c_domain == xmlerror.XML_FROM_RELAXNGP:
689
+ error_func = <xmlerror.xmlGenericErrorFunc>_receiveRelaxNGParseError
690
+ elif c_domain == xmlerror.XML_FROM_RELAXNGV:
691
+ error_func = <xmlerror.xmlGenericErrorFunc>_receiveRelaxNGValidationError
692
+
693
+ if log is None or error_func is NULL:
694
+ c_log = NULL
695
+ error_func = <xmlerror.xmlGenericErrorFunc>_nullGenericErrorFunc
696
+ xmlerror.xmlSetGenericErrorFunc(c_log, error_func)
697
+
698
+
699
+ cdef void _receiveGenericError(void* c_log_handler, int c_domain,
700
+ char* msg, cvarargs.va_list args) noexcept nogil:
701
+ # no Python objects here, may be called without thread context !
702
+ cdef xmlerror.xmlError c_error
703
+ cdef char* c_text
704
+ cdef char* c_message
705
+ cdef char* c_element
706
+ cdef char* c_pos
707
+ cdef char* c_name_pos
708
+ cdef char* c_str
709
+ cdef int text_size, element_size, format_count, c_int
710
+ if not __DEBUG or msg is NULL:
711
+ return
712
+ if msg[0] in b'\n\0':
713
+ return
714
+
715
+ c_text = c_element = c_error.file = c_error.node = NULL
716
+ c_error.line = 0
717
+
718
+ # parse "NAME %s" chunks from the format string
719
+ c_name_pos = c_pos = msg
720
+ format_count = 0
721
+ while c_pos[0]:
722
+ if c_pos[0] == b'%':
723
+ c_pos += 1
724
+ if c_pos[0] == b's': # "%s"
725
+ format_count += 1
726
+ c_str = cvarargs.va_charptr(args)
727
+ if c_pos == msg + 1:
728
+ c_text = c_str # msg == "%s..."
729
+ elif c_name_pos[0] == b'e':
730
+ if cstring_h.strncmp(c_name_pos, 'element %s', 10) == 0:
731
+ c_element = c_str
732
+ elif c_name_pos[0] == b'f':
733
+ if cstring_h.strncmp(c_name_pos, 'file %s', 7) == 0:
734
+ if cstring_h.strncmp('string://__STRING__XSLT',
735
+ c_str, 23) == 0:
736
+ c_str = '<xslt>'
737
+ c_error.file = c_str
738
+ elif c_pos[0] == b'd': # "%d"
739
+ format_count += 1
740
+ c_int = cvarargs.va_int(args)
741
+ if cstring_h.strncmp(c_name_pos, 'line %d', 7) == 0:
742
+ c_error.line = c_int
743
+ elif c_pos[0] != b'%': # "%%" == "%"
744
+ format_count += 1
745
+ break # unexpected format or end of string => abort
746
+ elif c_pos[0] == b' ':
747
+ if c_pos[1] != b'%':
748
+ c_name_pos = c_pos + 1
749
+ c_pos += 1
750
+
751
+ c_message = NULL
752
+ if c_text is NULL:
753
+ if c_element is not NULL and format_count == 1:
754
+ # special case: a single occurrence of 'element %s'
755
+ text_size = cstring_h.strlen(msg)
756
+ element_size = cstring_h.strlen(c_element)
757
+ c_message = <char*>stdlib.malloc(
758
+ (text_size + element_size + 1) * sizeof(char))
759
+ stdio.sprintf(c_message, msg, c_element)
760
+ c_error.message = c_message
761
+ else:
762
+ c_error.message = ''
763
+ elif c_element is NULL:
764
+ c_error.message = c_text
765
+ else:
766
+ text_size = cstring_h.strlen(c_text)
767
+ element_size = cstring_h.strlen(c_element)
768
+ c_message = <char*>stdlib.malloc(
769
+ (text_size + 12 + element_size + 1) * sizeof(char))
770
+ if c_message is NULL:
771
+ c_error.message = c_text
772
+ else:
773
+ stdio.sprintf(c_message, "%s, element '%s'", c_text, c_element)
774
+ c_error.message = c_message
775
+
776
+ c_error.domain = c_domain
777
+ c_error.code = xmlerror.XML_ERR_OK # what else?
778
+ c_error.level = xmlerror.XML_ERR_ERROR # what else?
779
+ c_error.int2 = 0
780
+
781
+ _forwardError(c_log_handler, &c_error)
782
+
783
+ if c_message is not NULL:
784
+ stdlib.free(c_message)
785
+
786
+ ################################################################################
787
+ ## CONSTANTS FROM "xmlerror.h" (or rather libxml-xmlerror.html)
788
+ ################################################################################
789
+
790
+ cdef __initErrorConstants():
791
+ "Called at setup time to parse the constants and build the classes below."
792
+ global __ERROR_LEVELS, __ERROR_DOMAINS, __PARSER_ERROR_TYPES, __RELAXNG_ERROR_TYPES
793
+ const_defs = ((ErrorLevels, __ERROR_LEVELS),
794
+ (ErrorDomains, __ERROR_DOMAINS),
795
+ (ErrorTypes, __PARSER_ERROR_TYPES),
796
+ (RelaxNGErrorTypes, __RELAXNG_ERROR_TYPES))
797
+
798
+ for cls, constants in const_defs:
799
+ reverse_dict = {}
800
+ cls._names = reverse_dict
801
+ cls._getName = reverse_dict.get
802
+ for line in constants.splitlines():
803
+ if not line:
804
+ continue
805
+ name, value = line.split('=')
806
+ value = int(value)
807
+ setattr(cls, name, value)
808
+ reverse_dict[value] = name
809
+
810
+ # discard the global string references after use
811
+ __ERROR_LEVELS = __ERROR_DOMAINS = __PARSER_ERROR_TYPES = __RELAXNG_ERROR_TYPES = None
812
+
813
+
814
+ class ErrorLevels(object):
815
+ """Libxml2 error levels"""
816
+
817
+ class ErrorDomains(object):
818
+ """Libxml2 error domains"""
819
+
820
+ class ErrorTypes(object):
821
+ """Libxml2 error types"""
822
+
823
+ class RelaxNGErrorTypes(object):
824
+ """Libxml2 RelaxNG error types"""
825
+
826
+
827
+ # --- BEGIN: GENERATED CONSTANTS ---
828
+
829
+ # This section is generated by the script 'update-error-constants.py'.
830
+
831
+ cdef object __ERROR_LEVELS = """\
832
+ NONE=0
833
+ WARNING=1
834
+ ERROR=2
835
+ FATAL=3
836
+ """
837
+
838
+ cdef object __ERROR_DOMAINS = """\
839
+ NONE=0
840
+ PARSER=1
841
+ TREE=2
842
+ NAMESPACE=3
843
+ DTD=4
844
+ HTML=5
845
+ MEMORY=6
846
+ OUTPUT=7
847
+ IO=8
848
+ FTP=9
849
+ HTTP=10
850
+ XINCLUDE=11
851
+ XPATH=12
852
+ XPOINTER=13
853
+ REGEXP=14
854
+ DATATYPE=15
855
+ SCHEMASP=16
856
+ SCHEMASV=17
857
+ RELAXNGP=18
858
+ RELAXNGV=19
859
+ CATALOG=20
860
+ C14N=21
861
+ XSLT=22
862
+ VALID=23
863
+ CHECK=24
864
+ WRITER=25
865
+ MODULE=26
866
+ I18N=27
867
+ SCHEMATRONV=28
868
+ BUFFER=29
869
+ URI=30
870
+ """
871
+
872
+ cdef object __PARSER_ERROR_TYPES = """\
873
+ ERR_OK=0
874
+ ERR_INTERNAL_ERROR=1
875
+ ERR_NO_MEMORY=2
876
+ ERR_DOCUMENT_START=3
877
+ ERR_DOCUMENT_EMPTY=4
878
+ ERR_DOCUMENT_END=5
879
+ ERR_INVALID_HEX_CHARREF=6
880
+ ERR_INVALID_DEC_CHARREF=7
881
+ ERR_INVALID_CHARREF=8
882
+ ERR_INVALID_CHAR=9
883
+ ERR_CHARREF_AT_EOF=10
884
+ ERR_CHARREF_IN_PROLOG=11
885
+ ERR_CHARREF_IN_EPILOG=12
886
+ ERR_CHARREF_IN_DTD=13
887
+ ERR_ENTITYREF_AT_EOF=14
888
+ ERR_ENTITYREF_IN_PROLOG=15
889
+ ERR_ENTITYREF_IN_EPILOG=16
890
+ ERR_ENTITYREF_IN_DTD=17
891
+ ERR_PEREF_AT_EOF=18
892
+ ERR_PEREF_IN_PROLOG=19
893
+ ERR_PEREF_IN_EPILOG=20
894
+ ERR_PEREF_IN_INT_SUBSET=21
895
+ ERR_ENTITYREF_NO_NAME=22
896
+ ERR_ENTITYREF_SEMICOL_MISSING=23
897
+ ERR_PEREF_NO_NAME=24
898
+ ERR_PEREF_SEMICOL_MISSING=25
899
+ ERR_UNDECLARED_ENTITY=26
900
+ WAR_UNDECLARED_ENTITY=27
901
+ ERR_UNPARSED_ENTITY=28
902
+ ERR_ENTITY_IS_EXTERNAL=29
903
+ ERR_ENTITY_IS_PARAMETER=30
904
+ ERR_UNKNOWN_ENCODING=31
905
+ ERR_UNSUPPORTED_ENCODING=32
906
+ ERR_STRING_NOT_STARTED=33
907
+ ERR_STRING_NOT_CLOSED=34
908
+ ERR_NS_DECL_ERROR=35
909
+ ERR_ENTITY_NOT_STARTED=36
910
+ ERR_ENTITY_NOT_FINISHED=37
911
+ ERR_LT_IN_ATTRIBUTE=38
912
+ ERR_ATTRIBUTE_NOT_STARTED=39
913
+ ERR_ATTRIBUTE_NOT_FINISHED=40
914
+ ERR_ATTRIBUTE_WITHOUT_VALUE=41
915
+ ERR_ATTRIBUTE_REDEFINED=42
916
+ ERR_LITERAL_NOT_STARTED=43
917
+ ERR_LITERAL_NOT_FINISHED=44
918
+ ERR_COMMENT_NOT_FINISHED=45
919
+ ERR_PI_NOT_STARTED=46
920
+ ERR_PI_NOT_FINISHED=47
921
+ ERR_NOTATION_NOT_STARTED=48
922
+ ERR_NOTATION_NOT_FINISHED=49
923
+ ERR_ATTLIST_NOT_STARTED=50
924
+ ERR_ATTLIST_NOT_FINISHED=51
925
+ ERR_MIXED_NOT_STARTED=52
926
+ ERR_MIXED_NOT_FINISHED=53
927
+ ERR_ELEMCONTENT_NOT_STARTED=54
928
+ ERR_ELEMCONTENT_NOT_FINISHED=55
929
+ ERR_XMLDECL_NOT_STARTED=56
930
+ ERR_XMLDECL_NOT_FINISHED=57
931
+ ERR_CONDSEC_NOT_STARTED=58
932
+ ERR_CONDSEC_NOT_FINISHED=59
933
+ ERR_EXT_SUBSET_NOT_FINISHED=60
934
+ ERR_DOCTYPE_NOT_FINISHED=61
935
+ ERR_MISPLACED_CDATA_END=62
936
+ ERR_CDATA_NOT_FINISHED=63
937
+ ERR_RESERVED_XML_NAME=64
938
+ ERR_SPACE_REQUIRED=65
939
+ ERR_SEPARATOR_REQUIRED=66
940
+ ERR_NMTOKEN_REQUIRED=67
941
+ ERR_NAME_REQUIRED=68
942
+ ERR_PCDATA_REQUIRED=69
943
+ ERR_URI_REQUIRED=70
944
+ ERR_PUBID_REQUIRED=71
945
+ ERR_LT_REQUIRED=72
946
+ ERR_GT_REQUIRED=73
947
+ ERR_LTSLASH_REQUIRED=74
948
+ ERR_EQUAL_REQUIRED=75
949
+ ERR_TAG_NAME_MISMATCH=76
950
+ ERR_TAG_NOT_FINISHED=77
951
+ ERR_STANDALONE_VALUE=78
952
+ ERR_ENCODING_NAME=79
953
+ ERR_HYPHEN_IN_COMMENT=80
954
+ ERR_INVALID_ENCODING=81
955
+ ERR_EXT_ENTITY_STANDALONE=82
956
+ ERR_CONDSEC_INVALID=83
957
+ ERR_VALUE_REQUIRED=84
958
+ ERR_NOT_WELL_BALANCED=85
959
+ ERR_EXTRA_CONTENT=86
960
+ ERR_ENTITY_CHAR_ERROR=87
961
+ ERR_ENTITY_PE_INTERNAL=88
962
+ ERR_ENTITY_LOOP=89
963
+ ERR_ENTITY_BOUNDARY=90
964
+ ERR_INVALID_URI=91
965
+ ERR_URI_FRAGMENT=92
966
+ WAR_CATALOG_PI=93
967
+ ERR_NO_DTD=94
968
+ ERR_CONDSEC_INVALID_KEYWORD=95
969
+ ERR_VERSION_MISSING=96
970
+ WAR_UNKNOWN_VERSION=97
971
+ WAR_LANG_VALUE=98
972
+ WAR_NS_URI=99
973
+ WAR_NS_URI_RELATIVE=100
974
+ ERR_MISSING_ENCODING=101
975
+ WAR_SPACE_VALUE=102
976
+ ERR_NOT_STANDALONE=103
977
+ ERR_ENTITY_PROCESSING=104
978
+ ERR_NOTATION_PROCESSING=105
979
+ WAR_NS_COLUMN=106
980
+ WAR_ENTITY_REDEFINED=107
981
+ ERR_UNKNOWN_VERSION=108
982
+ ERR_VERSION_MISMATCH=109
983
+ ERR_NAME_TOO_LONG=110
984
+ ERR_USER_STOP=111
985
+ ERR_COMMENT_ABRUPTLY_ENDED=112
986
+ WAR_ENCODING_MISMATCH=113
987
+ ERR_RESOURCE_LIMIT=114
988
+ ERR_ARGUMENT=115
989
+ ERR_SYSTEM=116
990
+ ERR_REDECL_PREDEF_ENTITY=117
991
+ ERR_INT_SUBSET_NOT_FINISHED=118
992
+ NS_ERR_XML_NAMESPACE=200
993
+ NS_ERR_UNDEFINED_NAMESPACE=201
994
+ NS_ERR_QNAME=202
995
+ NS_ERR_ATTRIBUTE_REDEFINED=203
996
+ NS_ERR_EMPTY=204
997
+ NS_ERR_COLON=205
998
+ DTD_ATTRIBUTE_DEFAULT=500
999
+ DTD_ATTRIBUTE_REDEFINED=501
1000
+ DTD_ATTRIBUTE_VALUE=502
1001
+ DTD_CONTENT_ERROR=503
1002
+ DTD_CONTENT_MODEL=504
1003
+ DTD_CONTENT_NOT_DETERMINIST=505
1004
+ DTD_DIFFERENT_PREFIX=506
1005
+ DTD_ELEM_DEFAULT_NAMESPACE=507
1006
+ DTD_ELEM_NAMESPACE=508
1007
+ DTD_ELEM_REDEFINED=509
1008
+ DTD_EMPTY_NOTATION=510
1009
+ DTD_ENTITY_TYPE=511
1010
+ DTD_ID_FIXED=512
1011
+ DTD_ID_REDEFINED=513
1012
+ DTD_ID_SUBSET=514
1013
+ DTD_INVALID_CHILD=515
1014
+ DTD_INVALID_DEFAULT=516
1015
+ DTD_LOAD_ERROR=517
1016
+ DTD_MISSING_ATTRIBUTE=518
1017
+ DTD_MIXED_CORRUPT=519
1018
+ DTD_MULTIPLE_ID=520
1019
+ DTD_NO_DOC=521
1020
+ DTD_NO_DTD=522
1021
+ DTD_NO_ELEM_NAME=523
1022
+ DTD_NO_PREFIX=524
1023
+ DTD_NO_ROOT=525
1024
+ DTD_NOTATION_REDEFINED=526
1025
+ DTD_NOTATION_VALUE=527
1026
+ DTD_NOT_EMPTY=528
1027
+ DTD_NOT_PCDATA=529
1028
+ DTD_NOT_STANDALONE=530
1029
+ DTD_ROOT_NAME=531
1030
+ DTD_STANDALONE_WHITE_SPACE=532
1031
+ DTD_UNKNOWN_ATTRIBUTE=533
1032
+ DTD_UNKNOWN_ELEM=534
1033
+ DTD_UNKNOWN_ENTITY=535
1034
+ DTD_UNKNOWN_ID=536
1035
+ DTD_UNKNOWN_NOTATION=537
1036
+ DTD_STANDALONE_DEFAULTED=538
1037
+ DTD_XMLID_VALUE=539
1038
+ DTD_XMLID_TYPE=540
1039
+ DTD_DUP_TOKEN=541
1040
+ HTML_STRUCURE_ERROR=800
1041
+ HTML_UNKNOWN_TAG=801
1042
+ HTML_INCORRECTLY_OPENED_COMMENT=802
1043
+ RNGP_ANYNAME_ATTR_ANCESTOR=1000
1044
+ RNGP_ATTR_CONFLICT=1001
1045
+ RNGP_ATTRIBUTE_CHILDREN=1002
1046
+ RNGP_ATTRIBUTE_CONTENT=1003
1047
+ RNGP_ATTRIBUTE_EMPTY=1004
1048
+ RNGP_ATTRIBUTE_NOOP=1005
1049
+ RNGP_CHOICE_CONTENT=1006
1050
+ RNGP_CHOICE_EMPTY=1007
1051
+ RNGP_CREATE_FAILURE=1008
1052
+ RNGP_DATA_CONTENT=1009
1053
+ RNGP_DEF_CHOICE_AND_INTERLEAVE=1010
1054
+ RNGP_DEFINE_CREATE_FAILED=1011
1055
+ RNGP_DEFINE_EMPTY=1012
1056
+ RNGP_DEFINE_MISSING=1013
1057
+ RNGP_DEFINE_NAME_MISSING=1014
1058
+ RNGP_ELEM_CONTENT_EMPTY=1015
1059
+ RNGP_ELEM_CONTENT_ERROR=1016
1060
+ RNGP_ELEMENT_EMPTY=1017
1061
+ RNGP_ELEMENT_CONTENT=1018
1062
+ RNGP_ELEMENT_NAME=1019
1063
+ RNGP_ELEMENT_NO_CONTENT=1020
1064
+ RNGP_ELEM_TEXT_CONFLICT=1021
1065
+ RNGP_EMPTY=1022
1066
+ RNGP_EMPTY_CONSTRUCT=1023
1067
+ RNGP_EMPTY_CONTENT=1024
1068
+ RNGP_EMPTY_NOT_EMPTY=1025
1069
+ RNGP_ERROR_TYPE_LIB=1026
1070
+ RNGP_EXCEPT_EMPTY=1027
1071
+ RNGP_EXCEPT_MISSING=1028
1072
+ RNGP_EXCEPT_MULTIPLE=1029
1073
+ RNGP_EXCEPT_NO_CONTENT=1030
1074
+ RNGP_EXTERNALREF_EMTPY=1031
1075
+ RNGP_EXTERNAL_REF_FAILURE=1032
1076
+ RNGP_EXTERNALREF_RECURSE=1033
1077
+ RNGP_FORBIDDEN_ATTRIBUTE=1034
1078
+ RNGP_FOREIGN_ELEMENT=1035
1079
+ RNGP_GRAMMAR_CONTENT=1036
1080
+ RNGP_GRAMMAR_EMPTY=1037
1081
+ RNGP_GRAMMAR_MISSING=1038
1082
+ RNGP_GRAMMAR_NO_START=1039
1083
+ RNGP_GROUP_ATTR_CONFLICT=1040
1084
+ RNGP_HREF_ERROR=1041
1085
+ RNGP_INCLUDE_EMPTY=1042
1086
+ RNGP_INCLUDE_FAILURE=1043
1087
+ RNGP_INCLUDE_RECURSE=1044
1088
+ RNGP_INTERLEAVE_ADD=1045
1089
+ RNGP_INTERLEAVE_CREATE_FAILED=1046
1090
+ RNGP_INTERLEAVE_EMPTY=1047
1091
+ RNGP_INTERLEAVE_NO_CONTENT=1048
1092
+ RNGP_INVALID_DEFINE_NAME=1049
1093
+ RNGP_INVALID_URI=1050
1094
+ RNGP_INVALID_VALUE=1051
1095
+ RNGP_MISSING_HREF=1052
1096
+ RNGP_NAME_MISSING=1053
1097
+ RNGP_NEED_COMBINE=1054
1098
+ RNGP_NOTALLOWED_NOT_EMPTY=1055
1099
+ RNGP_NSNAME_ATTR_ANCESTOR=1056
1100
+ RNGP_NSNAME_NO_NS=1057
1101
+ RNGP_PARAM_FORBIDDEN=1058
1102
+ RNGP_PARAM_NAME_MISSING=1059
1103
+ RNGP_PARENTREF_CREATE_FAILED=1060
1104
+ RNGP_PARENTREF_NAME_INVALID=1061
1105
+ RNGP_PARENTREF_NO_NAME=1062
1106
+ RNGP_PARENTREF_NO_PARENT=1063
1107
+ RNGP_PARENTREF_NOT_EMPTY=1064
1108
+ RNGP_PARSE_ERROR=1065
1109
+ RNGP_PAT_ANYNAME_EXCEPT_ANYNAME=1066
1110
+ RNGP_PAT_ATTR_ATTR=1067
1111
+ RNGP_PAT_ATTR_ELEM=1068
1112
+ RNGP_PAT_DATA_EXCEPT_ATTR=1069
1113
+ RNGP_PAT_DATA_EXCEPT_ELEM=1070
1114
+ RNGP_PAT_DATA_EXCEPT_EMPTY=1071
1115
+ RNGP_PAT_DATA_EXCEPT_GROUP=1072
1116
+ RNGP_PAT_DATA_EXCEPT_INTERLEAVE=1073
1117
+ RNGP_PAT_DATA_EXCEPT_LIST=1074
1118
+ RNGP_PAT_DATA_EXCEPT_ONEMORE=1075
1119
+ RNGP_PAT_DATA_EXCEPT_REF=1076
1120
+ RNGP_PAT_DATA_EXCEPT_TEXT=1077
1121
+ RNGP_PAT_LIST_ATTR=1078
1122
+ RNGP_PAT_LIST_ELEM=1079
1123
+ RNGP_PAT_LIST_INTERLEAVE=1080
1124
+ RNGP_PAT_LIST_LIST=1081
1125
+ RNGP_PAT_LIST_REF=1082
1126
+ RNGP_PAT_LIST_TEXT=1083
1127
+ RNGP_PAT_NSNAME_EXCEPT_ANYNAME=1084
1128
+ RNGP_PAT_NSNAME_EXCEPT_NSNAME=1085
1129
+ RNGP_PAT_ONEMORE_GROUP_ATTR=1086
1130
+ RNGP_PAT_ONEMORE_INTERLEAVE_ATTR=1087
1131
+ RNGP_PAT_START_ATTR=1088
1132
+ RNGP_PAT_START_DATA=1089
1133
+ RNGP_PAT_START_EMPTY=1090
1134
+ RNGP_PAT_START_GROUP=1091
1135
+ RNGP_PAT_START_INTERLEAVE=1092
1136
+ RNGP_PAT_START_LIST=1093
1137
+ RNGP_PAT_START_ONEMORE=1094
1138
+ RNGP_PAT_START_TEXT=1095
1139
+ RNGP_PAT_START_VALUE=1096
1140
+ RNGP_PREFIX_UNDEFINED=1097
1141
+ RNGP_REF_CREATE_FAILED=1098
1142
+ RNGP_REF_CYCLE=1099
1143
+ RNGP_REF_NAME_INVALID=1100
1144
+ RNGP_REF_NO_DEF=1101
1145
+ RNGP_REF_NO_NAME=1102
1146
+ RNGP_REF_NOT_EMPTY=1103
1147
+ RNGP_START_CHOICE_AND_INTERLEAVE=1104
1148
+ RNGP_START_CONTENT=1105
1149
+ RNGP_START_EMPTY=1106
1150
+ RNGP_START_MISSING=1107
1151
+ RNGP_TEXT_EXPECTED=1108
1152
+ RNGP_TEXT_HAS_CHILD=1109
1153
+ RNGP_TYPE_MISSING=1110
1154
+ RNGP_TYPE_NOT_FOUND=1111
1155
+ RNGP_TYPE_VALUE=1112
1156
+ RNGP_UNKNOWN_ATTRIBUTE=1113
1157
+ RNGP_UNKNOWN_COMBINE=1114
1158
+ RNGP_UNKNOWN_CONSTRUCT=1115
1159
+ RNGP_UNKNOWN_TYPE_LIB=1116
1160
+ RNGP_URI_FRAGMENT=1117
1161
+ RNGP_URI_NOT_ABSOLUTE=1118
1162
+ RNGP_VALUE_EMPTY=1119
1163
+ RNGP_VALUE_NO_CONTENT=1120
1164
+ RNGP_XMLNS_NAME=1121
1165
+ RNGP_XML_NS=1122
1166
+ XPATH_EXPRESSION_OK=1200
1167
+ XPATH_NUMBER_ERROR=1201
1168
+ XPATH_UNFINISHED_LITERAL_ERROR=1202
1169
+ XPATH_START_LITERAL_ERROR=1203
1170
+ XPATH_VARIABLE_REF_ERROR=1204
1171
+ XPATH_UNDEF_VARIABLE_ERROR=1205
1172
+ XPATH_INVALID_PREDICATE_ERROR=1206
1173
+ XPATH_EXPR_ERROR=1207
1174
+ XPATH_UNCLOSED_ERROR=1208
1175
+ XPATH_UNKNOWN_FUNC_ERROR=1209
1176
+ XPATH_INVALID_OPERAND=1210
1177
+ XPATH_INVALID_TYPE=1211
1178
+ XPATH_INVALID_ARITY=1212
1179
+ XPATH_INVALID_CTXT_SIZE=1213
1180
+ XPATH_INVALID_CTXT_POSITION=1214
1181
+ XPATH_MEMORY_ERROR=1215
1182
+ XPTR_SYNTAX_ERROR=1216
1183
+ XPTR_RESOURCE_ERROR=1217
1184
+ XPTR_SUB_RESOURCE_ERROR=1218
1185
+ XPATH_UNDEF_PREFIX_ERROR=1219
1186
+ XPATH_ENCODING_ERROR=1220
1187
+ XPATH_INVALID_CHAR_ERROR=1221
1188
+ TREE_INVALID_HEX=1300
1189
+ TREE_INVALID_DEC=1301
1190
+ TREE_UNTERMINATED_ENTITY=1302
1191
+ TREE_NOT_UTF8=1303
1192
+ SAVE_NOT_UTF8=1400
1193
+ SAVE_CHAR_INVALID=1401
1194
+ SAVE_NO_DOCTYPE=1402
1195
+ SAVE_UNKNOWN_ENCODING=1403
1196
+ REGEXP_COMPILE_ERROR=1450
1197
+ IO_UNKNOWN=1500
1198
+ IO_EACCES=1501
1199
+ IO_EAGAIN=1502
1200
+ IO_EBADF=1503
1201
+ IO_EBADMSG=1504
1202
+ IO_EBUSY=1505
1203
+ IO_ECANCELED=1506
1204
+ IO_ECHILD=1507
1205
+ IO_EDEADLK=1508
1206
+ IO_EDOM=1509
1207
+ IO_EEXIST=1510
1208
+ IO_EFAULT=1511
1209
+ IO_EFBIG=1512
1210
+ IO_EINPROGRESS=1513
1211
+ IO_EINTR=1514
1212
+ IO_EINVAL=1515
1213
+ IO_EIO=1516
1214
+ IO_EISDIR=1517
1215
+ IO_EMFILE=1518
1216
+ IO_EMLINK=1519
1217
+ IO_EMSGSIZE=1520
1218
+ IO_ENAMETOOLONG=1521
1219
+ IO_ENFILE=1522
1220
+ IO_ENODEV=1523
1221
+ IO_ENOENT=1524
1222
+ IO_ENOEXEC=1525
1223
+ IO_ENOLCK=1526
1224
+ IO_ENOMEM=1527
1225
+ IO_ENOSPC=1528
1226
+ IO_ENOSYS=1529
1227
+ IO_ENOTDIR=1530
1228
+ IO_ENOTEMPTY=1531
1229
+ IO_ENOTSUP=1532
1230
+ IO_ENOTTY=1533
1231
+ IO_ENXIO=1534
1232
+ IO_EPERM=1535
1233
+ IO_EPIPE=1536
1234
+ IO_ERANGE=1537
1235
+ IO_EROFS=1538
1236
+ IO_ESPIPE=1539
1237
+ IO_ESRCH=1540
1238
+ IO_ETIMEDOUT=1541
1239
+ IO_EXDEV=1542
1240
+ IO_NETWORK_ATTEMPT=1543
1241
+ IO_ENCODER=1544
1242
+ IO_FLUSH=1545
1243
+ IO_WRITE=1546
1244
+ IO_NO_INPUT=1547
1245
+ IO_BUFFER_FULL=1548
1246
+ IO_LOAD_ERROR=1549
1247
+ IO_ENOTSOCK=1550
1248
+ IO_EISCONN=1551
1249
+ IO_ECONNREFUSED=1552
1250
+ IO_ENETUNREACH=1553
1251
+ IO_EADDRINUSE=1554
1252
+ IO_EALREADY=1555
1253
+ IO_EAFNOSUPPORT=1556
1254
+ IO_UNSUPPORTED_PROTOCOL=1557
1255
+ XINCLUDE_RECURSION=1600
1256
+ XINCLUDE_PARSE_VALUE=1601
1257
+ XINCLUDE_ENTITY_DEF_MISMATCH=1602
1258
+ XINCLUDE_NO_HREF=1603
1259
+ XINCLUDE_NO_FALLBACK=1604
1260
+ XINCLUDE_HREF_URI=1605
1261
+ XINCLUDE_TEXT_FRAGMENT=1606
1262
+ XINCLUDE_TEXT_DOCUMENT=1607
1263
+ XINCLUDE_INVALID_CHAR=1608
1264
+ XINCLUDE_BUILD_FAILED=1609
1265
+ XINCLUDE_UNKNOWN_ENCODING=1610
1266
+ XINCLUDE_MULTIPLE_ROOT=1611
1267
+ XINCLUDE_XPTR_FAILED=1612
1268
+ XINCLUDE_XPTR_RESULT=1613
1269
+ XINCLUDE_INCLUDE_IN_INCLUDE=1614
1270
+ XINCLUDE_FALLBACKS_IN_INCLUDE=1615
1271
+ XINCLUDE_FALLBACK_NOT_IN_INCLUDE=1616
1272
+ XINCLUDE_DEPRECATED_NS=1617
1273
+ XINCLUDE_FRAGMENT_ID=1618
1274
+ CATALOG_MISSING_ATTR=1650
1275
+ CATALOG_ENTRY_BROKEN=1651
1276
+ CATALOG_PREFER_VALUE=1652
1277
+ CATALOG_NOT_CATALOG=1653
1278
+ CATALOG_RECURSION=1654
1279
+ SCHEMAP_PREFIX_UNDEFINED=1700
1280
+ SCHEMAP_ATTRFORMDEFAULT_VALUE=1701
1281
+ SCHEMAP_ATTRGRP_NONAME_NOREF=1702
1282
+ SCHEMAP_ATTR_NONAME_NOREF=1703
1283
+ SCHEMAP_COMPLEXTYPE_NONAME_NOREF=1704
1284
+ SCHEMAP_ELEMFORMDEFAULT_VALUE=1705
1285
+ SCHEMAP_ELEM_NONAME_NOREF=1706
1286
+ SCHEMAP_EXTENSION_NO_BASE=1707
1287
+ SCHEMAP_FACET_NO_VALUE=1708
1288
+ SCHEMAP_FAILED_BUILD_IMPORT=1709
1289
+ SCHEMAP_GROUP_NONAME_NOREF=1710
1290
+ SCHEMAP_IMPORT_NAMESPACE_NOT_URI=1711
1291
+ SCHEMAP_IMPORT_REDEFINE_NSNAME=1712
1292
+ SCHEMAP_IMPORT_SCHEMA_NOT_URI=1713
1293
+ SCHEMAP_INVALID_BOOLEAN=1714
1294
+ SCHEMAP_INVALID_ENUM=1715
1295
+ SCHEMAP_INVALID_FACET=1716
1296
+ SCHEMAP_INVALID_FACET_VALUE=1717
1297
+ SCHEMAP_INVALID_MAXOCCURS=1718
1298
+ SCHEMAP_INVALID_MINOCCURS=1719
1299
+ SCHEMAP_INVALID_REF_AND_SUBTYPE=1720
1300
+ SCHEMAP_INVALID_WHITE_SPACE=1721
1301
+ SCHEMAP_NOATTR_NOREF=1722
1302
+ SCHEMAP_NOTATION_NO_NAME=1723
1303
+ SCHEMAP_NOTYPE_NOREF=1724
1304
+ SCHEMAP_REF_AND_SUBTYPE=1725
1305
+ SCHEMAP_RESTRICTION_NONAME_NOREF=1726
1306
+ SCHEMAP_SIMPLETYPE_NONAME=1727
1307
+ SCHEMAP_TYPE_AND_SUBTYPE=1728
1308
+ SCHEMAP_UNKNOWN_ALL_CHILD=1729
1309
+ SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD=1730
1310
+ SCHEMAP_UNKNOWN_ATTR_CHILD=1731
1311
+ SCHEMAP_UNKNOWN_ATTRGRP_CHILD=1732
1312
+ SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP=1733
1313
+ SCHEMAP_UNKNOWN_BASE_TYPE=1734
1314
+ SCHEMAP_UNKNOWN_CHOICE_CHILD=1735
1315
+ SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD=1736
1316
+ SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD=1737
1317
+ SCHEMAP_UNKNOWN_ELEM_CHILD=1738
1318
+ SCHEMAP_UNKNOWN_EXTENSION_CHILD=1739
1319
+ SCHEMAP_UNKNOWN_FACET_CHILD=1740
1320
+ SCHEMAP_UNKNOWN_FACET_TYPE=1741
1321
+ SCHEMAP_UNKNOWN_GROUP_CHILD=1742
1322
+ SCHEMAP_UNKNOWN_IMPORT_CHILD=1743
1323
+ SCHEMAP_UNKNOWN_LIST_CHILD=1744
1324
+ SCHEMAP_UNKNOWN_NOTATION_CHILD=1745
1325
+ SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD=1746
1326
+ SCHEMAP_UNKNOWN_REF=1747
1327
+ SCHEMAP_UNKNOWN_RESTRICTION_CHILD=1748
1328
+ SCHEMAP_UNKNOWN_SCHEMAS_CHILD=1749
1329
+ SCHEMAP_UNKNOWN_SEQUENCE_CHILD=1750
1330
+ SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD=1751
1331
+ SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD=1752
1332
+ SCHEMAP_UNKNOWN_TYPE=1753
1333
+ SCHEMAP_UNKNOWN_UNION_CHILD=1754
1334
+ SCHEMAP_ELEM_DEFAULT_FIXED=1755
1335
+ SCHEMAP_REGEXP_INVALID=1756
1336
+ SCHEMAP_FAILED_LOAD=1757
1337
+ SCHEMAP_NOTHING_TO_PARSE=1758
1338
+ SCHEMAP_NOROOT=1759
1339
+ SCHEMAP_REDEFINED_GROUP=1760
1340
+ SCHEMAP_REDEFINED_TYPE=1761
1341
+ SCHEMAP_REDEFINED_ELEMENT=1762
1342
+ SCHEMAP_REDEFINED_ATTRGROUP=1763
1343
+ SCHEMAP_REDEFINED_ATTR=1764
1344
+ SCHEMAP_REDEFINED_NOTATION=1765
1345
+ SCHEMAP_FAILED_PARSE=1766
1346
+ SCHEMAP_UNKNOWN_PREFIX=1767
1347
+ SCHEMAP_DEF_AND_PREFIX=1768
1348
+ SCHEMAP_UNKNOWN_INCLUDE_CHILD=1769
1349
+ SCHEMAP_INCLUDE_SCHEMA_NOT_URI=1770
1350
+ SCHEMAP_INCLUDE_SCHEMA_NO_URI=1771
1351
+ SCHEMAP_NOT_SCHEMA=1772
1352
+ SCHEMAP_UNKNOWN_MEMBER_TYPE=1773
1353
+ SCHEMAP_INVALID_ATTR_USE=1774
1354
+ SCHEMAP_RECURSIVE=1775
1355
+ SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE=1776
1356
+ SCHEMAP_INVALID_ATTR_COMBINATION=1777
1357
+ SCHEMAP_INVALID_ATTR_INLINE_COMBINATION=1778
1358
+ SCHEMAP_MISSING_SIMPLETYPE_CHILD=1779
1359
+ SCHEMAP_INVALID_ATTR_NAME=1780
1360
+ SCHEMAP_REF_AND_CONTENT=1781
1361
+ SCHEMAP_CT_PROPS_CORRECT_1=1782
1362
+ SCHEMAP_CT_PROPS_CORRECT_2=1783
1363
+ SCHEMAP_CT_PROPS_CORRECT_3=1784
1364
+ SCHEMAP_CT_PROPS_CORRECT_4=1785
1365
+ SCHEMAP_CT_PROPS_CORRECT_5=1786
1366
+ SCHEMAP_DERIVATION_OK_RESTRICTION_1=1787
1367
+ SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1=1788
1368
+ SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2=1789
1369
+ SCHEMAP_DERIVATION_OK_RESTRICTION_2_2=1790
1370
+ SCHEMAP_DERIVATION_OK_RESTRICTION_3=1791
1371
+ SCHEMAP_WILDCARD_INVALID_NS_MEMBER=1792
1372
+ SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE=1793
1373
+ SCHEMAP_UNION_NOT_EXPRESSIBLE=1794
1374
+ SCHEMAP_SRC_IMPORT_3_1=1795
1375
+ SCHEMAP_SRC_IMPORT_3_2=1796
1376
+ SCHEMAP_DERIVATION_OK_RESTRICTION_4_1=1797
1377
+ SCHEMAP_DERIVATION_OK_RESTRICTION_4_2=1798
1378
+ SCHEMAP_DERIVATION_OK_RESTRICTION_4_3=1799
1379
+ SCHEMAP_COS_CT_EXTENDS_1_3=1800
1380
+ SCHEMAV_NOROOT=1801
1381
+ SCHEMAV_UNDECLAREDELEM=1802
1382
+ SCHEMAV_NOTTOPLEVEL=1803
1383
+ SCHEMAV_MISSING=1804
1384
+ SCHEMAV_WRONGELEM=1805
1385
+ SCHEMAV_NOTYPE=1806
1386
+ SCHEMAV_NOROLLBACK=1807
1387
+ SCHEMAV_ISABSTRACT=1808
1388
+ SCHEMAV_NOTEMPTY=1809
1389
+ SCHEMAV_ELEMCONT=1810
1390
+ SCHEMAV_HAVEDEFAULT=1811
1391
+ SCHEMAV_NOTNILLABLE=1812
1392
+ SCHEMAV_EXTRACONTENT=1813
1393
+ SCHEMAV_INVALIDATTR=1814
1394
+ SCHEMAV_INVALIDELEM=1815
1395
+ SCHEMAV_NOTDETERMINIST=1816
1396
+ SCHEMAV_CONSTRUCT=1817
1397
+ SCHEMAV_INTERNAL=1818
1398
+ SCHEMAV_NOTSIMPLE=1819
1399
+ SCHEMAV_ATTRUNKNOWN=1820
1400
+ SCHEMAV_ATTRINVALID=1821
1401
+ SCHEMAV_VALUE=1822
1402
+ SCHEMAV_FACET=1823
1403
+ SCHEMAV_CVC_DATATYPE_VALID_1_2_1=1824
1404
+ SCHEMAV_CVC_DATATYPE_VALID_1_2_2=1825
1405
+ SCHEMAV_CVC_DATATYPE_VALID_1_2_3=1826
1406
+ SCHEMAV_CVC_TYPE_3_1_1=1827
1407
+ SCHEMAV_CVC_TYPE_3_1_2=1828
1408
+ SCHEMAV_CVC_FACET_VALID=1829
1409
+ SCHEMAV_CVC_LENGTH_VALID=1830
1410
+ SCHEMAV_CVC_MINLENGTH_VALID=1831
1411
+ SCHEMAV_CVC_MAXLENGTH_VALID=1832
1412
+ SCHEMAV_CVC_MININCLUSIVE_VALID=1833
1413
+ SCHEMAV_CVC_MAXINCLUSIVE_VALID=1834
1414
+ SCHEMAV_CVC_MINEXCLUSIVE_VALID=1835
1415
+ SCHEMAV_CVC_MAXEXCLUSIVE_VALID=1836
1416
+ SCHEMAV_CVC_TOTALDIGITS_VALID=1837
1417
+ SCHEMAV_CVC_FRACTIONDIGITS_VALID=1838
1418
+ SCHEMAV_CVC_PATTERN_VALID=1839
1419
+ SCHEMAV_CVC_ENUMERATION_VALID=1840
1420
+ SCHEMAV_CVC_COMPLEX_TYPE_2_1=1841
1421
+ SCHEMAV_CVC_COMPLEX_TYPE_2_2=1842
1422
+ SCHEMAV_CVC_COMPLEX_TYPE_2_3=1843
1423
+ SCHEMAV_CVC_COMPLEX_TYPE_2_4=1844
1424
+ SCHEMAV_CVC_ELT_1=1845
1425
+ SCHEMAV_CVC_ELT_2=1846
1426
+ SCHEMAV_CVC_ELT_3_1=1847
1427
+ SCHEMAV_CVC_ELT_3_2_1=1848
1428
+ SCHEMAV_CVC_ELT_3_2_2=1849
1429
+ SCHEMAV_CVC_ELT_4_1=1850
1430
+ SCHEMAV_CVC_ELT_4_2=1851
1431
+ SCHEMAV_CVC_ELT_4_3=1852
1432
+ SCHEMAV_CVC_ELT_5_1_1=1853
1433
+ SCHEMAV_CVC_ELT_5_1_2=1854
1434
+ SCHEMAV_CVC_ELT_5_2_1=1855
1435
+ SCHEMAV_CVC_ELT_5_2_2_1=1856
1436
+ SCHEMAV_CVC_ELT_5_2_2_2_1=1857
1437
+ SCHEMAV_CVC_ELT_5_2_2_2_2=1858
1438
+ SCHEMAV_CVC_ELT_6=1859
1439
+ SCHEMAV_CVC_ELT_7=1860
1440
+ SCHEMAV_CVC_ATTRIBUTE_1=1861
1441
+ SCHEMAV_CVC_ATTRIBUTE_2=1862
1442
+ SCHEMAV_CVC_ATTRIBUTE_3=1863
1443
+ SCHEMAV_CVC_ATTRIBUTE_4=1864
1444
+ SCHEMAV_CVC_COMPLEX_TYPE_3_1=1865
1445
+ SCHEMAV_CVC_COMPLEX_TYPE_3_2_1=1866
1446
+ SCHEMAV_CVC_COMPLEX_TYPE_3_2_2=1867
1447
+ SCHEMAV_CVC_COMPLEX_TYPE_4=1868
1448
+ SCHEMAV_CVC_COMPLEX_TYPE_5_1=1869
1449
+ SCHEMAV_CVC_COMPLEX_TYPE_5_2=1870
1450
+ SCHEMAV_ELEMENT_CONTENT=1871
1451
+ SCHEMAV_DOCUMENT_ELEMENT_MISSING=1872
1452
+ SCHEMAV_CVC_COMPLEX_TYPE_1=1873
1453
+ SCHEMAV_CVC_AU=1874
1454
+ SCHEMAV_CVC_TYPE_1=1875
1455
+ SCHEMAV_CVC_TYPE_2=1876
1456
+ SCHEMAV_CVC_IDC=1877
1457
+ SCHEMAV_CVC_WILDCARD=1878
1458
+ SCHEMAV_MISC=1879
1459
+ XPTR_UNKNOWN_SCHEME=1900
1460
+ XPTR_CHILDSEQ_START=1901
1461
+ XPTR_EVAL_FAILED=1902
1462
+ XPTR_EXTRA_OBJECTS=1903
1463
+ C14N_CREATE_CTXT=1950
1464
+ C14N_REQUIRES_UTF8=1951
1465
+ C14N_CREATE_STACK=1952
1466
+ C14N_INVALID_NODE=1953
1467
+ C14N_UNKNOW_NODE=1954
1468
+ C14N_RELATIVE_NAMESPACE=1955
1469
+ FTP_PASV_ANSWER=2000
1470
+ FTP_EPSV_ANSWER=2001
1471
+ FTP_ACCNT=2002
1472
+ FTP_URL_SYNTAX=2003
1473
+ HTTP_URL_SYNTAX=2020
1474
+ HTTP_USE_IP=2021
1475
+ HTTP_UNKNOWN_HOST=2022
1476
+ SCHEMAP_SRC_SIMPLE_TYPE_1=3000
1477
+ SCHEMAP_SRC_SIMPLE_TYPE_2=3001
1478
+ SCHEMAP_SRC_SIMPLE_TYPE_3=3002
1479
+ SCHEMAP_SRC_SIMPLE_TYPE_4=3003
1480
+ SCHEMAP_SRC_RESOLVE=3004
1481
+ SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE=3005
1482
+ SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE=3006
1483
+ SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES=3007
1484
+ SCHEMAP_ST_PROPS_CORRECT_1=3008
1485
+ SCHEMAP_ST_PROPS_CORRECT_2=3009
1486
+ SCHEMAP_ST_PROPS_CORRECT_3=3010
1487
+ SCHEMAP_COS_ST_RESTRICTS_1_1=3011
1488
+ SCHEMAP_COS_ST_RESTRICTS_1_2=3012
1489
+ SCHEMAP_COS_ST_RESTRICTS_1_3_1=3013
1490
+ SCHEMAP_COS_ST_RESTRICTS_1_3_2=3014
1491
+ SCHEMAP_COS_ST_RESTRICTS_2_1=3015
1492
+ SCHEMAP_COS_ST_RESTRICTS_2_3_1_1=3016
1493
+ SCHEMAP_COS_ST_RESTRICTS_2_3_1_2=3017
1494
+ SCHEMAP_COS_ST_RESTRICTS_2_3_2_1=3018
1495
+ SCHEMAP_COS_ST_RESTRICTS_2_3_2_2=3019
1496
+ SCHEMAP_COS_ST_RESTRICTS_2_3_2_3=3020
1497
+ SCHEMAP_COS_ST_RESTRICTS_2_3_2_4=3021
1498
+ SCHEMAP_COS_ST_RESTRICTS_2_3_2_5=3022
1499
+ SCHEMAP_COS_ST_RESTRICTS_3_1=3023
1500
+ SCHEMAP_COS_ST_RESTRICTS_3_3_1=3024
1501
+ SCHEMAP_COS_ST_RESTRICTS_3_3_1_2=3025
1502
+ SCHEMAP_COS_ST_RESTRICTS_3_3_2_2=3026
1503
+ SCHEMAP_COS_ST_RESTRICTS_3_3_2_1=3027
1504
+ SCHEMAP_COS_ST_RESTRICTS_3_3_2_3=3028
1505
+ SCHEMAP_COS_ST_RESTRICTS_3_3_2_4=3029
1506
+ SCHEMAP_COS_ST_RESTRICTS_3_3_2_5=3030
1507
+ SCHEMAP_COS_ST_DERIVED_OK_2_1=3031
1508
+ SCHEMAP_COS_ST_DERIVED_OK_2_2=3032
1509
+ SCHEMAP_S4S_ELEM_NOT_ALLOWED=3033
1510
+ SCHEMAP_S4S_ELEM_MISSING=3034
1511
+ SCHEMAP_S4S_ATTR_NOT_ALLOWED=3035
1512
+ SCHEMAP_S4S_ATTR_MISSING=3036
1513
+ SCHEMAP_S4S_ATTR_INVALID_VALUE=3037
1514
+ SCHEMAP_SRC_ELEMENT_1=3038
1515
+ SCHEMAP_SRC_ELEMENT_2_1=3039
1516
+ SCHEMAP_SRC_ELEMENT_2_2=3040
1517
+ SCHEMAP_SRC_ELEMENT_3=3041
1518
+ SCHEMAP_P_PROPS_CORRECT_1=3042
1519
+ SCHEMAP_P_PROPS_CORRECT_2_1=3043
1520
+ SCHEMAP_P_PROPS_CORRECT_2_2=3044
1521
+ SCHEMAP_E_PROPS_CORRECT_2=3045
1522
+ SCHEMAP_E_PROPS_CORRECT_3=3046
1523
+ SCHEMAP_E_PROPS_CORRECT_4=3047
1524
+ SCHEMAP_E_PROPS_CORRECT_5=3048
1525
+ SCHEMAP_E_PROPS_CORRECT_6=3049
1526
+ SCHEMAP_SRC_INCLUDE=3050
1527
+ SCHEMAP_SRC_ATTRIBUTE_1=3051
1528
+ SCHEMAP_SRC_ATTRIBUTE_2=3052
1529
+ SCHEMAP_SRC_ATTRIBUTE_3_1=3053
1530
+ SCHEMAP_SRC_ATTRIBUTE_3_2=3054
1531
+ SCHEMAP_SRC_ATTRIBUTE_4=3055
1532
+ SCHEMAP_NO_XMLNS=3056
1533
+ SCHEMAP_NO_XSI=3057
1534
+ SCHEMAP_COS_VALID_DEFAULT_1=3058
1535
+ SCHEMAP_COS_VALID_DEFAULT_2_1=3059
1536
+ SCHEMAP_COS_VALID_DEFAULT_2_2_1=3060
1537
+ SCHEMAP_COS_VALID_DEFAULT_2_2_2=3061
1538
+ SCHEMAP_CVC_SIMPLE_TYPE=3062
1539
+ SCHEMAP_COS_CT_EXTENDS_1_1=3063
1540
+ SCHEMAP_SRC_IMPORT_1_1=3064
1541
+ SCHEMAP_SRC_IMPORT_1_2=3065
1542
+ SCHEMAP_SRC_IMPORT_2=3066
1543
+ SCHEMAP_SRC_IMPORT_2_1=3067
1544
+ SCHEMAP_SRC_IMPORT_2_2=3068
1545
+ SCHEMAP_INTERNAL=3069
1546
+ SCHEMAP_NOT_DETERMINISTIC=3070
1547
+ SCHEMAP_SRC_ATTRIBUTE_GROUP_1=3071
1548
+ SCHEMAP_SRC_ATTRIBUTE_GROUP_2=3072
1549
+ SCHEMAP_SRC_ATTRIBUTE_GROUP_3=3073
1550
+ SCHEMAP_MG_PROPS_CORRECT_1=3074
1551
+ SCHEMAP_MG_PROPS_CORRECT_2=3075
1552
+ SCHEMAP_SRC_CT_1=3076
1553
+ SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3=3077
1554
+ SCHEMAP_AU_PROPS_CORRECT_2=3078
1555
+ SCHEMAP_A_PROPS_CORRECT_2=3079
1556
+ SCHEMAP_C_PROPS_CORRECT=3080
1557
+ SCHEMAP_SRC_REDEFINE=3081
1558
+ SCHEMAP_SRC_IMPORT=3082
1559
+ SCHEMAP_WARN_SKIP_SCHEMA=3083
1560
+ SCHEMAP_WARN_UNLOCATED_SCHEMA=3084
1561
+ SCHEMAP_WARN_ATTR_REDECL_PROH=3085
1562
+ SCHEMAP_WARN_ATTR_POINTLESS_PROH=3086
1563
+ SCHEMAP_AG_PROPS_CORRECT=3087
1564
+ SCHEMAP_COS_CT_EXTENDS_1_2=3088
1565
+ SCHEMAP_AU_PROPS_CORRECT=3089
1566
+ SCHEMAP_A_PROPS_CORRECT_3=3090
1567
+ SCHEMAP_COS_ALL_LIMITED=3091
1568
+ SCHEMATRONV_ASSERT=4000
1569
+ SCHEMATRONV_REPORT=4001
1570
+ MODULE_OPEN=4900
1571
+ MODULE_CLOSE=4901
1572
+ CHECK_FOUND_ELEMENT=5000
1573
+ CHECK_FOUND_ATTRIBUTE=5001
1574
+ CHECK_FOUND_TEXT=5002
1575
+ CHECK_FOUND_CDATA=5003
1576
+ CHECK_FOUND_ENTITYREF=5004
1577
+ CHECK_FOUND_ENTITY=5005
1578
+ CHECK_FOUND_PI=5006
1579
+ CHECK_FOUND_COMMENT=5007
1580
+ CHECK_FOUND_DOCTYPE=5008
1581
+ CHECK_FOUND_FRAGMENT=5009
1582
+ CHECK_FOUND_NOTATION=5010
1583
+ CHECK_UNKNOWN_NODE=5011
1584
+ CHECK_ENTITY_TYPE=5012
1585
+ CHECK_NO_PARENT=5013
1586
+ CHECK_NO_DOC=5014
1587
+ CHECK_NO_NAME=5015
1588
+ CHECK_NO_ELEM=5016
1589
+ CHECK_WRONG_DOC=5017
1590
+ CHECK_NO_PREV=5018
1591
+ CHECK_WRONG_PREV=5019
1592
+ CHECK_NO_NEXT=5020
1593
+ CHECK_WRONG_NEXT=5021
1594
+ CHECK_NOT_DTD=5022
1595
+ CHECK_NOT_ATTR=5023
1596
+ CHECK_NOT_ATTR_DECL=5024
1597
+ CHECK_NOT_ELEM_DECL=5025
1598
+ CHECK_NOT_ENTITY_DECL=5026
1599
+ CHECK_NOT_NS_DECL=5027
1600
+ CHECK_NO_HREF=5028
1601
+ CHECK_WRONG_PARENT=5029
1602
+ CHECK_NS_SCOPE=5030
1603
+ CHECK_NS_ANCESTOR=5031
1604
+ CHECK_NOT_UTF8=5032
1605
+ CHECK_NO_DICT=5033
1606
+ CHECK_NOT_NCNAME=5034
1607
+ CHECK_OUTSIDE_DICT=5035
1608
+ CHECK_WRONG_NAME=5036
1609
+ CHECK_NAME_NOT_NULL=5037
1610
+ I18N_NO_NAME=6000
1611
+ I18N_NO_HANDLER=6001
1612
+ I18N_EXCESS_HANDLER=6002
1613
+ I18N_CONV_FAILED=6003
1614
+ I18N_NO_OUTPUT=6004
1615
+ BUF_OVERFLOW=7000
1616
+ """
1617
+
1618
+ cdef object __RELAXNG_ERROR_TYPES = """\
1619
+ RELAXNG_OK=0
1620
+ RELAXNG_ERR_MEMORY=1
1621
+ RELAXNG_ERR_TYPE=2
1622
+ RELAXNG_ERR_TYPEVAL=3
1623
+ RELAXNG_ERR_DUPID=4
1624
+ RELAXNG_ERR_TYPECMP=5
1625
+ RELAXNG_ERR_NOSTATE=6
1626
+ RELAXNG_ERR_NODEFINE=7
1627
+ RELAXNG_ERR_LISTEXTRA=8
1628
+ RELAXNG_ERR_LISTEMPTY=9
1629
+ RELAXNG_ERR_INTERNODATA=10
1630
+ RELAXNG_ERR_INTERSEQ=11
1631
+ RELAXNG_ERR_INTEREXTRA=12
1632
+ RELAXNG_ERR_ELEMNAME=13
1633
+ RELAXNG_ERR_ATTRNAME=14
1634
+ RELAXNG_ERR_ELEMNONS=15
1635
+ RELAXNG_ERR_ATTRNONS=16
1636
+ RELAXNG_ERR_ELEMWRONGNS=17
1637
+ RELAXNG_ERR_ATTRWRONGNS=18
1638
+ RELAXNG_ERR_ELEMEXTRANS=19
1639
+ RELAXNG_ERR_ATTREXTRANS=20
1640
+ RELAXNG_ERR_ELEMNOTEMPTY=21
1641
+ RELAXNG_ERR_NOELEM=22
1642
+ RELAXNG_ERR_NOTELEM=23
1643
+ RELAXNG_ERR_ATTRVALID=24
1644
+ RELAXNG_ERR_CONTENTVALID=25
1645
+ RELAXNG_ERR_EXTRACONTENT=26
1646
+ RELAXNG_ERR_INVALIDATTR=27
1647
+ RELAXNG_ERR_DATAELEM=28
1648
+ RELAXNG_ERR_VALELEM=29
1649
+ RELAXNG_ERR_LISTELEM=30
1650
+ RELAXNG_ERR_DATATYPE=31
1651
+ RELAXNG_ERR_VALUE=32
1652
+ RELAXNG_ERR_LIST=33
1653
+ RELAXNG_ERR_NOGRAMMAR=34
1654
+ RELAXNG_ERR_EXTRADATA=35
1655
+ RELAXNG_ERR_LACKDATA=36
1656
+ RELAXNG_ERR_INTERNAL=37
1657
+ RELAXNG_ERR_ELEMWRONG=38
1658
+ RELAXNG_ERR_TEXTWRONG=39
1659
+ """
1660
+ # --- END: GENERATED CONSTANTS ---
1661
+
1662
+ __initErrorConstants()
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xpath.pxi ADDED
@@ -0,0 +1,487 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # XPath evaluation
2
+
3
+ class XPathSyntaxError(LxmlSyntaxError, XPathError):
4
+ pass
5
+
6
+ ################################################################################
7
+ # XPath
8
+
9
+ cdef object _XPATH_SYNTAX_ERRORS = (
10
+ xmlerror.XML_XPATH_NUMBER_ERROR,
11
+ xmlerror.XML_XPATH_UNFINISHED_LITERAL_ERROR,
12
+ xmlerror.XML_XPATH_VARIABLE_REF_ERROR,
13
+ xmlerror.XML_XPATH_INVALID_PREDICATE_ERROR,
14
+ xmlerror.XML_XPATH_UNCLOSED_ERROR,
15
+ xmlerror.XML_XPATH_INVALID_CHAR_ERROR
16
+ )
17
+
18
+ cdef object _XPATH_EVAL_ERRORS = (
19
+ xmlerror.XML_XPATH_UNDEF_VARIABLE_ERROR,
20
+ xmlerror.XML_XPATH_UNDEF_PREFIX_ERROR,
21
+ xmlerror.XML_XPATH_UNKNOWN_FUNC_ERROR,
22
+ xmlerror.XML_XPATH_INVALID_OPERAND,
23
+ xmlerror.XML_XPATH_INVALID_TYPE,
24
+ xmlerror.XML_XPATH_INVALID_ARITY,
25
+ xmlerror.XML_XPATH_INVALID_CTXT_SIZE,
26
+ xmlerror.XML_XPATH_INVALID_CTXT_POSITION
27
+ )
28
+
29
+ cdef int _register_xpath_function(void* ctxt, name_utf, ns_utf) noexcept:
30
+ if ns_utf is None:
31
+ return xpath.xmlXPathRegisterFunc(
32
+ <xpath.xmlXPathContext*>ctxt, _xcstr(name_utf),
33
+ _xpath_function_call)
34
+ else:
35
+ return xpath.xmlXPathRegisterFuncNS(
36
+ <xpath.xmlXPathContext*>ctxt, _xcstr(name_utf), _xcstr(ns_utf),
37
+ _xpath_function_call)
38
+
39
+ cdef int _unregister_xpath_function(void* ctxt, name_utf, ns_utf) noexcept:
40
+ if ns_utf is None:
41
+ return xpath.xmlXPathRegisterFunc(
42
+ <xpath.xmlXPathContext*>ctxt, _xcstr(name_utf), NULL)
43
+ else:
44
+ return xpath.xmlXPathRegisterFuncNS(
45
+ <xpath.xmlXPathContext*>ctxt, _xcstr(name_utf), _xcstr(ns_utf), NULL)
46
+
47
+
48
+ @cython.final
49
+ @cython.internal
50
+ cdef class _XPathContext(_BaseContext):
51
+ cdef object _variables
52
+ def __init__(self, namespaces, extensions, error_log, enable_regexp, variables,
53
+ build_smart_strings):
54
+ self._variables = variables
55
+ _BaseContext.__init__(self, namespaces, extensions, error_log, enable_regexp,
56
+ build_smart_strings)
57
+
58
+ cdef set_context(self, xpath.xmlXPathContext* xpathCtxt):
59
+ self._set_xpath_context(xpathCtxt)
60
+ # This would be a good place to set up the XPath parser dict, but
61
+ # we cannot use the current thread dict as we do not know which
62
+ # thread will execute the XPath evaluator - so, no dict for now.
63
+ self.registerLocalNamespaces()
64
+ self.registerLocalFunctions(xpathCtxt, _register_xpath_function)
65
+
66
+ cdef register_context(self, _Document doc):
67
+ self._register_context(doc)
68
+ self.registerGlobalNamespaces()
69
+ self.registerGlobalFunctions(self._xpathCtxt, _register_xpath_function)
70
+ self.registerExsltFunctions()
71
+ if self._variables is not None:
72
+ self.registerVariables(self._variables)
73
+
74
+ cdef unregister_context(self):
75
+ self.unregisterGlobalFunctions(
76
+ self._xpathCtxt, _unregister_xpath_function)
77
+ self.unregisterGlobalNamespaces()
78
+ xpath.xmlXPathRegisteredVariablesCleanup(self._xpathCtxt)
79
+ self._cleanup_context()
80
+
81
+ cdef void registerExsltFunctions(self) noexcept:
82
+ if xslt.LIBXSLT_VERSION < 10125:
83
+ # we'd only execute dummy functions anyway
84
+ return
85
+ tree.xmlHashScan(
86
+ self._xpathCtxt.nsHash, _registerExsltFunctionsForNamespaces,
87
+ self._xpathCtxt)
88
+
89
+ cdef registerVariables(self, variable_dict):
90
+ for name, value in variable_dict.items():
91
+ name_utf = self._to_utf(name)
92
+ xpath.xmlXPathRegisterVariable(
93
+ self._xpathCtxt, _xcstr(name_utf), _wrapXPathObject(value, None, None))
94
+
95
+ cdef registerVariable(self, name, value):
96
+ name_utf = self._to_utf(name)
97
+ xpath.xmlXPathRegisterVariable(
98
+ self._xpathCtxt, _xcstr(name_utf), _wrapXPathObject(value, None, None))
99
+
100
+
101
+ cdef void _registerExsltFunctionsForNamespaces(
102
+ void* _c_href, void* _ctxt, const_xmlChar* c_prefix) noexcept:
103
+ c_href = <const_xmlChar*> _c_href
104
+ ctxt = <xpath.xmlXPathContext*> _ctxt
105
+
106
+ if tree.xmlStrcmp(c_href, xslt.EXSLT_DATE_NAMESPACE) == 0:
107
+ xslt.exsltDateXpathCtxtRegister(ctxt, c_prefix)
108
+ elif tree.xmlStrcmp(c_href, xslt.EXSLT_SETS_NAMESPACE) == 0:
109
+ xslt.exsltSetsXpathCtxtRegister(ctxt, c_prefix)
110
+ elif tree.xmlStrcmp(c_href, xslt.EXSLT_MATH_NAMESPACE) == 0:
111
+ xslt.exsltMathXpathCtxtRegister(ctxt, c_prefix)
112
+ elif tree.xmlStrcmp(c_href, xslt.EXSLT_STRINGS_NAMESPACE) == 0:
113
+ xslt.exsltStrXpathCtxtRegister(ctxt, c_prefix)
114
+
115
+
116
+ cdef class _XPathEvaluatorBase:
117
+ cdef xpath.xmlXPathContext* _xpathCtxt
118
+ cdef _XPathContext _context
119
+ cdef python.PyThread_type_lock _eval_lock
120
+ cdef _ErrorLog _error_log
121
+ def __cinit__(self):
122
+ self._xpathCtxt = NULL
123
+ if config.ENABLE_THREADING:
124
+ self._eval_lock = python.PyThread_allocate_lock()
125
+ if self._eval_lock is NULL:
126
+ raise MemoryError()
127
+ self._error_log = _ErrorLog()
128
+
129
+ def __init__(self, namespaces, extensions, enable_regexp,
130
+ smart_strings):
131
+ self._context = _XPathContext(namespaces, extensions, self._error_log,
132
+ enable_regexp, None, smart_strings)
133
+
134
+ @property
135
+ def error_log(self):
136
+ assert self._error_log is not None, "XPath evaluator not initialised"
137
+ return self._error_log.copy()
138
+
139
+ def __dealloc__(self):
140
+ if self._xpathCtxt is not NULL:
141
+ xpath.xmlXPathFreeContext(self._xpathCtxt)
142
+ if config.ENABLE_THREADING:
143
+ if self._eval_lock is not NULL:
144
+ python.PyThread_free_lock(self._eval_lock)
145
+
146
+ cdef set_context(self, xpath.xmlXPathContext* xpathCtxt):
147
+ self._xpathCtxt = xpathCtxt
148
+ self._context.set_context(xpathCtxt)
149
+
150
+ cdef bint _checkAbsolutePath(self, char* path) noexcept:
151
+ cdef char c
152
+ if path is NULL:
153
+ return 0
154
+ c = path[0]
155
+ while c == c' ' or c == c'\t':
156
+ path = path + 1
157
+ c = path[0]
158
+ return c == c'/'
159
+
160
+ @cython.final
161
+ cdef int _lock(self) except -1:
162
+ cdef int result
163
+ if config.ENABLE_THREADING and self._eval_lock != NULL:
164
+ with nogil:
165
+ result = python.PyThread_acquire_lock(
166
+ self._eval_lock, python.WAIT_LOCK)
167
+ if result == 0:
168
+ raise XPathError, "XPath evaluator locking failed"
169
+ return 0
170
+
171
+ @cython.final
172
+ cdef void _unlock(self) noexcept:
173
+ if config.ENABLE_THREADING and self._eval_lock != NULL:
174
+ python.PyThread_release_lock(self._eval_lock)
175
+
176
+ cdef _build_parse_error(self):
177
+ cdef _BaseErrorLog entries
178
+ entries = self._error_log.filter_types(_XPATH_SYNTAX_ERRORS)
179
+ if entries:
180
+ message = entries._buildExceptionMessage(None)
181
+ if message is not None:
182
+ return XPathSyntaxError(message, self._error_log)
183
+ return XPathSyntaxError(
184
+ self._error_log._buildExceptionMessage("Error in xpath expression"),
185
+ self._error_log)
186
+
187
+ cdef _build_eval_error(self):
188
+ cdef _BaseErrorLog entries
189
+ entries = self._error_log.filter_types(_XPATH_EVAL_ERRORS)
190
+ if not entries:
191
+ entries = self._error_log.filter_types(_XPATH_SYNTAX_ERRORS)
192
+ if entries:
193
+ message = entries._buildExceptionMessage(None)
194
+ if message is not None:
195
+ return XPathEvalError(message, self._error_log)
196
+ return XPathEvalError(
197
+ self._error_log._buildExceptionMessage("Error in xpath expression"),
198
+ self._error_log)
199
+
200
+ cdef object _handle_result(self, xpath.xmlXPathObject* xpathObj, _Document doc):
201
+ if self._context._exc._has_raised():
202
+ if xpathObj is not NULL:
203
+ _freeXPathObject(xpathObj)
204
+ xpathObj = NULL
205
+ self._context._release_temp_refs()
206
+ self._context._exc._raise_if_stored()
207
+
208
+ if xpathObj is NULL:
209
+ self._context._release_temp_refs()
210
+ raise self._build_eval_error()
211
+
212
+ try:
213
+ result = _unwrapXPathObject(xpathObj, doc, self._context)
214
+ finally:
215
+ _freeXPathObject(xpathObj)
216
+ self._context._release_temp_refs()
217
+
218
+ return result
219
+
220
+
221
+ cdef class XPathElementEvaluator(_XPathEvaluatorBase):
222
+ """XPathElementEvaluator(self, element, namespaces=None, extensions=None, regexp=True, smart_strings=True)
223
+ Create an XPath evaluator for an element.
224
+
225
+ Absolute XPath expressions (starting with '/') will be evaluated against
226
+ the ElementTree as returned by getroottree().
227
+
228
+ Additional namespace declarations can be passed with the
229
+ 'namespace' keyword argument. EXSLT regular expression support
230
+ can be disabled with the 'regexp' boolean keyword (defaults to
231
+ True). Smart strings will be returned for string results unless
232
+ you pass ``smart_strings=False``.
233
+ """
234
+ cdef _Element _element
235
+ def __init__(self, _Element element not None, *, namespaces=None,
236
+ extensions=None, regexp=True, smart_strings=True):
237
+ cdef xpath.xmlXPathContext* xpathCtxt
238
+ cdef int ns_register_status
239
+ cdef _Document doc
240
+ _assertValidNode(element)
241
+ _assertValidDoc(element._doc)
242
+ self._element = element
243
+ doc = element._doc
244
+ _XPathEvaluatorBase.__init__(self, namespaces, extensions,
245
+ regexp, smart_strings)
246
+ xpathCtxt = xpath.xmlXPathNewContext(doc._c_doc)
247
+ if xpathCtxt is NULL:
248
+ raise MemoryError()
249
+ self.set_context(xpathCtxt)
250
+
251
+ def register_namespace(self, prefix, uri):
252
+ """Register a namespace with the XPath context.
253
+ """
254
+ assert self._xpathCtxt is not NULL, "XPath context not initialised"
255
+ self._context.addNamespace(prefix, uri)
256
+
257
+ def register_namespaces(self, namespaces):
258
+ """Register a prefix -> uri dict.
259
+ """
260
+ assert self._xpathCtxt is not NULL, "XPath context not initialised"
261
+ for prefix, uri in namespaces.items():
262
+ self._context.addNamespace(prefix, uri)
263
+
264
+ def __call__(self, _path, **_variables):
265
+ """__call__(self, _path, **_variables)
266
+
267
+ Evaluate an XPath expression on the document.
268
+
269
+ Variables may be provided as keyword arguments. Note that namespaces
270
+ are currently not supported for variables.
271
+
272
+ Absolute XPath expressions (starting with '/') will be evaluated
273
+ against the ElementTree as returned by getroottree().
274
+ """
275
+ cdef xpath.xmlXPathObject* xpathObj
276
+ cdef _Document doc
277
+ assert self._xpathCtxt is not NULL, "XPath context not initialised"
278
+ path = _utf8(_path)
279
+ doc = self._element._doc
280
+
281
+ self._lock()
282
+ self._xpathCtxt.node = self._element._c_node
283
+ try:
284
+ self._context.register_context(doc)
285
+ self._context.registerVariables(_variables)
286
+ c_path = _xcstr(path)
287
+ with nogil:
288
+ xpathObj = xpath.xmlXPathEvalExpression(
289
+ c_path, self._xpathCtxt)
290
+ result = self._handle_result(xpathObj, doc)
291
+ finally:
292
+ self._context.unregister_context()
293
+ self._unlock()
294
+
295
+ return result
296
+
297
+
298
+ cdef class XPathDocumentEvaluator(XPathElementEvaluator):
299
+ """XPathDocumentEvaluator(self, etree, namespaces=None, extensions=None, regexp=True, smart_strings=True)
300
+ Create an XPath evaluator for an ElementTree.
301
+
302
+ Additional namespace declarations can be passed with the
303
+ 'namespace' keyword argument. EXSLT regular expression support
304
+ can be disabled with the 'regexp' boolean keyword (defaults to
305
+ True). Smart strings will be returned for string results unless
306
+ you pass ``smart_strings=False``.
307
+ """
308
+ def __init__(self, _ElementTree etree not None, *, namespaces=None,
309
+ extensions=None, regexp=True, smart_strings=True):
310
+ XPathElementEvaluator.__init__(
311
+ self, etree._context_node, namespaces=namespaces,
312
+ extensions=extensions, regexp=regexp,
313
+ smart_strings=smart_strings)
314
+
315
+ def __call__(self, _path, **_variables):
316
+ """__call__(self, _path, **_variables)
317
+
318
+ Evaluate an XPath expression on the document.
319
+
320
+ Variables may be provided as keyword arguments. Note that namespaces
321
+ are currently not supported for variables.
322
+ """
323
+ cdef xpath.xmlXPathObject* xpathObj
324
+ cdef xmlDoc* c_doc
325
+ cdef _Document doc
326
+ assert self._xpathCtxt is not NULL, "XPath context not initialised"
327
+ path = _utf8(_path)
328
+ doc = self._element._doc
329
+
330
+ self._lock()
331
+ try:
332
+ self._context.register_context(doc)
333
+ c_doc = _fakeRootDoc(doc._c_doc, self._element._c_node)
334
+ try:
335
+ self._context.registerVariables(_variables)
336
+ c_path = _xcstr(path)
337
+ with nogil:
338
+ self._xpathCtxt.doc = c_doc
339
+ self._xpathCtxt.node = tree.xmlDocGetRootElement(c_doc)
340
+ xpathObj = xpath.xmlXPathEvalExpression(
341
+ c_path, self._xpathCtxt)
342
+ result = self._handle_result(xpathObj, doc)
343
+ finally:
344
+ _destroyFakeDoc(doc._c_doc, c_doc)
345
+ self._context.unregister_context()
346
+ finally:
347
+ self._unlock()
348
+
349
+ return result
350
+
351
+
352
+ def XPathEvaluator(etree_or_element, *, namespaces=None, extensions=None,
353
+ regexp=True, smart_strings=True):
354
+ """XPathEvaluator(etree_or_element, namespaces=None, extensions=None, regexp=True, smart_strings=True)
355
+
356
+ Creates an XPath evaluator for an ElementTree or an Element.
357
+
358
+ The resulting object can be called with an XPath expression as argument
359
+ and XPath variables provided as keyword arguments.
360
+
361
+ Additional namespace declarations can be passed with the
362
+ 'namespace' keyword argument. EXSLT regular expression support
363
+ can be disabled with the 'regexp' boolean keyword (defaults to
364
+ True). Smart strings will be returned for string results unless
365
+ you pass ``smart_strings=False``.
366
+ """
367
+ if isinstance(etree_or_element, _ElementTree):
368
+ return XPathDocumentEvaluator(
369
+ etree_or_element, namespaces=namespaces,
370
+ extensions=extensions, regexp=regexp, smart_strings=smart_strings)
371
+ else:
372
+ return XPathElementEvaluator(
373
+ etree_or_element, namespaces=namespaces,
374
+ extensions=extensions, regexp=regexp, smart_strings=smart_strings)
375
+
376
+
377
+ cdef class XPath(_XPathEvaluatorBase):
378
+ """XPath(self, path, namespaces=None, extensions=None, regexp=True, smart_strings=True)
379
+ A compiled XPath expression that can be called on Elements and ElementTrees.
380
+
381
+ Besides the XPath expression, you can pass prefix-namespace
382
+ mappings and extension functions to the constructor through the
383
+ keyword arguments ``namespaces`` and ``extensions``. EXSLT
384
+ regular expression support can be disabled with the 'regexp'
385
+ boolean keyword (defaults to True). Smart strings will be
386
+ returned for string results unless you pass
387
+ ``smart_strings=False``.
388
+ """
389
+ cdef xpath.xmlXPathCompExpr* _xpath
390
+ cdef bytes _path
391
+ def __cinit__(self):
392
+ self._xpath = NULL
393
+
394
+ def __init__(self, path, *, namespaces=None, extensions=None,
395
+ regexp=True, smart_strings=True):
396
+ cdef xpath.xmlXPathContext* xpathCtxt
397
+ _XPathEvaluatorBase.__init__(self, namespaces, extensions,
398
+ regexp, smart_strings)
399
+ self._path = _utf8(path)
400
+ xpathCtxt = xpath.xmlXPathNewContext(NULL)
401
+ if xpathCtxt is NULL:
402
+ raise MemoryError()
403
+ self.set_context(xpathCtxt)
404
+ self._xpath = xpath.xmlXPathCtxtCompile(xpathCtxt, _xcstr(self._path))
405
+ if self._xpath is NULL:
406
+ raise self._build_parse_error()
407
+
408
+ def __call__(self, _etree_or_element, **_variables):
409
+ "__call__(self, _etree_or_element, **_variables)"
410
+ cdef xpath.xmlXPathObject* xpathObj
411
+ cdef _Document document
412
+ cdef _Element element
413
+
414
+ assert self._xpathCtxt is not NULL, "XPath context not initialised"
415
+ document = _documentOrRaise(_etree_or_element)
416
+ element = _rootNodeOrRaise(_etree_or_element)
417
+
418
+ self._lock()
419
+ self._xpathCtxt.doc = document._c_doc
420
+ self._xpathCtxt.node = element._c_node
421
+
422
+ try:
423
+ self._context.register_context(document)
424
+ self._context.registerVariables(_variables)
425
+ with nogil:
426
+ xpathObj = xpath.xmlXPathCompiledEval(
427
+ self._xpath, self._xpathCtxt)
428
+ result = self._handle_result(xpathObj, document)
429
+ finally:
430
+ self._context.unregister_context()
431
+ self._unlock()
432
+ return result
433
+
434
+ @property
435
+ def path(self):
436
+ """The literal XPath expression.
437
+ """
438
+ return self._path.decode('UTF-8')
439
+
440
+ def __dealloc__(self):
441
+ if self._xpath is not NULL:
442
+ xpath.xmlXPathFreeCompExpr(self._xpath)
443
+
444
+ def __repr__(self):
445
+ return self.path
446
+
447
+
448
+ cdef object _replace_strings = re.compile(b'("[^"]*")|(\'[^\']*\')').sub
449
+ cdef object _find_namespaces = re.compile(b'({[^}]+})').findall
450
+
451
+ cdef class ETXPath(XPath):
452
+ """ETXPath(self, path, extensions=None, regexp=True, smart_strings=True)
453
+ Special XPath class that supports the ElementTree {uri} notation for namespaces.
454
+
455
+ Note that this class does not accept the ``namespace`` keyword
456
+ argument. All namespaces must be passed as part of the path
457
+ string. Smart strings will be returned for string results unless
458
+ you pass ``smart_strings=False``.
459
+ """
460
+ def __init__(self, path, *, extensions=None, regexp=True,
461
+ smart_strings=True):
462
+ path, namespaces = self._nsextract_path(path)
463
+ XPath.__init__(self, path, namespaces=namespaces,
464
+ extensions=extensions, regexp=regexp,
465
+ smart_strings=smart_strings)
466
+
467
+ cdef _nsextract_path(self, path):
468
+ # replace {namespaces} by new prefixes
469
+ cdef dict namespaces = {}
470
+ cdef list namespace_defs = []
471
+ cdef int i
472
+ path_utf = _utf8(path)
473
+ stripped_path = _replace_strings(b'', path_utf) # remove string literals
474
+ i = 1
475
+ for namespace_def in _find_namespaces(stripped_path):
476
+ if namespace_def not in namespace_defs:
477
+ prefix = python.PyBytes_FromFormat("__xpp%02d", i)
478
+ i += 1
479
+ namespace_defs.append(namespace_def)
480
+ namespace = namespace_def[1:-1] # remove '{}'
481
+ namespace = (<bytes>namespace).decode('utf8')
482
+ namespaces[prefix.decode('utf8')] = namespace
483
+ prefix_str = prefix + b':'
484
+ # FIXME: this also replaces {namespaces} within strings!
485
+ path_utf = path_utf.replace(namespace_def, prefix_str)
486
+ path = path_utf.decode('utf8')
487
+ return path, namespaces
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/lxml/xsltext.pxi ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # XSLT extension elements
2
+
3
+ cdef class XSLTExtension:
4
+ """Base class of an XSLT extension element.
5
+ """
6
+ def execute(self, context, self_node, input_node, output_parent):
7
+ """execute(self, context, self_node, input_node, output_parent)
8
+ Execute this extension element.
9
+
10
+ Subclasses must override this method. They may append
11
+ elements to the `output_parent` element here, or set its text
12
+ content. To this end, the `input_node` provides read-only
13
+ access to the current node in the input document, and the
14
+ `self_node` points to the extension element in the stylesheet.
15
+
16
+ Note that the `output_parent` parameter may be `None` if there
17
+ is no parent element in the current context (e.g. no content
18
+ was added to the output tree yet).
19
+ """
20
+ pass
21
+
22
+ def apply_templates(self, _XSLTContext context not None, node, output_parent=None,
23
+ *, elements_only=False, remove_blank_text=False):
24
+ """apply_templates(self, context, node, output_parent=None, elements_only=False, remove_blank_text=False)
25
+
26
+ Call this method to retrieve the result of applying templates
27
+ to an element.
28
+
29
+ The return value is a list of elements or text strings that
30
+ were generated by the XSLT processor. If you pass
31
+ ``elements_only=True``, strings will be discarded from the result
32
+ list. The option ``remove_blank_text=True`` will only discard
33
+ strings that consist entirely of whitespace (e.g. formatting).
34
+ These options do not apply to Elements, only to bare string results.
35
+
36
+ If you pass an Element as `output_parent` parameter, the result
37
+ will instead be appended to the element (including attributes
38
+ etc.) and the return value will be `None`. This is a safe way
39
+ to generate content into the output document directly, without
40
+ having to take care of special values like text or attributes.
41
+ Note that the string discarding options will be ignored in this
42
+ case.
43
+ """
44
+ cdef xmlNode* c_parent
45
+ cdef xmlNode* c_node
46
+ cdef xmlNode* c_context_node
47
+ assert context._xsltCtxt is not NULL, "XSLT context not initialised"
48
+ c_context_node = _roNodeOf(node)
49
+ #assert c_context_node.doc is context._xsltContext.node.doc, \
50
+ # "switching input documents during transformation is not currently supported"
51
+
52
+ if output_parent is not None:
53
+ c_parent = _nonRoNodeOf(output_parent)
54
+ else:
55
+ c_parent = tree.xmlNewDocNode(
56
+ context._xsltCtxt.output, NULL, <unsigned char*>"fake-parent", NULL)
57
+
58
+ c_node = context._xsltCtxt.insert
59
+ context._xsltCtxt.insert = c_parent
60
+ xslt.xsltProcessOneNode(
61
+ context._xsltCtxt, c_context_node, NULL)
62
+ context._xsltCtxt.insert = c_node
63
+
64
+ if output_parent is not None:
65
+ return None
66
+
67
+ try:
68
+ return self._collectXSLTResultContent(
69
+ context, c_parent, elements_only, remove_blank_text)
70
+ finally:
71
+ # free all intermediate nodes that will not be freed by proxies
72
+ tree.xmlFreeNode(c_parent)
73
+
74
+ def process_children(self, _XSLTContext context not None, output_parent=None,
75
+ *, elements_only=False, remove_blank_text=False):
76
+ """process_children(self, context, output_parent=None, elements_only=False, remove_blank_text=False)
77
+
78
+ Call this method to process the XSLT content of the extension
79
+ element itself.
80
+
81
+ The return value is a list of elements or text strings that
82
+ were generated by the XSLT processor. If you pass
83
+ ``elements_only=True``, strings will be discarded from the result
84
+ list. The option ``remove_blank_text=True`` will only discard
85
+ strings that consist entirely of whitespace (e.g. formatting).
86
+ These options do not apply to Elements, only to bare string results.
87
+
88
+ If you pass an Element as `output_parent` parameter, the result
89
+ will instead be appended to the element (including attributes
90
+ etc.) and the return value will be `None`. This is a safe way
91
+ to generate content into the output document directly, without
92
+ having to take care of special values like text or attributes.
93
+ Note that the string discarding options will be ignored in this
94
+ case.
95
+ """
96
+ cdef xmlNode* c_parent
97
+ cdef xslt.xsltTransformContext* c_ctxt = context._xsltCtxt
98
+ cdef xmlNode* c_old_output_parent = c_ctxt.insert
99
+ assert context._xsltCtxt is not NULL, "XSLT context not initialised"
100
+
101
+ # output_parent node is used for adding results instead of
102
+ # elements list used in apply_templates, that's easier and allows to
103
+ # use attributes added to extension element with <xsl:attribute>.
104
+
105
+ if output_parent is not None:
106
+ c_parent = _nonRoNodeOf(output_parent)
107
+ else:
108
+ c_parent = tree.xmlNewDocNode(
109
+ context._xsltCtxt.output, NULL, <unsigned char*>"fake-parent", NULL)
110
+
111
+ c_ctxt.insert = c_parent
112
+ xslt.xsltApplyOneTemplate(c_ctxt,
113
+ c_ctxt.node, c_ctxt.inst.children, NULL, NULL)
114
+ c_ctxt.insert = c_old_output_parent
115
+
116
+ if output_parent is not None:
117
+ return None
118
+
119
+ try:
120
+ return self._collectXSLTResultContent(
121
+ context, c_parent, elements_only, remove_blank_text)
122
+ finally:
123
+ # free all intermediate nodes that will not be freed by proxies
124
+ tree.xmlFreeNode(c_parent)
125
+
126
+ cdef _collectXSLTResultContent(self, _XSLTContext context, xmlNode* c_parent,
127
+ bint elements_only, bint remove_blank_text):
128
+ cdef xmlNode* c_node
129
+ cdef xmlNode* c_next
130
+ cdef _ReadOnlyProxy proxy
131
+ cdef list results = [] # or maybe _collectAttributes(c_parent, 2) ?
132
+ c_node = c_parent.children
133
+ while c_node is not NULL:
134
+ c_next = c_node.next
135
+ if c_node.type == tree.XML_TEXT_NODE:
136
+ if not elements_only:
137
+ s = funicode(c_node.content)
138
+ if not remove_blank_text or s.strip():
139
+ results.append(s)
140
+ s = None
141
+ elif c_node.type == tree.XML_ELEMENT_NODE:
142
+ proxy = _newReadOnlyProxy(
143
+ context._extension_element_proxy, c_node)
144
+ results.append(proxy)
145
+ # unlink node and make sure it will be freed later on
146
+ tree.xmlUnlinkNode(c_node)
147
+ proxy.free_after_use()
148
+ else:
149
+ raise TypeError, \
150
+ f"unsupported XSLT result type: {c_node.type}"
151
+ c_node = c_next
152
+ return results
153
+
154
+
155
+ cdef _registerXSLTExtensions(xslt.xsltTransformContext* c_ctxt,
156
+ extension_dict):
157
+ for ns_utf, name_utf in extension_dict:
158
+ xslt.xsltRegisterExtElement(
159
+ c_ctxt, _xcstr(name_utf), _xcstr(ns_utf),
160
+ <xslt.xsltTransformFunction>_callExtensionElement)
161
+
162
+ cdef void _callExtensionElement(xslt.xsltTransformContext* c_ctxt,
163
+ xmlNode* c_context_node,
164
+ xmlNode* c_inst_node,
165
+ void* dummy) noexcept with gil:
166
+ cdef _XSLTContext context
167
+ cdef XSLTExtension extension
168
+ cdef python.PyObject* dict_result
169
+ cdef xmlNode* c_node
170
+ cdef _ReadOnlyProxy context_node = None, self_node = None
171
+ cdef object output_parent # not restricted to ro-nodes
172
+ c_uri = _getNs(c_inst_node)
173
+ if c_uri is NULL:
174
+ # not allowed, and should never happen
175
+ return
176
+ if c_ctxt.xpathCtxt.userData is NULL:
177
+ # just for safety, should never happen
178
+ return
179
+ context = <_XSLTContext>c_ctxt.xpathCtxt.userData
180
+ try:
181
+ try:
182
+ dict_result = python.PyDict_GetItem(
183
+ context._extension_elements, (c_uri, c_inst_node.name))
184
+ if dict_result is NULL:
185
+ raise KeyError, f"extension element {funicode(c_inst_node.name)} not found"
186
+ extension = <object>dict_result
187
+
188
+ try:
189
+ # build the context proxy nodes
190
+ self_node = _newReadOnlyProxy(None, c_inst_node)
191
+ if _isElement(c_ctxt.insert):
192
+ output_parent = _newAppendOnlyProxy(self_node, c_ctxt.insert)
193
+ else:
194
+ # may be the document node or other stuff
195
+ output_parent = _newOpaqueAppendOnlyNodeWrapper(c_ctxt.insert)
196
+ if c_context_node.type in (tree.XML_DOCUMENT_NODE,
197
+ tree.XML_HTML_DOCUMENT_NODE):
198
+ c_node = tree.xmlDocGetRootElement(<xmlDoc*>c_context_node)
199
+ if c_node is not NULL:
200
+ context_node = _newReadOnlyProxy(self_node, c_node)
201
+ else:
202
+ context_node = None
203
+ elif c_context_node.type in (tree.XML_ATTRIBUTE_NODE,
204
+ tree.XML_TEXT_NODE,
205
+ tree.XML_CDATA_SECTION_NODE):
206
+ # this isn't easy to support using read-only
207
+ # nodes, as the smart-string factory must
208
+ # instantiate the parent proxy somehow...
209
+ raise TypeError(f"Unsupported element type: {c_context_node.type}")
210
+ else:
211
+ context_node = _newReadOnlyProxy(self_node, c_context_node)
212
+
213
+ # run the XSLT extension
214
+ context._extension_element_proxy = self_node
215
+ extension.execute(context, self_node, context_node, output_parent)
216
+ finally:
217
+ context._extension_element_proxy = None
218
+ if self_node is not None:
219
+ _freeReadOnlyProxies(self_node)
220
+ except Exception as e:
221
+ try:
222
+ e = unicode(e).encode("UTF-8")
223
+ except:
224
+ e = repr(e).encode("UTF-8")
225
+ message = python.PyBytes_FromFormat(
226
+ "Error executing extension element '%s': %s",
227
+ c_inst_node.name, _cstr(e))
228
+ xslt.xsltTransformError(c_ctxt, NULL, c_inst_node, "%s", message)
229
+ context._exc._store_raised()
230
+ except:
231
+ # just in case
232
+ message = python.PyBytes_FromFormat(
233
+ "Error executing extension element '%s'", c_inst_node.name)
234
+ xslt.xsltTransformError(c_ctxt, NULL, c_inst_node, "%s", message)
235
+ context._exc._store_raised()
236
+ except:
237
+ # no Python functions here - everything can fail...
238
+ xslt.xsltTransformError(c_ctxt, NULL, c_inst_node,
239
+ "Error during XSLT extension element evaluation")
240
+ context._exc._store_raised()
241
+ finally:
242
+ return # swallow any further exceptions
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/__init__.py ADDED
@@ -0,0 +1,975 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # When adding a new object to this init, remember to add it twice: once inside the `_import_structure` dictionary and
16
+ # once inside the `if TYPE_CHECKING` branch. The `TYPE_CHECKING` should have import statements as usual, but they are
17
+ # only there for type checking. The `_import_structure` is a dictionary submodule to list of object names, and is used
18
+ # to defer the actual importing for when the objects are requested. This way `import transformers` provides the names
19
+ # in the namespace without actually importing anything (and especially none of the backends).
20
+
21
+ __version__ = "4.57.6"
22
+
23
+ from pathlib import Path
24
+ from typing import TYPE_CHECKING
25
+
26
+ # Check the dependencies satisfy the minimal versions required.
27
+ from . import dependency_versions_check
28
+ from .utils import (
29
+ OptionalDependencyNotAvailable,
30
+ _LazyModule,
31
+ is_essentia_available,
32
+ is_g2p_en_available,
33
+ is_librosa_available,
34
+ is_mistral_common_available,
35
+ is_mlx_available,
36
+ is_pretty_midi_available,
37
+ )
38
+
39
+ # Note: the following symbols are deliberately exported with `as`
40
+ # so that mypy, pylint or other static linters can recognize them,
41
+ # given that they are not exported using `__all__` in this file.
42
+ from .utils import is_bitsandbytes_available as is_bitsandbytes_available
43
+ from .utils import is_flax_available as is_flax_available
44
+ from .utils import is_keras_nlp_available as is_keras_nlp_available
45
+ from .utils import is_scipy_available as is_scipy_available
46
+ from .utils import is_sentencepiece_available as is_sentencepiece_available
47
+ from .utils import is_speech_available as is_speech_available
48
+ from .utils import is_tensorflow_text_available as is_tensorflow_text_available
49
+ from .utils import is_tf_available as is_tf_available
50
+ from .utils import is_timm_available as is_timm_available
51
+ from .utils import is_tokenizers_available as is_tokenizers_available
52
+ from .utils import is_torch_available as is_torch_available
53
+ from .utils import is_torchaudio_available as is_torchaudio_available
54
+ from .utils import is_torchvision_available as is_torchvision_available
55
+ from .utils import is_vision_available as is_vision_available
56
+ from .utils import logging as logging
57
+ from .utils.import_utils import define_import_structure
58
+
59
+
60
+ logger = logging.get_logger(__name__) # pylint: disable=invalid-name
61
+
62
+ # Base objects, independent of any specific backend
63
+ _import_structure = {
64
+ "audio_utils": [],
65
+ "commands": [],
66
+ "configuration_utils": ["PretrainedConfig"],
67
+ "convert_graph_to_onnx": [],
68
+ "convert_slow_tokenizers_checkpoints_to_fast": [],
69
+ "convert_tf_hub_seq_to_seq_bert_to_pytorch": [],
70
+ "data": [
71
+ "DataProcessor",
72
+ "InputExample",
73
+ "InputFeatures",
74
+ "SingleSentenceClassificationProcessor",
75
+ "SquadExample",
76
+ "SquadFeatures",
77
+ "SquadV1Processor",
78
+ "SquadV2Processor",
79
+ "glue_compute_metrics",
80
+ "glue_convert_examples_to_features",
81
+ "glue_output_modes",
82
+ "glue_processors",
83
+ "glue_tasks_num_labels",
84
+ "squad_convert_examples_to_features",
85
+ "xnli_compute_metrics",
86
+ "xnli_output_modes",
87
+ "xnli_processors",
88
+ "xnli_tasks_num_labels",
89
+ ],
90
+ "data.data_collator": [
91
+ "DataCollator",
92
+ "DataCollatorForLanguageModeling",
93
+ "DataCollatorForMultipleChoice",
94
+ "DataCollatorForPermutationLanguageModeling",
95
+ "DataCollatorForSeq2Seq",
96
+ "DataCollatorForSOP",
97
+ "DataCollatorForTokenClassification",
98
+ "DataCollatorForWholeWordMask",
99
+ "DataCollatorWithFlattening",
100
+ "DataCollatorWithPadding",
101
+ "DefaultDataCollator",
102
+ "default_data_collator",
103
+ ],
104
+ "data.metrics": [],
105
+ "data.processors": [],
106
+ "debug_utils": [],
107
+ "dependency_versions_check": [],
108
+ "dependency_versions_table": [],
109
+ "dynamic_module_utils": [],
110
+ "feature_extraction_sequence_utils": ["SequenceFeatureExtractor"],
111
+ "feature_extraction_utils": ["BatchFeature", "FeatureExtractionMixin"],
112
+ "file_utils": [],
113
+ "generation": [
114
+ "AsyncTextIteratorStreamer",
115
+ "CompileConfig",
116
+ "GenerationConfig",
117
+ "TextIteratorStreamer",
118
+ "TextStreamer",
119
+ "WatermarkingConfig",
120
+ ],
121
+ "hf_argparser": ["HfArgumentParser"],
122
+ "hyperparameter_search": [],
123
+ "image_transforms": [],
124
+ "integrations": [
125
+ "is_clearml_available",
126
+ "is_comet_available",
127
+ "is_dvclive_available",
128
+ "is_neptune_available",
129
+ "is_optuna_available",
130
+ "is_ray_available",
131
+ "is_ray_tune_available",
132
+ "is_sigopt_available",
133
+ "is_swanlab_available",
134
+ "is_tensorboard_available",
135
+ "is_trackio_available",
136
+ "is_wandb_available",
137
+ ],
138
+ "loss": [],
139
+ "modelcard": ["ModelCard"],
140
+ # Losses
141
+ "modeling_tf_pytorch_utils": [
142
+ "convert_tf_weight_name_to_pt_weight_name",
143
+ "load_pytorch_checkpoint_in_tf2_model",
144
+ "load_pytorch_model_in_tf2_model",
145
+ "load_pytorch_weights_in_tf2_model",
146
+ "load_tf2_checkpoint_in_pytorch_model",
147
+ "load_tf2_model_in_pytorch_model",
148
+ "load_tf2_weights_in_pytorch_model",
149
+ ],
150
+ # Models
151
+ "onnx": [],
152
+ "pipelines": [
153
+ "AudioClassificationPipeline",
154
+ "AutomaticSpeechRecognitionPipeline",
155
+ "CsvPipelineDataFormat",
156
+ "DepthEstimationPipeline",
157
+ "DocumentQuestionAnsweringPipeline",
158
+ "FeatureExtractionPipeline",
159
+ "FillMaskPipeline",
160
+ "ImageClassificationPipeline",
161
+ "ImageFeatureExtractionPipeline",
162
+ "ImageSegmentationPipeline",
163
+ "ImageTextToTextPipeline",
164
+ "ImageToImagePipeline",
165
+ "ImageToTextPipeline",
166
+ "JsonPipelineDataFormat",
167
+ "KeypointMatchingPipeline",
168
+ "MaskGenerationPipeline",
169
+ "NerPipeline",
170
+ "ObjectDetectionPipeline",
171
+ "PipedPipelineDataFormat",
172
+ "Pipeline",
173
+ "PipelineDataFormat",
174
+ "QuestionAnsweringPipeline",
175
+ "SummarizationPipeline",
176
+ "TableQuestionAnsweringPipeline",
177
+ "Text2TextGenerationPipeline",
178
+ "TextClassificationPipeline",
179
+ "TextGenerationPipeline",
180
+ "TextToAudioPipeline",
181
+ "TokenClassificationPipeline",
182
+ "TranslationPipeline",
183
+ "VideoClassificationPipeline",
184
+ "VisualQuestionAnsweringPipeline",
185
+ "ZeroShotAudioClassificationPipeline",
186
+ "ZeroShotClassificationPipeline",
187
+ "ZeroShotImageClassificationPipeline",
188
+ "ZeroShotObjectDetectionPipeline",
189
+ "pipeline",
190
+ ],
191
+ "processing_utils": ["ProcessorMixin"],
192
+ "quantizers": [],
193
+ "testing_utils": [],
194
+ "tokenization_utils": ["PreTrainedTokenizer"],
195
+ "tokenization_utils_base": [
196
+ "AddedToken",
197
+ "BatchEncoding",
198
+ "CharSpan",
199
+ "PreTrainedTokenizerBase",
200
+ "SpecialTokensMixin",
201
+ "TokenSpan",
202
+ ],
203
+ "trainer_callback": [
204
+ "DefaultFlowCallback",
205
+ "EarlyStoppingCallback",
206
+ "PrinterCallback",
207
+ "ProgressCallback",
208
+ "TrainerCallback",
209
+ "TrainerControl",
210
+ "TrainerState",
211
+ ],
212
+ "trainer_utils": [
213
+ "EvalPrediction",
214
+ "IntervalStrategy",
215
+ "SchedulerType",
216
+ "enable_full_determinism",
217
+ "set_seed",
218
+ ],
219
+ "training_args": ["TrainingArguments"],
220
+ "training_args_seq2seq": ["Seq2SeqTrainingArguments"],
221
+ "training_args_tf": ["TFTrainingArguments"],
222
+ "utils": [
223
+ "CONFIG_NAME",
224
+ "MODEL_CARD_NAME",
225
+ "PYTORCH_PRETRAINED_BERT_CACHE",
226
+ "PYTORCH_TRANSFORMERS_CACHE",
227
+ "SPIECE_UNDERLINE",
228
+ "TF2_WEIGHTS_NAME",
229
+ "TF_WEIGHTS_NAME",
230
+ "TRANSFORMERS_CACHE",
231
+ "WEIGHTS_NAME",
232
+ "TensorType",
233
+ "add_end_docstrings",
234
+ "add_start_docstrings",
235
+ "is_apex_available",
236
+ "is_av_available",
237
+ "is_bitsandbytes_available",
238
+ "is_datasets_available",
239
+ "is_faiss_available",
240
+ "is_flax_available",
241
+ "is_keras_nlp_available",
242
+ "is_matplotlib_available",
243
+ "is_mlx_available",
244
+ "is_phonemizer_available",
245
+ "is_psutil_available",
246
+ "is_py3nvml_available",
247
+ "is_pyctcdecode_available",
248
+ "is_sacremoses_available",
249
+ "is_safetensors_available",
250
+ "is_scipy_available",
251
+ "is_sentencepiece_available",
252
+ "is_sklearn_available",
253
+ "is_speech_available",
254
+ "is_tensorflow_text_available",
255
+ "is_tf_available",
256
+ "is_timm_available",
257
+ "is_tokenizers_available",
258
+ "is_torch_available",
259
+ "is_torch_hpu_available",
260
+ "is_torch_mlu_available",
261
+ "is_torch_musa_available",
262
+ "is_torch_neuroncore_available",
263
+ "is_torch_npu_available",
264
+ "is_torchvision_available",
265
+ "is_torch_xla_available",
266
+ "is_torch_xpu_available",
267
+ "is_vision_available",
268
+ "logging",
269
+ ],
270
+ "utils.quantization_config": [
271
+ "AqlmConfig",
272
+ "AutoRoundConfig",
273
+ "AwqConfig",
274
+ "BitNetQuantConfig",
275
+ "BitsAndBytesConfig",
276
+ "CompressedTensorsConfig",
277
+ "EetqConfig",
278
+ "FbgemmFp8Config",
279
+ "FineGrainedFP8Config",
280
+ "GPTQConfig",
281
+ "HiggsConfig",
282
+ "HqqConfig",
283
+ "Mxfp4Config",
284
+ "QuantoConfig",
285
+ "QuarkConfig",
286
+ "FPQuantConfig",
287
+ "SpQRConfig",
288
+ "TorchAoConfig",
289
+ "VptqConfig",
290
+ ],
291
+ "video_utils": [],
292
+ }
293
+
294
+ # tokenizers-backed objects
295
+ try:
296
+ if not is_tokenizers_available():
297
+ raise OptionalDependencyNotAvailable()
298
+ except OptionalDependencyNotAvailable:
299
+ from .utils import dummy_tokenizers_objects
300
+
301
+ _import_structure["utils.dummy_tokenizers_objects"] = [
302
+ name for name in dir(dummy_tokenizers_objects) if not name.startswith("_")
303
+ ]
304
+ else:
305
+ # Fast tokenizers structure
306
+ _import_structure["tokenization_utils_fast"] = ["PreTrainedTokenizerFast"]
307
+
308
+
309
+ try:
310
+ if not (is_sentencepiece_available() and is_tokenizers_available()):
311
+ raise OptionalDependencyNotAvailable()
312
+ except OptionalDependencyNotAvailable:
313
+ from .utils import dummy_sentencepiece_and_tokenizers_objects
314
+
315
+ _import_structure["utils.dummy_sentencepiece_and_tokenizers_objects"] = [
316
+ name for name in dir(dummy_sentencepiece_and_tokenizers_objects) if not name.startswith("_")
317
+ ]
318
+ else:
319
+ _import_structure["convert_slow_tokenizer"] = [
320
+ "SLOW_TO_FAST_CONVERTERS",
321
+ "convert_slow_tokenizer",
322
+ ]
323
+
324
+ try:
325
+ if not (is_mistral_common_available()):
326
+ raise OptionalDependencyNotAvailable()
327
+ except OptionalDependencyNotAvailable:
328
+ from .utils import dummy_mistral_common_objects
329
+
330
+ _import_structure["utils.dummy_mistral_common_objects"] = [
331
+ name for name in dir(dummy_mistral_common_objects) if not name.startswith("_")
332
+ ]
333
+ else:
334
+ _import_structure["tokenization_mistral_common"] = ["MistralCommonTokenizer"]
335
+
336
+ # Vision-specific objects
337
+ try:
338
+ if not is_vision_available():
339
+ raise OptionalDependencyNotAvailable()
340
+ except OptionalDependencyNotAvailable:
341
+ from .utils import dummy_vision_objects
342
+
343
+ _import_structure["utils.dummy_vision_objects"] = [
344
+ name for name in dir(dummy_vision_objects) if not name.startswith("_")
345
+ ]
346
+ else:
347
+ _import_structure["image_processing_base"] = ["ImageProcessingMixin"]
348
+ _import_structure["image_processing_utils"] = ["BaseImageProcessor"]
349
+ _import_structure["image_utils"] = ["ImageFeatureExtractionMixin"]
350
+
351
+ try:
352
+ if not is_torchvision_available():
353
+ raise OptionalDependencyNotAvailable()
354
+ except OptionalDependencyNotAvailable:
355
+ from .utils import dummy_torchvision_objects
356
+
357
+ _import_structure["utils.dummy_torchvision_objects"] = [
358
+ name for name in dir(dummy_torchvision_objects) if not name.startswith("_")
359
+ ]
360
+ else:
361
+ _import_structure["image_processing_utils_fast"] = ["BaseImageProcessorFast"]
362
+ _import_structure["video_processing_utils"] = ["BaseVideoProcessor"]
363
+
364
+ # PyTorch-backed objects
365
+ try:
366
+ if not is_torch_available():
367
+ raise OptionalDependencyNotAvailable()
368
+ except OptionalDependencyNotAvailable:
369
+ from .utils import dummy_pt_objects
370
+
371
+ _import_structure["utils.dummy_pt_objects"] = [name for name in dir(dummy_pt_objects) if not name.startswith("_")]
372
+ else:
373
+ _import_structure["model_debugging_utils"] = [
374
+ "model_addition_debugger_context",
375
+ ]
376
+ _import_structure["activations"] = []
377
+ _import_structure["cache_utils"] = [
378
+ "CacheLayerMixin",
379
+ "DynamicLayer",
380
+ "StaticLayer",
381
+ "StaticSlidingWindowLayer",
382
+ "SlidingWindowLayer",
383
+ "ChunkedSlidingLayer",
384
+ "QuantoQuantizedLayer",
385
+ "HQQQuantizedLayer",
386
+ "Cache",
387
+ "DynamicCache",
388
+ "EncoderDecoderCache",
389
+ "HQQQuantizedCache",
390
+ "HybridCache",
391
+ "HybridChunkedCache",
392
+ "OffloadedCache",
393
+ "OffloadedStaticCache",
394
+ "QuantizedCache",
395
+ "QuantoQuantizedCache",
396
+ "SinkCache",
397
+ "SlidingWindowCache",
398
+ "StaticCache",
399
+ ]
400
+ _import_structure["data.datasets"] = [
401
+ "GlueDataset",
402
+ "GlueDataTrainingArguments",
403
+ "LineByLineTextDataset",
404
+ "LineByLineWithRefDataset",
405
+ "LineByLineWithSOPTextDataset",
406
+ "SquadDataset",
407
+ "SquadDataTrainingArguments",
408
+ "TextDataset",
409
+ "TextDatasetForNextSentencePrediction",
410
+ ]
411
+ _import_structure["generation"].extend(
412
+ [
413
+ "AlternatingCodebooksLogitsProcessor",
414
+ "BayesianDetectorConfig",
415
+ "BayesianDetectorModel",
416
+ "BeamScorer",
417
+ "ClassifierFreeGuidanceLogitsProcessor",
418
+ "ConstrainedBeamSearchScorer",
419
+ "Constraint",
420
+ "ConstraintListState",
421
+ "DisjunctiveConstraint",
422
+ "EncoderNoRepeatNGramLogitsProcessor",
423
+ "EncoderRepetitionPenaltyLogitsProcessor",
424
+ "EosTokenCriteria",
425
+ "EpsilonLogitsWarper",
426
+ "EtaLogitsWarper",
427
+ "ExponentialDecayLengthPenalty",
428
+ "ForcedBOSTokenLogitsProcessor",
429
+ "ForcedEOSTokenLogitsProcessor",
430
+ "GenerationMixin",
431
+ "InfNanRemoveLogitsProcessor",
432
+ "LogitNormalization",
433
+ "LogitsProcessor",
434
+ "LogitsProcessorList",
435
+ "MaxLengthCriteria",
436
+ "MaxTimeCriteria",
437
+ "MinLengthLogitsProcessor",
438
+ "MinNewTokensLengthLogitsProcessor",
439
+ "MinPLogitsWarper",
440
+ "NoBadWordsLogitsProcessor",
441
+ "NoRepeatNGramLogitsProcessor",
442
+ "PhrasalConstraint",
443
+ "PrefixConstrainedLogitsProcessor",
444
+ "RepetitionPenaltyLogitsProcessor",
445
+ "SequenceBiasLogitsProcessor",
446
+ "StoppingCriteria",
447
+ "StoppingCriteriaList",
448
+ "StopStringCriteria",
449
+ "SuppressTokensAtBeginLogitsProcessor",
450
+ "SuppressTokensLogitsProcessor",
451
+ "SynthIDTextWatermarkDetector",
452
+ "SynthIDTextWatermarkingConfig",
453
+ "SynthIDTextWatermarkLogitsProcessor",
454
+ "TemperatureLogitsWarper",
455
+ "TopKLogitsWarper",
456
+ "TopPLogitsWarper",
457
+ "TypicalLogitsWarper",
458
+ "UnbatchedClassifierFreeGuidanceLogitsProcessor",
459
+ "WatermarkDetector",
460
+ "WatermarkLogitsProcessor",
461
+ "WhisperTimeStampLogitsProcessor",
462
+ ]
463
+ )
464
+
465
+ # PyTorch domain libraries integration
466
+ _import_structure["integrations.executorch"] = [
467
+ "TorchExportableModuleWithStaticCache",
468
+ "convert_and_export_with_cache",
469
+ ]
470
+
471
+ _import_structure["modeling_flash_attention_utils"] = []
472
+ _import_structure["modeling_layers"] = ["GradientCheckpointingLayer"]
473
+ _import_structure["modeling_outputs"] = []
474
+ _import_structure["modeling_rope_utils"] = ["ROPE_INIT_FUNCTIONS", "dynamic_rope_update"]
475
+ _import_structure["modeling_utils"] = ["PreTrainedModel", "AttentionInterface"]
476
+ _import_structure["masking_utils"] = ["AttentionMaskInterface"]
477
+ _import_structure["optimization"] = [
478
+ "Adafactor",
479
+ "get_constant_schedule",
480
+ "get_constant_schedule_with_warmup",
481
+ "get_cosine_schedule_with_warmup",
482
+ "get_cosine_with_hard_restarts_schedule_with_warmup",
483
+ "get_cosine_with_min_lr_schedule_with_warmup",
484
+ "get_cosine_with_min_lr_schedule_with_warmup_lr_rate",
485
+ "get_inverse_sqrt_schedule",
486
+ "get_linear_schedule_with_warmup",
487
+ "get_polynomial_decay_schedule_with_warmup",
488
+ "get_scheduler",
489
+ "get_wsd_schedule",
490
+ "get_reduce_on_plateau_schedule",
491
+ ]
492
+ _import_structure["pytorch_utils"] = [
493
+ "Conv1D",
494
+ "apply_chunking_to_forward",
495
+ "prune_layer",
496
+ "infer_device",
497
+ ]
498
+ _import_structure["sagemaker"] = []
499
+ _import_structure["time_series_utils"] = []
500
+ _import_structure["trainer"] = ["Trainer"]
501
+ _import_structure["trainer_pt_utils"] = ["torch_distributed_zero_first"]
502
+ _import_structure["trainer_seq2seq"] = ["Seq2SeqTrainer"]
503
+
504
+ # TensorFlow-backed objects
505
+ try:
506
+ if not is_tf_available():
507
+ raise OptionalDependencyNotAvailable()
508
+ except OptionalDependencyNotAvailable:
509
+ from .utils import dummy_tf_objects
510
+
511
+ _import_structure["utils.dummy_tf_objects"] = [name for name in dir(dummy_tf_objects) if not name.startswith("_")]
512
+ else:
513
+ _import_structure["activations_tf"] = []
514
+ _import_structure["generation"].extend(
515
+ [
516
+ "TFForcedBOSTokenLogitsProcessor",
517
+ "TFForcedEOSTokenLogitsProcessor",
518
+ "TFForceTokensLogitsProcessor",
519
+ "TFGenerationMixin",
520
+ "TFLogitsProcessor",
521
+ "TFLogitsProcessorList",
522
+ "TFLogitsWarper",
523
+ "TFMinLengthLogitsProcessor",
524
+ "TFNoBadWordsLogitsProcessor",
525
+ "TFNoRepeatNGramLogitsProcessor",
526
+ "TFRepetitionPenaltyLogitsProcessor",
527
+ "TFSuppressTokensAtBeginLogitsProcessor",
528
+ "TFSuppressTokensLogitsProcessor",
529
+ "TFTemperatureLogitsWarper",
530
+ "TFTopKLogitsWarper",
531
+ "TFTopPLogitsWarper",
532
+ ]
533
+ )
534
+ _import_structure["keras_callbacks"] = ["KerasMetricCallback", "PushToHubCallback"]
535
+ _import_structure["modeling_tf_outputs"] = []
536
+ _import_structure["modeling_tf_utils"] = [
537
+ "TFPreTrainedModel",
538
+ "TFSequenceSummary",
539
+ "TFSharedEmbeddings",
540
+ "shape_list",
541
+ ]
542
+ _import_structure["optimization_tf"] = [
543
+ "AdamWeightDecay",
544
+ "GradientAccumulator",
545
+ "WarmUp",
546
+ "create_optimizer",
547
+ ]
548
+ _import_structure["tf_utils"] = []
549
+
550
+
551
+ # FLAX-backed objects
552
+ try:
553
+ if not is_flax_available():
554
+ raise OptionalDependencyNotAvailable()
555
+ except OptionalDependencyNotAvailable:
556
+ from .utils import dummy_flax_objects
557
+
558
+ _import_structure["utils.dummy_flax_objects"] = [
559
+ name for name in dir(dummy_flax_objects) if not name.startswith("_")
560
+ ]
561
+ else:
562
+ _import_structure["generation"].extend(
563
+ [
564
+ "FlaxForcedBOSTokenLogitsProcessor",
565
+ "FlaxForcedEOSTokenLogitsProcessor",
566
+ "FlaxForceTokensLogitsProcessor",
567
+ "FlaxGenerationMixin",
568
+ "FlaxLogitsProcessor",
569
+ "FlaxLogitsProcessorList",
570
+ "FlaxLogitsWarper",
571
+ "FlaxMinLengthLogitsProcessor",
572
+ "FlaxTemperatureLogitsWarper",
573
+ "FlaxSuppressTokensAtBeginLogitsProcessor",
574
+ "FlaxSuppressTokensLogitsProcessor",
575
+ "FlaxTopKLogitsWarper",
576
+ "FlaxTopPLogitsWarper",
577
+ "FlaxWhisperTimeStampLogitsProcessor",
578
+ ]
579
+ )
580
+ _import_structure["modeling_flax_outputs"] = []
581
+ _import_structure["modeling_flax_utils"] = ["FlaxPreTrainedModel"]
582
+
583
+ # Direct imports for type-checking
584
+ if TYPE_CHECKING:
585
+ # All modeling imports
586
+ from .cache_utils import Cache as Cache
587
+ from .cache_utils import ChunkedSlidingLayer as ChunkedSlidingLayer
588
+ from .cache_utils import DynamicCache as DynamicCache
589
+ from .cache_utils import DynamicLayer as DynamicLayer
590
+ from .cache_utils import EncoderDecoderCache as EncoderDecoderCache
591
+ from .cache_utils import HQQQuantizedCache as HQQQuantizedCache
592
+ from .cache_utils import HQQQuantizedLayer as HQQQuantizedLayer
593
+ from .cache_utils import HybridCache as HybridCache
594
+ from .cache_utils import OffloadedCache as OffloadedCache
595
+ from .cache_utils import OffloadedStaticCache as OffloadedStaticCache
596
+ from .cache_utils import QuantizedCache as QuantizedCache
597
+ from .cache_utils import QuantoQuantizedCache as QuantoQuantizedCache
598
+ from .cache_utils import QuantoQuantizedLayer as QuantoQuantizedLayer
599
+ from .cache_utils import SinkCache as SinkCache
600
+ from .cache_utils import SlidingWindowCache as SlidingWindowCache
601
+ from .cache_utils import SlidingWindowLayer as SlidingWindowLayer
602
+ from .cache_utils import StaticCache as StaticCache
603
+ from .cache_utils import StaticLayer as StaticLayer
604
+ from .cache_utils import StaticSlidingWindowLayer as StaticSlidingWindowLayer
605
+ from .configuration_utils import PretrainedConfig as PretrainedConfig
606
+ from .convert_slow_tokenizer import SLOW_TO_FAST_CONVERTERS as SLOW_TO_FAST_CONVERTERS
607
+ from .convert_slow_tokenizer import convert_slow_tokenizer as convert_slow_tokenizer
608
+
609
+ # Data
610
+ from .data import DataProcessor as DataProcessor
611
+ from .data import InputExample as InputExample
612
+ from .data import InputFeatures as InputFeatures
613
+ from .data import SingleSentenceClassificationProcessor as SingleSentenceClassificationProcessor
614
+ from .data import SquadExample as SquadExample
615
+ from .data import SquadFeatures as SquadFeatures
616
+ from .data import SquadV1Processor as SquadV1Processor
617
+ from .data import SquadV2Processor as SquadV2Processor
618
+ from .data import glue_compute_metrics as glue_compute_metrics
619
+ from .data import glue_convert_examples_to_features as glue_convert_examples_to_features
620
+ from .data import glue_output_modes as glue_output_modes
621
+ from .data import glue_processors as glue_processors
622
+ from .data import glue_tasks_num_labels as glue_tasks_num_labels
623
+ from .data import squad_convert_examples_to_features as squad_convert_examples_to_features
624
+ from .data import xnli_compute_metrics as xnli_compute_metrics
625
+ from .data import xnli_output_modes as xnli_output_modes
626
+ from .data import xnli_processors as xnli_processors
627
+ from .data import xnli_tasks_num_labels as xnli_tasks_num_labels
628
+ from .data.data_collator import DataCollator as DataCollator
629
+ from .data.data_collator import DataCollatorForLanguageModeling as DataCollatorForLanguageModeling
630
+ from .data.data_collator import DataCollatorForMultipleChoice as DataCollatorForMultipleChoice
631
+ from .data.data_collator import (
632
+ DataCollatorForPermutationLanguageModeling as DataCollatorForPermutationLanguageModeling,
633
+ )
634
+ from .data.data_collator import DataCollatorForSeq2Seq as DataCollatorForSeq2Seq
635
+ from .data.data_collator import DataCollatorForSOP as DataCollatorForSOP
636
+ from .data.data_collator import DataCollatorForTokenClassification as DataCollatorForTokenClassification
637
+ from .data.data_collator import DataCollatorForWholeWordMask as DataCollatorForWholeWordMask
638
+ from .data.data_collator import DataCollatorWithFlattening as DataCollatorWithFlattening
639
+ from .data.data_collator import DataCollatorWithPadding as DataCollatorWithPadding
640
+ from .data.data_collator import DefaultDataCollator as DefaultDataCollator
641
+ from .data.data_collator import default_data_collator as default_data_collator
642
+ from .data.datasets import GlueDataset as GlueDataset
643
+ from .data.datasets import GlueDataTrainingArguments as GlueDataTrainingArguments
644
+ from .data.datasets import LineByLineTextDataset as LineByLineTextDataset
645
+ from .data.datasets import LineByLineWithRefDataset as LineByLineWithRefDataset
646
+ from .data.datasets import LineByLineWithSOPTextDataset as LineByLineWithSOPTextDataset
647
+ from .data.datasets import SquadDataset as SquadDataset
648
+ from .data.datasets import SquadDataTrainingArguments as SquadDataTrainingArguments
649
+ from .data.datasets import TextDataset as TextDataset
650
+ from .data.datasets import TextDatasetForNextSentencePrediction as TextDatasetForNextSentencePrediction
651
+ from .feature_extraction_sequence_utils import SequenceFeatureExtractor as SequenceFeatureExtractor
652
+
653
+ # Feature Extractor
654
+ from .feature_extraction_utils import BatchFeature as BatchFeature
655
+ from .feature_extraction_utils import FeatureExtractionMixin as FeatureExtractionMixin
656
+
657
+ # Generation
658
+ from .generation import AlternatingCodebooksLogitsProcessor as AlternatingCodebooksLogitsProcessor
659
+ from .generation import AsyncTextIteratorStreamer as AsyncTextIteratorStreamer
660
+ from .generation import BayesianDetectorConfig as BayesianDetectorConfig
661
+ from .generation import BayesianDetectorModel as BayesianDetectorModel
662
+ from .generation import BeamScorer as BeamScorer
663
+ from .generation import ClassifierFreeGuidanceLogitsProcessor as ClassifierFreeGuidanceLogitsProcessor
664
+ from .generation import CompileConfig as CompileConfig
665
+ from .generation import ConstrainedBeamSearchScorer as ConstrainedBeamSearchScorer
666
+ from .generation import Constraint as Constraint
667
+ from .generation import ConstraintListState as ConstraintListState
668
+ from .generation import DisjunctiveConstraint as DisjunctiveConstraint
669
+ from .generation import EncoderNoRepeatNGramLogitsProcessor as EncoderNoRepeatNGramLogitsProcessor
670
+ from .generation import EncoderRepetitionPenaltyLogitsProcessor as EncoderRepetitionPenaltyLogitsProcessor
671
+ from .generation import EosTokenCriteria as EosTokenCriteria
672
+ from .generation import EpsilonLogitsWarper as EpsilonLogitsWarper
673
+ from .generation import EtaLogitsWarper as EtaLogitsWarper
674
+ from .generation import ExponentialDecayLengthPenalty as ExponentialDecayLengthPenalty
675
+ from .generation import FlaxForcedBOSTokenLogitsProcessor as FlaxForcedBOSTokenLogitsProcessor
676
+ from .generation import FlaxForcedEOSTokenLogitsProcessor as FlaxForcedEOSTokenLogitsProcessor
677
+ from .generation import FlaxForceTokensLogitsProcessor as FlaxForceTokensLogitsProcessor
678
+ from .generation import FlaxGenerationMixin as FlaxGenerationMixin
679
+ from .generation import FlaxLogitsProcessor as FlaxLogitsProcessor
680
+ from .generation import FlaxLogitsProcessorList as FlaxLogitsProcessorList
681
+ from .generation import FlaxLogitsWarper as FlaxLogitsWarper
682
+ from .generation import FlaxMinLengthLogitsProcessor as FlaxMinLengthLogitsProcessor
683
+ from .generation import FlaxSuppressTokensAtBeginLogitsProcessor as FlaxSuppressTokensAtBeginLogitsProcessor
684
+ from .generation import FlaxSuppressTokensLogitsProcessor as FlaxSuppressTokensLogitsProcessor
685
+ from .generation import FlaxTemperatureLogitsWarper as FlaxTemperatureLogitsWarper
686
+ from .generation import FlaxTopKLogitsWarper as FlaxTopKLogitsWarper
687
+ from .generation import FlaxTopPLogitsWarper as FlaxTopPLogitsWarper
688
+ from .generation import FlaxWhisperTimeStampLogitsProcessor as FlaxWhisperTimeStampLogitsProcessor
689
+ from .generation import ForcedBOSTokenLogitsProcessor as ForcedBOSTokenLogitsProcessor
690
+ from .generation import ForcedEOSTokenLogitsProcessor as ForcedEOSTokenLogitsProcessor
691
+ from .generation import GenerationConfig as GenerationConfig
692
+ from .generation import GenerationMixin as GenerationMixin
693
+ from .generation import InfNanRemoveLogitsProcessor as InfNanRemoveLogitsProcessor
694
+ from .generation import LogitNormalization as LogitNormalization
695
+ from .generation import LogitsProcessor as LogitsProcessor
696
+ from .generation import LogitsProcessorList as LogitsProcessorList
697
+ from .generation import MaxLengthCriteria as MaxLengthCriteria
698
+ from .generation import MaxTimeCriteria as MaxTimeCriteria
699
+ from .generation import MinLengthLogitsProcessor as MinLengthLogitsProcessor
700
+ from .generation import MinNewTokensLengthLogitsProcessor as MinNewTokensLengthLogitsProcessor
701
+ from .generation import MinPLogitsWarper as MinPLogitsWarper
702
+ from .generation import NoBadWordsLogitsProcessor as NoBadWordsLogitsProcessor
703
+ from .generation import NoRepeatNGramLogitsProcessor as NoRepeatNGramLogitsProcessor
704
+ from .generation import PhrasalConstraint as PhrasalConstraint
705
+ from .generation import PrefixConstrainedLogitsProcessor as PrefixConstrainedLogitsProcessor
706
+ from .generation import RepetitionPenaltyLogitsProcessor as RepetitionPenaltyLogitsProcessor
707
+ from .generation import SequenceBiasLogitsProcessor as SequenceBiasLogitsProcessor
708
+ from .generation import StoppingCriteria as StoppingCriteria
709
+ from .generation import StoppingCriteriaList as StoppingCriteriaList
710
+ from .generation import StopStringCriteria as StopStringCriteria
711
+ from .generation import SuppressTokensAtBeginLogitsProcessor as SuppressTokensAtBeginLogitsProcessor
712
+ from .generation import SuppressTokensLogitsProcessor as SuppressTokensLogitsProcessor
713
+ from .generation import SynthIDTextWatermarkDetector as SynthIDTextWatermarkDetector
714
+ from .generation import SynthIDTextWatermarkingConfig as SynthIDTextWatermarkingConfig
715
+ from .generation import SynthIDTextWatermarkLogitsProcessor as SynthIDTextWatermarkLogitsProcessor
716
+ from .generation import TemperatureLogitsWarper as TemperatureLogitsWarper
717
+ from .generation import TextIteratorStreamer as TextIteratorStreamer
718
+ from .generation import TextStreamer as TextStreamer
719
+ from .generation import TFForcedBOSTokenLogitsProcessor as TFForcedBOSTokenLogitsProcessor
720
+ from .generation import TFForcedEOSTokenLogitsProcessor as TFForcedEOSTokenLogitsProcessor
721
+ from .generation import TFForceTokensLogitsProcessor as TFForceTokensLogitsProcessor
722
+ from .generation import TFGenerationMixin as TFGenerationMixin
723
+ from .generation import TFLogitsProcessor as TFLogitsProcessor
724
+ from .generation import TFLogitsProcessorList as TFLogitsProcessorList
725
+ from .generation import TFLogitsWarper as TFLogitsWarper
726
+ from .generation import TFMinLengthLogitsProcessor as TFMinLengthLogitsProcessor
727
+ from .generation import TFNoBadWordsLogitsProcessor as TFNoBadWordsLogitsProcessor
728
+ from .generation import TFNoRepeatNGramLogitsProcessor as TFNoRepeatNGramLogitsProcessor
729
+ from .generation import TFRepetitionPenaltyLogitsProcessor as TFRepetitionPenaltyLogitsProcessor
730
+ from .generation import TFSuppressTokensAtBeginLogitsProcessor as TFSuppressTokensAtBeginLogitsProcessor
731
+ from .generation import TFSuppressTokensLogitsProcessor as TFSuppressTokensLogitsProcessor
732
+ from .generation import TFTemperatureLogitsWarper as TFTemperatureLogitsWarper
733
+ from .generation import TFTopKLogitsWarper as TFTopKLogitsWarper
734
+ from .generation import TFTopPLogitsWarper as TFTopPLogitsWarper
735
+ from .generation import TopKLogitsWarper as TopKLogitsWarper
736
+ from .generation import TopPLogitsWarper as TopPLogitsWarper
737
+ from .generation import TypicalLogitsWarper as TypicalLogitsWarper
738
+ from .generation import (
739
+ UnbatchedClassifierFreeGuidanceLogitsProcessor as UnbatchedClassifierFreeGuidanceLogitsProcessor,
740
+ )
741
+ from .generation import WatermarkDetector as WatermarkDetector
742
+ from .generation import WatermarkingConfig as WatermarkingConfig
743
+ from .generation import WatermarkLogitsProcessor as WatermarkLogitsProcessor
744
+ from .generation import WhisperTimeStampLogitsProcessor as WhisperTimeStampLogitsProcessor
745
+ from .hf_argparser import HfArgumentParser as HfArgumentParser
746
+ from .image_processing_base import ImageProcessingMixin as ImageProcessingMixin
747
+ from .image_processing_utils import BaseImageProcessor as BaseImageProcessor
748
+ from .image_processing_utils_fast import BaseImageProcessorFast as BaseImageProcessorFast
749
+ from .image_utils import ImageFeatureExtractionMixin as ImageFeatureExtractionMixin
750
+
751
+ # Integrations
752
+ from .integrations import is_clearml_available as is_clearml_available
753
+ from .integrations import is_comet_available as is_comet_available
754
+ from .integrations import is_dvclive_available as is_dvclive_available
755
+ from .integrations import is_neptune_available as is_neptune_available
756
+ from .integrations import is_optuna_available as is_optuna_available
757
+ from .integrations import is_ray_available as is_ray_available
758
+ from .integrations import is_ray_tune_available as is_ray_tune_available
759
+ from .integrations import is_sigopt_available as is_sigopt_available
760
+ from .integrations import is_swanlab_available as is_swanlab_available
761
+ from .integrations import is_tensorboard_available as is_tensorboard_available
762
+ from .integrations import is_trackio_available as is_trackio_available
763
+ from .integrations import is_wandb_available as is_wandb_available
764
+ from .integrations.executorch import TorchExportableModuleWithStaticCache as TorchExportableModuleWithStaticCache
765
+ from .integrations.executorch import convert_and_export_with_cache as convert_and_export_with_cache
766
+ from .keras_callbacks import KerasMetricCallback as KerasMetricCallback
767
+ from .keras_callbacks import PushToHubCallback as PushToHubCallback
768
+ from .masking_utils import AttentionMaskInterface as AttentionMaskInterface
769
+ from .model_debugging_utils import model_addition_debugger_context as model_addition_debugger_context
770
+
771
+ # Model Cards
772
+ from .modelcard import ModelCard as ModelCard
773
+ from .modeling_flax_utils import FlaxPreTrainedModel as FlaxPreTrainedModel
774
+ from .modeling_layers import GradientCheckpointingLayer as GradientCheckpointingLayer
775
+ from .modeling_rope_utils import ROPE_INIT_FUNCTIONS as ROPE_INIT_FUNCTIONS
776
+ from .modeling_rope_utils import dynamic_rope_update as dynamic_rope_update
777
+
778
+ # TF 2.0 <=> PyTorch conversion utilities
779
+ from .modeling_tf_pytorch_utils import (
780
+ convert_tf_weight_name_to_pt_weight_name as convert_tf_weight_name_to_pt_weight_name,
781
+ )
782
+ from .modeling_tf_pytorch_utils import load_pytorch_checkpoint_in_tf2_model as load_pytorch_checkpoint_in_tf2_model
783
+ from .modeling_tf_pytorch_utils import load_pytorch_model_in_tf2_model as load_pytorch_model_in_tf2_model
784
+ from .modeling_tf_pytorch_utils import load_pytorch_weights_in_tf2_model as load_pytorch_weights_in_tf2_model
785
+ from .modeling_tf_pytorch_utils import load_tf2_checkpoint_in_pytorch_model as load_tf2_checkpoint_in_pytorch_model
786
+ from .modeling_tf_pytorch_utils import load_tf2_model_in_pytorch_model as load_tf2_model_in_pytorch_model
787
+ from .modeling_tf_pytorch_utils import load_tf2_weights_in_pytorch_model as load_tf2_weights_in_pytorch_model
788
+ from .modeling_tf_utils import TFPreTrainedModel as TFPreTrainedModel
789
+ from .modeling_tf_utils import TFSequenceSummary as TFSequenceSummary
790
+ from .modeling_tf_utils import TFSharedEmbeddings as TFSharedEmbeddings
791
+ from .modeling_tf_utils import shape_list as shape_list
792
+ from .modeling_utils import AttentionInterface as AttentionInterface
793
+ from .modeling_utils import PreTrainedModel as PreTrainedModel
794
+ from .models import *
795
+ from .models.mamba.modeling_mamba import MambaCache as MambaCache
796
+ from .models.timm_wrapper import TimmWrapperImageProcessor as TimmWrapperImageProcessor
797
+
798
+ # Optimization
799
+ from .optimization import Adafactor as Adafactor
800
+ from .optimization import get_constant_schedule as get_constant_schedule
801
+ from .optimization import get_constant_schedule_with_warmup as get_constant_schedule_with_warmup
802
+ from .optimization import get_cosine_schedule_with_warmup as get_cosine_schedule_with_warmup
803
+ from .optimization import (
804
+ get_cosine_with_hard_restarts_schedule_with_warmup as get_cosine_with_hard_restarts_schedule_with_warmup,
805
+ )
806
+ from .optimization import (
807
+ get_cosine_with_min_lr_schedule_with_warmup as get_cosine_with_min_lr_schedule_with_warmup,
808
+ )
809
+ from .optimization import (
810
+ get_cosine_with_min_lr_schedule_with_warmup_lr_rate as get_cosine_with_min_lr_schedule_with_warmup_lr_rate,
811
+ )
812
+ from .optimization import get_inverse_sqrt_schedule as get_inverse_sqrt_schedule
813
+ from .optimization import get_linear_schedule_with_warmup as get_linear_schedule_with_warmup
814
+ from .optimization import get_polynomial_decay_schedule_with_warmup as get_polynomial_decay_schedule_with_warmup
815
+ from .optimization import get_scheduler as get_scheduler
816
+ from .optimization import get_wsd_schedule as get_wsd_schedule
817
+
818
+ # Optimization
819
+ from .optimization_tf import AdamWeightDecay as AdamWeightDecay
820
+ from .optimization_tf import GradientAccumulator as GradientAccumulator
821
+ from .optimization_tf import WarmUp as WarmUp
822
+ from .optimization_tf import create_optimizer as create_optimizer
823
+
824
+ # Pipelines
825
+ from .pipelines import AudioClassificationPipeline as AudioClassificationPipeline
826
+ from .pipelines import AutomaticSpeechRecognitionPipeline as AutomaticSpeechRecognitionPipeline
827
+ from .pipelines import CsvPipelineDataFormat as CsvPipelineDataFormat
828
+ from .pipelines import DepthEstimationPipeline as DepthEstimationPipeline
829
+ from .pipelines import DocumentQuestionAnsweringPipeline as DocumentQuestionAnsweringPipeline
830
+ from .pipelines import FeatureExtractionPipeline as FeatureExtractionPipeline
831
+ from .pipelines import FillMaskPipeline as FillMaskPipeline
832
+ from .pipelines import ImageClassificationPipeline as ImageClassificationPipeline
833
+ from .pipelines import ImageFeatureExtractionPipeline as ImageFeatureExtractionPipeline
834
+ from .pipelines import ImageSegmentationPipeline as ImageSegmentationPipeline
835
+ from .pipelines import ImageTextToTextPipeline as ImageTextToTextPipeline
836
+ from .pipelines import ImageToImagePipeline as ImageToImagePipeline
837
+ from .pipelines import ImageToTextPipeline as ImageToTextPipeline
838
+ from .pipelines import JsonPipelineDataFormat as JsonPipelineDataFormat
839
+ from .pipelines import KeypointMatchingPipeline as KeypointMatchingPipeline
840
+ from .pipelines import MaskGenerationPipeline as MaskGenerationPipeline
841
+ from .pipelines import NerPipeline as NerPipeline
842
+ from .pipelines import ObjectDetectionPipeline as ObjectDetectionPipeline
843
+ from .pipelines import PipedPipelineDataFormat as PipedPipelineDataFormat
844
+ from .pipelines import Pipeline as Pipeline
845
+ from .pipelines import PipelineDataFormat as PipelineDataFormat
846
+ from .pipelines import QuestionAnsweringPipeline as QuestionAnsweringPipeline
847
+ from .pipelines import SummarizationPipeline as SummarizationPipeline
848
+ from .pipelines import TableQuestionAnsweringPipeline as TableQuestionAnsweringPipeline
849
+ from .pipelines import Text2TextGenerationPipeline as Text2TextGenerationPipeline
850
+ from .pipelines import TextClassificationPipeline as TextClassificationPipeline
851
+ from .pipelines import TextGenerationPipeline as TextGenerationPipeline
852
+ from .pipelines import TextToAudioPipeline as TextToAudioPipeline
853
+ from .pipelines import TokenClassificationPipeline as TokenClassificationPipeline
854
+ from .pipelines import TranslationPipeline as TranslationPipeline
855
+ from .pipelines import VideoClassificationPipeline as VideoClassificationPipeline
856
+ from .pipelines import VisualQuestionAnsweringPipeline as VisualQuestionAnsweringPipeline
857
+ from .pipelines import ZeroShotAudioClassificationPipeline as ZeroShotAudioClassificationPipeline
858
+ from .pipelines import ZeroShotClassificationPipeline as ZeroShotClassificationPipeline
859
+ from .pipelines import ZeroShotImageClassificationPipeline as ZeroShotImageClassificationPipeline
860
+ from .pipelines import ZeroShotObjectDetectionPipeline as ZeroShotObjectDetectionPipeline
861
+ from .pipelines import pipeline as pipeline
862
+ from .processing_utils import ProcessorMixin as ProcessorMixin
863
+ from .pytorch_utils import Conv1D as Conv1D
864
+ from .pytorch_utils import apply_chunking_to_forward as apply_chunking_to_forward
865
+ from .pytorch_utils import prune_layer as prune_layer
866
+
867
+ # Tokenization
868
+ from .tokenization_utils import PreTrainedTokenizer as PreTrainedTokenizer
869
+ from .tokenization_utils_base import AddedToken as AddedToken
870
+ from .tokenization_utils_base import BatchEncoding as BatchEncoding
871
+ from .tokenization_utils_base import CharSpan as CharSpan
872
+ from .tokenization_utils_base import PreTrainedTokenizerBase as PreTrainedTokenizerBase
873
+ from .tokenization_utils_base import SpecialTokensMixin as SpecialTokensMixin
874
+ from .tokenization_utils_base import TokenSpan as TokenSpan
875
+ from .tokenization_utils_fast import PreTrainedTokenizerFast as PreTrainedTokenizerFast
876
+
877
+ # Trainer
878
+ from .trainer import Trainer as Trainer
879
+
880
+ # Trainer
881
+ from .trainer_callback import DefaultFlowCallback as DefaultFlowCallback
882
+ from .trainer_callback import EarlyStoppingCallback as EarlyStoppingCallback
883
+ from .trainer_callback import PrinterCallback as PrinterCallback
884
+ from .trainer_callback import ProgressCallback as ProgressCallback
885
+ from .trainer_callback import TrainerCallback as TrainerCallback
886
+ from .trainer_callback import TrainerControl as TrainerControl
887
+ from .trainer_callback import TrainerState as TrainerState
888
+ from .trainer_pt_utils import torch_distributed_zero_first as torch_distributed_zero_first
889
+ from .trainer_seq2seq import Seq2SeqTrainer as Seq2SeqTrainer
890
+ from .trainer_utils import EvalPrediction as EvalPrediction
891
+ from .trainer_utils import IntervalStrategy as IntervalStrategy
892
+ from .trainer_utils import SchedulerType as SchedulerType
893
+ from .trainer_utils import enable_full_determinism as enable_full_determinism
894
+ from .trainer_utils import set_seed as set_seed
895
+ from .training_args import TrainingArguments as TrainingArguments
896
+ from .training_args_seq2seq import Seq2SeqTrainingArguments as Seq2SeqTrainingArguments
897
+ from .training_args_tf import TFTrainingArguments as TFTrainingArguments
898
+
899
+ # Files and general utilities
900
+ from .utils import CONFIG_NAME as CONFIG_NAME
901
+ from .utils import MODEL_CARD_NAME as MODEL_CARD_NAME
902
+ from .utils import PYTORCH_PRETRAINED_BERT_CACHE as PYTORCH_PRETRAINED_BERT_CACHE
903
+ from .utils import PYTORCH_TRANSFORMERS_CACHE as PYTORCH_TRANSFORMERS_CACHE
904
+ from .utils import SPIECE_UNDERLINE as SPIECE_UNDERLINE
905
+ from .utils import TF2_WEIGHTS_NAME as TF2_WEIGHTS_NAME
906
+ from .utils import TF_WEIGHTS_NAME as TF_WEIGHTS_NAME
907
+ from .utils import TRANSFORMERS_CACHE as TRANSFORMERS_CACHE
908
+ from .utils import WEIGHTS_NAME as WEIGHTS_NAME
909
+ from .utils import TensorType as TensorType
910
+ from .utils import add_end_docstrings as add_end_docstrings
911
+ from .utils import add_start_docstrings as add_start_docstrings
912
+ from .utils import is_apex_available as is_apex_available
913
+ from .utils import is_av_available as is_av_available
914
+ from .utils import is_datasets_available as is_datasets_available
915
+ from .utils import is_faiss_available as is_faiss_available
916
+ from .utils import is_matplotlib_available as is_matplotlib_available
917
+ from .utils import is_phonemizer_available as is_phonemizer_available
918
+ from .utils import is_psutil_available as is_psutil_available
919
+ from .utils import is_py3nvml_available as is_py3nvml_available
920
+ from .utils import is_pyctcdecode_available as is_pyctcdecode_available
921
+ from .utils import is_sacremoses_available as is_sacremoses_available
922
+ from .utils import is_safetensors_available as is_safetensors_available
923
+ from .utils import is_sklearn_available as is_sklearn_available
924
+ from .utils import is_torch_hpu_available as is_torch_hpu_available
925
+ from .utils import is_torch_mlu_available as is_torch_mlu_available
926
+ from .utils import is_torch_musa_available as is_torch_musa_available
927
+ from .utils import is_torch_neuroncore_available as is_torch_neuroncore_available
928
+ from .utils import is_torch_npu_available as is_torch_npu_available
929
+ from .utils import is_torch_xla_available as is_torch_xla_available
930
+ from .utils import is_torch_xpu_available as is_torch_xpu_available
931
+
932
+ # bitsandbytes config
933
+ from .utils.quantization_config import AqlmConfig as AqlmConfig
934
+ from .utils.quantization_config import AutoRoundConfig as AutoRoundConfig
935
+ from .utils.quantization_config import AwqConfig as AwqConfig
936
+ from .utils.quantization_config import BitNetQuantConfig as BitNetQuantConfig
937
+ from .utils.quantization_config import BitsAndBytesConfig as BitsAndBytesConfig
938
+ from .utils.quantization_config import CompressedTensorsConfig as CompressedTensorsConfig
939
+ from .utils.quantization_config import EetqConfig as EetqConfig
940
+ from .utils.quantization_config import FbgemmFp8Config as FbgemmFp8Config
941
+ from .utils.quantization_config import FineGrainedFP8Config as FineGrainedFP8Config
942
+ from .utils.quantization_config import FPQuantConfig as FPQuantConfig
943
+ from .utils.quantization_config import GPTQConfig as GPTQConfig
944
+ from .utils.quantization_config import HiggsConfig as HiggsConfig
945
+ from .utils.quantization_config import HqqConfig as HqqConfig
946
+ from .utils.quantization_config import QuantoConfig as QuantoConfig
947
+ from .utils.quantization_config import QuarkConfig as QuarkConfig
948
+ from .utils.quantization_config import SpQRConfig as SpQRConfig
949
+ from .utils.quantization_config import TorchAoConfig as TorchAoConfig
950
+ from .utils.quantization_config import VptqConfig as VptqConfig
951
+ from .video_processing_utils import BaseVideoProcessor as BaseVideoProcessor
952
+
953
+ else:
954
+ import sys
955
+
956
+ _import_structure = {k: set(v) for k, v in _import_structure.items()}
957
+
958
+ import_structure = define_import_structure(Path(__file__).parent / "models", prefix="models")
959
+ import_structure[frozenset({})].update(_import_structure)
960
+
961
+ sys.modules[__name__] = _LazyModule(
962
+ __name__,
963
+ globals()["__file__"],
964
+ import_structure,
965
+ module_spec=__spec__,
966
+ extra_objects={"__version__": __version__},
967
+ )
968
+
969
+
970
+ if not is_tf_available() and not is_torch_available() and not is_flax_available():
971
+ logger.warning_advice(
972
+ "None of PyTorch, TensorFlow >= 2.0, or Flax have been found. "
973
+ "Models won't be available and only tokenizers, configuration "
974
+ "and file/data utilities can be used."
975
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/activations.py ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import functools
16
+ import math
17
+ from collections import OrderedDict
18
+
19
+ import torch
20
+ from torch import Tensor, nn
21
+
22
+ from .integrations.hub_kernels import use_kernel_forward_from_hub
23
+ from .utils import logging
24
+ from .utils.import_utils import is_torchdynamo_compiling
25
+
26
+
27
+ logger = logging.get_logger(__name__)
28
+
29
+
30
+ @use_kernel_forward_from_hub("GeluTanh")
31
+ class GELUTanh(nn.Module):
32
+ """
33
+ A fast C implementation of the tanh approximation of the GeLU activation function. See
34
+ https://huggingface.co/papers/1606.08415.
35
+
36
+ This implementation is equivalent to NewGELU and FastGELU but much faster. However, it is not an exact numerical
37
+ match due to rounding errors.
38
+ """
39
+
40
+ def __init__(self, use_gelu_tanh_python: bool = False):
41
+ super().__init__()
42
+ if use_gelu_tanh_python:
43
+ self.act = self._gelu_tanh_python
44
+ else:
45
+ self.act = functools.partial(nn.functional.gelu, approximate="tanh")
46
+
47
+ def _gelu_tanh_python(self, input: Tensor) -> Tensor:
48
+ return input * 0.5 * (1.0 + torch.tanh(math.sqrt(2.0 / math.pi) * (input + 0.044715 * torch.pow(input, 3.0))))
49
+
50
+ def forward(self, input: Tensor) -> Tensor:
51
+ return self.act(input)
52
+
53
+
54
+ @use_kernel_forward_from_hub("NewGELU")
55
+ class NewGELUActivation(nn.Module):
56
+ """
57
+ Implementation of the GELU activation function currently in Google BERT repo (identical to OpenAI GPT). Also see
58
+ the Gaussian Error Linear Units paper: https://huggingface.co/papers/1606.08415
59
+ """
60
+
61
+ def forward(self, input: Tensor) -> Tensor:
62
+ return 0.5 * input * (1.0 + torch.tanh(math.sqrt(2.0 / math.pi) * (input + 0.044715 * torch.pow(input, 3.0))))
63
+
64
+
65
+ @use_kernel_forward_from_hub("GeLU")
66
+ class GELUActivation(nn.Module):
67
+ """
68
+ Original Implementation of the GELU activation function in Google BERT repo when initially created. For
69
+ information: OpenAI GPT's GELU is slightly different (and gives slightly different results): 0.5 * x * (1 +
70
+ torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))) This is now written in C in nn.functional
71
+ Also see the Gaussian Error Linear Units paper: https://huggingface.co/papers/1606.08415
72
+ """
73
+
74
+ def __init__(self, use_gelu_python: bool = False):
75
+ super().__init__()
76
+ if use_gelu_python:
77
+ self.act = self._gelu_python
78
+ else:
79
+ self.act = nn.functional.gelu
80
+
81
+ def _gelu_python(self, input: Tensor) -> Tensor:
82
+ return input * 0.5 * (1.0 + torch.erf(input / math.sqrt(2.0)))
83
+
84
+ def forward(self, input: Tensor) -> Tensor:
85
+ return self.act(input)
86
+
87
+
88
+ @use_kernel_forward_from_hub("SiLU")
89
+ class SiLUActivation(nn.Module):
90
+ """
91
+ See Gaussian Error Linear Units (Hendrycks et al., https://arxiv.org/abs/1606.08415) where the SiLU (Sigmoid Linear
92
+ Unit) was originally introduced and coined, and see Sigmoid-Weighted Linear Units for Neural Network Function
93
+ Approximation in Reinforcement Learning (Elfwing et al., https://arxiv.org/abs/1702.03118) and Swish: a Self-Gated
94
+ Activation Function (Ramachandran et al., https://arxiv.org/abs/1710.05941v1) where the SiLU was experimented with
95
+ later.
96
+ """
97
+
98
+ def forward(self, input: Tensor) -> Tensor:
99
+ return nn.functional.silu(input)
100
+
101
+
102
+ @use_kernel_forward_from_hub("FastGELU")
103
+ class FastGELUActivation(nn.Module):
104
+ """
105
+ Applies GELU approximation that is slower than QuickGELU but more accurate. See: https://github.com/hendrycks/GELUs
106
+ """
107
+
108
+ def forward(self, input: Tensor) -> Tensor:
109
+ return 0.5 * input * (1.0 + torch.tanh(input * 0.7978845608 * (1.0 + 0.044715 * input * input)))
110
+
111
+
112
+ @use_kernel_forward_from_hub("QuickGELU")
113
+ class QuickGELUActivation(nn.Module):
114
+ """
115
+ Applies GELU approximation that is fast but somewhat inaccurate. See: https://github.com/hendrycks/GELUs
116
+ """
117
+
118
+ def forward(self, input: Tensor) -> Tensor:
119
+ return input * torch.sigmoid(1.702 * input)
120
+
121
+
122
+ class ClippedGELUActivation(nn.Module):
123
+ """
124
+ Clip the range of possible GeLU outputs between [min, max]. This is especially useful for quantization purpose, as
125
+ it allows mapping negatives values in the GeLU spectrum. For more information on this trick, please refer to
126
+ https://huggingface.co/papers/2004.09602.
127
+
128
+ Gaussian Error Linear Unit. Original Implementation of the gelu activation function in Google Bert repo when
129
+ initially created.
130
+
131
+ For information: OpenAI GPT's gelu is slightly different (and gives slightly different results): 0.5 * x * (1 +
132
+ torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))). See https://huggingface.co/papers/1606.08415
133
+ """
134
+
135
+ def __init__(self, min: float, max: float):
136
+ if min > max:
137
+ raise ValueError(f"min should be < max (got min: {min}, max: {max})")
138
+
139
+ super().__init__()
140
+ self.min = min
141
+ self.max = max
142
+
143
+ def forward(self, x: Tensor) -> Tensor:
144
+ return torch.clip(gelu(x), self.min, self.max)
145
+
146
+
147
+ class AccurateGELUActivation(nn.Module):
148
+ """
149
+ Applies GELU approximation that is faster than default and more accurate than QuickGELU. See:
150
+ https://github.com/hendrycks/GELUs
151
+
152
+ Implemented along with MEGA (Moving Average Equipped Gated Attention)
153
+ """
154
+
155
+ def __init__(self):
156
+ super().__init__()
157
+ self.precomputed_constant = math.sqrt(2 / math.pi)
158
+
159
+ def forward(self, input: Tensor) -> Tensor:
160
+ return 0.5 * input * (1 + torch.tanh(self.precomputed_constant * (input + 0.044715 * torch.pow(input, 3))))
161
+
162
+
163
+ class MishActivation(nn.Module):
164
+ """
165
+ See Mish: A Self-Regularized Non-Monotonic Activation Function (Misra., https://huggingface.co/papers/1908.08681). Also
166
+ visit the official repository for the paper: https://github.com/digantamisra98/Mish
167
+ """
168
+
169
+ def __init__(self):
170
+ super().__init__()
171
+ self.act = nn.functional.mish
172
+
173
+ def _mish_python(self, input: Tensor) -> Tensor:
174
+ return input * torch.tanh(nn.functional.softplus(input))
175
+
176
+ def forward(self, input: Tensor) -> Tensor:
177
+ return self.act(input)
178
+
179
+
180
+ class LinearActivation(nn.Module):
181
+ """
182
+ Applies the linear activation function, i.e. forwarding input directly to output.
183
+ """
184
+
185
+ def forward(self, input: Tensor) -> Tensor:
186
+ return input
187
+
188
+
189
+ class LaplaceActivation(nn.Module):
190
+ """
191
+ Applies elementwise activation based on Laplace function, introduced in MEGA as an attention activation. See
192
+ https://huggingface.co/papers/2209.10655
193
+
194
+ Inspired by squared relu, but with bounded range and gradient for better stability
195
+ """
196
+
197
+ def forward(self, input, mu=0.707107, sigma=0.282095):
198
+ input = (input - mu).div(sigma * math.sqrt(2.0))
199
+ return 0.5 * (1.0 + torch.erf(input))
200
+
201
+
202
+ class ReLUSquaredActivation(nn.Module):
203
+ """
204
+ Applies the relu^2 activation introduced in https://huggingface.co/papers/2109.08668v2
205
+ """
206
+
207
+ def forward(self, input):
208
+ relu_applied = nn.functional.relu(input)
209
+ squared = torch.square(relu_applied)
210
+ return squared
211
+
212
+
213
+ class ClassInstantier(OrderedDict):
214
+ def __getitem__(self, key):
215
+ content = super().__getitem__(key)
216
+ cls, kwargs = content if isinstance(content, tuple) else (content, {})
217
+ return cls(**kwargs)
218
+
219
+
220
+ class XIELUActivation(nn.Module):
221
+ """
222
+ Applies the xIELU activation function introduced in https://arxiv.org/abs/2411.13010
223
+
224
+ If the user has installed the nickjbrowning/XIELU wheel, we import xIELU CUDA
225
+ Otherwise, we emit a single warning and use xIELU Python
226
+ """
227
+
228
+ def __init__(
229
+ self,
230
+ alpha_p_init=0.8,
231
+ alpha_n_init=0.8,
232
+ beta=0.5,
233
+ eps=-1e-6,
234
+ dtype=torch.bfloat16,
235
+ with_vector_loads=False,
236
+ ):
237
+ super().__init__()
238
+ self.alpha_p = nn.Parameter(torch.log(torch.expm1(torch.tensor(alpha_p_init, dtype=dtype))).unsqueeze(0))
239
+ self.alpha_n = nn.Parameter(
240
+ torch.log(torch.expm1(torch.tensor(alpha_n_init - beta, dtype=dtype))).unsqueeze(0)
241
+ )
242
+ self.register_buffer("beta", torch.tensor(beta, dtype=dtype))
243
+ self.register_buffer("eps", torch.tensor(eps, dtype=dtype))
244
+ self.with_vector_loads = with_vector_loads
245
+ # Temporary until xIELU CUDA fully implemented
246
+ self._beta_scalar = float(self.beta.detach().cpu().float().item())
247
+ self._eps_scalar = float(self.eps.detach().cpu().float().item())
248
+
249
+ self._xielu_cuda_obj = None
250
+ try:
251
+ import xielu.ops # noqa: F401
252
+
253
+ self._xielu_cuda_obj = torch.classes.xielu.XIELU()
254
+ msg = "Using experimental xIELU CUDA."
255
+ try:
256
+ from torch._dynamo import allow_in_graph
257
+
258
+ self._xielu_cuda_fn = allow_in_graph(self._xielu_cuda)
259
+ msg += " Enabled torch._dynamo for xIELU CUDA."
260
+ except Exception as err:
261
+ msg += f" Could not enable torch._dynamo for xIELU ({err}) - this may result in slower performance."
262
+ self._xielu_cuda_fn = self._xielu_cuda
263
+ logger.warning_once(msg)
264
+ except Exception as err:
265
+ logger.warning_once(
266
+ "CUDA-fused xIELU not available (%s) – falling back to a Python version.\n"
267
+ "For CUDA xIELU (experimental), `pip install git+https://github.com/nickjbrowning/XIELU`",
268
+ str(err),
269
+ )
270
+
271
+ def _xielu_python(self, x: Tensor) -> Tensor:
272
+ alpha_p = nn.functional.softplus(self.alpha_p)
273
+ alpha_n = self.beta + nn.functional.softplus(self.alpha_n)
274
+ return torch.where(
275
+ x > 0,
276
+ alpha_p * x * x + self.beta * x,
277
+ (torch.expm1(torch.min(x, self.eps)) - x) * alpha_n + self.beta * x,
278
+ )
279
+
280
+ def _xielu_cuda(self, x: Tensor) -> Tensor:
281
+ """Firewall function to prevent torch.compile from seeing .item() calls"""
282
+ original_shape = x.shape
283
+ # CUDA kernel expects 3D tensors, reshape if needed
284
+ while x.dim() < 3:
285
+ x = x.unsqueeze(0)
286
+ if x.dim() > 3:
287
+ x = x.view(-1, 1, x.size(-1))
288
+ if original_shape != x.shape:
289
+ logger.warning_once(
290
+ "Warning: xIELU input tensor expects 3 dimensions but got (shape: %s). Reshaping to (shape: %s).",
291
+ original_shape,
292
+ x.shape,
293
+ )
294
+ result = self._xielu_cuda_obj.forward(
295
+ x,
296
+ self.alpha_p.to(x.dtype),
297
+ self.alpha_n.to(x.dtype),
298
+ # Temporary until xIELU CUDA fully implemented -> self.{beta,eps}.item()
299
+ self._beta_scalar,
300
+ self._eps_scalar,
301
+ self.with_vector_loads,
302
+ )
303
+ return result.view(original_shape)
304
+
305
+ def forward(self, input: Tensor) -> Tensor:
306
+ if self._xielu_cuda_obj is not None and input.is_cuda:
307
+ if not is_torchdynamo_compiling():
308
+ return self._xielu_cuda_fn(input)
309
+ else:
310
+ logger.warning_once("torch._dynamo is compiling, using Python version of xIELU.")
311
+ return self._xielu_python(input)
312
+
313
+
314
+ ACT2CLS = {
315
+ "gelu": GELUActivation,
316
+ "gelu_10": (ClippedGELUActivation, {"min": -10, "max": 10}),
317
+ "gelu_fast": FastGELUActivation,
318
+ "gelu_new": NewGELUActivation,
319
+ "gelu_python": (GELUActivation, {"use_gelu_python": True}),
320
+ "gelu_pytorch_tanh": GELUTanh,
321
+ "gelu_python_tanh": (GELUTanh, {"use_gelu_tanh_python": True}),
322
+ "gelu_accurate": AccurateGELUActivation,
323
+ "laplace": LaplaceActivation,
324
+ "leaky_relu": nn.LeakyReLU,
325
+ "linear": LinearActivation,
326
+ "mish": MishActivation,
327
+ "quick_gelu": QuickGELUActivation,
328
+ "relu": nn.ReLU,
329
+ "relu2": ReLUSquaredActivation,
330
+ "relu6": nn.ReLU6,
331
+ "sigmoid": nn.Sigmoid,
332
+ "silu": SiLUActivation,
333
+ "swish": nn.SiLU,
334
+ "tanh": nn.Tanh,
335
+ "prelu": nn.PReLU,
336
+ "xielu": XIELUActivation,
337
+ }
338
+ ACT2FN = ClassInstantier(ACT2CLS)
339
+
340
+
341
+ def get_activation(activation_string):
342
+ if activation_string in ACT2FN:
343
+ return ACT2FN[activation_string]
344
+ else:
345
+ raise KeyError(f"function {activation_string} not found in ACT2FN mapping {list(ACT2FN.keys())}")
346
+
347
+
348
+ # For backwards compatibility with: from activations import gelu_python
349
+ gelu_python = get_activation("gelu_python")
350
+ gelu_new = get_activation("gelu_new")
351
+ gelu = get_activation("gelu")
352
+ gelu_fast = get_activation("gelu_fast")
353
+ quick_gelu = get_activation("quick_gelu")
354
+ silu = get_activation("silu")
355
+ mish = get_activation("mish")
356
+ linear_act = get_activation("linear")
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/activations_tf.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import math
16
+
17
+ import tensorflow as tf
18
+ from packaging.version import parse
19
+
20
+
21
+ try:
22
+ import tf_keras as keras
23
+ except (ModuleNotFoundError, ImportError):
24
+ import keras
25
+
26
+ if parse(keras.__version__).major > 2:
27
+ raise ValueError(
28
+ "Your currently installed version of Keras is Keras 3, but this is not yet supported in "
29
+ "Transformers. Please install the backwards-compatible tf-keras package with "
30
+ "`pip install tf-keras`."
31
+ )
32
+
33
+
34
+ def _gelu(x):
35
+ """
36
+ Gaussian Error Linear Unit. Original Implementation of the gelu activation function in Google Bert repo when
37
+ initially created. For information: OpenAI GPT's gelu is slightly different (and gives slightly different results):
38
+ 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))) Also see
39
+ https://huggingface.co/papers/1606.08415
40
+ """
41
+ x = tf.convert_to_tensor(x)
42
+ cdf = 0.5 * (1.0 + tf.math.erf(x / tf.cast(tf.sqrt(2.0), x.dtype)))
43
+
44
+ return x * cdf
45
+
46
+
47
+ def _gelu_new(x):
48
+ """
49
+ Gaussian Error Linear Unit. This is a smoother version of the GELU. Original paper: https://huggingface.co/papers/1606.0841
50
+
51
+ Args:
52
+ x: float Tensor to perform activation
53
+
54
+ Returns:
55
+ `x` with the GELU activation applied.
56
+ """
57
+ x = tf.convert_to_tensor(x)
58
+ pi = tf.cast(math.pi, x.dtype)
59
+ coeff = tf.cast(0.044715, x.dtype)
60
+ cdf = 0.5 * (1.0 + tf.tanh(tf.sqrt(2.0 / pi) * (x + coeff * tf.pow(x, 3))))
61
+
62
+ return x * cdf
63
+
64
+
65
+ def mish(x):
66
+ x = tf.convert_to_tensor(x)
67
+
68
+ return x * tf.tanh(tf.math.softplus(x))
69
+
70
+
71
+ def gelu_fast(x):
72
+ x = tf.convert_to_tensor(x)
73
+ coeff1 = tf.cast(0.044715, x.dtype)
74
+ coeff2 = tf.cast(0.7978845608, x.dtype)
75
+
76
+ return 0.5 * x * (1.0 + tf.tanh(x * coeff2 * (1.0 + coeff1 * x * x)))
77
+
78
+
79
+ def quick_gelu(x):
80
+ x = tf.convert_to_tensor(x)
81
+ coeff = tf.cast(1.702, x.dtype)
82
+ return x * tf.math.sigmoid(coeff * x)
83
+
84
+
85
+ def gelu_10(x):
86
+ """
87
+ Clip the range of possible GeLU outputs between [-10, 10]. This is especially useful for quantization purpose, as
88
+ it allows mapping 2 negatives values in the GeLU spectrum. For more information on this trick, please refer to
89
+ https://huggingface.co/papers/2004.09602
90
+
91
+ Gaussian Error Linear Unit. Original Implementation of the gelu activation function in Google Bert repo when
92
+ initially created. For information: OpenAI GPT's gelu is slightly different (and gives slightly different results):
93
+ 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))) Also see
94
+ https://huggingface.co/papers/1606.08415 :param x: :return:
95
+ """
96
+ return tf.clip_by_value(_gelu(x), -10, 10)
97
+
98
+
99
+ def glu(x, axis=-1):
100
+ """
101
+ Gated Linear Unit. Implementation as defined in the original paper (see https://huggingface.co/papers/1612.08083), where
102
+ the input `x` is split in two halves across a dimension (`axis`), A and B, returning A * sigmoid(B).
103
+
104
+ Args:
105
+ `x`: float Tensor to perform activation
106
+ `axis`: dimension across which `x` be split in half
107
+
108
+ Returns:
109
+ `x` with the GLU activation applied (with its size halved across the dimension `axis`).
110
+ """
111
+ a, b = tf.split(x, 2, axis=axis)
112
+ return a * tf.math.sigmoid(b)
113
+
114
+
115
+ if parse(tf.version.VERSION) >= parse("2.4"):
116
+
117
+ def approximate_gelu_wrap(x):
118
+ return keras.activations.gelu(x, approximate=True)
119
+
120
+ gelu = keras.activations.gelu
121
+ gelu_new = approximate_gelu_wrap
122
+ else:
123
+ gelu = _gelu
124
+ gelu_new = _gelu_new
125
+
126
+
127
+ ACT2FN = {
128
+ "gelu": gelu,
129
+ "gelu_10": gelu_10,
130
+ "gelu_fast": gelu_fast,
131
+ "gelu_new": gelu_new,
132
+ "glu": glu,
133
+ "mish": mish,
134
+ "quick_gelu": quick_gelu,
135
+ "relu": keras.activations.relu,
136
+ "sigmoid": keras.activations.sigmoid,
137
+ "silu": keras.activations.swish,
138
+ "swish": keras.activations.swish,
139
+ "tanh": keras.activations.tanh,
140
+ }
141
+
142
+
143
+ def get_tf_activation(activation_string):
144
+ if activation_string in ACT2FN:
145
+ return ACT2FN[activation_string]
146
+ else:
147
+ raise KeyError(f"function {activation_string} not found in ACT2FN mapping {list(ACT2FN.keys())}")
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/audio_utils.py ADDED
@@ -0,0 +1,1224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023 The HuggingFace Inc. team and the librosa & torchaudio authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ Audio processing functions to extract features from audio waveforms. This code is pure numpy to support all frameworks
16
+ and remove unnecessary dependencies.
17
+ """
18
+
19
+ import base64
20
+ import importlib
21
+ import io
22
+ import os
23
+ import warnings
24
+ from collections.abc import Sequence
25
+ from io import BytesIO
26
+ from typing import TYPE_CHECKING, Any, Optional, Union
27
+
28
+
29
+ if TYPE_CHECKING:
30
+ import torch
31
+ import numpy as np
32
+ import requests
33
+ from packaging import version
34
+
35
+ from .utils import (
36
+ is_librosa_available,
37
+ is_numpy_array,
38
+ is_soundfile_available,
39
+ is_torch_tensor,
40
+ is_torchcodec_available,
41
+ requires_backends,
42
+ )
43
+
44
+
45
+ if is_soundfile_available():
46
+ import soundfile as sf
47
+
48
+ if is_librosa_available():
49
+ import librosa
50
+
51
+ # TODO: @eustlb, we actually don't need librosa but soxr is installed with librosa
52
+ import soxr
53
+
54
+ if is_torchcodec_available():
55
+ TORCHCODEC_VERSION = version.parse(importlib.metadata.version("torchcodec"))
56
+
57
+ AudioInput = Union[np.ndarray, "torch.Tensor", Sequence[np.ndarray], Sequence["torch.Tensor"]]
58
+
59
+
60
+ def load_audio(audio: Union[str, np.ndarray], sampling_rate=16000, timeout=None) -> np.ndarray:
61
+ """
62
+ Loads `audio` to an np.ndarray object.
63
+
64
+ Args:
65
+ audio (`str` or `np.ndarray`):
66
+ The audio to be loaded to the numpy array format.
67
+ sampling_rate (`int`, *optional*, defaults to 16000):
68
+ The sampling rate to be used when loading the audio. It should be same as the
69
+ sampling rate the model you will be using further was trained with.
70
+ timeout (`float`, *optional*):
71
+ The timeout value in seconds for the URL request.
72
+
73
+ Returns:
74
+ `np.ndarray`: A numpy array representing the audio.
75
+ """
76
+ if isinstance(audio, str):
77
+ # Try to load with `torchcodec` but do not enforce users to install it. If not found
78
+ # fallback to `librosa`. If using an audio-only model, most probably `torchcodec` won't be
79
+ # needed. Do not raise any errors if not installed or versions do not match
80
+ if is_torchcodec_available() and TORCHCODEC_VERSION >= version.parse("0.3.0"):
81
+ audio = load_audio_torchcodec(audio, sampling_rate=sampling_rate)
82
+ else:
83
+ audio = load_audio_librosa(audio, sampling_rate=sampling_rate, timeout=timeout)
84
+ elif not isinstance(audio, np.ndarray):
85
+ raise TypeError(
86
+ "Incorrect format used for `audio`. Should be an url linking to an audio, a local path, or numpy array."
87
+ )
88
+ return audio
89
+
90
+
91
+ def load_audio_torchcodec(audio: Union[str, np.ndarray], sampling_rate=16000) -> np.ndarray:
92
+ """
93
+ Loads `audio` to an np.ndarray object using `torchcodec`.
94
+
95
+ Args:
96
+ audio (`str` or `np.ndarray`):
97
+ The audio to be loaded to the numpy array format.
98
+ sampling_rate (`int`, *optional*, defaults to 16000):
99
+ The sampling rate to be used when loading the audio. It should be same as the
100
+ sampling rate the model you will be using further was trained with.
101
+
102
+ Returns:
103
+ `np.ndarray`: A numpy array representing the audio.
104
+ """
105
+ # Lazy import so that issues in torchcodec compatibility don't crash the whole library
106
+ requires_backends(load_audio_torchcodec, ["torchcodec"])
107
+ from torchcodec.decoders import AudioDecoder
108
+
109
+ # Set `num_channels` to `1` which is what most models expects and the default in librosa
110
+ decoder = AudioDecoder(audio, sample_rate=sampling_rate, num_channels=1)
111
+ audio = decoder.get_all_samples().data[0].numpy() # NOTE: feature extractors don't accept torch tensors
112
+ return audio
113
+
114
+
115
+ def load_audio_librosa(audio: Union[str, np.ndarray], sampling_rate=16000, timeout=None) -> np.ndarray:
116
+ """
117
+ Loads `audio` to an np.ndarray object using `librosa`.
118
+
119
+ Args:
120
+ audio (`str` or `np.ndarray`):
121
+ The audio to be loaded to the numpy array format.
122
+ sampling_rate (`int`, *optional*, defaults to 16000):
123
+ The sampling rate to be used when loading the audio. It should be same as the
124
+ sampling rate the model you will be using further was trained with.
125
+ timeout (`float`, *optional*):
126
+ The timeout value in seconds for the URL request.
127
+
128
+ Returns:
129
+ `np.ndarray`: A numpy array representing the audio.
130
+ """
131
+ requires_backends(load_audio_librosa, ["librosa"])
132
+
133
+ # Load audio from URL (e.g https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen2-Audio/audio/translate_to_chinese.wav)
134
+ if audio.startswith("http://") or audio.startswith("https://"):
135
+ audio = librosa.load(BytesIO(requests.get(audio, timeout=timeout).content), sr=sampling_rate)[0]
136
+ elif os.path.isfile(audio):
137
+ audio = librosa.load(audio, sr=sampling_rate)[0]
138
+ return audio
139
+
140
+
141
+ def load_audio_as(
142
+ audio: str,
143
+ return_format: str,
144
+ timeout: Optional[int] = None,
145
+ force_mono: bool = False,
146
+ sampling_rate: Optional[int] = None,
147
+ ) -> Union[str, dict[str, Any], io.BytesIO, None]:
148
+ """
149
+ Load audio from either a local file path or URL and return in specified format.
150
+
151
+ Args:
152
+ audio (`str`): Either a local file path or a URL to an audio file
153
+ return_format (`str`): Format to return the audio in:
154
+ - "base64": Base64 encoded string
155
+ - "dict": Dictionary with data and format
156
+ - "buffer": BytesIO object
157
+ timeout (`int`, *optional*): Timeout for URL requests in seconds
158
+ force_mono (`bool`): Whether to convert stereo audio to mono
159
+ sampling_rate (`int`, *optional*): If provided, the audio will be resampled to the specified sampling rate.
160
+
161
+ Returns:
162
+ `Union[str, Dict[str, Any], io.BytesIO, None]`:
163
+ - `str`: Base64 encoded audio data (if return_format="base64")
164
+ - `dict`: Dictionary with 'data' (base64 encoded audio data) and 'format' keys (if return_format="dict")
165
+ - `io.BytesIO`: BytesIO object containing audio data (if return_format="buffer")
166
+ """
167
+ # TODO: @eustlb, we actually don't need librosa but soxr is installed with librosa
168
+ requires_backends(load_audio_as, ["librosa"])
169
+
170
+ if return_format not in ["base64", "dict", "buffer"]:
171
+ raise ValueError(f"Invalid return_format: {return_format}. Must be 'base64', 'dict', or 'buffer'")
172
+
173
+ try:
174
+ # Load audio bytes from URL or file
175
+ audio_bytes = None
176
+ if audio.startswith(("http://", "https://")):
177
+ response = requests.get(audio, timeout=timeout)
178
+ response.raise_for_status()
179
+ audio_bytes = response.content
180
+ elif os.path.isfile(audio):
181
+ with open(audio, "rb") as audio_file:
182
+ audio_bytes = audio_file.read()
183
+ else:
184
+ raise ValueError(f"File not found: {audio}")
185
+
186
+ # Process audio data
187
+ with io.BytesIO(audio_bytes) as audio_file:
188
+ with sf.SoundFile(audio_file) as f:
189
+ audio_array = f.read(dtype="float32")
190
+ original_sr = f.samplerate
191
+ audio_format = f.format
192
+ if sampling_rate is not None and sampling_rate != original_sr:
193
+ # Resample audio to target sampling rate
194
+ audio_array = soxr.resample(audio_array, original_sr, sampling_rate, quality="HQ")
195
+ else:
196
+ sampling_rate = original_sr
197
+
198
+ # Convert to mono if needed
199
+ if force_mono and audio_array.ndim != 1:
200
+ audio_array = audio_array.mean(axis=1)
201
+
202
+ buffer = io.BytesIO()
203
+ sf.write(buffer, audio_array, sampling_rate, format=audio_format.upper())
204
+ buffer.seek(0)
205
+
206
+ if return_format == "buffer":
207
+ return buffer
208
+ elif return_format == "base64":
209
+ return base64.b64encode(buffer.read()).decode("utf-8")
210
+ elif return_format == "dict":
211
+ return {
212
+ "data": base64.b64encode(buffer.read()).decode("utf-8"),
213
+ "format": audio_format.lower(),
214
+ }
215
+
216
+ except Exception as e:
217
+ raise ValueError(f"Error loading audio: {e}")
218
+
219
+
220
+ def is_valid_audio(audio):
221
+ return is_numpy_array(audio) or is_torch_tensor(audio)
222
+
223
+
224
+ def is_valid_list_of_audio(audio):
225
+ return audio and all(is_valid_audio(audio_i) for audio_i in audio)
226
+
227
+
228
+ def make_list_of_audio(
229
+ audio: Union[list[AudioInput], AudioInput],
230
+ ) -> AudioInput:
231
+ """
232
+ Ensure that the output is a list of audio.
233
+ Args:
234
+ audio (`Union[list[AudioInput], AudioInput]`):
235
+ The input audio.
236
+ Returns:
237
+ list: A list of audio.
238
+ """
239
+ # If it's a list of audios, it's already in the right format
240
+ if isinstance(audio, (list, tuple)) and is_valid_list_of_audio(audio):
241
+ return audio
242
+
243
+ # If it's a single audio, convert it to a list of
244
+ if is_valid_audio(audio):
245
+ return [audio]
246
+
247
+ raise ValueError("Invalid input type. Must be a single audio or a list of audio")
248
+
249
+
250
+ def hertz_to_mel(freq: Union[float, np.ndarray], mel_scale: str = "htk") -> Union[float, np.ndarray]:
251
+ """
252
+ Convert frequency from hertz to mels.
253
+
254
+ Args:
255
+ freq (`float` or `np.ndarray`):
256
+ The frequency, or multiple frequencies, in hertz (Hz).
257
+ mel_scale (`str`, *optional*, defaults to `"htk"`):
258
+ The mel frequency scale to use, `"htk"`, `"kaldi"` or `"slaney"`.
259
+
260
+ Returns:
261
+ `float` or `np.ndarray`: The frequencies on the mel scale.
262
+ """
263
+
264
+ if mel_scale not in ["slaney", "htk", "kaldi"]:
265
+ raise ValueError('mel_scale should be one of "htk", "slaney" or "kaldi".')
266
+
267
+ if mel_scale == "htk":
268
+ return 2595.0 * np.log10(1.0 + (freq / 700.0))
269
+ elif mel_scale == "kaldi":
270
+ return 1127.0 * np.log(1.0 + (freq / 700.0))
271
+
272
+ min_log_hertz = 1000.0
273
+ min_log_mel = 15.0
274
+ logstep = 27.0 / np.log(6.4)
275
+ mels = 3.0 * freq / 200.0
276
+
277
+ if isinstance(freq, np.ndarray):
278
+ log_region = freq >= min_log_hertz
279
+ mels[log_region] = min_log_mel + np.log(freq[log_region] / min_log_hertz) * logstep
280
+ elif freq >= min_log_hertz:
281
+ mels = min_log_mel + np.log(freq / min_log_hertz) * logstep
282
+
283
+ return mels
284
+
285
+
286
+ def mel_to_hertz(mels: Union[float, np.ndarray], mel_scale: str = "htk") -> Union[float, np.ndarray]:
287
+ """
288
+ Convert frequency from mels to hertz.
289
+
290
+ Args:
291
+ mels (`float` or `np.ndarray`):
292
+ The frequency, or multiple frequencies, in mels.
293
+ mel_scale (`str`, *optional*, `"htk"`):
294
+ The mel frequency scale to use, `"htk"`, `"kaldi"` or `"slaney"`.
295
+
296
+ Returns:
297
+ `float` or `np.ndarray`: The frequencies in hertz.
298
+ """
299
+
300
+ if mel_scale not in ["slaney", "htk", "kaldi"]:
301
+ raise ValueError('mel_scale should be one of "htk", "slaney" or "kaldi".')
302
+
303
+ if mel_scale == "htk":
304
+ return 700.0 * (np.power(10, mels / 2595.0) - 1.0)
305
+ elif mel_scale == "kaldi":
306
+ return 700.0 * (np.exp(mels / 1127.0) - 1.0)
307
+
308
+ min_log_hertz = 1000.0
309
+ min_log_mel = 15.0
310
+ logstep = np.log(6.4) / 27.0
311
+ freq = 200.0 * mels / 3.0
312
+
313
+ if isinstance(mels, np.ndarray):
314
+ log_region = mels >= min_log_mel
315
+ freq[log_region] = min_log_hertz * np.exp(logstep * (mels[log_region] - min_log_mel))
316
+ elif mels >= min_log_mel:
317
+ freq = min_log_hertz * np.exp(logstep * (mels - min_log_mel))
318
+
319
+ return freq
320
+
321
+
322
+ def hertz_to_octave(freq: Union[float, np.ndarray], tuning: float = 0.0, bins_per_octave: int = 12):
323
+ """
324
+ Convert frequency from hertz to fractional octave numbers.
325
+ Adapted from *librosa*.
326
+
327
+ Args:
328
+ freq (`float` or `np.ndarray`):
329
+ The frequency, or multiple frequencies, in hertz (Hz).
330
+ tuning (`float`, defaults to `0.`):
331
+ Tuning deviation from the Stuttgart pitch (A440) in (fractional) bins per octave.
332
+ bins_per_octave (`int`, defaults to `12`):
333
+ Number of bins per octave.
334
+
335
+ Returns:
336
+ `float` or `np.ndarray`: The frequencies on the octave scale.
337
+ """
338
+ stuttgart_pitch = 440.0 * 2.0 ** (tuning / bins_per_octave)
339
+ octave = np.log2(freq / (float(stuttgart_pitch) / 16))
340
+ return octave
341
+
342
+
343
+ def _create_triangular_filter_bank(fft_freqs: np.ndarray, filter_freqs: np.ndarray) -> np.ndarray:
344
+ """
345
+ Creates a triangular filter bank.
346
+
347
+ Adapted from *torchaudio* and *librosa*.
348
+
349
+ Args:
350
+ fft_freqs (`np.ndarray` of shape `(num_frequency_bins,)`):
351
+ Discrete frequencies of the FFT bins in Hz.
352
+ filter_freqs (`np.ndarray` of shape `(num_mel_filters,)`):
353
+ Center frequencies of the triangular filters to create, in Hz.
354
+
355
+ Returns:
356
+ `np.ndarray` of shape `(num_frequency_bins, num_mel_filters)`
357
+ """
358
+ filter_diff = np.diff(filter_freqs)
359
+ slopes = np.expand_dims(filter_freqs, 0) - np.expand_dims(fft_freqs, 1)
360
+ down_slopes = -slopes[:, :-2] / filter_diff[:-1]
361
+ up_slopes = slopes[:, 2:] / filter_diff[1:]
362
+ return np.maximum(np.zeros(1), np.minimum(down_slopes, up_slopes))
363
+
364
+
365
+ def chroma_filter_bank(
366
+ num_frequency_bins: int,
367
+ num_chroma: int,
368
+ sampling_rate: int,
369
+ tuning: float = 0.0,
370
+ power: Optional[float] = 2.0,
371
+ weighting_parameters: Optional[tuple[float, float]] = (5.0, 2.0),
372
+ start_at_c_chroma: bool = True,
373
+ ):
374
+ """
375
+ Creates a chroma filter bank, i.e a linear transformation to project spectrogram bins onto chroma bins.
376
+
377
+ Adapted from *librosa*.
378
+
379
+ Args:
380
+ num_frequency_bins (`int`):
381
+ Number of frequencies used to compute the spectrogram (should be the same as in `stft`).
382
+ num_chroma (`int`):
383
+ Number of chroma bins (i.e pitch classes).
384
+ sampling_rate (`float`):
385
+ Sample rate of the audio waveform.
386
+ tuning (`float`):
387
+ Tuning deviation from A440 in fractions of a chroma bin.
388
+ power (`float`, *optional*, defaults to 2.0):
389
+ If 12.0, normalizes each column with their L2 norm. If 1.0, normalizes each column with their L1 norm.
390
+ weighting_parameters (`tuple[float, float]`, *optional*, defaults to `(5., 2.)`):
391
+ If specified, apply a Gaussian weighting parameterized by the first element of the tuple being the center and
392
+ the second element being the Gaussian half-width.
393
+ start_at_c_chroma (`bool`, *optional*, defaults to `True`):
394
+ If True, the filter bank will start at the 'C' pitch class. Otherwise, it will start at 'A'.
395
+ Returns:
396
+ `np.ndarray` of shape `(num_frequency_bins, num_chroma)`
397
+ """
398
+ # Get the FFT bins, not counting the DC component
399
+ frequencies = np.linspace(0, sampling_rate, num_frequency_bins, endpoint=False)[1:]
400
+
401
+ freq_bins = num_chroma * hertz_to_octave(frequencies, tuning=tuning, bins_per_octave=num_chroma)
402
+
403
+ # make up a value for the 0 Hz bin = 1.5 octaves below bin 1
404
+ # (so chroma is 50% rotated from bin 1, and bin width is broad)
405
+ freq_bins = np.concatenate(([freq_bins[0] - 1.5 * num_chroma], freq_bins))
406
+
407
+ bins_width = np.concatenate((np.maximum(freq_bins[1:] - freq_bins[:-1], 1.0), [1]))
408
+
409
+ chroma_filters = np.subtract.outer(freq_bins, np.arange(0, num_chroma, dtype="d")).T
410
+
411
+ num_chroma2 = np.round(float(num_chroma) / 2)
412
+
413
+ # Project into range -num_chroma/2 .. num_chroma/2
414
+ # add on fixed offset of 10*num_chroma to ensure all values passed to
415
+ # rem are positive
416
+ chroma_filters = np.remainder(chroma_filters + num_chroma2 + 10 * num_chroma, num_chroma) - num_chroma2
417
+
418
+ # Gaussian bumps - 2*D to make them narrower
419
+ chroma_filters = np.exp(-0.5 * (2 * chroma_filters / np.tile(bins_width, (num_chroma, 1))) ** 2)
420
+
421
+ # normalize each column
422
+ if power is not None:
423
+ chroma_filters = chroma_filters / np.sum(chroma_filters**power, axis=0, keepdims=True) ** (1.0 / power)
424
+
425
+ # Maybe apply scaling for fft bins
426
+ if weighting_parameters is not None:
427
+ center, half_width = weighting_parameters
428
+ chroma_filters *= np.tile(
429
+ np.exp(-0.5 * (((freq_bins / num_chroma - center) / half_width) ** 2)),
430
+ (num_chroma, 1),
431
+ )
432
+
433
+ if start_at_c_chroma:
434
+ chroma_filters = np.roll(chroma_filters, -3 * (num_chroma // 12), axis=0)
435
+
436
+ # remove aliasing columns, copy to ensure row-contiguity
437
+ return np.ascontiguousarray(chroma_filters[:, : int(1 + num_frequency_bins / 2)])
438
+
439
+
440
+ def mel_filter_bank(
441
+ num_frequency_bins: int,
442
+ num_mel_filters: int,
443
+ min_frequency: float,
444
+ max_frequency: float,
445
+ sampling_rate: int,
446
+ norm: Optional[str] = None,
447
+ mel_scale: str = "htk",
448
+ triangularize_in_mel_space: bool = False,
449
+ ) -> np.ndarray:
450
+ """
451
+ Creates a frequency bin conversion matrix used to obtain a mel spectrogram. This is called a *mel filter bank*, and
452
+ various implementation exist, which differ in the number of filters, the shape of the filters, the way the filters
453
+ are spaced, the bandwidth of the filters, and the manner in which the spectrum is warped. The goal of these
454
+ features is to approximate the non-linear human perception of the variation in pitch with respect to the frequency.
455
+
456
+ Different banks of mel filters were introduced in the literature. The following variations are supported:
457
+
458
+ - MFCC FB-20: introduced in 1980 by Davis and Mermelstein, it assumes a sampling frequency of 10 kHz and a speech
459
+ bandwidth of `[0, 4600]` Hz.
460
+ - MFCC FB-24 HTK: from the Cambridge HMM Toolkit (HTK) (1995) uses a filter bank of 24 filters for a speech
461
+ bandwidth of `[0, 8000]` Hz. This assumes sampling rate ≥ 16 kHz.
462
+ - MFCC FB-40: from the Auditory Toolbox for MATLAB written by Slaney in 1998, assumes a sampling rate of 16 kHz and
463
+ speech bandwidth of `[133, 6854]` Hz. This version also includes area normalization.
464
+ - HFCC-E FB-29 (Human Factor Cepstral Coefficients) of Skowronski and Harris (2004), assumes a sampling rate of
465
+ 12.5 kHz and speech bandwidth of `[0, 6250]` Hz.
466
+
467
+ This code is adapted from *torchaudio* and *librosa*. Note that the default parameters of torchaudio's
468
+ `melscale_fbanks` implement the `"htk"` filters while librosa uses the `"slaney"` implementation.
469
+
470
+ Args:
471
+ num_frequency_bins (`int`):
472
+ Number of frequency bins (should be the same as `n_fft // 2 + 1` where `n_fft` is the size of the Fourier Transform used to compute the spectrogram).
473
+ num_mel_filters (`int`):
474
+ Number of mel filters to generate.
475
+ min_frequency (`float`):
476
+ Lowest frequency of interest in Hz.
477
+ max_frequency (`float`):
478
+ Highest frequency of interest in Hz. This should not exceed `sampling_rate / 2`.
479
+ sampling_rate (`int`):
480
+ Sample rate of the audio waveform.
481
+ norm (`str`, *optional*):
482
+ If `"slaney"`, divide the triangular mel weights by the width of the mel band (area normalization).
483
+ mel_scale (`str`, *optional*, defaults to `"htk"`):
484
+ The mel frequency scale to use, `"htk"`, `"kaldi"` or `"slaney"`.
485
+ triangularize_in_mel_space (`bool`, *optional*, defaults to `False`):
486
+ If this option is enabled, the triangular filter is applied in mel space rather than frequency space. This
487
+ should be set to `true` in order to get the same results as `torchaudio` when computing mel filters.
488
+
489
+ Returns:
490
+ `np.ndarray` of shape (`num_frequency_bins`, `num_mel_filters`): Triangular filter bank matrix. This is a
491
+ projection matrix to go from a spectrogram to a mel spectrogram.
492
+ """
493
+ if norm is not None and norm != "slaney":
494
+ raise ValueError('norm must be one of None or "slaney"')
495
+
496
+ if num_frequency_bins < 2:
497
+ raise ValueError(f"Require num_frequency_bins: {num_frequency_bins} >= 2")
498
+
499
+ if min_frequency > max_frequency:
500
+ raise ValueError(f"Require min_frequency: {min_frequency} <= max_frequency: {max_frequency}")
501
+
502
+ # center points of the triangular mel filters
503
+ mel_min = hertz_to_mel(min_frequency, mel_scale=mel_scale)
504
+ mel_max = hertz_to_mel(max_frequency, mel_scale=mel_scale)
505
+ mel_freqs = np.linspace(mel_min, mel_max, num_mel_filters + 2)
506
+ filter_freqs = mel_to_hertz(mel_freqs, mel_scale=mel_scale)
507
+
508
+ if triangularize_in_mel_space:
509
+ # frequencies of FFT bins in Hz, but filters triangularized in mel space
510
+ fft_bin_width = sampling_rate / ((num_frequency_bins - 1) * 2)
511
+ fft_freqs = hertz_to_mel(fft_bin_width * np.arange(num_frequency_bins), mel_scale=mel_scale)
512
+ filter_freqs = mel_freqs
513
+ else:
514
+ # frequencies of FFT bins in Hz
515
+ fft_freqs = np.linspace(0, sampling_rate // 2, num_frequency_bins)
516
+
517
+ mel_filters = _create_triangular_filter_bank(fft_freqs, filter_freqs)
518
+
519
+ if norm is not None and norm == "slaney":
520
+ # Slaney-style mel is scaled to be approx constant energy per channel
521
+ enorm = 2.0 / (filter_freqs[2 : num_mel_filters + 2] - filter_freqs[:num_mel_filters])
522
+ mel_filters *= np.expand_dims(enorm, 0)
523
+
524
+ if (mel_filters.max(axis=0) == 0.0).any():
525
+ warnings.warn(
526
+ "At least one mel filter has all zero values. "
527
+ f"The value for `num_mel_filters` ({num_mel_filters}) may be set too high. "
528
+ f"Or, the value for `num_frequency_bins` ({num_frequency_bins}) may be set too low."
529
+ )
530
+
531
+ return mel_filters
532
+
533
+
534
+ def optimal_fft_length(window_length: int) -> int:
535
+ """
536
+ Finds the best FFT input size for a given `window_length`. This function takes a given window length and, if not
537
+ already a power of two, rounds it up to the next power or two.
538
+
539
+ The FFT algorithm works fastest when the length of the input is a power of two, which may be larger than the size
540
+ of the window or analysis frame. For example, if the window is 400 samples, using an FFT input size of 512 samples
541
+ is more optimal than an FFT size of 400 samples. Using a larger FFT size does not affect the detected frequencies,
542
+ it simply gives a higher frequency resolution (i.e. the frequency bins are smaller).
543
+ """
544
+ return 2 ** int(np.ceil(np.log2(window_length)))
545
+
546
+
547
+ def window_function(
548
+ window_length: int,
549
+ name: str = "hann",
550
+ periodic: bool = True,
551
+ frame_length: Optional[int] = None,
552
+ center: bool = True,
553
+ ) -> np.ndarray:
554
+ """
555
+ Returns an array containing the specified window. This window is intended to be used with `stft`.
556
+
557
+ The following window types are supported:
558
+
559
+ - `"boxcar"`: a rectangular window
560
+ - `"hamming"`: the Hamming window
561
+ - `"hann"`: the Hann window
562
+ - `"povey"`: the Povey window
563
+
564
+ Args:
565
+ window_length (`int`):
566
+ The length of the window in samples.
567
+ name (`str`, *optional*, defaults to `"hann"`):
568
+ The name of the window function.
569
+ periodic (`bool`, *optional*, defaults to `True`):
570
+ Whether the window is periodic or symmetric.
571
+ frame_length (`int`, *optional*):
572
+ The length of the analysis frames in samples. Provide a value for `frame_length` if the window is smaller
573
+ than the frame length, so that it will be zero-padded.
574
+ center (`bool`, *optional*, defaults to `True`):
575
+ Whether to center the window inside the FFT buffer. Only used when `frame_length` is provided.
576
+
577
+ Returns:
578
+ `np.ndarray` of shape `(window_length,)` or `(frame_length,)` containing the window.
579
+ """
580
+ length = window_length + 1 if periodic else window_length
581
+
582
+ if name == "boxcar":
583
+ window = np.ones(length)
584
+ elif name in ["hamming", "hamming_window"]:
585
+ window = np.hamming(length)
586
+ elif name in ["hann", "hann_window"]:
587
+ window = np.hanning(length)
588
+ elif name == "povey":
589
+ window = np.power(np.hanning(length), 0.85)
590
+ else:
591
+ raise ValueError(f"Unknown window function '{name}'")
592
+
593
+ if periodic:
594
+ window = window[:-1]
595
+
596
+ if frame_length is None:
597
+ return window
598
+
599
+ if window_length > frame_length:
600
+ raise ValueError(
601
+ f"Length of the window ({window_length}) may not be larger than frame_length ({frame_length})"
602
+ )
603
+
604
+ padded_window = np.zeros(frame_length)
605
+ offset = (frame_length - window_length) // 2 if center else 0
606
+ padded_window[offset : offset + window_length] = window
607
+ return padded_window
608
+
609
+
610
+ # TODO This method does not support batching yet as we are mainly focused on inference.
611
+ def spectrogram(
612
+ waveform: np.ndarray,
613
+ window: np.ndarray,
614
+ frame_length: int,
615
+ hop_length: int,
616
+ fft_length: Optional[int] = None,
617
+ power: Optional[float] = 1.0,
618
+ center: bool = True,
619
+ pad_mode: str = "reflect",
620
+ onesided: bool = True,
621
+ dither: float = 0.0,
622
+ preemphasis: Optional[float] = None,
623
+ mel_filters: Optional[np.ndarray] = None,
624
+ mel_floor: float = 1e-10,
625
+ log_mel: Optional[str] = None,
626
+ reference: float = 1.0,
627
+ min_value: float = 1e-10,
628
+ db_range: Optional[float] = None,
629
+ remove_dc_offset: bool = False,
630
+ dtype: np.dtype = np.float32,
631
+ ) -> np.ndarray:
632
+ """
633
+ Calculates a spectrogram over one waveform using the Short-Time Fourier Transform.
634
+
635
+ This function can create the following kinds of spectrograms:
636
+
637
+ - amplitude spectrogram (`power = 1.0`)
638
+ - power spectrogram (`power = 2.0`)
639
+ - complex-valued spectrogram (`power = None`)
640
+ - log spectrogram (use `log_mel` argument)
641
+ - mel spectrogram (provide `mel_filters`)
642
+ - log-mel spectrogram (provide `mel_filters` and `log_mel`)
643
+
644
+ How this works:
645
+
646
+ 1. The input waveform is split into frames of size `frame_length` that are partially overlapping by `frame_length
647
+ - hop_length` samples.
648
+ 2. Each frame is multiplied by the window and placed into a buffer of size `fft_length`.
649
+ 3. The DFT is taken of each windowed frame.
650
+ 4. The results are stacked into a spectrogram.
651
+
652
+ We make a distinction between the following "blocks" of sample data, each of which may have a different lengths:
653
+
654
+ - The analysis frame. This is the size of the time slices that the input waveform is split into.
655
+ - The window. Each analysis frame is multiplied by the window to avoid spectral leakage.
656
+ - The FFT input buffer. The length of this determines how many frequency bins are in the spectrogram.
657
+
658
+ In this implementation, the window is assumed to be zero-padded to have the same size as the analysis frame. A
659
+ padded window can be obtained from `window_function()`. The FFT input buffer may be larger than the analysis frame,
660
+ typically the next power of two.
661
+
662
+ Note: This function is not optimized for speed yet. It should be mostly compatible with `librosa.stft` and
663
+ `torchaudio.functional.transforms.Spectrogram`, although it is more flexible due to the different ways spectrograms
664
+ can be constructed.
665
+
666
+ Args:
667
+ waveform (`np.ndarray` of shape `(length,)`):
668
+ The input waveform. This must be a single real-valued, mono waveform.
669
+ window (`np.ndarray` of shape `(frame_length,)`):
670
+ The windowing function to apply, including zero-padding if necessary. The actual window length may be
671
+ shorter than `frame_length`, but we're assuming the array has already been zero-padded.
672
+ frame_length (`int`):
673
+ The length of the analysis frames in samples. With librosa this is always equal to `fft_length` but we also
674
+ allow smaller sizes.
675
+ hop_length (`int`):
676
+ The stride between successive analysis frames in samples.
677
+ fft_length (`int`, *optional*):
678
+ The size of the FFT buffer in samples. This determines how many frequency bins the spectrogram will have.
679
+ For optimal speed, this should be a power of two. If `None`, uses `frame_length`.
680
+ power (`float`, *optional*, defaults to 1.0):
681
+ If 1.0, returns the amplitude spectrogram. If 2.0, returns the power spectrogram. If `None`, returns
682
+ complex numbers.
683
+ center (`bool`, *optional*, defaults to `True`):
684
+ Whether to pad the waveform so that frame `t` is centered around time `t * hop_length`. If `False`, frame
685
+ `t` will start at time `t * hop_length`.
686
+ pad_mode (`str`, *optional*, defaults to `"reflect"`):
687
+ Padding mode used when `center` is `True`. Possible values are: `"constant"` (pad with zeros), `"edge"`
688
+ (pad with edge values), `"reflect"` (pads with mirrored values).
689
+ onesided (`bool`, *optional*, defaults to `True`):
690
+ If True, only computes the positive frequencies and returns a spectrogram containing `fft_length // 2 + 1`
691
+ frequency bins. If False, also computes the negative frequencies and returns `fft_length` frequency bins.
692
+ dither (`float`, *optional*, defaults to 0.0):
693
+ Adds dithering. In other words, adds a small Gaussian noise to each frame.
694
+ E.g. use 4.0 to add dithering with a normal distribution centered
695
+ around 0.0 with standard deviation 4.0, 0.0 means no dithering.
696
+ Dithering has similar effect as `mel_floor`. It reduces the high log_mel_fbank
697
+ values for signals with hard-zero sections, when VAD cutoff is present in the signal.
698
+ preemphasis (`float`, *optional*)
699
+ Coefficient for a low-pass filter that applies pre-emphasis before the DFT.
700
+ mel_filters (`np.ndarray` of shape `(num_freq_bins, num_mel_filters)`, *optional*):
701
+ The mel filter bank. If supplied, applies a this filter bank to create a mel spectrogram.
702
+ mel_floor (`float`, *optional*, defaults to 1e-10):
703
+ Minimum value of mel frequency banks.
704
+ log_mel (`str`, *optional*):
705
+ How to convert the spectrogram to log scale. Possible options are: `None` (don't convert), `"log"` (take
706
+ the natural logarithm) `"log10"` (take the base-10 logarithm), `"dB"` (convert to decibels). Can only be
707
+ used when `power` is not `None`.
708
+ reference (`float`, *optional*, defaults to 1.0):
709
+ Sets the input spectrogram value that corresponds to 0 dB. For example, use `np.max(spectrogram)` to set
710
+ the loudest part to 0 dB. Must be greater than zero.
711
+ min_value (`float`, *optional*, defaults to `1e-10`):
712
+ The spectrogram will be clipped to this minimum value before conversion to decibels, to avoid taking
713
+ `log(0)`. For a power spectrogram, the default of `1e-10` corresponds to a minimum of -100 dB. For an
714
+ amplitude spectrogram, the value `1e-5` corresponds to -100 dB. Must be greater than zero.
715
+ db_range (`float`, *optional*):
716
+ Sets the maximum dynamic range in decibels. For example, if `db_range = 80`, the difference between the
717
+ peak value and the smallest value will never be more than 80 dB. Must be greater than zero.
718
+ remove_dc_offset (`bool`, *optional*):
719
+ Subtract mean from waveform on each frame, applied before pre-emphasis. This should be set to `true` in
720
+ order to get the same results as `torchaudio.compliance.kaldi.fbank` when computing mel filters.
721
+ dtype (`np.dtype`, *optional*, defaults to `np.float32`):
722
+ Data type of the spectrogram tensor. If `power` is None, this argument is ignored and the dtype will be
723
+ `np.complex64`.
724
+
725
+ Returns:
726
+ `nd.array` containing a spectrogram of shape `(num_frequency_bins, length)` for a regular spectrogram or shape
727
+ `(num_mel_filters, length)` for a mel spectrogram.
728
+ """
729
+ window_length = len(window)
730
+
731
+ if fft_length is None:
732
+ fft_length = frame_length
733
+
734
+ if frame_length > fft_length:
735
+ raise ValueError(f"frame_length ({frame_length}) may not be larger than fft_length ({fft_length})")
736
+
737
+ if window_length != frame_length:
738
+ raise ValueError(f"Length of the window ({window_length}) must equal frame_length ({frame_length})")
739
+
740
+ if hop_length <= 0:
741
+ raise ValueError("hop_length must be greater than zero")
742
+
743
+ if waveform.ndim != 1:
744
+ raise ValueError(f"Input waveform must have only one dimension, shape is {waveform.shape}")
745
+
746
+ if np.iscomplexobj(waveform):
747
+ raise ValueError("Complex-valued input waveforms are not currently supported")
748
+
749
+ if power is None and mel_filters is not None:
750
+ raise ValueError(
751
+ "You have provided `mel_filters` but `power` is `None`. Mel spectrogram computation is not yet supported for complex-valued spectrogram."
752
+ "Specify `power` to fix this issue."
753
+ )
754
+
755
+ # center pad the waveform
756
+ if center:
757
+ padding = [(int(frame_length // 2), int(frame_length // 2))]
758
+ waveform = np.pad(waveform, padding, mode=pad_mode)
759
+
760
+ # promote to float64, since np.fft uses float64 internally
761
+ waveform = waveform.astype(np.float64)
762
+ window = window.astype(np.float64)
763
+
764
+ # split waveform into frames of frame_length size
765
+ num_frames = int(1 + np.floor((waveform.size - frame_length) / hop_length))
766
+
767
+ num_frequency_bins = (fft_length // 2) + 1 if onesided else fft_length
768
+ spectrogram = np.empty((num_frames, num_frequency_bins), dtype=np.complex64)
769
+
770
+ # rfft is faster than fft
771
+ fft_func = np.fft.rfft if onesided else np.fft.fft
772
+ buffer = np.zeros(fft_length)
773
+
774
+ timestep = 0
775
+ for frame_idx in range(num_frames):
776
+ buffer[:frame_length] = waveform[timestep : timestep + frame_length]
777
+
778
+ if dither != 0.0:
779
+ buffer[:frame_length] += dither * np.random.randn(frame_length)
780
+
781
+ if remove_dc_offset:
782
+ buffer[:frame_length] = buffer[:frame_length] - buffer[:frame_length].mean()
783
+
784
+ if preemphasis is not None:
785
+ buffer[1:frame_length] -= preemphasis * buffer[: frame_length - 1]
786
+ buffer[0] *= 1 - preemphasis
787
+
788
+ buffer[:frame_length] *= window
789
+
790
+ spectrogram[frame_idx] = fft_func(buffer)
791
+ timestep += hop_length
792
+
793
+ # note: ** is much faster than np.power
794
+ if power is not None:
795
+ spectrogram = np.abs(spectrogram, dtype=np.float64) ** power
796
+
797
+ spectrogram = spectrogram.T
798
+
799
+ if mel_filters is not None:
800
+ spectrogram = np.maximum(mel_floor, np.dot(mel_filters.T, spectrogram))
801
+
802
+ if power is not None and log_mel is not None:
803
+ if log_mel == "log":
804
+ spectrogram = np.log(spectrogram)
805
+ elif log_mel == "log10":
806
+ spectrogram = np.log10(spectrogram)
807
+ elif log_mel == "dB":
808
+ if power == 1.0:
809
+ spectrogram = amplitude_to_db(spectrogram, reference, min_value, db_range)
810
+ elif power == 2.0:
811
+ spectrogram = power_to_db(spectrogram, reference, min_value, db_range)
812
+ else:
813
+ raise ValueError(f"Cannot use log_mel option '{log_mel}' with power {power}")
814
+ else:
815
+ raise ValueError(f"Unknown log_mel option: {log_mel}")
816
+
817
+ spectrogram = np.asarray(spectrogram, dtype)
818
+
819
+ return spectrogram
820
+
821
+
822
+ def spectrogram_batch(
823
+ waveform_list: list[np.ndarray],
824
+ window: np.ndarray,
825
+ frame_length: int,
826
+ hop_length: int,
827
+ fft_length: Optional[int] = None,
828
+ power: Optional[float] = 1.0,
829
+ center: bool = True,
830
+ pad_mode: str = "reflect",
831
+ onesided: bool = True,
832
+ dither: float = 0.0,
833
+ preemphasis: Optional[float] = None,
834
+ mel_filters: Optional[np.ndarray] = None,
835
+ mel_floor: float = 1e-10,
836
+ log_mel: Optional[str] = None,
837
+ reference: float = 1.0,
838
+ min_value: float = 1e-10,
839
+ db_range: Optional[float] = None,
840
+ remove_dc_offset: bool = False,
841
+ dtype: np.dtype = np.float32,
842
+ ) -> list[np.ndarray]:
843
+ """
844
+ Calculates spectrograms for a list of waveforms using the Short-Time Fourier Transform, optimized for batch processing.
845
+ This function extends the capabilities of the `spectrogram` function to handle multiple waveforms efficiently by leveraging broadcasting.
846
+
847
+ It supports generating various types of spectrograms:
848
+
849
+ - amplitude spectrogram (`power = 1.0`)
850
+ - power spectrogram (`power = 2.0`)
851
+ - complex-valued spectrogram (`power = None`)
852
+ - log spectrogram (use `log_mel` argument)
853
+ - mel spectrogram (provide `mel_filters`)
854
+ - log-mel spectrogram (provide `mel_filters` and `log_mel`)
855
+
856
+ How this works:
857
+
858
+ 1. The input waveform is split into frames of size `frame_length` that are partially overlapping by `frame_length
859
+ - hop_length` samples.
860
+ 2. Each frame is multiplied by the window and placed into a buffer of size `fft_length`.
861
+ 3. The DFT is taken of each windowed frame.
862
+ 4. The results are stacked into a spectrogram.
863
+
864
+ We make a distinction between the following "blocks" of sample data, each of which may have a different lengths:
865
+
866
+ - The analysis frame. This is the size of the time slices that the input waveform is split into.
867
+ - The window. Each analysis frame is multiplied by the window to avoid spectral leakage.
868
+ - The FFT input buffer. The length of this determines how many frequency bins are in the spectrogram.
869
+
870
+ In this implementation, the window is assumed to be zero-padded to have the same size as the analysis frame. A
871
+ padded window can be obtained from `window_function()`. The FFT input buffer may be larger than the analysis frame,
872
+ typically the next power of two.
873
+
874
+ Note: This function is designed for efficient batch processing of multiple waveforms but retains compatibility with individual waveform processing methods like `librosa.stft`.
875
+
876
+ Args:
877
+ waveform_list (`list[np.ndarray]` with arrays of shape `(length,)`):
878
+ The list of input waveforms, each a single-channel (mono) signal.
879
+ window (`np.ndarray` of shape `(frame_length,)`):
880
+ The windowing function to apply, including zero-padding if necessary.
881
+ frame_length (`int`):
882
+ The length of each frame for analysis.
883
+ hop_length (`int`):
884
+ The step size between successive frames.
885
+ fft_length (`int`, *optional*):
886
+ The size of the FFT buffer, defining frequency bin resolution.
887
+ power (`float`, *optional*, defaults to 1.0):
888
+ Determines the type of spectrogram: 1.0 for amplitude, 2.0 for power, None for complex.
889
+ center (`bool`, *optional*, defaults to `True`):
890
+ Whether to center-pad the waveform frames.
891
+ pad_mode (`str`, *optional*, defaults to `"reflect"`):
892
+ The padding strategy when `center` is `True`.
893
+ onesided (`bool`, *optional*, defaults to `True`):
894
+ If True, returns a one-sided spectrogram for real input signals.
895
+ dither (`float`, *optional*, defaults to 0.0):
896
+ Adds dithering. In other words, adds a small Gaussian noise to each frame.
897
+ E.g. use 4.0 to add dithering with a normal distribution centered
898
+ around 0.0 with standard deviation 4.0, 0.0 means no dithering.
899
+ preemphasis (`float`, *optional*):
900
+ Applies a pre-emphasis filter to each frame.
901
+ mel_filters (`np.ndarray`, *optional*):
902
+ Mel filter bank for converting to mel spectrogram.
903
+ mel_floor (`float`, *optional*, defaults to 1e-10):
904
+ Floor value for mel spectrogram to avoid log(0).
905
+ log_mel (`str`, *optional*):
906
+ Specifies log scaling strategy; options are None, "log", "log10", "dB".
907
+ reference (`float`, *optional*, defaults to 1.0):
908
+ Reference value for dB conversion in log_mel.
909
+ min_value (`float`, *optional*, defaults to 1e-10):
910
+ Minimum floor value for log scale conversions.
911
+ db_range (`float`, *optional*):
912
+ Dynamic range for dB scale spectrograms.
913
+ remove_dc_offset (`bool`, *optional*):
914
+ Whether to remove the DC offset from each frame.
915
+ dtype (`np.dtype`, *optional*, defaults to `np.float32`):
916
+ Data type of the output spectrogram.
917
+
918
+ Returns:
919
+ list[`np.ndarray`]: A list of spectrogram arrays, one for each input waveform.
920
+ """
921
+ window_length = len(window)
922
+
923
+ if fft_length is None:
924
+ fft_length = frame_length
925
+
926
+ if frame_length > fft_length:
927
+ raise ValueError(f"frame_length ({frame_length}) may not be larger than fft_length ({fft_length})")
928
+
929
+ if window_length != frame_length:
930
+ raise ValueError(f"Length of the window ({window_length}) must equal frame_length ({frame_length})")
931
+
932
+ if hop_length <= 0:
933
+ raise ValueError("hop_length must be greater than zero")
934
+
935
+ # Check the dimensions of the waveform , and if waveform is complex
936
+ for waveform in waveform_list:
937
+ if waveform.ndim != 1:
938
+ raise ValueError(f"Input waveform must have only one dimension, shape is {waveform.shape}")
939
+ if np.iscomplexobj(waveform):
940
+ raise ValueError("Complex-valued input waveforms are not currently supported")
941
+ # Center pad the waveform
942
+ if center:
943
+ padding = [(int(frame_length // 2), int(frame_length // 2))]
944
+ waveform_list = [
945
+ np.pad(
946
+ waveform,
947
+ padding,
948
+ mode=pad_mode,
949
+ )
950
+ for waveform in waveform_list
951
+ ]
952
+ original_waveform_lengths = [
953
+ len(waveform) for waveform in waveform_list
954
+ ] # these lengths will be used to remove padding later
955
+
956
+ # Batch pad the waveform
957
+ max_length = max(original_waveform_lengths)
958
+ padded_waveform_batch = np.array(
959
+ [
960
+ np.pad(waveform, (0, max_length - len(waveform)), mode="constant", constant_values=0)
961
+ for waveform in waveform_list
962
+ ],
963
+ dtype=dtype,
964
+ )
965
+
966
+ # Promote to float64, since np.fft uses float64 internally
967
+ padded_waveform_batch = padded_waveform_batch.astype(np.float64)
968
+ window = window.astype(np.float64)
969
+
970
+ # Split waveform into frames of frame_length size
971
+ num_frames = int(1 + np.floor((padded_waveform_batch.shape[1] - frame_length) / hop_length))
972
+ # these lengths will be used to remove padding later
973
+ true_num_frames = [int(1 + np.floor((length - frame_length) / hop_length)) for length in original_waveform_lengths]
974
+ num_batches = padded_waveform_batch.shape[0]
975
+
976
+ num_frequency_bins = (fft_length // 2) + 1 if onesided else fft_length
977
+ spectrogram = np.empty((num_batches, num_frames, num_frequency_bins), dtype=np.complex64)
978
+
979
+ # rfft is faster than fft
980
+ fft_func = np.fft.rfft if onesided else np.fft.fft
981
+ buffer = np.zeros((num_batches, fft_length))
982
+
983
+ for frame_idx in range(num_frames):
984
+ timestep = frame_idx * hop_length
985
+ buffer[:, :frame_length] = padded_waveform_batch[:, timestep : timestep + frame_length]
986
+
987
+ if dither != 0.0:
988
+ buffer[:, :frame_length] += dither * np.random.randn(*buffer[:, :frame_length].shape)
989
+
990
+ if remove_dc_offset:
991
+ buffer[:, :frame_length] -= buffer[:, :frame_length].mean(axis=1, keepdims=True)
992
+
993
+ if preemphasis is not None:
994
+ buffer[:, 1:frame_length] -= preemphasis * buffer[:, : frame_length - 1]
995
+ buffer[:, 0] *= 1 - preemphasis
996
+
997
+ buffer[:, :frame_length] *= window
998
+
999
+ spectrogram[:, frame_idx] = fft_func(buffer)
1000
+
1001
+ # Note: ** is much faster than np.power
1002
+ if power is not None:
1003
+ spectrogram = np.abs(spectrogram, dtype=np.float64) ** power
1004
+
1005
+ # Apply mel filters if provided
1006
+ if mel_filters is not None:
1007
+ result = np.tensordot(spectrogram, mel_filters.T, axes=([2], [1]))
1008
+ spectrogram = np.maximum(mel_floor, result)
1009
+
1010
+ # Convert to log scale if specified
1011
+ if power is not None and log_mel is not None:
1012
+ if log_mel == "log":
1013
+ spectrogram = np.log(spectrogram)
1014
+ elif log_mel == "log10":
1015
+ spectrogram = np.log10(spectrogram)
1016
+ elif log_mel == "dB":
1017
+ if power == 1.0:
1018
+ spectrogram = amplitude_to_db_batch(spectrogram, reference, min_value, db_range)
1019
+ elif power == 2.0:
1020
+ spectrogram = power_to_db_batch(spectrogram, reference, min_value, db_range)
1021
+ else:
1022
+ raise ValueError(f"Cannot use log_mel option '{log_mel}' with power {power}")
1023
+ else:
1024
+ raise ValueError(f"Unknown log_mel option: {log_mel}")
1025
+
1026
+ spectrogram = np.asarray(spectrogram, dtype)
1027
+
1028
+ spectrogram_list = [spectrogram[i, : true_num_frames[i], :].T for i in range(len(true_num_frames))]
1029
+
1030
+ return spectrogram_list
1031
+
1032
+
1033
+ def power_to_db(
1034
+ spectrogram: np.ndarray,
1035
+ reference: float = 1.0,
1036
+ min_value: float = 1e-10,
1037
+ db_range: Optional[float] = None,
1038
+ ) -> np.ndarray:
1039
+ """
1040
+ Converts a power spectrogram to the decibel scale. This computes `10 * log10(spectrogram / reference)`, using basic
1041
+ logarithm properties for numerical stability.
1042
+
1043
+ The motivation behind applying the log function on the (mel) spectrogram is that humans do not hear loudness on a
1044
+ linear scale. Generally to double the perceived volume of a sound we need to put 8 times as much energy into it.
1045
+ This means that large variations in energy may not sound all that different if the sound is loud to begin with.
1046
+ This compression operation makes the (mel) spectrogram features match more closely what humans actually hear.
1047
+
1048
+ Based on the implementation of `librosa.power_to_db`.
1049
+
1050
+ Args:
1051
+ spectrogram (`np.ndarray`):
1052
+ The input power (mel) spectrogram. Note that a power spectrogram has the amplitudes squared!
1053
+ reference (`float`, *optional*, defaults to 1.0):
1054
+ Sets the input spectrogram value that corresponds to 0 dB. For example, use `np.max(spectrogram)` to set
1055
+ the loudest part to 0 dB. Must be greater than zero.
1056
+ min_value (`float`, *optional*, defaults to `1e-10`):
1057
+ The spectrogram will be clipped to this minimum value before conversion to decibels, to avoid taking
1058
+ `log(0)`. The default of `1e-10` corresponds to a minimum of -100 dB. Must be greater than zero.
1059
+ db_range (`float`, *optional*):
1060
+ Sets the maximum dynamic range in decibels. For example, if `db_range = 80`, the difference between the
1061
+ peak value and the smallest value will never be more than 80 dB. Must be greater than zero.
1062
+
1063
+ Returns:
1064
+ `np.ndarray`: the spectrogram in decibels
1065
+ """
1066
+ if reference <= 0.0:
1067
+ raise ValueError("reference must be greater than zero")
1068
+ if min_value <= 0.0:
1069
+ raise ValueError("min_value must be greater than zero")
1070
+
1071
+ reference = max(min_value, reference)
1072
+
1073
+ spectrogram = np.clip(spectrogram, a_min=min_value, a_max=None)
1074
+ spectrogram = 10.0 * (np.log10(spectrogram) - np.log10(reference))
1075
+
1076
+ if db_range is not None:
1077
+ if db_range <= 0.0:
1078
+ raise ValueError("db_range must be greater than zero")
1079
+ spectrogram = np.clip(spectrogram, a_min=spectrogram.max() - db_range, a_max=None)
1080
+
1081
+ return spectrogram
1082
+
1083
+
1084
+ def power_to_db_batch(
1085
+ spectrogram: np.ndarray,
1086
+ reference: float = 1.0,
1087
+ min_value: float = 1e-10,
1088
+ db_range: Optional[float] = None,
1089
+ ) -> np.ndarray:
1090
+ """
1091
+ Converts a batch of power spectrograms to the decibel scale. This computes `10 * log10(spectrogram / reference)`,
1092
+ using basic logarithm properties for numerical stability.
1093
+
1094
+ This function supports batch processing, where each item in the batch is an individual power (mel) spectrogram.
1095
+
1096
+ Args:
1097
+ spectrogram (`np.ndarray`):
1098
+ The input batch of power (mel) spectrograms. Expected shape is (batch_size, *spectrogram_shape).
1099
+ Note that a power spectrogram has the amplitudes squared!
1100
+ reference (`float`, *optional*, defaults to 1.0):
1101
+ Sets the input spectrogram value that corresponds to 0 dB. For example, use `np.max(spectrogram)` to set
1102
+ the loudest part to 0 dB. Must be greater than zero.
1103
+ min_value (`float`, *optional*, defaults to `1e-10`):
1104
+ The spectrogram will be clipped to this minimum value before conversion to decibels, to avoid taking
1105
+ `log(0)`. The default of `1e-10` corresponds to a minimum of -100 dB. Must be greater than zero.
1106
+ db_range (`float`, *optional*):
1107
+ Sets the maximum dynamic range in decibels. For example, if `db_range = 80`, the difference between the
1108
+ peak value and the smallest value will never be more than 80 dB. Must be greater than zero.
1109
+
1110
+ Returns:
1111
+ `np.ndarray`: the batch of spectrograms in decibels
1112
+ """
1113
+ if reference <= 0.0:
1114
+ raise ValueError("reference must be greater than zero")
1115
+ if min_value <= 0.0:
1116
+ raise ValueError("min_value must be greater than zero")
1117
+
1118
+ reference = max(min_value, reference)
1119
+
1120
+ spectrogram = np.clip(spectrogram, a_min=min_value, a_max=None)
1121
+ spectrogram = 10.0 * (np.log10(spectrogram) - np.log10(reference))
1122
+
1123
+ if db_range is not None:
1124
+ if db_range <= 0.0:
1125
+ raise ValueError("db_range must be greater than zero")
1126
+ # Apply db_range clipping per batch item
1127
+ max_values = spectrogram.max(axis=(1, 2), keepdims=True)
1128
+ spectrogram = np.clip(spectrogram, a_min=max_values - db_range, a_max=None)
1129
+
1130
+ return spectrogram
1131
+
1132
+
1133
+ def amplitude_to_db(
1134
+ spectrogram: np.ndarray,
1135
+ reference: float = 1.0,
1136
+ min_value: float = 1e-5,
1137
+ db_range: Optional[float] = None,
1138
+ ) -> np.ndarray:
1139
+ """
1140
+ Converts an amplitude spectrogram to the decibel scale. This computes `20 * log10(spectrogram / reference)`, using
1141
+ basic logarithm properties for numerical stability.
1142
+
1143
+ The motivation behind applying the log function on the (mel) spectrogram is that humans do not hear loudness on a
1144
+ linear scale. Generally to double the perceived volume of a sound we need to put 8 times as much energy into it.
1145
+ This means that large variations in energy may not sound all that different if the sound is loud to begin with.
1146
+ This compression operation makes the (mel) spectrogram features match more closely what humans actually hear.
1147
+
1148
+ Args:
1149
+ spectrogram (`np.ndarray`):
1150
+ The input amplitude (mel) spectrogram.
1151
+ reference (`float`, *optional*, defaults to 1.0):
1152
+ Sets the input spectrogram value that corresponds to 0 dB. For example, use `np.max(spectrogram)` to set
1153
+ the loudest part to 0 dB. Must be greater than zero.
1154
+ min_value (`float`, *optional*, defaults to `1e-5`):
1155
+ The spectrogram will be clipped to this minimum value before conversion to decibels, to avoid taking
1156
+ `log(0)`. The default of `1e-5` corresponds to a minimum of -100 dB. Must be greater than zero.
1157
+ db_range (`float`, *optional*):
1158
+ Sets the maximum dynamic range in decibels. For example, if `db_range = 80`, the difference between the
1159
+ peak value and the smallest value will never be more than 80 dB. Must be greater than zero.
1160
+
1161
+ Returns:
1162
+ `np.ndarray`: the spectrogram in decibels
1163
+ """
1164
+ if reference <= 0.0:
1165
+ raise ValueError("reference must be greater than zero")
1166
+ if min_value <= 0.0:
1167
+ raise ValueError("min_value must be greater than zero")
1168
+
1169
+ reference = max(min_value, reference)
1170
+
1171
+ spectrogram = np.clip(spectrogram, a_min=min_value, a_max=None)
1172
+ spectrogram = 20.0 * (np.log10(spectrogram) - np.log10(reference))
1173
+
1174
+ if db_range is not None:
1175
+ if db_range <= 0.0:
1176
+ raise ValueError("db_range must be greater than zero")
1177
+ spectrogram = np.clip(spectrogram, a_min=spectrogram.max() - db_range, a_max=None)
1178
+
1179
+ return spectrogram
1180
+
1181
+
1182
+ def amplitude_to_db_batch(
1183
+ spectrogram: np.ndarray, reference: float = 1.0, min_value: float = 1e-5, db_range: Optional[float] = None
1184
+ ) -> np.ndarray:
1185
+ """
1186
+ Converts a batch of amplitude spectrograms to the decibel scale. This computes `20 * log10(spectrogram / reference)`,
1187
+ using basic logarithm properties for numerical stability.
1188
+
1189
+ The function supports batch processing, where each item in the batch is an individual amplitude (mel) spectrogram.
1190
+
1191
+ Args:
1192
+ spectrogram (`np.ndarray`):
1193
+ The input batch of amplitude (mel) spectrograms. Expected shape is (batch_size, *spectrogram_shape).
1194
+ reference (`float`, *optional*, defaults to 1.0):
1195
+ Sets the input spectrogram value that corresponds to 0 dB. For example, use `np.max(spectrogram)` to set
1196
+ the loudest part to 0 dB. Must be greater than zero.
1197
+ min_value (`float`, *optional*, defaults to `1e-5`):
1198
+ The spectrogram will be clipped to this minimum value before conversion to decibels, to avoid taking
1199
+ `log(0)`. The default of `1e-5` corresponds to a minimum of -100 dB. Must be greater than zero.
1200
+ db_range (`float`, *optional*):
1201
+ Sets the maximum dynamic range in decibels. For example, if `db_range = 80`, the difference between the
1202
+ peak value and the smallest value will never be more than 80 dB. Must be greater than zero.
1203
+
1204
+ Returns:
1205
+ `np.ndarray`: the batch of spectrograms in decibels
1206
+ """
1207
+ if reference <= 0.0:
1208
+ raise ValueError("reference must be greater than zero")
1209
+ if min_value <= 0.0:
1210
+ raise ValueError("min_value must be greater than zero")
1211
+
1212
+ reference = max(min_value, reference)
1213
+
1214
+ spectrogram = np.clip(spectrogram, a_min=min_value, a_max=None)
1215
+ spectrogram = 20.0 * (np.log10(spectrogram) - np.log10(reference))
1216
+
1217
+ if db_range is not None:
1218
+ if db_range <= 0.0:
1219
+ raise ValueError("db_range must be greater than zero")
1220
+ # Apply db_range clipping per batch item
1221
+ max_values = spectrogram.max(axis=(1, 2), keepdims=True)
1222
+ spectrogram = np.clip(spectrogram, a_min=max_values - db_range, a_max=None)
1223
+
1224
+ return spectrogram
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/cache_utils.py ADDED
@@ -0,0 +1,1493 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ from collections.abc import Iterable
3
+ from typing import Any, Optional
4
+
5
+ import torch
6
+
7
+ from .configuration_utils import PretrainedConfig
8
+ from .utils import (
9
+ is_hqq_available,
10
+ is_quanto_greater,
11
+ is_torch_greater_or_equal,
12
+ is_torchdynamo_compiling,
13
+ logging,
14
+ )
15
+
16
+
17
+ if is_hqq_available():
18
+ from hqq.core.quantize import Quantizer as HQQQuantizer
19
+
20
+ _is_torch_greater_or_equal_than_2_7 = is_torch_greater_or_equal("2.7", accept_dev=True)
21
+
22
+
23
+ logger = logging.get_logger(__name__)
24
+
25
+
26
+ class CacheLayerMixin(ABC):
27
+ """Base, abstract class for a single layer's cache."""
28
+
29
+ is_compileable = False
30
+
31
+ def __init__(self):
32
+ self.keys: Optional[torch.Tensor] = None
33
+ self.values: Optional[torch.Tensor] = None
34
+ self.is_initialized = False
35
+
36
+ def __repr__(self):
37
+ return f"{self.__class__.__name__}"
38
+
39
+ @abstractmethod
40
+ def lazy_initialization(self, key_states: torch.Tensor): ...
41
+
42
+ @abstractmethod
43
+ def update(
44
+ self, key_states: torch.Tensor, value_states: torch.Tensor, cache_kwargs: Optional[dict[str, Any]] = None
45
+ ) -> tuple[torch.Tensor, torch.Tensor]: ...
46
+
47
+ @abstractmethod
48
+ def get_mask_sizes(self, cache_position: torch.Tensor) -> tuple[int, int]: ...
49
+
50
+ @abstractmethod
51
+ def get_seq_length(self) -> int: ...
52
+
53
+ @abstractmethod
54
+ def get_max_cache_shape(self) -> int: ...
55
+
56
+ def offload(self):
57
+ """Offload this layer's data to CPU device."""
58
+ if self.is_initialized:
59
+ self.keys = self.keys.to("cpu", non_blocking=True)
60
+ self.values = self.values.to("cpu", non_blocking=True)
61
+
62
+ def prefetch(self):
63
+ """In case of layer offloading, this allows to move the data back to the layer's device ahead of time."""
64
+ if self.is_initialized and self.keys.device != self.device:
65
+ self.keys = self.keys.to(self.device, non_blocking=True)
66
+ self.values = self.values.to(self.device, non_blocking=True)
67
+
68
+ def reset(self) -> None:
69
+ """Resets the cache values while preserving the objects"""
70
+ if self.is_initialized:
71
+ self.keys.zero_()
72
+ self.values.zero_()
73
+ # This attribute is set on several Layers
74
+ if hasattr(self, "cumulative_length"):
75
+ self.cumulative_length = 0
76
+
77
+ def reorder_cache(self, beam_idx: torch.LongTensor) -> None:
78
+ """Reorders this layer's cache for beam search."""
79
+ if self.get_seq_length() > 0:
80
+ self.keys = self.keys.index_select(0, beam_idx.to(self.keys.device))
81
+ self.values = self.values.index_select(0, beam_idx.to(self.values.device))
82
+
83
+
84
+ class DynamicLayer(CacheLayerMixin):
85
+ """
86
+ A cache layer that grows dynamically as more tokens are generated. This is the default for generative models.
87
+ It stores the key and value states as tensors of shape `[batch_size, num_heads, seq_len, head_dim]`.
88
+ """
89
+
90
+ is_sliding = False
91
+
92
+ def lazy_initialization(self, key_states: torch.Tensor):
93
+ self.dtype, self.device = key_states.dtype, key_states.device
94
+ self.keys = torch.tensor([], dtype=self.dtype, device=self.device)
95
+ self.values = torch.tensor([], dtype=self.dtype, device=self.device)
96
+ self.is_initialized = True
97
+
98
+ def update(
99
+ self,
100
+ key_states: torch.Tensor,
101
+ value_states: torch.Tensor,
102
+ cache_kwargs: Optional[dict[str, Any]] = None,
103
+ ) -> tuple[torch.Tensor, torch.Tensor]:
104
+ """
105
+ Update the key and value caches in-place, and return the necessary keys and value states.
106
+
107
+ Args:
108
+ key_states (`torch.Tensor`): The new key states to cache.
109
+ value_states (`torch.Tensor`): The new value states to cache.
110
+ cache_kwargs (`dict[str, Any]`, *optional*): Additional arguments for the cache.
111
+
112
+ Returns:
113
+ tuple[`torch.Tensor`, `torch.Tensor`]: The key and value states.
114
+ """
115
+ # Lazy initialization
116
+ if not self.is_initialized:
117
+ self.lazy_initialization(key_states)
118
+
119
+ self.keys = torch.cat([self.keys, key_states], dim=-2)
120
+ self.values = torch.cat([self.values, value_states], dim=-2)
121
+ return self.keys, self.values
122
+
123
+ def get_mask_sizes(self, cache_position: torch.Tensor) -> tuple[int, int]:
124
+ """Return the length and offset of the cache, used to generate the mask"""
125
+ kv_offset = 0
126
+ query_length = cache_position.shape[0]
127
+ kv_length = self.get_seq_length() + query_length
128
+ return kv_length, kv_offset
129
+
130
+ def get_seq_length(self) -> int:
131
+ """Returns the sequence length of the cached states."""
132
+ if not self.is_initialized or self.keys.numel() == 0:
133
+ return 0
134
+ return self.keys.shape[-2]
135
+
136
+ def get_max_cache_shape(self) -> int:
137
+ """Returns the maximum sequence length of the cache object. DynamicLayer does not have a maximum length."""
138
+ return -1
139
+
140
+ def crop(self, max_length: int) -> None:
141
+ """
142
+ Crop the past key values up to a new `max_length` in terms of tokens. `max_length` can also be negative
143
+ to remove `max_length` tokens.
144
+ """
145
+ if max_length < 0:
146
+ max_length = self.get_seq_length() - abs(max_length)
147
+
148
+ if self.get_seq_length() <= max_length:
149
+ return
150
+
151
+ self.keys = self.keys[..., :max_length, :]
152
+ self.values = self.values[..., :max_length, :]
153
+
154
+ def batch_repeat_interleave(self, repeats: int) -> None:
155
+ """Repeat the cache `repeats` times in the batch dimension."""
156
+ if self.get_seq_length() > 0:
157
+ self.keys = self.keys.repeat_interleave(repeats, dim=0)
158
+ self.values = self.values.repeat_interleave(repeats, dim=0)
159
+
160
+ def batch_select_indices(self, indices: torch.Tensor) -> None:
161
+ """Only keep the `indices` in the batch dimension of the cache."""
162
+ if self.get_seq_length() > 0:
163
+ self.keys = self.keys[indices, ...]
164
+ self.values = self.values[indices, ...]
165
+
166
+
167
+ class DynamicSlidingWindowLayer(DynamicLayer):
168
+ """
169
+ A cache layer that grows dynamically as more tokens are generated, up until the sliding window size.
170
+ It stores the key and value states as tensors of shape `[batch_size, num_heads, min(seq_len, sliding_window), head_dim]`.
171
+ """
172
+
173
+ is_sliding = True
174
+
175
+ def __init__(self, sliding_window: int):
176
+ super().__init__()
177
+ self.sliding_window = sliding_window
178
+ self.cumulative_length = 0
179
+
180
+ def update(
181
+ self,
182
+ key_states: torch.Tensor,
183
+ value_states: torch.Tensor,
184
+ cache_kwargs: Optional[dict[str, Any]] = None,
185
+ ) -> tuple[torch.Tensor, torch.Tensor]:
186
+ """
187
+ Update the key and value caches in-place, and return the necessary keys and value states.
188
+
189
+ Args:
190
+ key_states (`torch.Tensor`): The new key states to cache.
191
+ value_states (`torch.Tensor`): The new value states to cache.
192
+ cache_kwargs (`dict[str, Any]`, *optional*): Additional arguments for the cache.
193
+
194
+ Returns:
195
+ tuple[`torch.Tensor`, `torch.Tensor`]: The key and value states.
196
+ """
197
+ # Lazy initialization
198
+ if not self.is_initialized:
199
+ self.lazy_initialization(key_states)
200
+
201
+ self.cumulative_length += key_states.shape[-2]
202
+
203
+ # Compute the full states
204
+ full_key_states = torch.cat([self.keys, key_states], dim=-2)
205
+ full_value_states = torch.cat([self.values, value_states], dim=-2)
206
+ # Only cache the last `self.sliding_window - 1` tokens (or all of them if lower than that)
207
+ self.keys = full_key_states[:, :, -self.sliding_window + 1 :, :]
208
+ self.values = full_value_states[:, :, -self.sliding_window + 1 :, :]
209
+
210
+ # Return the full states
211
+ return full_key_states, full_value_states
212
+
213
+ def get_mask_sizes(self, cache_position: torch.Tensor) -> tuple[int, int]:
214
+ """Return the length and offset of the cache, used to generate the attention mask"""
215
+ query_length = cache_position.shape[0]
216
+ is_full = self.cumulative_length >= self.sliding_window
217
+
218
+ kv_offset = max(self.cumulative_length - self.sliding_window + 1, 0)
219
+ if is_full:
220
+ kv_length = self.sliding_window - 1 + query_length
221
+ else:
222
+ kv_length = self.cumulative_length + query_length
223
+
224
+ return kv_length, kv_offset
225
+
226
+ def get_seq_length(self) -> int:
227
+ """Returns the sequence length of the cached states."""
228
+ return self.cumulative_length
229
+
230
+ def get_max_cache_shape(self) -> int:
231
+ """Return the maximum cache shape of the cache"""
232
+ return self.sliding_window
233
+
234
+ def crop(self, max_length: int) -> None:
235
+ """
236
+ Crop the past key values up to a new `max_length` in terms of tokens. `max_length` can also be
237
+ negative to remove `max_length` tokens.
238
+ """
239
+ if self.get_seq_length() >= self.sliding_window:
240
+ raise ValueError(
241
+ "Cannot `crop` a `DynamicSlidingWindowLayer` after it has seen more tokens than its"
242
+ "sliding window (otherwise some states are lost)"
243
+ )
244
+ super().crop(max_length)
245
+ self.cumulative_length = self.keys.shape[-2]
246
+
247
+
248
+ class StaticLayer(CacheLayerMixin):
249
+ """
250
+ A static cache layer that stores the key and value states as static tensors of shape `[batch_size, num_heads, max_cache_len), head_dim]`.
251
+ It lazily allocates its full backing tensors, and then mutates them in-place. Built for `torch.compile` support.
252
+
253
+ Args:
254
+ max_cache_len (`int`):
255
+ Maximum number of tokens that can be stored, used for tensor preallocation.
256
+ """
257
+
258
+ is_compileable = True
259
+ is_sliding = False
260
+
261
+ def __init__(self, max_cache_len: int):
262
+ super().__init__()
263
+ self.max_cache_len = max_cache_len
264
+
265
+ def lazy_initialization(self, key_states: torch.Tensor):
266
+ """
267
+ Lazy initialization of the keys and values tensors. This allows to get all properties (dtype, device,
268
+ num_heads in case of TP etc...) at runtime directly, which is extremely practical as it avoids moving
269
+ devices, dtypes etc later on for each `update` (which could break the static dynamo addresses as well).
270
+
271
+ If this is unwanted, one can call `early_initialization(...)` on the Cache directly, which will call this
272
+ function ahead-of-time (this is required for `torch.export` for example). Note that for `compile`, as we
273
+ internally don't compile the prefill, this is guaranteed to have been called already when compiling.
274
+ If compiling the prefill as well, e.g. calling `model.compile(...)` before `generate` with a static cache,
275
+ it is still supported in general, but without guarantees depending on the compilation options (e.g. cuda graphs,
276
+ i.e. `mode="reduce-overhead"` is known to fail). But it will in general work correctly, and prefill should
277
+ not be compiled anyway for performances!
278
+ """
279
+ self.max_batch_size, self.num_heads, _, self.head_dim = key_states.shape
280
+ self.dtype, self.device = key_states.dtype, key_states.device
281
+
282
+ self.keys = torch.zeros(
283
+ (self.max_batch_size, self.num_heads, self.max_cache_len, self.head_dim),
284
+ dtype=self.dtype,
285
+ device=self.device,
286
+ )
287
+ self.values = torch.zeros(
288
+ (self.max_batch_size, self.num_heads, self.max_cache_len, self.head_dim),
289
+ dtype=self.dtype,
290
+ device=self.device,
291
+ )
292
+ # Note: `mark_static_address` is used to tag the cache as a fixed data pointer, preventing compiled graph
293
+ # breaks when updating the cache. However, it is not supported when tracing the graph, so we skip it in this case.
294
+ # As prefill should never be compiled, this is not an issue and it will still be run (except when users compile
295
+ # prefill explicitly, but this should be avoided!)
296
+ if not is_torchdynamo_compiling():
297
+ torch._dynamo.mark_static_address(self.keys)
298
+ torch._dynamo.mark_static_address(self.values)
299
+
300
+ self.is_initialized = True
301
+
302
+ def update(
303
+ self,
304
+ key_states: torch.Tensor,
305
+ value_states: torch.Tensor,
306
+ cache_kwargs: Optional[dict[str, Any]] = None,
307
+ ) -> tuple[torch.Tensor, torch.Tensor]:
308
+ """
309
+ Update the key and value caches in-place, and return the necessary keys and value states.
310
+
311
+ Args:
312
+ key_states (`torch.Tensor`): The new key states to cache.
313
+ value_states (`torch.Tensor`): The new value states to cache.
314
+ cache_kwargs (`dict[str, Any]`, *optional*): Additional arguments for the cache.
315
+
316
+ Returns:
317
+ tuple[`torch.Tensor`, `torch.Tensor`]: The key and value states.
318
+ """
319
+ # Lazy initialization
320
+ if not self.is_initialized:
321
+ self.lazy_initialization(key_states)
322
+
323
+ # Some old models give None for `cache_position` or even omit passing `cache_kwargs` when used as cross-attention,
324
+ # in which case we should copy the whole Layer (key_states.shape[-2] == self.max_cache_len)
325
+ cache_position = cache_kwargs.get("cache_position") if cache_kwargs is not None else None
326
+ cache_position = (
327
+ cache_position if cache_position is not None else torch.arange(key_states.shape[-2], device=self.device)
328
+ )
329
+
330
+ # Update the cache
331
+ try:
332
+ self.keys.index_copy_(2, cache_position, key_states)
333
+ self.values.index_copy_(2, cache_position, value_states)
334
+ except NotImplementedError:
335
+ # Fallback for devices like MPS where index_copy_ might not be supported.
336
+ self.keys[:, :, cache_position] = key_states
337
+ self.values[:, :, cache_position] = value_states
338
+ return self.keys, self.values
339
+
340
+ def get_mask_sizes(self, cache_position: torch.Tensor) -> tuple[int, int]:
341
+ """Return the length and offset of the cache, used to generate the attention mask"""
342
+ kv_offset = 0
343
+ kv_length = self.max_cache_len
344
+ return kv_length, kv_offset
345
+
346
+ def get_seq_length(self) -> int:
347
+ """Returns the sequence length of the cached states."""
348
+ # Occupied cache == any slot in the 3rd dim (sequence length) holds a non-zero value. To save on compute, let's
349
+ # limit the check to the first batch member and head dimension.
350
+ return (self.keys[0, 0].any(dim=-1)).sum() if self.is_initialized else 0
351
+
352
+ def get_max_cache_shape(self) -> int:
353
+ """Return the maximum cache shape of the cache"""
354
+ return self.max_cache_len
355
+
356
+
357
+ class StaticSlidingWindowLayer(StaticLayer):
358
+ """
359
+ A static cache layer that stores the key and value states as static tensors of shape
360
+ `[batch_size, num_heads, min(max_cache_len, sliding_window), head_dim]`. It lazily allocates its full backing
361
+ tensors, and then mutates them in-place. Built for `torch.compile` support.
362
+
363
+ Args:
364
+ max_cache_len (`int`):
365
+ Maximum number of tokens that can be stored, used for tensor preallocation.
366
+ sliding_window (`int`):
367
+ The size of the sliding window.
368
+ """
369
+
370
+ is_sliding = True
371
+
372
+ def __init__(self, max_cache_len: int, sliding_window: int):
373
+ effective_max_cache_len = min(sliding_window, max_cache_len)
374
+ super().__init__(max_cache_len=effective_max_cache_len)
375
+ self.cumulative_length = 0
376
+
377
+ def update(
378
+ self,
379
+ key_states: torch.Tensor,
380
+ value_states: torch.Tensor,
381
+ cache_kwargs: Optional[dict[str, Any]] = None,
382
+ ) -> tuple[torch.Tensor, torch.Tensor]:
383
+ """
384
+ Update the key and value caches in-place, and return the necessary keys and value states.
385
+
386
+ Args:
387
+ key_states (`torch.Tensor`): The new key states to cache.
388
+ value_states (`torch.Tensor`): The new value states to cache.
389
+ cache_kwargs (`dict[str, Any]`, *optional*): Additional arguments for the cache.
390
+
391
+ Returns:
392
+ tuple[`torch.Tensor`, `torch.Tensor`]: The key and value states.
393
+ """
394
+ # Lazy initialization
395
+ if not self.is_initialized:
396
+ self.lazy_initialization(key_states)
397
+
398
+ # Some old models give None for `cache_position` or even omit passing `cache_kwargs` when used as cross-attention,
399
+ # in which case we should copy the whole Layer (key_states.shape[-2] == self.max_cache_len)
400
+ cache_position = cache_kwargs.get("cache_position") if cache_kwargs is not None else None
401
+ cache_position = (
402
+ cache_position if cache_position is not None else torch.arange(key_states.shape[-2], device=self.device)
403
+ )
404
+
405
+ cumulative_length = self.cumulative_length
406
+ is_full = cumulative_length >= self.max_cache_len
407
+ # Update it now that we saved the value above
408
+ self.cumulative_length += key_states.shape[-2]
409
+
410
+ if is_full:
411
+ # In general, we should use a much simpler `cat` here as well, independently of the states size. However,
412
+ # dynamo is currently bugged when doing it - see https://github.com/pytorch/pytorch/issues/159855 for more details
413
+ if key_states.shape[-2] == 1:
414
+ # Roll all values to the left by 1 position
415
+ new_keys = self.keys.roll(-1, dims=-2)
416
+ new_values = self.values.roll(-1, dims=-2)
417
+ # Overwrite the last position with new states
418
+ # (note: very important to use a tensor to index here, see https://github.com/pytorch/pytorch/issues/159855)
419
+ index = torch.tensor([-1], dtype=int, device=self.device)
420
+ new_keys[:, :, index] = key_states
421
+ new_values[:, :, index] = value_states
422
+
423
+ # Copy back into `self` (do not just assign again) in order to keep the static dynamo address
424
+ self.keys.copy_(new_keys)
425
+ self.values.copy_(new_values)
426
+ # Very important to return the `self` tensors here, as they have the static dynamo address
427
+ return self.keys, self.values
428
+ # Already full but using more than 1 new token (e.g. prefill caching, chat continuation, etc...)
429
+ else:
430
+ full_key_states = torch.cat((self.keys[:, :, 1:, :], key_states), dim=-2)
431
+ full_value_states = torch.cat((self.values[:, :, 1:, :], value_states), dim=-2)
432
+ # Not yet full, but becoming full on this update
433
+ elif cumulative_length + key_states.shape[2] > self.max_cache_len:
434
+ # Fast prefill path, no need to cat() in this case, as the cache is currently empty
435
+ if cumulative_length == 0:
436
+ full_key_states = key_states
437
+ full_value_states = value_states
438
+ else:
439
+ full_key_states = torch.cat((self.keys[:, :, :cumulative_length, :], key_states), dim=-2)
440
+ full_value_states = torch.cat((self.values[:, :, :cumulative_length, :], value_states), dim=-2)
441
+ else:
442
+ try:
443
+ self.keys.index_copy_(2, cache_position, key_states)
444
+ self.values.index_copy_(2, cache_position, value_states)
445
+ except NotImplementedError:
446
+ self.keys[:, :, cache_position] = key_states
447
+ self.values[:, :, cache_position] = value_states
448
+
449
+ # Very important to return the `self` tensors here, as they have the static dynamo address
450
+ return self.keys, self.values
451
+
452
+ # We only cache the last `sliding_window` tokens
453
+ self.keys.copy_(full_key_states[:, :, -self.max_cache_len :, :])
454
+ self.values.copy_(full_value_states[:, :, -self.max_cache_len :, :])
455
+ # we should return the whole states instead of `self.keys/values` here, as otherwise we lose some context
456
+ return full_key_states, full_value_states
457
+
458
+ def get_mask_sizes(self, cache_position: torch.Tensor) -> tuple[int, int]:
459
+ """Return the length and offset of the cache, used to generate the attention mask"""
460
+ query_length = cache_position.shape[0]
461
+ sliding_window = self.max_cache_len
462
+ is_full = self.cumulative_length >= self.max_cache_len
463
+
464
+ kv_offset = max(self.cumulative_length - sliding_window + 1, 0)
465
+ # The cache is already full
466
+ if is_full:
467
+ kv_length = sliding_window + query_length - 1
468
+ # Not yet full, but becoming full on this update
469
+ elif self.cumulative_length + query_length > sliding_window:
470
+ kv_length = self.cumulative_length + query_length
471
+ # Here the Cache is still smaller than the local size, but we return the local size as it's static
472
+ else:
473
+ kv_length = sliding_window
474
+
475
+ return kv_length, kv_offset
476
+
477
+ def get_seq_length(self) -> int:
478
+ """Returns the sequence length of the cached states."""
479
+ return self.cumulative_length
480
+
481
+
482
+ class QuantizedLayer(DynamicLayer):
483
+ """
484
+ A quantized layer similar to what is described in the [KIVI: A Tuning-Free Asymmetric 2bit Quantization for KV Cache paper](https://huggingface.co/papers/2402.02750).
485
+ It allows the model to generate longer sequence length without allocating too much memory for the key and value caches by
486
+ applying quantization.
487
+
488
+ The cache has two types of storage, one for original precision and one for the quantized cache. A `residual length`
489
+ is set as a maximum capacity for the original precision cache. When the length goes beyond maximum capacity, the original
490
+ precision cache is discarded and moved into the quantized cache. The quantization is done per-channel with a set `q_group_size`
491
+ for both Keys and Values, in contrast to what was described in the paper.
492
+ """
493
+
494
+ def __init__(
495
+ self,
496
+ nbits: int = 4,
497
+ axis_key: int = 0,
498
+ axis_value: int = 0,
499
+ q_group_size: int = 64,
500
+ residual_length: int = 128,
501
+ ):
502
+ super().__init__()
503
+ self.nbits = nbits
504
+ self.axis_key = axis_key
505
+ self.axis_value = axis_value
506
+ self.q_group_size = q_group_size
507
+ self.residual_length = residual_length
508
+ self.cumulative_length = 0
509
+
510
+ def update(
511
+ self,
512
+ key_states: torch.Tensor,
513
+ value_states: torch.Tensor,
514
+ cache_kwargs: Optional[dict[str, Any]] = None,
515
+ ) -> tuple[torch.Tensor, torch.Tensor]:
516
+ """
517
+ Update the key and value caches in-place, and return the necessary keys and value states.
518
+
519
+ Args:
520
+ key_states (`torch.Tensor`): The new key states to cache.
521
+ value_states (`torch.Tensor`): The new value states to cache.
522
+ cache_kwargs (`dict[str, Any]`, *optional*): Additional arguments for the cache.
523
+
524
+ Returns:
525
+ tuple[`torch.Tensor`, `torch.Tensor`]: The key and value states.
526
+ """
527
+ self.cumulative_length += key_states.shape[-2]
528
+
529
+ # Lazy initialization
530
+ if not self.is_initialized:
531
+ self.lazy_initialization(key_states)
532
+ self._quantized_keys = self._quantize(key_states.contiguous(), axis=self.axis_key)
533
+ self._quantized_values = self._quantize(value_states.contiguous(), axis=self.axis_value)
534
+ return key_states, value_states
535
+
536
+ dequant_keys = self._dequantize(self._quantized_keys)
537
+ dequant_values = self._dequantize(self._quantized_values)
538
+ keys_to_return = torch.cat([dequant_keys, self.keys, key_states], dim=-2)
539
+ values_to_return = torch.cat([dequant_values, self.values, value_states], dim=-2)
540
+ if self.keys.dim() == 4 and self.keys.shape[-2] + 1 >= self.residual_length:
541
+ self._quantized_keys = self._quantize(keys_to_return.contiguous(), axis=self.axis_key)
542
+ self._quantized_values = self._quantize(values_to_return.contiguous(), axis=self.axis_value)
543
+ self.keys = torch.tensor([], dtype=key_states.dtype, device=key_states.device)
544
+ self.values = torch.tensor([], dtype=key_states.dtype, device=key_states.device)
545
+ else:
546
+ self.keys = torch.cat([self.keys, key_states], dim=-2)
547
+ self.values = torch.cat([self.values, value_states], dim=-2)
548
+
549
+ return keys_to_return, values_to_return
550
+
551
+ @abstractmethod
552
+ def _quantize(self, tensor, axis): ...
553
+
554
+ @abstractmethod
555
+ def _dequantize(self, q_tensor): ...
556
+
557
+ def get_seq_length(self) -> int:
558
+ """Returns the sequence length of the cached states."""
559
+ return self.cumulative_length
560
+
561
+
562
+ class QuantoQuantizedLayer(QuantizedLayer):
563
+ def __init__(
564
+ self,
565
+ nbits: int = 4,
566
+ axis_key: int = 0,
567
+ axis_value: int = 0,
568
+ q_group_size: int = 64,
569
+ residual_length: int = 128,
570
+ ):
571
+ super().__init__(
572
+ nbits=nbits,
573
+ axis_key=axis_key,
574
+ axis_value=axis_value,
575
+ q_group_size=q_group_size,
576
+ residual_length=residual_length,
577
+ )
578
+
579
+ # We need to import quanto here to avoid circular imports due to optimum/quanto/models/transformers_models.py
580
+ if is_quanto_greater("0.2.5", accept_dev=True):
581
+ from optimum.quanto import MaxOptimizer, qint2, qint4
582
+ else:
583
+ raise ImportError(
584
+ "You need optimum-quanto package version to be greater or equal than 0.2.5 to use `QuantoQuantizedCache`. "
585
+ )
586
+
587
+ if self.nbits not in [2, 4]:
588
+ raise ValueError(f"`nbits` for `quanto` backend has to be one of [`2`, `4`] but got {self.nbits}")
589
+
590
+ if self.axis_key not in [0, -1]:
591
+ raise ValueError(f"`axis_key` for `quanto` backend has to be one of [`0`, `-1`] but got {self.axis_key}")
592
+
593
+ if self.axis_value not in [0, -1]:
594
+ raise ValueError(
595
+ f"`axis_value` for `quanto` backend has to be one of [`0`, `-1`] but got {self.axis_value}"
596
+ )
597
+
598
+ self.qtype = qint4 if self.nbits == 4 else qint2
599
+ self.optimizer = MaxOptimizer() # hardcode as it's the only one for per-channel quantization
600
+
601
+ def _quantize(self, tensor, axis):
602
+ from optimum.quanto import quantize_weight
603
+
604
+ scale, zeropoint = self.optimizer(tensor, self.qtype, axis, self.q_group_size)
605
+ qtensor = quantize_weight(tensor, self.qtype, axis, scale, zeropoint, self.q_group_size)
606
+ return qtensor
607
+
608
+ def _dequantize(self, qtensor):
609
+ return qtensor.dequantize()
610
+
611
+
612
+ class HQQQuantizedLayer(QuantizedLayer):
613
+ def __init__(
614
+ self,
615
+ nbits: int = 4,
616
+ axis_key: int = 0,
617
+ axis_value: int = 0,
618
+ q_group_size: int = 64,
619
+ residual_length: int = 128,
620
+ ):
621
+ super().__init__(
622
+ nbits=nbits,
623
+ axis_key=axis_key,
624
+ axis_value=axis_value,
625
+ q_group_size=q_group_size,
626
+ residual_length=residual_length,
627
+ )
628
+
629
+ if not is_hqq_available():
630
+ raise ImportError("You need to install `hqq` to use `HQQQuantizedLayer`")
631
+
632
+ if self.nbits not in [1, 2, 3, 4, 8]:
633
+ raise ValueError(
634
+ f"`nbits` for `HQQ` backend has to be one of [`1`, `2`, `3`, `4`, `8`] but got {self.nbits}"
635
+ )
636
+
637
+ if self.axis_key not in [0, 1]:
638
+ raise ValueError(f"`axis_key` for `HQQ` backend has to be one of [`0`, `1`] but got {self.axis_key}")
639
+
640
+ if self.axis_value not in [0, 1]:
641
+ raise ValueError(f"`axis_value` for `HQQ` backend has to be one of [`0`, `1`] but got {self.axis_value}")
642
+
643
+ self.quantizer = HQQQuantizer
644
+
645
+ def _quantize(self, tensor, axis):
646
+ qtensor, meta = self.quantizer.quantize(
647
+ tensor,
648
+ axis=axis,
649
+ device=self.keys.device,
650
+ compute_dtype=self.keys.dtype,
651
+ nbits=self.nbits,
652
+ group_size=self.q_group_size,
653
+ )
654
+ meta["compute_dtype"] = self.keys.dtype
655
+ self.quantizer.cuda(qtensor, meta=meta, device=self.keys.device) # Move to device and cast to dtype
656
+ meta["scale"] = meta["scale"].to(qtensor.device)
657
+ meta["zero"] = meta["zero"].to(qtensor.device)
658
+ return qtensor, meta
659
+
660
+ def _dequantize(self, qtensor):
661
+ quant_tensor, meta = qtensor
662
+ tensor = self.quantizer.dequantize(quant_tensor, meta)
663
+ return tensor
664
+
665
+
666
+ class Cache:
667
+ """
668
+ A `Cache` is mostly a list of `CacheLayerMixin` objects, one per model layer. It serves as a container for
669
+ the Cache of each layer.
670
+
671
+ Args:
672
+ layers (`Optional`, *optional*):
673
+ A list of pre-created `CacheLayerMixin`. If omitted (`None`), then `layer_class_to_replicate` will
674
+ be used.
675
+ layer_class_to_replicate (`type[CacheLayerMixin]`, *optional*):
676
+ Only used if `layers` is omitted (`None`), in which case it will be used as the base class for each layer,
677
+ and the layers will be added lazily as soon as `update` is called with a `layer_idx` greater than the current
678
+ list of layers.
679
+ offloading (`bool`, *optional*, defaults to `False`):
680
+ Whether to perform offloading of the layers to `cpu`, to save GPU memory.
681
+ offload_only_non_sliding (`bool`, *optional*, defaults to `True`):
682
+ If `offloading` is `True`, this further decides if only the non-sliding layers will be offloaded (because
683
+ usually the sliding layers are small in size, so there is no need to offload them, and skipping it is faster).
684
+ """
685
+
686
+ def __init__(
687
+ self,
688
+ layers: Optional[list[CacheLayerMixin]] = None,
689
+ layer_class_to_replicate: Optional[type[CacheLayerMixin]] = None,
690
+ offloading: bool = False,
691
+ offload_only_non_sliding: bool = True,
692
+ ):
693
+ if layers is not None and layer_class_to_replicate is not None:
694
+ raise ValueError(
695
+ "You can construct a Cache either from a list `layers` of all the predefined `CacheLayer`, or from a "
696
+ "`layer_class_to_replicate`, in which case the Cache will append a new layer corresponding to "
697
+ "`layer_class_to_replicate` for each new call to `update` with an idx not already in the Cache."
698
+ )
699
+ if layers is None and layer_class_to_replicate is None:
700
+ raise ValueError(
701
+ "You should provide exactly one of `layers` or `layer_class_to_replicate` to initialize a Cache."
702
+ )
703
+ self.layers = layers if layers is not None else []
704
+ self.layer_class_to_replicate = layer_class_to_replicate
705
+ self.offloading = offloading
706
+ if self.offloading:
707
+ self.only_non_sliding = offload_only_non_sliding
708
+ self.prefetch_stream = torch.Stream() if _is_torch_greater_or_equal_than_2_7 else torch.cuda.Stream()
709
+
710
+ def __repr__(self):
711
+ return f"{self.__class__.__name__}(layers={self.layers})"
712
+
713
+ def prefetch(self, layer_idx: int, only_non_sliding: bool = True):
714
+ """
715
+ Prefetch a given layer on its device. If `only_non_sliding` is True, it will try to prefetch only the layers
716
+ which are non-sliding. If the `layer_idx` is outside the range, this will circle back to the first layers.
717
+ Note that we use a non-default stream for this, to avoid blocking.
718
+ """
719
+ if only_non_sliding:
720
+ # Try to find next non-sliding, starting at `layer_idx`
721
+ try:
722
+ layer_idx = layer_idx + self.is_sliding[layer_idx:].index(False)
723
+ # In this case, we need to circle back to the beginning
724
+ except ValueError:
725
+ layer_idx = self.is_sliding.index(False)
726
+ else:
727
+ layer_idx = layer_idx if layer_idx < len(self.layers) else 0
728
+
729
+ # Prefetch
730
+ with self.prefetch_stream if _is_torch_greater_or_equal_than_2_7 else torch.cuda.stream(self.prefetch_stream):
731
+ self.layers[layer_idx].prefetch()
732
+
733
+ def offload(self, layer_idx: int, only_non_sliding: bool = True):
734
+ """
735
+ Offload a given `layer_idx`. If `only_non_sliding` is True, it will offload `layer_idx` only if it is a
736
+ non-sliding layer. Note that we do it on the default stream, so that we ensure all earlier
737
+ computation in the layer's `update` methods are finished.
738
+ """
739
+ if not (only_non_sliding and self.is_sliding[layer_idx]):
740
+ self.layers[layer_idx].offload()
741
+
742
+ def update(
743
+ self,
744
+ key_states: torch.Tensor,
745
+ value_states: torch.Tensor,
746
+ layer_idx: int,
747
+ cache_kwargs: Optional[dict[str, Any]] = None,
748
+ ) -> tuple[torch.Tensor, torch.Tensor]:
749
+ """
750
+ Updates the cache with the new `key_states` and `value_states` for the layer `layer_idx`.
751
+
752
+ Parameters:
753
+ key_states (`torch.Tensor`):
754
+ The new key states to cache.
755
+ value_states (`torch.Tensor`):
756
+ The new value states to cache.
757
+ layer_idx (`int`):
758
+ The index of the layer to cache the states for.
759
+ cache_kwargs (`dict[str, Any]`, *optional*):
760
+ Additional arguments for the cache subclass. These are specific to each subclass and allow new types of
761
+ cache to be created.
762
+
763
+ Return:
764
+ A tuple containing the updated key and value states.
765
+ """
766
+ # In this case, the `layers` were not provided, and we must append as much as `layer_idx`
767
+ if self.layer_class_to_replicate is not None:
768
+ while len(self.layers) <= layer_idx:
769
+ self.layers.append(self.layer_class_to_replicate())
770
+
771
+ if self.offloading:
772
+ # Wait for the stream to finish if needed, and start prefetching the next layer
773
+ torch.cuda.default_stream(key_states.device).wait_stream(self.prefetch_stream)
774
+ self.prefetch(layer_idx + 1, self.only_non_sliding)
775
+
776
+ keys, values = self.layers[layer_idx].update(key_states, value_states, cache_kwargs)
777
+
778
+ if self.offloading:
779
+ self.offload(layer_idx, self.only_non_sliding)
780
+
781
+ return keys, values
782
+
783
+ def early_initialization(
784
+ self, batch_size: int, num_heads: int, head_dim: int, dtype: torch.dtype, device: torch.device
785
+ ):
786
+ """
787
+ Initialize all the layers in advance (it's otherwise lazily initialized on the first `update` call).
788
+ This is useful for our `export` recipes, as `export` needs everything in advance.
789
+ """
790
+ # Note that the initialization needs all dimensions (except -2), as well as device and dtype, so we use
791
+ # this fake tensor approach. It has size 0 on the -2 dimension, so it does not allocate any data (it only
792
+ # creates an empty tensor with correct shape, dtype and device), which is very efficient and practical
793
+ fake_keys_tensor = torch.zeros((batch_size, num_heads, 0, head_dim), dtype=dtype, device=device)
794
+ # Init all layers
795
+ for layer in self.layers:
796
+ layer.lazy_initialization(fake_keys_tensor)
797
+
798
+ def get_seq_length(self, layer_idx: int = 0) -> int:
799
+ """Returns the sequence length of the cache for the given layer."""
800
+ if layer_idx >= len(self.layers):
801
+ return 0
802
+ return self.layers[layer_idx].get_seq_length()
803
+
804
+ def get_mask_sizes(self, cache_position: torch.Tensor, layer_idx: int) -> tuple[int, int]:
805
+ """
806
+ Return a tuple (kv_length, kv_offset) corresponding to the length and offset that will be returned for
807
+ the given layer at `layer_idx`.
808
+ The masks are then prepared according to the given lengths (kv_length, kv_offset) and patterns for each layer.
809
+ """
810
+ # For DynamicCache, where the layers are created at runtime -> if it was not yet created, the size is
811
+ # simply the shape of `cache_position`
812
+ if layer_idx >= len(self.layers):
813
+ return cache_position.shape[0], 0
814
+ return self.layers[layer_idx].get_mask_sizes(cache_position)
815
+
816
+ def get_max_cache_shape(self, layer_idx: int = 0) -> int:
817
+ """Returns maximum sequence length of the cache object. Dynamic caches do not have a maximum length."""
818
+ # For DynamicCache, where the layers are created at runtime -> if it was not yet created, return -1
819
+ # as DynamicLayer does
820
+ if layer_idx >= len(self.layers):
821
+ return -1
822
+ return self.layers[layer_idx].get_max_cache_shape()
823
+
824
+ def reset(self):
825
+ """Recursively reset all layers tensors"""
826
+ for layer_idx in range(len(self.layers)):
827
+ self.layers[layer_idx].reset()
828
+
829
+ def reorder_cache(self, beam_idx: torch.LongTensor):
830
+ """Reorder the cache for beam search"""
831
+ for layer_idx in range(len(self.layers)):
832
+ self.layers[layer_idx].reorder_cache(beam_idx)
833
+
834
+ def crop(self, max_length: int):
835
+ """Crop the cache to the given length"""
836
+ for layer_idx in range(len(self.layers)):
837
+ self.layers[layer_idx].crop(max_length)
838
+
839
+ def batch_repeat_interleave(self, repeats: int):
840
+ """Repeat and interleave the cache"""
841
+ for layer_idx in range(len(self.layers)):
842
+ self.layers[layer_idx].batch_repeat_interleave(repeats)
843
+
844
+ def batch_select_indices(self, indices: torch.Tensor):
845
+ """Select indices from the cache"""
846
+ for layer_idx in range(len(self.layers)):
847
+ self.layers[layer_idx].batch_select_indices(indices)
848
+
849
+ @property
850
+ def max_batch_size(self) -> int:
851
+ """Return the maximum batch size of the cache"""
852
+ values = [layer.max_batch_size for layer in self.layers]
853
+ if len(set(values)) > 1:
854
+ raise ValueError(f"Max batch size is not consistent across layers: {values}")
855
+ return values[0]
856
+
857
+ @property
858
+ def max_cache_len(self) -> int:
859
+ """Return the maximum cache length of the cache"""
860
+ values = [layer.max_cache_len for layer in self.layers]
861
+ return max(values)
862
+
863
+ @property
864
+ def is_compileable(self) -> bool:
865
+ """Return whether the cache is compileable"""
866
+ # For DynamicCache dispatching the layers lazily (otherwise, all([]) is True)
867
+ if len(self.layers) == 0:
868
+ return False
869
+ return all(layer.is_compileable for layer in self.layers)
870
+
871
+ @property
872
+ def is_initialized(self) -> bool:
873
+ """Return whether the cache data is initialized"""
874
+ return len(self.layers) > 0 and all(layer.is_initialized for layer in self.layers)
875
+
876
+ @property
877
+ def is_sliding(self) -> list[bool]:
878
+ """Return whether the layers of the cache are sliding window"""
879
+ return [getattr(layer, "is_sliding", False) for layer in self.layers]
880
+
881
+ def __getitem__(self, layer_idx: int) -> tuple[torch.Tensor, torch.Tensor]:
882
+ """
883
+ Support for backwards-compatible `past_key_values` indexing, e.g. `past_key_values[0][0].shape[2]` to get the
884
+ sequence length.
885
+ """
886
+ if layer_idx < len(self.layers):
887
+ return self.layers[layer_idx].keys, self.layers[layer_idx].values
888
+ else:
889
+ raise KeyError(
890
+ f"Cache only has {len(self.layers)} layers, attempted to access layer with index {layer_idx}"
891
+ )
892
+
893
+ def __iter__(self):
894
+ """
895
+ Support for backwards-compatible `past_key_values` iteration, e.g. `for x in past_key_values:` to iterate over
896
+ keys and values
897
+ """
898
+ for layer_idx in range(len(self)):
899
+ yield (self.layers[layer_idx].keys, self.layers[layer_idx].values)
900
+
901
+ def __len__(self):
902
+ """
903
+ This value corresponds to the number of layers in the model.
904
+ """
905
+ # Note: for DynamicCache, layers are initialized lazily, so this will not be accurate before the first
906
+ # forward through all the layers
907
+ return len(self.layers)
908
+
909
+
910
+ class DynamicCache(Cache):
911
+ """
912
+ A cache that grows dynamically as more tokens are generated. This is the default for generative models.
913
+ It stores the key and value states as a list of `CacheLayer`, one for each layer. The expected shape for each tensor
914
+ in the `CacheLayer`s is `[batch_size, num_heads, seq_len, head_dim]`.
915
+ If a config is passed, it will additionally check for sliding or hybrid cache structure, greatly reducing the
916
+ memory requirement of the cached tensors to `[batch_size, num_heads, min(seq_len, sliding_window), head_dim]`.
917
+
918
+ See `Cache` for details on common methods that are implemented by all cache classes.
919
+
920
+ Args:
921
+ ddp_cache_data (`Iterable[tuple[torch.Tensor, torch.Tensor]]`, *optional*):
922
+ It was originally added for compatibility with `torch.distributed` (DDP). In a nutshell, it is
923
+ `map(gather_map, zip(*caches))`, i.e. each item in the iterable contains the key and value states
924
+ for a layer gathered across replicas by torch.distributed (shape=[global batch size, num_heads, seq_len, head_dim]).
925
+ Note: it needs to be the 1st arg as well to work correctly
926
+ config (`PretrainedConfig`, *optional*):
927
+ The config of the model for which this Cache will be used. If passed, it will be used to check for sliding
928
+ or hybrid layer structure, greatly reducing the memory requirement of the cached tensors to
929
+ `[batch_size, num_heads, min(seq_len, sliding_window), head_dim]`.
930
+ offloading (`bool`, *optional*, defaults to `False`):
931
+ Whether to perform offloading of the layers to `cpu`, to save GPU memory.
932
+ offload_only_non_sliding (`bool`, *optional*, defaults to `False`):
933
+ If `offloading` is `True`, this further decides if only the non-sliding layers will be offloaded (because
934
+ usually the sliding layers are small in size, so there is no need to offload them, and skipping it is faster).
935
+
936
+ Example:
937
+
938
+ ```python
939
+ >>> from transformers import AutoTokenizer, AutoModelForCausalLM, DynamicCache
940
+
941
+ >>> model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
942
+ >>> tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
943
+
944
+ >>> inputs = tokenizer(text="My name is Qwen2", return_tensors="pt")
945
+
946
+ >>> # Prepare a cache class and pass it to model's forward
947
+ >>> past_key_values = DynamicCache(config=model.config)
948
+ >>> outputs = model(**inputs, past_key_values=past_key_values, use_cache=True)
949
+ >>> outputs.past_key_values # access cache filled with key/values from generation
950
+ ```
951
+ """
952
+
953
+ def __init__(
954
+ self,
955
+ ddp_cache_data: Optional[Iterable[tuple[torch.Tensor, torch.Tensor]]] = None,
956
+ config: Optional[PretrainedConfig] = None,
957
+ offloading: bool = False,
958
+ offload_only_non_sliding: bool = False,
959
+ ):
960
+ layers = []
961
+ # If a config is passed, use it to infer the layer types and initialize accordingly
962
+ if config is not None:
963
+ decoder_config = config.get_text_config(decoder=True)
964
+ sliding_window = getattr(decoder_config, "sliding_window", None) or getattr(
965
+ decoder_config, "attention_chunk_size", None
966
+ )
967
+ layer_types = getattr(decoder_config, "layer_types", None)
968
+ if layer_types is None:
969
+ layer_types = [
970
+ "sliding_attention" if sliding_window is not None else "full_attention"
971
+ for _ in range(decoder_config.num_hidden_layers)
972
+ ]
973
+ # Some models have shared layers thus no cache is needed for them (e.g. Gemma3n)
974
+ if hasattr(decoder_config, "num_kv_shared_layers"):
975
+ layer_types = layer_types[: -decoder_config.num_kv_shared_layers]
976
+
977
+ for layer_type in layer_types:
978
+ # From a cache point of view, both sliding and chunked are the same in how they should behave and how many
979
+ # states they should return - only the mask changes to make them different at the end!
980
+ if layer_type in ("sliding_attention", "chunked_attention"):
981
+ layers.append(DynamicSlidingWindowLayer(sliding_window=sliding_window))
982
+ else:
983
+ layers.append(DynamicLayer())
984
+
985
+ # In this case, use the passed data to already fill in the Cache
986
+ if ddp_cache_data is not None:
987
+ # Init all the layers with the data
988
+ for layer_idx, (key_states, value_states) in enumerate(ddp_cache_data):
989
+ # If the config was not passed above, initialize a DynamicLayer for each entry of the ddp_data
990
+ if config is None:
991
+ layers.append(DynamicLayer())
992
+ # Update the layer with the data
993
+ _, _ = layers[layer_idx].update(key_states, value_states)
994
+
995
+ # If neither of config nor ddp_data was passed, then simply lazy init a full cache of DynamicLayer
996
+ if len(layers) == 0:
997
+ super().__init__(
998
+ layer_class_to_replicate=DynamicLayer,
999
+ offloading=offloading,
1000
+ offload_only_non_sliding=offload_only_non_sliding,
1001
+ )
1002
+ else:
1003
+ super().__init__(layers=layers, offloading=offloading, offload_only_non_sliding=offload_only_non_sliding)
1004
+
1005
+ def to_legacy_cache(self) -> tuple[tuple[torch.Tensor, torch.Tensor]]:
1006
+ """
1007
+ Converts the `Cache` instance into the its equivalent in the legacy cache format. Used for
1008
+ backward compatibility.
1009
+ """
1010
+ legacy_cache = ()
1011
+ for layer in self.layers:
1012
+ legacy_cache += ((layer.keys, layer.values),)
1013
+ return legacy_cache
1014
+
1015
+ @classmethod
1016
+ def from_legacy_cache(cls, past_key_values: tuple[tuple[torch.Tensor, torch.Tensor]]) -> "DynamicCache":
1017
+ """
1018
+ Converts a cache in the legacy cache format into an equivalent `Cache`. Used for
1019
+ backward compatibility.
1020
+ """
1021
+ cache = cls()
1022
+ if past_key_values is None:
1023
+ logger.warning_once("past_key_values should not be None in from_legacy_cache()")
1024
+ if past_key_values is not None:
1025
+ for layer_idx in range(len(past_key_values)):
1026
+ key_states, value_states = past_key_values[layer_idx]
1027
+ cache.update(key_states, value_states, layer_idx)
1028
+ return cache
1029
+
1030
+
1031
+ class StaticCache(Cache):
1032
+ """
1033
+ Static Cache class to be used with `torch.compile(model)` and `torch.export()`. It will check the `config`
1034
+ for potential hybrid cache structure, and initialize each layer accordingly.
1035
+
1036
+ See `Cache` for details on common methods that are implemented by all cache classes.
1037
+
1038
+ Args:
1039
+ config (`PretrainedConfig`):
1040
+ The config of the model for which this Cache will be used. It will be used to check for sliding
1041
+ or hybrid layer structure, and initialize each layer accordingly.
1042
+ max_cache_len (`int`):
1043
+ The maximum number of tokens that this Cache should hold.
1044
+ offloading (`bool`, *optional*, defaults to `False`):
1045
+ Whether to perform offloading of the layers to `cpu`, to save GPU memory.
1046
+ offload_only_non_sliding (`bool`, *optional*, defaults to `True`):
1047
+ If `offloading` is `True`, this further decides if only the non-sliding layers will be offloaded (because
1048
+ usually the sliding layers are small in size, so there is no need to offload them, and skipping it is faster).
1049
+
1050
+ Example:
1051
+
1052
+ ```python
1053
+ >>> from transformers import AutoTokenizer, AutoModelForCausalLM, StaticCache
1054
+
1055
+ >>> model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
1056
+ >>> tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
1057
+
1058
+ >>> inputs = tokenizer(text="My name is Llama", return_tensors="pt")
1059
+
1060
+ >>> # Prepare a cache class and pass it to model's forward
1061
+ >>> # Leave empty space for 10 new tokens, which can be used when calling forward iteratively 10 times to generate
1062
+ >>> max_generated_length = inputs.input_ids.shape[1] + 10
1063
+ >>> past_key_values = StaticCache(config=model.config, max_cache_len=max_generated_length)
1064
+ >>> outputs = model(**inputs, past_key_values=past_key_values, use_cache=True)
1065
+ >>> outputs.past_key_values # access cache filled with key/values from generation
1066
+ StaticCache()
1067
+ ```
1068
+ """
1069
+
1070
+ # Pass-in kwargs as well to avoid crashing for BC (it used more arguments before)
1071
+ def __init__(
1072
+ self,
1073
+ config: PretrainedConfig,
1074
+ max_cache_len: int,
1075
+ offloading: bool = False,
1076
+ offload_only_non_sliding: bool = True,
1077
+ **kwargs,
1078
+ ):
1079
+ config = config.get_text_config(decoder=True)
1080
+ layer_types = getattr(config, "layer_types", None)
1081
+ # If `layer_types` is not explicitly provided, infer if the model is fully sliding
1082
+ if layer_types is None:
1083
+ if getattr(config, "sliding_window", None) is not None:
1084
+ layer_types = ["sliding_attention" for _ in range(config.num_hidden_layers)]
1085
+ elif getattr(config, "attention_chunk_size", None) is not None:
1086
+ layer_types = ["chunked_attention" for _ in range(config.num_hidden_layers)]
1087
+ else:
1088
+ layer_types = ["full_attention" for _ in range(config.num_hidden_layers)]
1089
+ # Some models have shared layers thus no cache is needed for them (e.g. Gemma3n)
1090
+ if hasattr(config, "num_kv_shared_layers"):
1091
+ layer_types = layer_types[: -config.num_kv_shared_layers]
1092
+
1093
+ layers = []
1094
+ for layer_type in layer_types:
1095
+ if layer_type == "sliding_attention":
1096
+ layer = StaticSlidingWindowLayer(max_cache_len=max_cache_len, sliding_window=config.sliding_window)
1097
+ elif layer_type == "chunked_attention":
1098
+ # From a cache point of view, both sliding and chunked are the same in how they should behave and how many
1099
+ # states they should return - only the mask changes to make them different at the end!
1100
+ layer = StaticSlidingWindowLayer(
1101
+ max_cache_len=max_cache_len, sliding_window=config.attention_chunk_size
1102
+ )
1103
+ else:
1104
+ layer = StaticLayer(max_cache_len=max_cache_len)
1105
+ layers.append(layer)
1106
+
1107
+ super().__init__(layers=layers, offloading=offloading, offload_only_non_sliding=offload_only_non_sliding)
1108
+
1109
+
1110
+ class QuantizedCache(Cache):
1111
+ """
1112
+ A quantizer cache similar to what is described in the
1113
+ [KIVI: A Tuning-Free Asymmetric 2bit Quantization for KV Cache paper](https://huggingface.co/papers/2402.02750).
1114
+ It allows the model to generate longer sequence length without allocating too much memory for keys and values
1115
+ by applying quantization.
1116
+ The cache has two types of storage, one for original precision and one for the
1117
+ quantized cache. A `residual length` is set as a maximum capacity for the original precision cache. When the
1118
+ length goes beyond maximum capacity, the original precision cache is discarded and moved into the quantized cache.
1119
+ The quantization is done per-channel with a set `q_group_size` for both keys and values, in contrast to what was
1120
+ described in the paper.
1121
+
1122
+ See `Cache` for details on common methods that are implemented by all cache classes.
1123
+
1124
+ Args:
1125
+ backend (`str`):
1126
+ The quantization backend to use. One of `("quanto", "hqq").
1127
+ config (`PretrainedConfig`):
1128
+ The config of the model for which this Cache will be used.
1129
+ nbits (`int`, *optional*, defaults to 4):
1130
+ The number of bits for quantization.
1131
+ axis_key (`int`, *optional*, defaults to 0):
1132
+ The axis on which to quantize the keys.
1133
+ axis_value (`int`, *optional*, defaults to 0):
1134
+ The axis on which to quantize the values.
1135
+ q_group_size (`int`, *optional*, defaults to 64):
1136
+ Quantization is done per-channel according to a set `q_group_size` for both keys and values.
1137
+ residual_length (`int`, *optional*, defaults to 128):
1138
+ Maximum capacity for the original precision cache
1139
+ """
1140
+
1141
+ def __init__(
1142
+ self,
1143
+ backend: str,
1144
+ config: PretrainedConfig,
1145
+ nbits: int = 4,
1146
+ axis_key: int = 0,
1147
+ axis_value: int = 0,
1148
+ q_group_size: int = 64,
1149
+ residual_length: int = 128,
1150
+ ):
1151
+ if backend == "quanto":
1152
+ layer_class = QuantoQuantizedLayer
1153
+ elif backend == "hqq":
1154
+ layer_class = HQQQuantizedLayer
1155
+ else:
1156
+ raise ValueError(f"Unknown quantization backend `{backend}`")
1157
+
1158
+ config = config.get_text_config(decoder=True)
1159
+ layers = [
1160
+ layer_class(nbits, axis_key, axis_value, q_group_size, residual_length)
1161
+ for _ in range(config.num_hidden_layers)
1162
+ ]
1163
+ super().__init__(layers=layers)
1164
+
1165
+
1166
+ class EncoderDecoderCache(Cache):
1167
+ """
1168
+ Base, abstract class for all encoder-decoder caches. Can be used to hold combinations of self-attention and
1169
+ cross-attention caches.
1170
+
1171
+ See `Cache` for details on common methods that are implemented by all cache classes.
1172
+
1173
+ Args:
1174
+ caches (`Iterable`):
1175
+ Usually an iterable of length 2, containing 2 `Cache` objects, the first one for self-attention, the
1176
+ second one for cross-attention. Can optionally also be an iterable of length 1, containing a
1177
+ `tuple[tuple[torch.Tensor]]` (usually used for compatibility with torch dp and ddp).
1178
+
1179
+ Example:
1180
+
1181
+ ```python
1182
+ >>> from transformers import AutoProcessor, AutoModelForCausalLM, DynamicCache, EncoderDecoderCache
1183
+
1184
+ >>> model = AutoModelForCausalLM.from_pretrained("openai/whisper-small")
1185
+ >>> processor = AutoProcessor.from_pretrained("openai/whisper-small")
1186
+
1187
+ >>> inputs = processor(audio=YOUR-AUDIO, return_tensors="pt")
1188
+
1189
+ >>> # Prepare cache classes for encoder and decoder and pass it to model's forward
1190
+ >>> self_attention_cache = DynamicCache(config=self.config)
1191
+ >>> cross_attention_cache = DynamicCache(config=self.config)
1192
+ >>> past_key_values = EncoderDecoderCache(self_attention_cache, cross_attention_cache)
1193
+ >>> outputs = model(**inputs, past_key_values=past_key_values, use_cache=True)
1194
+ >>> outputs.past_key_values # access cache filled with key/values from generation
1195
+ EncoderDecoderCache()
1196
+ ```
1197
+ """
1198
+
1199
+ def __init__(self, *caches) -> None:
1200
+ # For dp and ddp support, if only one argument is passed, it should be an iterable of tuples of tensors
1201
+ if len(caches) == 1:
1202
+ self.self_attention_cache = DynamicCache()
1203
+ self.cross_attention_cache = DynamicCache()
1204
+ # Populate cache from the iterable
1205
+ for layer_idx, key_value_states in enumerate(caches[0]):
1206
+ key_states, value_states = key_value_states[:2]
1207
+ self.self_attention_cache.update(key_states, value_states, layer_idx)
1208
+ if len(key_value_states) > 2:
1209
+ key_states, value_states = key_value_states[2:]
1210
+ self.cross_attention_cache.update(key_states, value_states, layer_idx)
1211
+ # Otherwise, we should get two arguments, a self-attention cache and a cross-attention cache
1212
+ elif len(caches) == 2:
1213
+ if not isinstance(caches[0], Cache) or not isinstance(caches[1], Cache):
1214
+ raise TypeError(f"One of the two arguments is not a Cache: {type(caches[0]) = }, {type(caches[1]) = }")
1215
+ self.self_attention_cache = caches[0]
1216
+ self.cross_attention_cache = caches[1]
1217
+ # Error case
1218
+ else:
1219
+ raise ValueError(f"Expected 1 or 2 arguments, got {len(caches)}")
1220
+
1221
+ self.is_updated = {}
1222
+ for layer_idx in range(len(self.cross_attention_cache)):
1223
+ self.is_updated[layer_idx] = bool(self.cross_attention_cache.get_seq_length(layer_idx) > 0)
1224
+
1225
+ def __repr__(self) -> str:
1226
+ return (
1227
+ f"{self.__class__.__name__}(self_attention_cache={self.self_attention_cache}, cross_attention_cache="
1228
+ f"{self.cross_attention_cache})"
1229
+ )
1230
+
1231
+ def __iter__(self):
1232
+ """
1233
+ Support for backwards-compatible `past_key_values` iteration, e.g. `for x in past_key_values:` to iterate over
1234
+ keys and values
1235
+ """
1236
+ for layer_idx in range(len(self)):
1237
+ yield (
1238
+ self.self_attention_cache.layers[layer_idx].keys,
1239
+ self.self_attention_cache.layers[layer_idx].values,
1240
+ self.cross_attention_cache.layers[layer_idx].keys,
1241
+ self.cross_attention_cache.layers[layer_idx].values,
1242
+ )
1243
+
1244
+ def __getitem__(self, layer_idx: int) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
1245
+ """
1246
+ Support for backwards-compatible `past_key_values` indexing, e.g. `past_key_values[0][0].shape[2]` to get the
1247
+ sequence length.
1248
+ """
1249
+ if layer_idx < len(self):
1250
+ return (
1251
+ self.self_attention_cache.layers[layer_idx].keys,
1252
+ self.self_attention_cache.layers[layer_idx].values,
1253
+ self.cross_attention_cache.layers[layer_idx].keys,
1254
+ self.cross_attention_cache.layers[layer_idx].values,
1255
+ )
1256
+ else:
1257
+ raise KeyError(f"Cache only has {len(self)} layers, attempted to access layer with index {layer_idx}")
1258
+
1259
+ def __len__(self):
1260
+ """
1261
+ Support for backwards-compatible `past_key_values` length, e.g. `len(past_key_values)`. This value corresponds
1262
+ to the number of layers in the model.
1263
+ """
1264
+ return len(self.self_attention_cache)
1265
+
1266
+ def to_legacy_cache(self) -> tuple[tuple[torch.Tensor]]:
1267
+ """Converts the `EncoderDecoderCache` instance into its equivalent in the legacy cache format."""
1268
+ legacy_cache = ()
1269
+ if len(self.cross_attention_cache) > 0:
1270
+ for self_attn, cross_attn in zip(
1271
+ self.self_attention_cache.to_legacy_cache(), self.cross_attention_cache.to_legacy_cache()
1272
+ ):
1273
+ legacy_cache += (self_attn + cross_attn,)
1274
+ else:
1275
+ legacy_cache = self.self_attention_cache.to_legacy_cache()
1276
+ return legacy_cache
1277
+
1278
+ @classmethod
1279
+ def from_legacy_cache(
1280
+ cls, past_key_values: Optional[Iterable[tuple[torch.FloatTensor, ...]]]
1281
+ ) -> "EncoderDecoderCache":
1282
+ """Converts a cache in the legacy cache format into an equivalent `EncoderDecoderCache`."""
1283
+ cache = cls(DynamicCache(), DynamicCache())
1284
+ if past_key_values is None:
1285
+ logger.warning_once("past_key_values should not be None in from_legacy_cache()")
1286
+ else:
1287
+ for layer_idx, key_value_states in enumerate(past_key_values):
1288
+ key_states, value_states = key_value_states[:2]
1289
+ cache.self_attention_cache.update(key_states, value_states, layer_idx)
1290
+ if len(key_value_states) > 2:
1291
+ key_states, value_states = key_value_states[2:]
1292
+ cache.cross_attention_cache.update(key_states, value_states, layer_idx)
1293
+ cache.is_updated[layer_idx] = True
1294
+ return cache
1295
+
1296
+ def get_seq_length(self, layer_idx: int = 0) -> int:
1297
+ """Returns the sequence length of the cached states. A layer index can be optionally passed."""
1298
+ return self.self_attention_cache.get_seq_length(layer_idx)
1299
+
1300
+ def reset(self):
1301
+ self.self_attention_cache.reset()
1302
+ self.cross_attention_cache.reset()
1303
+ for layer_idx in self.is_updated:
1304
+ self.is_updated[layer_idx] = False
1305
+
1306
+ def reorder_cache(self, beam_idx: torch.LongTensor):
1307
+ """Reorders the cache for beam search, given the selected beam indices."""
1308
+ self.self_attention_cache.reorder_cache(beam_idx)
1309
+ self.cross_attention_cache.reorder_cache(beam_idx)
1310
+
1311
+ def check_dynamic_cache(self, method: str):
1312
+ if not (
1313
+ isinstance(self.self_attention_cache, DynamicCache)
1314
+ and isinstance(self.cross_attention_cache, DynamicCache)
1315
+ ):
1316
+ raise ValueError(
1317
+ f"`{method}` is only defined for dynamic cache, got {self.self_attention_cache.__str__()} for the self "
1318
+ f"attention cache and {self.cross_attention_cache.__str__()} for the cross attention cache."
1319
+ )
1320
+
1321
+ # TODO(gante, sanchit-gandhi): move following functionality into `.generate`
1322
+ def crop(self, maximum_length: int):
1323
+ """
1324
+ Crop the past key values up to a new `maximum_length` in terms of tokens. `maximum_length` can also be
1325
+ negative to remove `maximum_length` tokens. This is used in assisted decoding and contrastive search (on the Hub).
1326
+ """
1327
+ self.check_dynamic_cache(self.crop.__name__)
1328
+ self.self_attention_cache.crop(maximum_length)
1329
+
1330
+ def batch_split(self, full_batch_size: int, split_size: int) -> "list[EncoderDecoderCache]":
1331
+ """
1332
+ Split the current instance into a list of `DynamicCache` by the batch size. This will be used by
1333
+ `_split_model_inputs()` in `generation.utils`
1334
+ """
1335
+ self.check_dynamic_cache(self.batch_split.__name__)
1336
+ self_attention_cache = self.self_attention_cache.batch_split(full_batch_size, split_size)
1337
+ cross_attention_cache = self.cross_attention_cache.batch_split(full_batch_size, split_size)
1338
+
1339
+ out = []
1340
+ for self_attn, cross_attn in zip(self_attention_cache, cross_attention_cache):
1341
+ out.append(EncoderDecoderCache(self_attn, cross_attn))
1342
+ return out
1343
+
1344
+ def batch_repeat_interleave(self, repeats: int):
1345
+ """Repeat the cache `repeats` times in the batch dimension. Used in contrastive search (on the Hub)."""
1346
+ self.check_dynamic_cache(self.batch_repeat_interleave.__name__)
1347
+ self.self_attention_cache.batch_repeat_interleave(repeats)
1348
+ self.cross_attention_cache.batch_repeat_interleave(repeats)
1349
+
1350
+ def batch_select_indices(self, indices: torch.Tensor):
1351
+ """Only keep the `indices` in the batch dimension of the cache. Used in contrastive search (on the Hub)."""
1352
+ self.check_dynamic_cache(self.batch_select_indices.__name__)
1353
+ self.self_attention_cache.batch_select_indices(indices)
1354
+ self.cross_attention_cache.batch_select_indices(indices)
1355
+
1356
+ def get_max_cache_shape(self) -> int:
1357
+ """Returns the maximum sequence length (i.e. max capacity) of the cache object"""
1358
+ return self.self_attention_cache.get_max_cache_shape()
1359
+
1360
+ def get_mask_sizes(self, cache_position: torch.Tensor, layer_idx: int) -> tuple[int, int]:
1361
+ return self.self_attention_cache.get_mask_sizes(cache_position, layer_idx)
1362
+
1363
+ @property
1364
+ def is_sliding(self):
1365
+ return self.self_attention_cache.is_sliding
1366
+
1367
+ @property
1368
+ def is_compileable(self) -> bool:
1369
+ return self.self_attention_cache.is_compileable
1370
+
1371
+
1372
+ ### Deprecated classes
1373
+
1374
+
1375
+ class SlidingWindowLayer(StaticSlidingWindowLayer):
1376
+ def __init__(self, max_cache_len: int, sliding_window: int):
1377
+ logger.warning_once(
1378
+ "`SlidingWindowLayer` is deprecated and will be removed in version v4.59 "
1379
+ "Use `StaticSlidingWindowLayer` instead, which is a better name for it."
1380
+ )
1381
+ super().__init__(max_cache_len, sliding_window)
1382
+
1383
+
1384
+ class ChunkedSlidingLayer(StaticSlidingWindowLayer):
1385
+ def __init__(self, max_cache_len: int, sliding_window: int):
1386
+ logger.warning_once(
1387
+ "`ChunkedSlidingLayer` is deprecated and will be removed in version v4.59 "
1388
+ "Use `StaticSlidingWindowLayer` instead, which has the exact same functionalities."
1389
+ )
1390
+ super().__init__(max_cache_len, sliding_window)
1391
+
1392
+
1393
+ class OffloadedCache(DynamicCache):
1394
+ def __init__(self) -> None:
1395
+ logger.warning_once(
1396
+ "`OffloadedCache` is deprecated and will be removed in version v4.59 "
1397
+ "Use `DynamicCache(offloading=True)` instead"
1398
+ )
1399
+ super().__init__(offloading=True)
1400
+
1401
+
1402
+ class OffloadedStaticCache(StaticCache):
1403
+ def __init__(self, config: PretrainedConfig, max_cache_len: int, *args, **kwargs):
1404
+ logger.warning_once(
1405
+ "`OffloadedStaticCache` is deprecated and will be removed in version v4.59 "
1406
+ "Use `StaticCache(..., offloading=True)` instead"
1407
+ )
1408
+ super().__init__(config=config, max_cache_len=max_cache_len, offloading=True)
1409
+
1410
+
1411
+ class SlidingWindowCache(StaticCache):
1412
+ def __init__(self, config: PretrainedConfig, max_cache_len: int, *args, **kwargs):
1413
+ logger.warning_once(
1414
+ "`SlidingWindowCache` is deprecated and will be removed in version v4.59 "
1415
+ "Use `StaticCache(...)` instead which will correctly infer the type of each layer."
1416
+ )
1417
+ super().__init__(config=config, max_cache_len=max_cache_len)
1418
+
1419
+
1420
+ class HybridCache(StaticCache):
1421
+ def __init__(self, config: PretrainedConfig, max_cache_len: int, *args, **kwargs):
1422
+ logger.warning_once(
1423
+ "`HybridCache` is deprecated and will be removed in version v4.59 "
1424
+ "Use `StaticCache(...)` instead which will correctly infer the type of each layer."
1425
+ )
1426
+ super().__init__(config=config, max_cache_len=max_cache_len)
1427
+
1428
+
1429
+ class HybridChunkedCache(StaticCache):
1430
+ def __init__(self, config: PretrainedConfig, max_cache_len: int, *args, **kwargs):
1431
+ logger.warning_once(
1432
+ "`HybridChunkedCache` is deprecated and will be removed in version v4.59 "
1433
+ "Use `StaticCache(...)` instead which will correctly infer the type of each layer."
1434
+ )
1435
+ super().__init__(config=config, max_cache_len=max_cache_len)
1436
+
1437
+
1438
+ class OffloadedHybridCache(StaticCache):
1439
+ def __init__(self, config: PretrainedConfig, max_cache_len: int, *args, **kwargs):
1440
+ logger.warning_once(
1441
+ "`OffloadedHybridCache` is deprecated and will be removed in version v4.59 "
1442
+ "Use `StaticCache(..., offload=True)` instead which will correctly infer the type of each layer."
1443
+ )
1444
+ super().__init__(config=config, max_cache_len=max_cache_len, offloading=True)
1445
+
1446
+
1447
+ class QuantoQuantizedCache(QuantizedCache):
1448
+ def __init__(
1449
+ self,
1450
+ config: PretrainedConfig,
1451
+ nbits: int = 4,
1452
+ axis_key: int = 0,
1453
+ axis_value: int = 0,
1454
+ q_group_size: int = 64,
1455
+ residual_length: int = 128,
1456
+ ):
1457
+ logger.warning_once(
1458
+ "`QuantoQuantizedCache` is deprecated and will be removed in version v4.59 "
1459
+ "Use `QuantizedCache(backend='quanto', ...)` instead."
1460
+ )
1461
+ super().__init__("quanto", config, nbits, axis_key, axis_value, q_group_size, residual_length)
1462
+
1463
+
1464
+ class HQQQuantizedCache(QuantizedCache):
1465
+ def __init__(
1466
+ self,
1467
+ config: PretrainedConfig,
1468
+ nbits: int = 4,
1469
+ axis_key: int = 0,
1470
+ axis_value: int = 0,
1471
+ q_group_size: int = 64,
1472
+ residual_length: int = 128,
1473
+ ):
1474
+ logger.warning_once(
1475
+ "`HQQQuantizedCache` is deprecated and will be removed in version v4.59 "
1476
+ "Use `QuantizedCache(backend='hqq', ...)` instead."
1477
+ )
1478
+ super().__init__("hqq", config, nbits, axis_key, axis_value, q_group_size, residual_length)
1479
+
1480
+
1481
+ class SinkCache(Cache):
1482
+ """
1483
+ It is now a `custom_generate` repository on the Hub: https://huggingface.co/transformers-community/sink_cache.
1484
+ See [these docs](https://huggingface.co/docs/transformers/generation_strategies#custom-decoding-methods) for
1485
+ general `custom_generate`usage.
1486
+ """
1487
+
1488
+ # TODO (joao, manuel): Remove this class in v4.59.0
1489
+ def __init__(self, **kwargs) -> None:
1490
+ raise NotImplementedError(
1491
+ "`SinkCache` has been moved as a `custom_generate` repository on the Hub: "
1492
+ "https://huggingface.co/transformers-community/sink_cache. See the repository for usage examples."
1493
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/convert_tf_hub_seq_to_seq_bert_to_pytorch.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Convert Seq2Seq TF Hub checkpoint."""
15
+
16
+ import argparse
17
+
18
+ from . import (
19
+ BertConfig,
20
+ BertGenerationConfig,
21
+ BertGenerationDecoder,
22
+ BertGenerationEncoder,
23
+ load_tf_weights_in_bert_generation,
24
+ logging,
25
+ )
26
+
27
+
28
+ logging.set_verbosity_info()
29
+
30
+
31
+ def convert_tf_checkpoint_to_pytorch(tf_hub_path, pytorch_dump_path, is_encoder_named_decoder, vocab_size, is_encoder):
32
+ # Initialise PyTorch model
33
+ bert_config = BertConfig.from_pretrained(
34
+ "google-bert/bert-large-cased",
35
+ vocab_size=vocab_size,
36
+ max_position_embeddings=512,
37
+ is_decoder=True,
38
+ add_cross_attention=True,
39
+ )
40
+ bert_config_dict = bert_config.to_dict()
41
+ del bert_config_dict["type_vocab_size"]
42
+ config = BertGenerationConfig(**bert_config_dict)
43
+ if is_encoder:
44
+ model = BertGenerationEncoder(config)
45
+ else:
46
+ model = BertGenerationDecoder(config)
47
+ print(f"Building PyTorch model from configuration: {config}")
48
+
49
+ # Load weights from tf checkpoint
50
+ load_tf_weights_in_bert_generation(
51
+ model,
52
+ tf_hub_path,
53
+ model_class="bert",
54
+ is_encoder_named_decoder=is_encoder_named_decoder,
55
+ is_encoder=is_encoder,
56
+ )
57
+
58
+ # Save pytorch-model
59
+ print(f"Save PyTorch model and config to {pytorch_dump_path}")
60
+ model.save_pretrained(pytorch_dump_path)
61
+
62
+
63
+ if __name__ == "__main__":
64
+ parser = argparse.ArgumentParser()
65
+ # Required parameters
66
+ parser.add_argument(
67
+ "--tf_hub_path", default=None, type=str, required=True, help="Path to the TensorFlow checkpoint path."
68
+ )
69
+ parser.add_argument(
70
+ "--pytorch_dump_path", default=None, type=str, required=True, help="Path to the output PyTorch model."
71
+ )
72
+ parser.add_argument(
73
+ "--is_encoder_named_decoder",
74
+ action="store_true",
75
+ help="If decoder has to be renamed to encoder in PyTorch model.",
76
+ )
77
+ parser.add_argument("--is_encoder", action="store_true", help="If model is an encoder.")
78
+ parser.add_argument("--vocab_size", default=50358, type=int, help="Vocab size of model")
79
+ args = parser.parse_args()
80
+ convert_tf_checkpoint_to_pytorch(
81
+ args.tf_hub_path,
82
+ args.pytorch_dump_path,
83
+ args.is_encoder_named_decoder,
84
+ args.vocab_size,
85
+ is_encoder=args.is_encoder,
86
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/debug_utils.py ADDED
@@ -0,0 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import collections
16
+
17
+ from .utils import ExplicitEnum, is_torch_available, logging
18
+
19
+
20
+ if is_torch_available():
21
+ import torch
22
+
23
+
24
+ logger = logging.get_logger(__name__)
25
+
26
+
27
+ class DebugUnderflowOverflow:
28
+ """
29
+ This debug class helps detect and understand where the model starts getting very large or very small, and more
30
+ importantly `nan` or `inf` weight and activation elements.
31
+
32
+ There are 2 working modes:
33
+
34
+ 1. Underflow/overflow detection (default)
35
+ 2. Specific batch absolute min/max tracing without detection
36
+
37
+ Mode 1: Underflow/overflow detection
38
+
39
+ To activate the underflow/overflow detection, initialize the object with the model :
40
+
41
+ ```python
42
+ debug_overflow = DebugUnderflowOverflow(model)
43
+ ```
44
+
45
+ then run the training as normal and if `nan` or `inf` gets detected in at least one of the weight, input or output
46
+ elements this module will throw an exception and will print `max_frames_to_save` frames that lead to this event,
47
+ each frame reporting
48
+
49
+ 1. the fully qualified module name plus the class name whose `forward` was run
50
+ 2. the absolute min and max value of all elements for each module weights, and the inputs and output
51
+
52
+ For example, here is the header and the last few frames in detection report for `google/mt5-small` run in fp16
53
+ mixed precision :
54
+
55
+ ```
56
+ Detected inf/nan during batch_number=0
57
+ Last 21 forward frames:
58
+ abs min abs max metadata
59
+ [...]
60
+ encoder.block.2.layer.1.DenseReluDense.wi_0 Linear
61
+ 2.17e-07 4.50e+00 weight
62
+ 1.79e-06 4.65e+00 input[0]
63
+ 2.68e-06 3.70e+01 output
64
+ encoder.block.2.layer.1.DenseReluDense.wi_1 Linear
65
+ 8.08e-07 2.66e+01 weight
66
+ 1.79e-06 4.65e+00 input[0]
67
+ 1.27e-04 2.37e+02 output
68
+ encoder.block.2.layer.1.DenseReluDense.wo Linear
69
+ 1.01e-06 6.44e+00 weight
70
+ 0.00e+00 9.74e+03 input[0]
71
+ 3.18e-04 6.27e+04 output
72
+ encoder.block.2.layer.1.DenseReluDense T5DenseGatedGeluDense
73
+ 1.79e-06 4.65e+00 input[0]
74
+ 3.18e-04 6.27e+04 output
75
+ encoder.block.2.layer.1.dropout Dropout
76
+ 3.18e-04 6.27e+04 input[0]
77
+ 0.00e+00 inf output
78
+ ```
79
+
80
+ You can see here, that `T5DenseGatedGeluDense.forward` resulted in output activations, whose absolute max value was
81
+ around 62.7K, which is very close to fp16's top limit of 64K. In the next frame we have `Dropout` which
82
+ renormalizes the weights, after it zeroed some of the elements, which pushes the absolute max value to more than
83
+ 64K, and we get an overflow.
84
+
85
+ As you can see it's the previous frames that we need to look into when the numbers start going into very large for
86
+ fp16 numbers.
87
+
88
+ The tracking is done in a forward hook, which gets invoked immediately after `forward` has completed.
89
+
90
+ By default the last 21 frames are printed. You can change the default to adjust for your needs. For example :
91
+
92
+ ```python
93
+ debug_overflow = DebugUnderflowOverflow(model, max_frames_to_save=100)
94
+ ```
95
+
96
+ To validate that you have set up this debugging feature correctly, and you intend to use it in a training that
97
+ may take hours to complete, first run it with normal tracing enabled for one of a few batches as explained in
98
+ the next section.
99
+
100
+
101
+ Mode 2. Specific batch absolute min/max tracing without detection
102
+
103
+ The second work mode is per-batch tracing with the underflow/overflow detection feature turned off.
104
+
105
+ Let's say you want to watch the absolute min and max values for all the ingredients of each `forward` call of a
106
+ given batch, and only do that for batches 1 and 3. Then you instantiate this class as :
107
+
108
+ ```python
109
+ debug_overflow = DebugUnderflowOverflow(model, trace_batch_nums=[1, 3])
110
+ ```
111
+
112
+ And now full batches 1 and 3 will be traced using the same format as explained above. Batches are 0-indexed.
113
+
114
+ This is helpful if you know that the program starts misbehaving after a certain batch number, so you can
115
+ fast-forward right to that area.
116
+
117
+
118
+ Early stopping:
119
+
120
+ You can also specify the batch number after which to stop the training, with :
121
+
122
+ ```python
123
+ debug_overflow = DebugUnderflowOverflow(model, trace_batch_nums=[1, 3], abort_after_batch_num=3)
124
+ ```
125
+
126
+ This feature is mainly useful in the tracing mode, but you can use it for any mode.
127
+
128
+
129
+ **Performance**:
130
+
131
+ As this module measures absolute `min`/``max` of each weight of the model on every forward it'll slow the training
132
+ down. Therefore remember to turn it off once the debugging needs have been met.
133
+
134
+ Args:
135
+ model (`nn.Module`):
136
+ The model to debug.
137
+ max_frames_to_save (`int`, *optional*, defaults to 21):
138
+ How many frames back to record
139
+ trace_batch_nums(`list[int]`, *optional*, defaults to `[]`):
140
+ Which batch numbers to trace (turns detection off)
141
+ abort_after_batch_num (`int``, *optional*):
142
+ Whether to abort after a certain batch number has finished
143
+ """
144
+
145
+ def __init__(self, model, max_frames_to_save=21, trace_batch_nums=[], abort_after_batch_num=None):
146
+ self.model = model
147
+ self.trace_batch_nums = trace_batch_nums
148
+ self.abort_after_batch_num = abort_after_batch_num
149
+
150
+ # keep a LIFO buffer of frames to dump as soon as inf/nan is encountered to give context to the problem emergence
151
+ self.frames = collections.deque([], max_frames_to_save)
152
+ self.frame = []
153
+ self.batch_number = 0
154
+ self.total_calls = 0
155
+ self.detected_overflow = False
156
+ self.prefix = " "
157
+
158
+ self.analyse_model()
159
+
160
+ self.register_forward_hook()
161
+
162
+ def save_frame(self, frame=None):
163
+ if frame is not None:
164
+ self.expand_frame(frame)
165
+ self.frames.append("\n".join(self.frame))
166
+ self.frame = [] # start a new frame
167
+
168
+ def expand_frame(self, line):
169
+ self.frame.append(line)
170
+
171
+ def trace_frames(self):
172
+ print("\n".join(self.frames))
173
+ self.frames = []
174
+
175
+ def reset_saved_frames(self):
176
+ self.frames = []
177
+
178
+ def dump_saved_frames(self):
179
+ print(f"\nDetected inf/nan during batch_number={self.batch_number}")
180
+ print(f"Last {len(self.frames)} forward frames:")
181
+ print(f"{'abs min':8} {'abs max':8} metadata")
182
+ print("\n".join(self.frames))
183
+ print("\n\n")
184
+ self.frames = []
185
+
186
+ def analyse_model(self):
187
+ # extract the fully qualified module names, to be able to report at run time. e.g.:
188
+ # encoder.block.2.layer.0.SelfAttention.o
189
+ #
190
+ # for shared weights only the first shared module name will be registered
191
+ self.module_names = {m: name for name, m in self.model.named_modules()}
192
+ # self.longest_module_name = max(len(v) for v in self.module_names.values())
193
+
194
+ def analyse_variable(self, var, ctx):
195
+ if torch.is_tensor(var):
196
+ self.expand_frame(get_abs_min_max(var, ctx))
197
+ if detect_overflow(var, ctx):
198
+ self.detected_overflow = True
199
+ elif var is None:
200
+ self.expand_frame(f"{'None':>17} {ctx}")
201
+ else:
202
+ self.expand_frame(f"{'not a tensor':>17} {ctx}")
203
+
204
+ def batch_start_frame(self):
205
+ self.expand_frame(f"\n\n{self.prefix} *** Starting batch number={self.batch_number} ***")
206
+ self.expand_frame(f"{'abs min':8} {'abs max':8} metadata")
207
+
208
+ def batch_end_frame(self):
209
+ self.expand_frame(f"{self.prefix} *** Finished batch number={self.batch_number - 1} ***\n\n")
210
+
211
+ def create_frame(self, module, input, output):
212
+ self.expand_frame(f"{self.prefix} {self.module_names[module]} {module.__class__.__name__}")
213
+
214
+ # params
215
+ for name, p in module.named_parameters(recurse=False):
216
+ self.analyse_variable(p, name)
217
+
218
+ # inputs
219
+ if isinstance(input, tuple):
220
+ for i, x in enumerate(input):
221
+ self.analyse_variable(x, f"input[{i}]")
222
+ else:
223
+ self.analyse_variable(input, "input")
224
+
225
+ # outputs
226
+ if isinstance(output, tuple):
227
+ for i, x in enumerate(output):
228
+ # possibly a tuple of tuples
229
+ if isinstance(x, tuple):
230
+ for j, y in enumerate(x):
231
+ self.analyse_variable(y, f"output[{i}][{j}]")
232
+ else:
233
+ self.analyse_variable(x, f"output[{i}]")
234
+ else:
235
+ self.analyse_variable(output, "output")
236
+
237
+ self.save_frame()
238
+
239
+ def register_forward_hook(self):
240
+ self.model.apply(self._register_forward_hook)
241
+
242
+ def _register_forward_hook(self, module):
243
+ module.register_forward_hook(self.forward_hook)
244
+
245
+ def forward_hook(self, module, input, output):
246
+ # - input is a tuple of packed inputs (could be non-Tensors)
247
+ # - output could be a Tensor or a tuple of Tensors and non-Tensors
248
+
249
+ last_frame_of_batch = False
250
+
251
+ trace_mode = self.batch_number in self.trace_batch_nums
252
+ if trace_mode:
253
+ self.reset_saved_frames()
254
+
255
+ if self.total_calls == 0:
256
+ self.batch_start_frame()
257
+ self.total_calls += 1
258
+
259
+ # count batch numbers - the very first forward hook of the batch will be called when the
260
+ # batch completes - i.e. it gets called very last - we know this batch has finished
261
+ if module == self.model:
262
+ self.batch_number += 1
263
+ last_frame_of_batch = True
264
+
265
+ self.create_frame(module, input, output)
266
+
267
+ # if last_frame_of_batch:
268
+ # self.batch_end_frame()
269
+
270
+ if trace_mode:
271
+ self.trace_frames()
272
+
273
+ if last_frame_of_batch:
274
+ self.batch_start_frame()
275
+
276
+ if self.detected_overflow and not trace_mode:
277
+ self.dump_saved_frames()
278
+
279
+ # now we can abort, as it's pointless to continue running
280
+ raise ValueError(
281
+ "DebugUnderflowOverflow: inf/nan detected, aborting as there is no point running further. "
282
+ "Please scroll up above this traceback to see the activation values prior to this event."
283
+ )
284
+
285
+ # abort after certain batch if requested to do so
286
+ if self.abort_after_batch_num is not None and self.batch_number > self.abort_after_batch_num:
287
+ raise ValueError(
288
+ f"DebugUnderflowOverflow: aborting after {self.batch_number} batches due to"
289
+ f" `abort_after_batch_num={self.abort_after_batch_num}` arg"
290
+ )
291
+
292
+
293
+ def get_abs_min_max(var, ctx):
294
+ abs_var = var.abs()
295
+ return f"{abs_var.min():8.2e} {abs_var.max():8.2e} {ctx}"
296
+
297
+
298
+ def detect_overflow(var, ctx):
299
+ """
300
+ Report whether the tensor contains any `nan` or `inf` entries.
301
+
302
+ This is useful for detecting overflows/underflows and best to call right after the function that did some math that
303
+ modified the tensor in question.
304
+
305
+ This function contains a few other helper features that you can enable and tweak directly if you want to track
306
+ various other things.
307
+
308
+ Args:
309
+ var: the tensor variable to check
310
+ ctx: the message to print as a context
311
+
312
+ Return:
313
+ `True` if `inf` or `nan` was detected, `False` otherwise
314
+ """
315
+ detected = False
316
+ if torch.isnan(var).any().item():
317
+ detected = True
318
+ print(f"{ctx} has nans")
319
+ if torch.isinf(var).any().item():
320
+ detected = True
321
+ print(f"{ctx} has infs")
322
+
323
+ # if needed to monitor large elements can enable the following
324
+ if 0: # and detected:
325
+ n100 = var[torch.ge(var.abs(), 100)]
326
+ if n100.numel() > 0:
327
+ print(f"{ctx}: n100={n100.numel()}")
328
+ n1000 = var[torch.ge(var.abs(), 1000)]
329
+ if n1000.numel() > 0:
330
+ print(f"{ctx}: n1000={n1000.numel()}")
331
+ n10000 = var[torch.ge(var.abs(), 10000)]
332
+ if n10000.numel() > 0:
333
+ print(f"{ctx}: n10000={n10000.numel()}")
334
+
335
+ if 0:
336
+ print(f"min={var.min():9.2e} max={var.max():9.2e}")
337
+
338
+ if 0:
339
+ print(f"min={var.min():9.2e} max={var.max():9.2e} var={var.var():9.2e} mean={var.mean():9.2e} ({ctx})")
340
+
341
+ return detected
342
+
343
+
344
+ class DebugOption(ExplicitEnum):
345
+ UNDERFLOW_OVERFLOW = "underflow_overflow"
346
+ TPU_METRICS_DEBUG = "tpu_metrics_debug"
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/dependency_versions_table.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # THIS FILE HAS BEEN AUTOGENERATED. To update:
2
+ # 1. modify the `_deps` dict in setup.py
3
+ # 2. run `make deps_table_update``
4
+ deps = {
5
+ "Pillow": "Pillow>=10.0.1,<=15.0",
6
+ "accelerate": "accelerate>=0.26.0",
7
+ "av": "av",
8
+ "beautifulsoup4": "beautifulsoup4",
9
+ "blobfile": "blobfile",
10
+ "codecarbon": "codecarbon>=2.8.1",
11
+ "cookiecutter": "cookiecutter==1.7.3",
12
+ "dataclasses": "dataclasses",
13
+ "datasets": "datasets>=2.15.0",
14
+ "deepspeed": "deepspeed>=0.9.3",
15
+ "diffusers": "diffusers",
16
+ "dill": "dill<0.3.5",
17
+ "evaluate": "evaluate>=0.2.0",
18
+ "faiss-cpu": "faiss-cpu",
19
+ "fastapi": "fastapi",
20
+ "filelock": "filelock",
21
+ "flax": "flax>=0.4.1,<=0.7.0",
22
+ "ftfy": "ftfy",
23
+ "fugashi": "fugashi>=1.0",
24
+ "GitPython": "GitPython<3.1.19",
25
+ "hf-doc-builder": "hf-doc-builder>=0.3.0",
26
+ "hf_xet": "hf_xet",
27
+ "huggingface-hub": "huggingface-hub>=0.34.0,<1.0",
28
+ "importlib_metadata": "importlib_metadata",
29
+ "ipadic": "ipadic>=1.0.0,<2.0",
30
+ "jax": "jax>=0.4.1,<=0.4.13",
31
+ "jaxlib": "jaxlib>=0.4.1,<=0.4.13",
32
+ "jinja2": "jinja2>=3.1.0",
33
+ "kenlm": "kenlm",
34
+ "keras": "keras>2.9,<2.16",
35
+ "keras-nlp": "keras-nlp>=0.3.1,<0.14.0",
36
+ "kernels": "kernels>=0.6.1,<=0.9",
37
+ "librosa": "librosa",
38
+ "natten": "natten>=0.14.6,<0.15.0",
39
+ "nltk": "nltk<=3.8.1",
40
+ "num2words": "num2words",
41
+ "numpy": "numpy>=1.17",
42
+ "onnxconverter-common": "onnxconverter-common",
43
+ "onnxruntime-tools": "onnxruntime-tools>=1.4.2",
44
+ "onnxruntime": "onnxruntime>=1.4.0",
45
+ "openai": "openai>=1.98.0",
46
+ "opencv-python": "opencv-python",
47
+ "optimum-benchmark": "optimum-benchmark>=0.3.0",
48
+ "optuna": "optuna",
49
+ "optax": "optax>=0.0.8,<=0.1.4",
50
+ "pandas": "pandas<2.3.0",
51
+ "packaging": "packaging>=20.0",
52
+ "parameterized": "parameterized>=0.9",
53
+ "phonemizer": "phonemizer",
54
+ "protobuf": "protobuf",
55
+ "psutil": "psutil",
56
+ "pyyaml": "pyyaml>=5.1",
57
+ "pydantic": "pydantic>=2",
58
+ "pytest": "pytest>=7.2.0",
59
+ "pytest-asyncio": "pytest-asyncio",
60
+ "pytest-rerunfailures": "pytest-rerunfailures<16.0",
61
+ "pytest-timeout": "pytest-timeout",
62
+ "pytest-xdist": "pytest-xdist",
63
+ "pytest-order": "pytest-order",
64
+ "python": "python>=3.9.0",
65
+ "ray[tune]": "ray[tune]>=2.7.0",
66
+ "regex": "regex!=2019.12.17",
67
+ "requests": "requests",
68
+ "rhoknp": "rhoknp>=1.1.0,<1.3.1",
69
+ "rjieba": "rjieba",
70
+ "rouge-score": "rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1",
71
+ "ruff": "ruff==0.13.1",
72
+ "sacrebleu": "sacrebleu>=1.4.12,<2.0.0",
73
+ "sacremoses": "sacremoses",
74
+ "safetensors": "safetensors>=0.4.3",
75
+ "sagemaker": "sagemaker>=2.31.0",
76
+ "schedulefree": "schedulefree>=1.2.6",
77
+ "scikit-learn": "scikit-learn",
78
+ "scipy": "scipy<1.13.0",
79
+ "sentencepiece": "sentencepiece>=0.1.91,!=0.1.92",
80
+ "sigopt": "sigopt",
81
+ "starlette": "starlette",
82
+ "sudachipy": "sudachipy>=0.6.6",
83
+ "sudachidict_core": "sudachidict_core>=20220729",
84
+ "tensorboard": "tensorboard",
85
+ "tensorflow-cpu": "tensorflow-cpu>2.9,<2.16",
86
+ "tensorflow": "tensorflow>2.9,<2.16",
87
+ "tensorflow-text": "tensorflow-text<2.16",
88
+ "tensorflow-probability": "tensorflow-probability<0.24",
89
+ "tf2onnx": "tf2onnx",
90
+ "timeout-decorator": "timeout-decorator",
91
+ "tiktoken": "tiktoken",
92
+ "timm": "timm<=1.0.19,!=1.0.18",
93
+ "tokenizers": "tokenizers>=0.22.0,<=0.23.0",
94
+ "torch": "torch>=2.2",
95
+ "torchaudio": "torchaudio",
96
+ "torchvision": "torchvision",
97
+ "pyctcdecode": "pyctcdecode>=0.4.0",
98
+ "tqdm": "tqdm>=4.27",
99
+ "unidic": "unidic>=1.0.2",
100
+ "unidic_lite": "unidic_lite>=1.0.7",
101
+ "urllib3": "urllib3<2.0.0",
102
+ "uvicorn": "uvicorn",
103
+ "pytest-rich": "pytest-rich",
104
+ "libcst": "libcst",
105
+ "rich": "rich",
106
+ "opentelemetry-api": "opentelemetry-api",
107
+ "mistral-common[opencv]": "mistral-common[opencv]>=1.6.3",
108
+ }
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/dynamic_module_utils.py ADDED
@@ -0,0 +1,843 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Utilities to dynamically load objects from the Hub."""
15
+
16
+ import ast
17
+ import filecmp
18
+ import hashlib
19
+ import importlib
20
+ import importlib.metadata
21
+ import importlib.util
22
+ import keyword
23
+ import os
24
+ import re
25
+ import shutil
26
+ import signal
27
+ import sys
28
+ import threading
29
+ import warnings
30
+ from pathlib import Path
31
+ from types import ModuleType
32
+ from typing import Any, Optional, Union
33
+
34
+ from huggingface_hub import try_to_load_from_cache
35
+ from packaging import version
36
+
37
+ from .utils import (
38
+ HF_MODULES_CACHE,
39
+ TRANSFORMERS_DYNAMIC_MODULE_NAME,
40
+ cached_file,
41
+ extract_commit_hash,
42
+ is_offline_mode,
43
+ logging,
44
+ )
45
+ from .utils.import_utils import VersionComparison, split_package_version
46
+
47
+
48
+ logger = logging.get_logger(__name__) # pylint: disable=invalid-name
49
+
50
+
51
+ def _sanitize_module_name(name: str) -> str:
52
+ r"""
53
+ Tries to sanitize a module name so that it can be used as a Python module.
54
+
55
+ The following transformations are applied:
56
+
57
+ 1. Replace `.` in module names with `_dot_`.
58
+ 2. Replace `-` in module names with `_hyphen_`.
59
+ 3. If the module name starts with a digit, prepend it with `_`.
60
+ 4. Warn if the sanitized name is a Python reserved keyword or not a valid identifier.
61
+
62
+ If the input name is already a valid identifier, it is returned unchanged.
63
+ """
64
+ # We not replacing `\W` characters with `_` to avoid collisions. Because `_` is a very common
65
+ # separator used in module names, replacing `\W` with `_` would create too many collisions.
66
+ # Once a module is imported, it is cached in `sys.modules` and the second import would return
67
+ # the first module, which might not be the expected behavior if name collisions happen.
68
+ new_name = name.replace(".", "_dot_").replace("-", "_hyphen_")
69
+ if new_name and new_name[0].isdigit():
70
+ new_name = f"_{new_name}"
71
+ if keyword.iskeyword(new_name):
72
+ logger.warning(
73
+ f"The module name {new_name} (originally {name}) is a reserved keyword in Python. "
74
+ "Please rename the original module to avoid import issues."
75
+ )
76
+ elif not new_name.isidentifier():
77
+ logger.warning(
78
+ f"The module name {new_name} (originally {name}) is not a valid Python identifier. "
79
+ "Please rename the original module to avoid import issues."
80
+ )
81
+ return new_name
82
+
83
+
84
+ _HF_REMOTE_CODE_LOCK = threading.Lock()
85
+
86
+
87
+ def init_hf_modules():
88
+ """
89
+ Creates the cache directory for modules with an init, and adds it to the Python path.
90
+ """
91
+ # This function has already been executed if HF_MODULES_CACHE already is in the Python path.
92
+ if HF_MODULES_CACHE in sys.path:
93
+ return
94
+
95
+ sys.path.append(HF_MODULES_CACHE)
96
+ os.makedirs(HF_MODULES_CACHE, exist_ok=True)
97
+ init_path = Path(HF_MODULES_CACHE) / "__init__.py"
98
+ if not init_path.exists():
99
+ init_path.touch()
100
+ importlib.invalidate_caches()
101
+
102
+
103
+ def create_dynamic_module(name: Union[str, os.PathLike]) -> None:
104
+ """
105
+ Creates a dynamic module in the cache directory for modules.
106
+
107
+ Args:
108
+ name (`str` or `os.PathLike`):
109
+ The name of the dynamic module to create.
110
+ """
111
+ init_hf_modules()
112
+ dynamic_module_path = (Path(HF_MODULES_CACHE) / name).resolve()
113
+ # If the parent module does not exist yet, recursively create it.
114
+ if not dynamic_module_path.parent.exists():
115
+ create_dynamic_module(dynamic_module_path.parent)
116
+ os.makedirs(dynamic_module_path, exist_ok=True)
117
+ init_path = dynamic_module_path / "__init__.py"
118
+ if not init_path.exists():
119
+ init_path.touch()
120
+ # It is extremely important to invalidate the cache when we change stuff in those modules, or users end up
121
+ # with errors about module that do not exist. Same for all other `invalidate_caches` in this file.
122
+ importlib.invalidate_caches()
123
+
124
+
125
+ def get_relative_imports(module_file: Union[str, os.PathLike]) -> list[str]:
126
+ """
127
+ Get the list of modules that are relatively imported in a module file.
128
+
129
+ Args:
130
+ module_file (`str` or `os.PathLike`): The module file to inspect.
131
+
132
+ Returns:
133
+ `list[str]`: The list of relative imports in the module.
134
+ """
135
+ with open(module_file, encoding="utf-8") as f:
136
+ content = f.read()
137
+
138
+ # Imports of the form `import .xxx`
139
+ relative_imports = re.findall(r"^\s*import\s+\.(\S+)\s*$", content, flags=re.MULTILINE)
140
+ # Imports of the form `from .xxx import yyy`
141
+ relative_imports += re.findall(r"^\s*from\s+\.(\S+)\s+import", content, flags=re.MULTILINE)
142
+ # Unique-ify
143
+ return list(set(relative_imports))
144
+
145
+
146
+ def get_relative_import_files(module_file: Union[str, os.PathLike]) -> list[str]:
147
+ """
148
+ Get the list of all files that are needed for a given module. Note that this function recurses through the relative
149
+ imports (if a imports b and b imports c, it will return module files for b and c).
150
+
151
+ Args:
152
+ module_file (`str` or `os.PathLike`): The module file to inspect.
153
+
154
+ Returns:
155
+ `list[str]`: The list of all relative imports a given module needs (recursively), which will give us the list
156
+ of module files a given module needs.
157
+ """
158
+ no_change = False
159
+ files_to_check = [module_file]
160
+ all_relative_imports = []
161
+
162
+ # Let's recurse through all relative imports
163
+ while not no_change:
164
+ new_imports = []
165
+ for f in files_to_check:
166
+ new_imports.extend(get_relative_imports(f))
167
+
168
+ module_path = Path(module_file).parent
169
+ new_import_files = [f"{str(module_path / m)}.py" for m in new_imports]
170
+ files_to_check = [f for f in new_import_files if f not in all_relative_imports]
171
+
172
+ no_change = len(files_to_check) == 0
173
+ all_relative_imports.extend(files_to_check)
174
+
175
+ return all_relative_imports
176
+
177
+
178
+ def get_imports(filename: Union[str, os.PathLike]) -> list[str]:
179
+ """
180
+ Extracts all the libraries (not relative imports this time) that are imported in a file.
181
+
182
+ Args:
183
+ filename (`str` or `os.PathLike`): The module file to inspect.
184
+
185
+ Returns:
186
+ `list[str]`: The list of all packages required to use the input module.
187
+ """
188
+ with open(filename, encoding="utf-8") as f:
189
+ content = f.read()
190
+ imported_modules = set()
191
+
192
+ import transformers.utils
193
+
194
+ def recursive_look_for_imports(node):
195
+ if isinstance(node, ast.Try):
196
+ return # Don't recurse into Try blocks and ignore imports in them
197
+ elif isinstance(node, ast.If):
198
+ test = node.test
199
+ for condition_node in ast.walk(test):
200
+ if isinstance(condition_node, ast.Call):
201
+ check_function = getattr(condition_node.func, "id", "")
202
+ if (
203
+ check_function.endswith("available")
204
+ and check_function.startswith("is_flash_attn")
205
+ or hasattr(transformers.utils.import_utils, check_function)
206
+ ):
207
+ # Don't recurse into "if flash_attn_available()" or any "if library_available" blocks
208
+ # that appears in `transformers.utils.import_utils` and ignore imports in them
209
+ return
210
+ elif isinstance(node, ast.Import):
211
+ # Handle 'import x' statements
212
+ for alias in node.names:
213
+ top_module = alias.name.split(".")[0]
214
+ if top_module:
215
+ imported_modules.add(top_module)
216
+ elif isinstance(node, ast.ImportFrom):
217
+ # Handle 'from x import y' statements, ignoring relative imports
218
+ if node.level == 0 and node.module:
219
+ top_module = node.module.split(".")[0]
220
+ if top_module:
221
+ imported_modules.add(top_module)
222
+
223
+ # Recursively visit all children
224
+ for child in ast.iter_child_nodes(node):
225
+ recursive_look_for_imports(child)
226
+
227
+ tree = ast.parse(content)
228
+ recursive_look_for_imports(tree)
229
+
230
+ return sorted(imported_modules)
231
+
232
+
233
+ def check_imports(filename: Union[str, os.PathLike]) -> list[str]:
234
+ """
235
+ Check if the current Python environment contains all the libraries that are imported in a file. Will raise if a
236
+ library is missing.
237
+
238
+ Args:
239
+ filename (`str` or `os.PathLike`): The module file to check.
240
+
241
+ Returns:
242
+ `list[str]`: The list of relative imports in the file.
243
+ """
244
+ imports = get_imports(filename)
245
+ missing_packages = []
246
+ for imp in imports:
247
+ try:
248
+ importlib.import_module(imp)
249
+ except ImportError as exception:
250
+ logger.warning(f"Encountered exception while importing {imp}: {exception}")
251
+ # Some packages can fail with an ImportError because of a dependency issue.
252
+ # This check avoids hiding such errors.
253
+ # See https://github.com/huggingface/transformers/issues/33604
254
+ if "No module named" in str(exception):
255
+ missing_packages.append(imp)
256
+ else:
257
+ raise
258
+
259
+ if len(missing_packages) > 0:
260
+ raise ImportError(
261
+ "This modeling file requires the following packages that were not found in your environment: "
262
+ f"{', '.join(missing_packages)}. Run `pip install {' '.join(missing_packages)}`"
263
+ )
264
+
265
+ return get_relative_imports(filename)
266
+
267
+
268
+ def get_class_in_module(
269
+ class_name: str,
270
+ module_path: Union[str, os.PathLike],
271
+ *,
272
+ force_reload: bool = False,
273
+ ) -> type:
274
+ """
275
+ Import a module on the cache directory for modules and extract a class from it.
276
+
277
+ Args:
278
+ class_name (`str`): The name of the class to import.
279
+ module_path (`str` or `os.PathLike`): The path to the module to import.
280
+ force_reload (`bool`, *optional*, defaults to `False`):
281
+ Whether to reload the dynamic module from file if it already exists in `sys.modules`.
282
+ Otherwise, the module is only reloaded if the file has changed.
283
+
284
+ Returns:
285
+ `typing.Type`: The class looked for.
286
+ """
287
+ name = os.path.normpath(module_path)
288
+ name = name.removesuffix(".py")
289
+ name = name.replace(os.path.sep, ".")
290
+ module_file: Path = Path(HF_MODULES_CACHE) / module_path
291
+ with _HF_REMOTE_CODE_LOCK:
292
+ if force_reload:
293
+ sys.modules.pop(name, None)
294
+ importlib.invalidate_caches()
295
+ cached_module: Optional[ModuleType] = sys.modules.get(name)
296
+ module_spec = importlib.util.spec_from_file_location(name, location=module_file)
297
+
298
+ # Hash the module file and all its relative imports to check if we need to reload it
299
+ module_files: list[Path] = [module_file] + sorted(map(Path, get_relative_import_files(module_file)))
300
+ module_hash: str = hashlib.sha256(b"".join(bytes(f) + f.read_bytes() for f in module_files)).hexdigest()
301
+
302
+ module: ModuleType
303
+ if cached_module is None:
304
+ module = importlib.util.module_from_spec(module_spec)
305
+ # insert it into sys.modules before any loading begins
306
+ sys.modules[name] = module
307
+ else:
308
+ module = cached_module
309
+ # reload in both cases, unless the module is already imported and the hash hits
310
+ if getattr(module, "__transformers_module_hash__", "") != module_hash:
311
+ module_spec.loader.exec_module(module)
312
+ module.__transformers_module_hash__ = module_hash
313
+ return getattr(module, class_name)
314
+
315
+
316
+ def get_cached_module_file(
317
+ pretrained_model_name_or_path: Union[str, os.PathLike],
318
+ module_file: str,
319
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
320
+ force_download: bool = False,
321
+ resume_download: Optional[bool] = None,
322
+ proxies: Optional[dict[str, str]] = None,
323
+ token: Optional[Union[bool, str]] = None,
324
+ revision: Optional[str] = None,
325
+ local_files_only: bool = False,
326
+ repo_type: Optional[str] = None,
327
+ _commit_hash: Optional[str] = None,
328
+ **deprecated_kwargs,
329
+ ) -> str:
330
+ """
331
+ Prepares Downloads a module from a local folder or a distant repo and returns its path inside the cached
332
+ Transformers module.
333
+
334
+ Args:
335
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
336
+ This can be either:
337
+
338
+ - a string, the *model id* of a pretrained model configuration hosted inside a model repo on
339
+ huggingface.co.
340
+ - a path to a *directory* containing a configuration file saved using the
341
+ [`~PreTrainedTokenizer.save_pretrained`] method, e.g., `./my_model_directory/`.
342
+
343
+ module_file (`str`):
344
+ The name of the module file containing the class to look for.
345
+ cache_dir (`str` or `os.PathLike`, *optional*):
346
+ Path to a directory in which a downloaded pretrained model configuration should be cached if the standard
347
+ cache should not be used.
348
+ force_download (`bool`, *optional*, defaults to `False`):
349
+ Whether or not to force to (re-)download the configuration files and override the cached versions if they
350
+ exist.
351
+ resume_download:
352
+ Deprecated and ignored. All downloads are now resumed by default when possible.
353
+ Will be removed in v5 of Transformers.
354
+ proxies (`dict[str, str]`, *optional*):
355
+ A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
356
+ 'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.
357
+ token (`str` or *bool*, *optional*):
358
+ The token to use as HTTP bearer authorization for remote files. If `True`, will use the token generated
359
+ when running `hf auth login` (stored in `~/.huggingface`).
360
+ revision (`str`, *optional*, defaults to `"main"`):
361
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
362
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
363
+ identifier allowed by git.
364
+ local_files_only (`bool`, *optional*, defaults to `False`):
365
+ If `True`, will only try to load the tokenizer configuration from local files.
366
+ repo_type (`str`, *optional*):
367
+ Specify the repo type (useful when downloading from a space for instance).
368
+
369
+ <Tip>
370
+
371
+ Passing `token=True` is required when you want to use a private model.
372
+
373
+ </Tip>
374
+
375
+ Returns:
376
+ `str`: The path to the module inside the cache.
377
+ """
378
+ use_auth_token = deprecated_kwargs.pop("use_auth_token", None)
379
+ if use_auth_token is not None:
380
+ warnings.warn(
381
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
382
+ FutureWarning,
383
+ )
384
+ if token is not None:
385
+ raise ValueError("`token` and `use_auth_token` are both specified. Please set only the argument `token`.")
386
+ token = use_auth_token
387
+
388
+ if is_offline_mode() and not local_files_only:
389
+ logger.info("Offline mode: forcing local_files_only=True")
390
+ local_files_only = True
391
+
392
+ # Download and cache module_file from the repo `pretrained_model_name_or_path` of grab it if it's a local file.
393
+ pretrained_model_name_or_path = str(pretrained_model_name_or_path)
394
+ is_local = os.path.isdir(pretrained_model_name_or_path)
395
+ if is_local:
396
+ submodule = _sanitize_module_name(os.path.basename(pretrained_model_name_or_path))
397
+ else:
398
+ submodule = os.path.sep.join(map(_sanitize_module_name, pretrained_model_name_or_path.split("/")))
399
+ cached_module = try_to_load_from_cache(
400
+ pretrained_model_name_or_path, module_file, cache_dir=cache_dir, revision=_commit_hash, repo_type=repo_type
401
+ )
402
+
403
+ new_files = []
404
+ try:
405
+ # Load from URL or cache if already cached
406
+ resolved_module_file = cached_file(
407
+ pretrained_model_name_or_path,
408
+ module_file,
409
+ cache_dir=cache_dir,
410
+ force_download=force_download,
411
+ proxies=proxies,
412
+ resume_download=resume_download,
413
+ local_files_only=local_files_only,
414
+ token=token,
415
+ revision=revision,
416
+ repo_type=repo_type,
417
+ _commit_hash=_commit_hash,
418
+ )
419
+ if not is_local and cached_module != resolved_module_file:
420
+ new_files.append(module_file)
421
+
422
+ except OSError:
423
+ logger.info(f"Could not locate the {module_file} inside {pretrained_model_name_or_path}.")
424
+ raise
425
+
426
+ # Check we have all the requirements in our environment
427
+ modules_needed = check_imports(resolved_module_file)
428
+
429
+ # Now we move the module inside our cached dynamic modules.
430
+ full_submodule = TRANSFORMERS_DYNAMIC_MODULE_NAME + os.path.sep + submodule
431
+ create_dynamic_module(full_submodule)
432
+ submodule_path = Path(HF_MODULES_CACHE) / full_submodule
433
+ if submodule == _sanitize_module_name(os.path.basename(pretrained_model_name_or_path)):
434
+ # We copy local files to avoid putting too many folders in sys.path. This copy is done when the file is new or
435
+ # has changed since last copy.
436
+ if not (submodule_path / module_file).exists() or not filecmp.cmp(
437
+ resolved_module_file, str(submodule_path / module_file)
438
+ ):
439
+ (submodule_path / module_file).parent.mkdir(parents=True, exist_ok=True)
440
+ shutil.copy(resolved_module_file, submodule_path / module_file)
441
+ importlib.invalidate_caches()
442
+ for module_needed in modules_needed:
443
+ module_needed = Path(module_file).parent / f"{module_needed}.py"
444
+ module_needed_file = os.path.join(pretrained_model_name_or_path, module_needed)
445
+ if not (submodule_path / module_needed).exists() or not filecmp.cmp(
446
+ module_needed_file, str(submodule_path / module_needed)
447
+ ):
448
+ shutil.copy(module_needed_file, submodule_path / module_needed)
449
+ importlib.invalidate_caches()
450
+ else:
451
+ # Get the commit hash
452
+ commit_hash = extract_commit_hash(resolved_module_file, _commit_hash)
453
+
454
+ # The module file will end up being placed in a subfolder with the git hash of the repo. This way we get the
455
+ # benefit of versioning.
456
+ submodule_path = submodule_path / commit_hash
457
+ full_submodule = full_submodule + os.path.sep + commit_hash
458
+ full_submodule_module_file_path = os.path.join(full_submodule, module_file)
459
+ create_dynamic_module(Path(full_submodule_module_file_path).parent)
460
+
461
+ if not (submodule_path / module_file).exists():
462
+ shutil.copy(resolved_module_file, submodule_path / module_file)
463
+ importlib.invalidate_caches()
464
+ # Make sure we also have every file with relative
465
+ for module_needed in modules_needed:
466
+ if not ((submodule_path / module_file).parent / f"{module_needed}.py").exists():
467
+ get_cached_module_file(
468
+ pretrained_model_name_or_path,
469
+ f"{Path(module_file).parent / module_needed}.py",
470
+ cache_dir=cache_dir,
471
+ force_download=force_download,
472
+ resume_download=resume_download,
473
+ proxies=proxies,
474
+ token=token,
475
+ revision=revision,
476
+ local_files_only=local_files_only,
477
+ _commit_hash=commit_hash,
478
+ )
479
+ new_files.append(f"{module_needed}.py")
480
+
481
+ if len(new_files) > 0 and revision is None:
482
+ new_files = "\n".join([f"- {f}" for f in new_files])
483
+ repo_type_str = "" if repo_type is None else f"{repo_type}s/"
484
+ url = f"https://huggingface.co/{repo_type_str}{pretrained_model_name_or_path}"
485
+ logger.warning(
486
+ f"A new version of the following files was downloaded from {url}:\n{new_files}"
487
+ "\n. Make sure to double-check they do not contain any added malicious code. To avoid downloading new "
488
+ "versions of the code file, you can pin a revision."
489
+ )
490
+
491
+ return os.path.join(full_submodule, module_file)
492
+
493
+
494
+ def get_class_from_dynamic_module(
495
+ class_reference: str,
496
+ pretrained_model_name_or_path: Union[str, os.PathLike],
497
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
498
+ force_download: bool = False,
499
+ resume_download: Optional[bool] = None,
500
+ proxies: Optional[dict[str, str]] = None,
501
+ token: Optional[Union[bool, str]] = None,
502
+ revision: Optional[str] = None,
503
+ local_files_only: bool = False,
504
+ repo_type: Optional[str] = None,
505
+ code_revision: Optional[str] = None,
506
+ **kwargs,
507
+ ) -> type:
508
+ """
509
+ Extracts a class from a module file, present in the local folder or repository of a model.
510
+
511
+ <Tip warning={true}>
512
+
513
+ Calling this function will execute the code in the module file found locally or downloaded from the Hub. It should
514
+ therefore only be called on trusted repos.
515
+
516
+ </Tip>
517
+
518
+
519
+
520
+ Args:
521
+ class_reference (`str`):
522
+ The full name of the class to load, including its module and optionally its repo.
523
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
524
+ This can be either:
525
+
526
+ - a string, the *model id* of a pretrained model configuration hosted inside a model repo on
527
+ huggingface.co.
528
+ - a path to a *directory* containing a configuration file saved using the
529
+ [`~PreTrainedTokenizer.save_pretrained`] method, e.g., `./my_model_directory/`.
530
+
531
+ This is used when `class_reference` does not specify another repo.
532
+ module_file (`str`):
533
+ The name of the module file containing the class to look for.
534
+ class_name (`str`):
535
+ The name of the class to import in the module.
536
+ cache_dir (`str` or `os.PathLike`, *optional*):
537
+ Path to a directory in which a downloaded pretrained model configuration should be cached if the standard
538
+ cache should not be used.
539
+ force_download (`bool`, *optional*, defaults to `False`):
540
+ Whether or not to force to (re-)download the configuration files and override the cached versions if they
541
+ exist.
542
+ resume_download:
543
+ Deprecated and ignored. All downloads are now resumed by default when possible.
544
+ Will be removed in v5 of Transformers.
545
+ proxies (`dict[str, str]`, *optional*):
546
+ A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
547
+ 'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.
548
+ token (`str` or `bool`, *optional*):
549
+ The token to use as HTTP bearer authorization for remote files. If `True`, will use the token generated
550
+ when running `hf auth login` (stored in `~/.huggingface`).
551
+ revision (`str`, *optional*, defaults to `"main"`):
552
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
553
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
554
+ identifier allowed by git.
555
+ local_files_only (`bool`, *optional*, defaults to `False`):
556
+ If `True`, will only try to load the tokenizer configuration from local files.
557
+ repo_type (`str`, *optional*):
558
+ Specify the repo type (useful when downloading from a space for instance).
559
+ code_revision (`str`, *optional*, defaults to `"main"`):
560
+ The specific revision to use for the code on the Hub, if the code leaves in a different repository than the
561
+ rest of the model. It can be a branch name, a tag name, or a commit id, since we use a git-based system for
562
+ storing models and other artifacts on huggingface.co, so `revision` can be any identifier allowed by git.
563
+
564
+ <Tip>
565
+
566
+ Passing `token=True` is required when you want to use a private model.
567
+
568
+ </Tip>
569
+
570
+ Returns:
571
+ `typing.Type`: The class, dynamically imported from the module.
572
+
573
+ Examples:
574
+
575
+ ```python
576
+ # Download module `modeling.py` from huggingface.co and cache then extract the class `MyBertModel` from this
577
+ # module.
578
+ cls = get_class_from_dynamic_module("modeling.MyBertModel", "sgugger/my-bert-model")
579
+
580
+ # Download module `modeling.py` from a given repo and cache then extract the class `MyBertModel` from this
581
+ # module.
582
+ cls = get_class_from_dynamic_module("sgugger/my-bert-model--modeling.MyBertModel", "sgugger/another-bert-model")
583
+ ```"""
584
+ use_auth_token = kwargs.pop("use_auth_token", None)
585
+ if use_auth_token is not None:
586
+ warnings.warn(
587
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
588
+ FutureWarning,
589
+ )
590
+ if token is not None:
591
+ raise ValueError("`token` and `use_auth_token` are both specified. Please set only the argument `token`.")
592
+ token = use_auth_token
593
+
594
+ # Catch the name of the repo if it's specified in `class_reference`
595
+ if "--" in class_reference:
596
+ repo_id, class_reference = class_reference.split("--")
597
+ else:
598
+ repo_id = pretrained_model_name_or_path
599
+ module_file, class_name = class_reference.split(".")
600
+
601
+ if code_revision is None and pretrained_model_name_or_path == repo_id:
602
+ code_revision = revision
603
+ # And lastly we get the class inside our newly created module
604
+ final_module = get_cached_module_file(
605
+ repo_id,
606
+ module_file + ".py",
607
+ cache_dir=cache_dir,
608
+ force_download=force_download,
609
+ resume_download=resume_download,
610
+ proxies=proxies,
611
+ token=token,
612
+ revision=code_revision,
613
+ local_files_only=local_files_only,
614
+ repo_type=repo_type,
615
+ )
616
+ return get_class_in_module(class_name, final_module, force_reload=force_download)
617
+
618
+
619
+ def custom_object_save(obj: Any, folder: Union[str, os.PathLike], config: Optional[dict] = None) -> list[str]:
620
+ """
621
+ Save the modeling files corresponding to a custom model/configuration/tokenizer etc. in a given folder. Optionally
622
+ adds the proper fields in a config.
623
+
624
+ Args:
625
+ obj (`Any`): The object for which to save the module files.
626
+ folder (`str` or `os.PathLike`): The folder where to save.
627
+ config (`PretrainedConfig` or dictionary, `optional`):
628
+ A config in which to register the auto_map corresponding to this custom object.
629
+
630
+ Returns:
631
+ `list[str]`: The list of files saved.
632
+ """
633
+ if obj.__module__ == "__main__":
634
+ logger.warning(
635
+ f"We can't save the code defining {obj} in {folder} as it's been defined in __main__. You should put "
636
+ "this code in a separate module so we can include it in the saved folder and make it easier to share via "
637
+ "the Hub."
638
+ )
639
+ return
640
+
641
+ def _set_auto_map_in_config(_config):
642
+ module_name = obj.__class__.__module__
643
+ last_module = module_name.split(".")[-1]
644
+ full_name = f"{last_module}.{obj.__class__.__name__}"
645
+ # Special handling for tokenizers
646
+ if "Tokenizer" in full_name:
647
+ slow_tokenizer_class = None
648
+ fast_tokenizer_class = None
649
+ if obj.__class__.__name__.endswith("Fast"):
650
+ # Fast tokenizer: we have the fast tokenizer class and we may have the slow one has an attribute.
651
+ fast_tokenizer_class = f"{last_module}.{obj.__class__.__name__}"
652
+ if getattr(obj, "slow_tokenizer_class", None) is not None:
653
+ slow_tokenizer = getattr(obj, "slow_tokenizer_class")
654
+ slow_tok_module_name = slow_tokenizer.__module__
655
+ last_slow_tok_module = slow_tok_module_name.split(".")[-1]
656
+ slow_tokenizer_class = f"{last_slow_tok_module}.{slow_tokenizer.__name__}"
657
+ else:
658
+ # Slow tokenizer: no way to have the fast class
659
+ slow_tokenizer_class = f"{last_module}.{obj.__class__.__name__}"
660
+
661
+ full_name = (slow_tokenizer_class, fast_tokenizer_class)
662
+
663
+ if isinstance(_config, dict):
664
+ auto_map = _config.get("auto_map", {})
665
+ auto_map[obj._auto_class] = full_name
666
+ _config["auto_map"] = auto_map
667
+ elif getattr(_config, "auto_map", None) is not None:
668
+ _config.auto_map[obj._auto_class] = full_name
669
+ else:
670
+ _config.auto_map = {obj._auto_class: full_name}
671
+
672
+ # Add object class to the config auto_map
673
+ if isinstance(config, (list, tuple)):
674
+ for cfg in config:
675
+ _set_auto_map_in_config(cfg)
676
+ elif config is not None:
677
+ _set_auto_map_in_config(config)
678
+
679
+ result = []
680
+ # Copy module file to the output folder.
681
+ object_file = sys.modules[obj.__module__].__file__
682
+ dest_file = Path(folder) / (Path(object_file).name)
683
+ shutil.copy(object_file, dest_file)
684
+ result.append(dest_file)
685
+
686
+ # Gather all relative imports recursively and make sure they are copied as well.
687
+ for needed_file in get_relative_import_files(object_file):
688
+ dest_file = Path(folder) / (Path(needed_file).name)
689
+ shutil.copy(needed_file, dest_file)
690
+ result.append(dest_file)
691
+
692
+ return result
693
+
694
+
695
+ def _raise_timeout_error(signum, frame):
696
+ raise ValueError(
697
+ "Loading this model requires you to execute custom code contained in the model repository on your local "
698
+ "machine. Please set the option `trust_remote_code=True` to permit loading of this model."
699
+ )
700
+
701
+
702
+ TIME_OUT_REMOTE_CODE = 15
703
+
704
+
705
+ def resolve_trust_remote_code(
706
+ trust_remote_code, model_name, has_local_code, has_remote_code, error_message=None, upstream_repo=None
707
+ ):
708
+ """
709
+ Resolves the `trust_remote_code` argument. If there is remote code to be loaded, the user must opt-in to loading
710
+ it.
711
+
712
+ Args:
713
+ trust_remote_code (`bool` or `None`):
714
+ User-defined `trust_remote_code` value.
715
+ model_name (`str`):
716
+ The name of the model repository in huggingface.co.
717
+ has_local_code (`bool`):
718
+ Whether the model has local code.
719
+ has_remote_code (`bool`):
720
+ Whether the model has remote code.
721
+ error_message (`str`, *optional*):
722
+ Custom error message to display if there is remote code to load and the user didn't opt-in. If unset, the error
723
+ message will be regarding loading a model with custom code.
724
+
725
+ Returns:
726
+ The resolved `trust_remote_code` value.
727
+ """
728
+ if error_message is None:
729
+ if upstream_repo is not None:
730
+ error_message = (
731
+ f"The repository {model_name} references custom code contained in {upstream_repo} which "
732
+ f"must be executed to correctly load the model. You can inspect the repository "
733
+ f"content at https://hf.co/{upstream_repo} .\n"
734
+ )
735
+ elif os.path.isdir(model_name):
736
+ error_message = (
737
+ f"The repository {model_name} contains custom code which must be executed "
738
+ f"to correctly load the model. You can inspect the repository "
739
+ f"content at {os.path.abspath(model_name)} .\n"
740
+ )
741
+ else:
742
+ error_message = (
743
+ f"The repository {model_name} contains custom code which must be executed "
744
+ f"to correctly load the model. You can inspect the repository "
745
+ f"content at https://hf.co/{model_name} .\n"
746
+ )
747
+
748
+ if trust_remote_code is None:
749
+ if has_local_code:
750
+ trust_remote_code = False
751
+ elif has_remote_code and TIME_OUT_REMOTE_CODE > 0:
752
+ prev_sig_handler = None
753
+ try:
754
+ prev_sig_handler = signal.signal(signal.SIGALRM, _raise_timeout_error)
755
+ signal.alarm(TIME_OUT_REMOTE_CODE)
756
+ while trust_remote_code is None:
757
+ answer = input(
758
+ f"{error_message} You can inspect the repository content at https://hf.co/{model_name}.\n"
759
+ f"You can avoid this prompt in future by passing the argument `trust_remote_code=True`.\n\n"
760
+ f"Do you wish to run the custom code? [y/N] "
761
+ )
762
+ if answer.lower() in ["yes", "y", "1"]:
763
+ trust_remote_code = True
764
+ elif answer.lower() in ["no", "n", "0", ""]:
765
+ trust_remote_code = False
766
+ signal.alarm(0)
767
+ except Exception:
768
+ # OS which does not support signal.SIGALRM
769
+ raise ValueError(
770
+ f"{error_message} You can inspect the repository content at https://hf.co/{model_name}.\n"
771
+ f"Please pass the argument `trust_remote_code=True` to allow custom code to be run."
772
+ )
773
+ finally:
774
+ if prev_sig_handler is not None:
775
+ signal.signal(signal.SIGALRM, prev_sig_handler)
776
+ signal.alarm(0)
777
+ elif has_remote_code:
778
+ # For the CI which puts the timeout at 0
779
+ _raise_timeout_error(None, None)
780
+
781
+ if has_remote_code and not has_local_code and not trust_remote_code:
782
+ raise ValueError(
783
+ f"{error_message} You can inspect the repository content at https://hf.co/{model_name}.\n"
784
+ f"Please pass the argument `trust_remote_code=True` to allow custom code to be run."
785
+ )
786
+
787
+ return trust_remote_code
788
+
789
+
790
+ def check_python_requirements(path_or_repo_id, requirements_file="requirements.txt", **kwargs):
791
+ """
792
+ Tries to locate `requirements_file` in a local folder or repo, and confirms that the environment has all the
793
+ python dependencies installed.
794
+
795
+ Args:
796
+ path_or_repo_id (`str` or `os.PathLike`):
797
+ This can be either:
798
+ - a string, the *model id* of a model repo on huggingface.co.
799
+ - a path to a *directory* potentially containing the file.
800
+ kwargs (`dict[str, Any]`, *optional*):
801
+ Additional arguments to pass to `cached_file`.
802
+ """
803
+ failed = [] # error messages regarding requirements
804
+ try:
805
+ requirements = cached_file(path_or_repo_id=path_or_repo_id, filename=requirements_file, **kwargs)
806
+ with open(requirements, "r") as f:
807
+ requirements = f.readlines()
808
+
809
+ for requirement in requirements:
810
+ requirement = requirement.strip()
811
+ if not requirement or requirement.startswith("#"): # skip empty lines and comments
812
+ continue
813
+
814
+ try:
815
+ # e.g. "torch>2.6.0" -> "torch", ">", "2.6.0"
816
+ package_name, delimiter, version_number = split_package_version(requirement)
817
+ except ValueError: # e.g. "torch", as opposed to "torch>2.6.0"
818
+ package_name = requirement
819
+ delimiter, version_number = None, None
820
+
821
+ try:
822
+ local_package_version = importlib.metadata.version(package_name)
823
+ except importlib.metadata.PackageNotFoundError:
824
+ failed.append(f"{requirement} (installed: None)")
825
+ continue
826
+
827
+ if delimiter is not None and version_number is not None:
828
+ is_satisfied = VersionComparison.from_string(delimiter)(
829
+ version.parse(local_package_version), version.parse(version_number)
830
+ )
831
+ else:
832
+ is_satisfied = True
833
+
834
+ if not is_satisfied:
835
+ failed.append(f"{requirement} (installed: {local_package_version})")
836
+
837
+ except OSError: # no requirements.txt
838
+ pass
839
+
840
+ if failed:
841
+ raise ImportError(
842
+ f"Missing requirements in your local environment for `{path_or_repo_id}`:\n" + "\n".join(failed)
843
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/feature_extraction_sequence_utils.py ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ Sequence feature extraction class for common feature extractors to preprocess sequences.
16
+ """
17
+
18
+ from typing import Optional, Union
19
+
20
+ import numpy as np
21
+
22
+ from .feature_extraction_utils import BatchFeature, FeatureExtractionMixin
23
+ from .utils import PaddingStrategy, TensorType, is_tf_tensor, is_torch_tensor, logging, to_numpy
24
+
25
+
26
+ logger = logging.get_logger(__name__)
27
+
28
+
29
+ class SequenceFeatureExtractor(FeatureExtractionMixin):
30
+ """
31
+ This is a general feature extraction class for speech recognition.
32
+
33
+ Args:
34
+ feature_size (`int`):
35
+ The feature dimension of the extracted features.
36
+ sampling_rate (`int`):
37
+ The sampling rate at which the audio files should be digitalized expressed in hertz (Hz).
38
+ padding_value (`float`):
39
+ The value that is used to fill the padding values / vectors.
40
+ """
41
+
42
+ def __init__(self, feature_size: int, sampling_rate: int, padding_value: float, **kwargs):
43
+ self.feature_size = feature_size
44
+ self.sampling_rate = sampling_rate
45
+ self.padding_value = padding_value
46
+
47
+ self.padding_side = kwargs.pop("padding_side", "right")
48
+ self.return_attention_mask = kwargs.pop("return_attention_mask", True)
49
+
50
+ super().__init__(**kwargs)
51
+
52
+ def pad(
53
+ self,
54
+ processed_features: Union[
55
+ BatchFeature,
56
+ list[BatchFeature],
57
+ dict[str, BatchFeature],
58
+ dict[str, list[BatchFeature]],
59
+ list[dict[str, BatchFeature]],
60
+ ],
61
+ padding: Union[bool, str, PaddingStrategy] = True,
62
+ max_length: Optional[int] = None,
63
+ truncation: bool = False,
64
+ pad_to_multiple_of: Optional[int] = None,
65
+ return_attention_mask: Optional[bool] = None,
66
+ return_tensors: Optional[Union[str, TensorType]] = None,
67
+ ) -> BatchFeature:
68
+ """
69
+ Pad input values / input vectors or a batch of input values / input vectors up to predefined length or to the
70
+ max sequence length in the batch.
71
+
72
+ Padding side (left/right) padding values are defined at the feature extractor level (with `self.padding_side`,
73
+ `self.padding_value`)
74
+
75
+ <Tip>
76
+
77
+ If the `processed_features` passed are dictionary of numpy arrays, PyTorch tensors or TensorFlow tensors, the
78
+ result will use the same type unless you provide a different tensor type with `return_tensors`. In the case of
79
+ PyTorch tensors, you will lose the specific device of your tensors however.
80
+
81
+ </Tip>
82
+
83
+ Args:
84
+ processed_features ([`BatchFeature`], list of [`BatchFeature`], `dict[str, list[float]]`, `dict[str, list[list[float]]` or `list[dict[str, list[float]]]`):
85
+ Processed inputs. Can represent one input ([`BatchFeature`] or `dict[str, list[float]]`) or a batch of
86
+ input values / vectors (list of [`BatchFeature`], *dict[str, list[list[float]]]* or *list[dict[str,
87
+ list[float]]]*) so you can use this method during preprocessing as well as in a PyTorch Dataloader
88
+ collate function.
89
+
90
+ Instead of `list[float]` you can have tensors (numpy arrays, PyTorch tensors or TensorFlow tensors),
91
+ see the note above for the return type.
92
+ padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `True`):
93
+ Select a strategy to pad the returned sequences (according to the model's padding side and padding
94
+ index) among:
95
+
96
+ - `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single
97
+ sequence if provided).
98
+ - `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
99
+ acceptable input length for the model if that argument is not provided.
100
+ - `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
101
+ lengths).
102
+ max_length (`int`, *optional*):
103
+ Maximum length of the returned list and optionally padding length (see above).
104
+ truncation (`bool`):
105
+ Activates truncation to cut input sequences longer than `max_length` to `max_length`.
106
+ pad_to_multiple_of (`int`, *optional*):
107
+ If set will pad the sequence to a multiple of the provided value.
108
+
109
+ This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability
110
+ `>= 7.5` (Volta), or on TPUs which benefit from having sequence lengths be a multiple of 128.
111
+ return_attention_mask (`bool`, *optional*):
112
+ Whether to return the attention mask. If left to the default, will return the attention mask according
113
+ to the specific feature_extractor's default.
114
+
115
+ [What are attention masks?](../glossary#attention-mask)
116
+ return_tensors (`str` or [`~utils.TensorType`], *optional*):
117
+ If set, will return tensors instead of list of python integers. Acceptable values are:
118
+
119
+ - `'tf'`: Return TensorFlow `tf.constant` objects.
120
+ - `'pt'`: Return PyTorch `torch.Tensor` objects.
121
+ - `'np'`: Return Numpy `np.ndarray` objects.
122
+ """
123
+ # If we have a list of dicts, let's convert it in a dict of lists
124
+ # We do this to allow using this method as a collate_fn function in PyTorch Dataloader
125
+ if isinstance(processed_features, (list, tuple)) and isinstance(processed_features[0], (dict, BatchFeature)):
126
+ processed_features = {
127
+ key: [example[key] for example in processed_features] for key in processed_features[0]
128
+ }
129
+
130
+ # The model's main input name, usually `input_values`, has be passed for padding
131
+ if self.model_input_names[0] not in processed_features:
132
+ raise ValueError(
133
+ "You should supply an instance of `transformers.BatchFeature` or list of `transformers.BatchFeature`"
134
+ f" to this method that includes {self.model_input_names[0]}, but you provided"
135
+ f" {list(processed_features.keys())}"
136
+ )
137
+
138
+ required_input = processed_features[self.model_input_names[0]]
139
+ return_attention_mask = (
140
+ return_attention_mask if return_attention_mask is not None else self.return_attention_mask
141
+ )
142
+
143
+ if len(required_input) == 0:
144
+ if return_attention_mask:
145
+ processed_features["attention_mask"] = []
146
+ return processed_features
147
+
148
+ # If we have PyTorch/TF tensors or lists as inputs, we cast them as Numpy arrays
149
+ # and rebuild them afterwards if no return_tensors is specified
150
+ # Note that we lose the specific device the tensor may be on for PyTorch
151
+
152
+ first_element = required_input[0]
153
+ if isinstance(first_element, (list, tuple)):
154
+ # first_element might be an empty list/tuple in some edge cases so we grab the first non empty element.
155
+ index = 0
156
+ while len(required_input[index]) == 0:
157
+ index += 1
158
+ if index < len(required_input):
159
+ first_element = required_input[index][0]
160
+
161
+ if return_tensors is None:
162
+ if is_tf_tensor(first_element):
163
+ return_tensors = "tf"
164
+ elif is_torch_tensor(first_element):
165
+ return_tensors = "pt"
166
+ elif isinstance(first_element, (int, float, list, tuple, np.ndarray)):
167
+ return_tensors = "np"
168
+ else:
169
+ raise ValueError(
170
+ f"type of {first_element} unknown: {type(first_element)}. "
171
+ "Should be one of a python, numpy, pytorch or tensorflow object."
172
+ )
173
+
174
+ for key, value in processed_features.items():
175
+ if isinstance(value[0], (int, float)):
176
+ processed_features[key] = to_numpy(value)
177
+ else:
178
+ processed_features[key] = [to_numpy(v) for v in value]
179
+
180
+ # Convert padding_strategy in PaddingStrategy
181
+ padding_strategy = self._get_padding_strategies(padding=padding, max_length=max_length)
182
+
183
+ required_input = processed_features[self.model_input_names[0]]
184
+
185
+ batch_size = len(required_input)
186
+ if not all(len(v) == batch_size for v in processed_features.values()):
187
+ raise ValueError("Some items in the output dictionary have a different batch size than others.")
188
+
189
+ truncated_inputs = []
190
+ for i in range(batch_size):
191
+ inputs = {k: v[i] for k, v in processed_features.items()}
192
+ # truncation
193
+ inputs_slice = self._truncate(
194
+ inputs,
195
+ max_length=max_length,
196
+ pad_to_multiple_of=pad_to_multiple_of,
197
+ truncation=truncation,
198
+ )
199
+ truncated_inputs.append(inputs_slice)
200
+
201
+ if padding_strategy == PaddingStrategy.LONGEST:
202
+ # make sure that `max_length` cannot be longer than the longest truncated length
203
+ max_length = max(len(input_slice[self.model_input_names[0]]) for input_slice in truncated_inputs)
204
+ padding_strategy = PaddingStrategy.MAX_LENGTH
205
+
206
+ batch_outputs = {}
207
+ for i in range(batch_size):
208
+ # padding
209
+ outputs = self._pad(
210
+ truncated_inputs[i],
211
+ max_length=max_length,
212
+ padding_strategy=padding_strategy,
213
+ pad_to_multiple_of=pad_to_multiple_of,
214
+ return_attention_mask=return_attention_mask,
215
+ )
216
+
217
+ for key, value in outputs.items():
218
+ if key not in batch_outputs:
219
+ batch_outputs[key] = []
220
+ if value.dtype is np.dtype(np.float64):
221
+ value = value.astype(np.float32)
222
+ batch_outputs[key].append(value)
223
+
224
+ return BatchFeature(batch_outputs, tensor_type=return_tensors)
225
+
226
+ def _pad(
227
+ self,
228
+ processed_features: Union[dict[str, np.ndarray], BatchFeature],
229
+ max_length: Optional[int] = None,
230
+ padding_strategy: PaddingStrategy = PaddingStrategy.DO_NOT_PAD,
231
+ pad_to_multiple_of: Optional[int] = None,
232
+ return_attention_mask: Optional[bool] = None,
233
+ ) -> dict:
234
+ """
235
+ Pad inputs (on left/right and up to predefined length or max length in the batch)
236
+
237
+ Args:
238
+ processed_features (`Union[dict[str, np.ndarray], BatchFeature]`):
239
+ Dictionary of input values (`np.ndarray[float]`) / input vectors (`list[np.ndarray[float]]`) or batch
240
+ of inputs values (`list[np.ndarray[int]]`) / input vectors (`list[np.ndarray[int]]`)
241
+ max_length (`int`, *optional*):
242
+ Maximum length of the returned list and optionally padding length (see below)
243
+ padding_strategy (`PaddingStrategy`, *optional*, default to `PaddingStrategy.DO_NOT_PAD`):
244
+ PaddingStrategy to use for padding.
245
+
246
+ - PaddingStrategy.LONGEST Pad to the longest sequence in the batch
247
+ - PaddingStrategy.MAX_LENGTH: Pad to the max length (default)
248
+ - PaddingStrategy.DO_NOT_PAD: Do not pad
249
+ The feature_extractor padding sides are defined in self.padding_side:
250
+
251
+ - 'left': pads on the left of the sequences
252
+ - 'right': pads on the right of the sequences
253
+ pad_to_multiple_of (`int`, *optional*):
254
+ Integer if set will pad the sequence to a multiple of the provided value. This is especially useful to
255
+ enable the use of Tensor Core on NVIDIA hardware with compute capability `>= 7.5` (Volta), or on TPUs
256
+ which benefit from having sequence lengths be a multiple of 128.
257
+ return_attention_mask (`bool`, *optional*):
258
+ Set to False to avoid returning attention mask (default: set to model specifics)
259
+ """
260
+ required_input = processed_features[self.model_input_names[0]]
261
+
262
+ if padding_strategy == PaddingStrategy.LONGEST:
263
+ max_length = len(required_input)
264
+
265
+ if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
266
+ max_length = ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of
267
+
268
+ needs_to_be_padded = padding_strategy != PaddingStrategy.DO_NOT_PAD and len(required_input) < max_length
269
+
270
+ if return_attention_mask and "attention_mask" not in processed_features:
271
+ processed_features["attention_mask"] = np.ones(len(required_input), dtype=np.int32)
272
+
273
+ if needs_to_be_padded:
274
+ difference = max_length - len(required_input)
275
+ if self.padding_side == "right":
276
+ if return_attention_mask:
277
+ processed_features["attention_mask"] = np.pad(
278
+ processed_features["attention_mask"], (0, difference)
279
+ )
280
+ padding_shape = ((0, difference), (0, 0)) if self.feature_size > 1 else (0, difference)
281
+ processed_features[self.model_input_names[0]] = np.pad(
282
+ required_input, padding_shape, "constant", constant_values=self.padding_value
283
+ )
284
+ elif self.padding_side == "left":
285
+ if return_attention_mask:
286
+ processed_features["attention_mask"] = np.pad(
287
+ processed_features["attention_mask"], (difference, 0)
288
+ )
289
+ padding_shape = ((difference, 0), (0, 0)) if self.feature_size > 1 else (difference, 0)
290
+ processed_features[self.model_input_names[0]] = np.pad(
291
+ required_input, padding_shape, "constant", constant_values=self.padding_value
292
+ )
293
+ else:
294
+ raise ValueError("Invalid padding strategy:" + str(self.padding_side))
295
+
296
+ return processed_features
297
+
298
+ def _truncate(
299
+ self,
300
+ processed_features: Union[dict[str, np.ndarray], BatchFeature],
301
+ max_length: Optional[int] = None,
302
+ pad_to_multiple_of: Optional[int] = None,
303
+ truncation: Optional[bool] = None,
304
+ ):
305
+ """
306
+ Truncate inputs to predefined length or max length in the batch
307
+
308
+ Args:
309
+ processed_features(`Union[dict[str, np.ndarray], BatchFeature]`):
310
+ Dictionary of input values (`np.ndarray[float]`) / input vectors (`list[np.ndarray[float]]`) or batch
311
+ of inputs values (`list[np.ndarray[int]]`) / input vectors (`list[np.ndarray[int]]`)
312
+ max_length (`int`, *optional*):
313
+ maximum length of the returned list and optionally padding length (see below)
314
+ pad_to_multiple_of (`int`, *optional*) :
315
+ Integer if set will pad the sequence to a multiple of the provided value. This is especially useful to
316
+ enable the use of Tensor Core on NVIDIA hardware with compute capability `>= 7.5` (Volta), or on TPUs
317
+ which benefit from having sequence lengths be a multiple of 128.
318
+ truncation (`bool`, *optional*):
319
+ Activates truncation to cut input sequences longer than `max_length` to `max_length`.
320
+ """
321
+ if not truncation:
322
+ return processed_features
323
+ elif truncation and max_length is None:
324
+ raise ValueError("When setting ``truncation=True``, make sure that ``max_length`` is defined.")
325
+
326
+ required_input = processed_features[self.model_input_names[0]]
327
+
328
+ # find `max_length` that fits `pad_to_multiple_of`
329
+ if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
330
+ max_length = ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of
331
+
332
+ needs_to_be_truncated = len(required_input) > max_length
333
+
334
+ if needs_to_be_truncated:
335
+ processed_features[self.model_input_names[0]] = processed_features[self.model_input_names[0]][:max_length]
336
+ if "attention_mask" in processed_features:
337
+ processed_features["attention_mask"] = processed_features["attention_mask"][:max_length]
338
+
339
+ return processed_features
340
+
341
+ def _get_padding_strategies(self, padding=False, max_length=None):
342
+ """
343
+ Find the correct padding strategy
344
+ """
345
+
346
+ # Get padding strategy
347
+ if padding is not False:
348
+ if padding is True:
349
+ padding_strategy = PaddingStrategy.LONGEST # Default to pad to the longest sequence in the batch
350
+ elif not isinstance(padding, PaddingStrategy):
351
+ padding_strategy = PaddingStrategy(padding)
352
+ elif isinstance(padding, PaddingStrategy):
353
+ padding_strategy = padding
354
+ else:
355
+ padding_strategy = PaddingStrategy.DO_NOT_PAD
356
+
357
+ # Set max length if needed
358
+ if max_length is None:
359
+ if padding_strategy == PaddingStrategy.MAX_LENGTH:
360
+ raise ValueError(
361
+ f"When setting ``padding={PaddingStrategy.MAX_LENGTH}``, make sure that max_length is defined"
362
+ )
363
+
364
+ # Test if we have a padding value
365
+ if padding_strategy != PaddingStrategy.DO_NOT_PAD and (self.padding_value is None):
366
+ raise ValueError(
367
+ "Asking to pad but the feature_extractor does not have a padding value. Please select a value to use"
368
+ " as `padding_value`. For example: `feature_extractor.padding_value = 0.0`."
369
+ )
370
+
371
+ return padding_strategy
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/feature_extraction_utils.py ADDED
@@ -0,0 +1,697 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ Feature extraction saving/loading class for common feature extractors.
16
+ """
17
+
18
+ import copy
19
+ import json
20
+ import os
21
+ import warnings
22
+ from collections import UserDict
23
+ from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
24
+
25
+ import numpy as np
26
+
27
+ from .dynamic_module_utils import custom_object_save
28
+ from .utils import (
29
+ FEATURE_EXTRACTOR_NAME,
30
+ PROCESSOR_NAME,
31
+ PushToHubMixin,
32
+ TensorType,
33
+ copy_func,
34
+ download_url,
35
+ is_flax_available,
36
+ is_jax_tensor,
37
+ is_numpy_array,
38
+ is_offline_mode,
39
+ is_remote_url,
40
+ is_tf_available,
41
+ is_torch_available,
42
+ is_torch_device,
43
+ is_torch_dtype,
44
+ logging,
45
+ requires_backends,
46
+ )
47
+ from .utils.hub import cached_file
48
+
49
+
50
+ if TYPE_CHECKING:
51
+ from .feature_extraction_sequence_utils import SequenceFeatureExtractor
52
+
53
+
54
+ logger = logging.get_logger(__name__)
55
+
56
+ PreTrainedFeatureExtractor = Union["SequenceFeatureExtractor"]
57
+
58
+ # type hinting: specifying the type of feature extractor class that inherits from FeatureExtractionMixin
59
+ SpecificFeatureExtractorType = TypeVar("SpecificFeatureExtractorType", bound="FeatureExtractionMixin")
60
+
61
+
62
+ class BatchFeature(UserDict):
63
+ r"""
64
+ Holds the output of the [`~SequenceFeatureExtractor.pad`] and feature extractor specific `__call__` methods.
65
+
66
+ This class is derived from a python dictionary and can be used as a dictionary.
67
+
68
+ Args:
69
+ data (`dict`, *optional*):
70
+ Dictionary of lists/arrays/tensors returned by the __call__/pad methods ('input_values', 'attention_mask',
71
+ etc.).
72
+ tensor_type (`Union[None, str, TensorType]`, *optional*):
73
+ You can give a tensor_type here to convert the lists of integers in PyTorch/TensorFlow/Numpy Tensors at
74
+ initialization.
75
+ """
76
+
77
+ def __init__(self, data: Optional[dict[str, Any]] = None, tensor_type: Union[None, str, TensorType] = None):
78
+ super().__init__(data)
79
+ self.convert_to_tensors(tensor_type=tensor_type)
80
+
81
+ def __getitem__(self, item: str) -> Any:
82
+ """
83
+ If the key is a string, returns the value of the dict associated to `key` ('input_values', 'attention_mask',
84
+ etc.).
85
+ """
86
+ if isinstance(item, str):
87
+ return self.data[item]
88
+ else:
89
+ raise KeyError("Indexing with integers is not available when using Python based feature extractors")
90
+
91
+ def __getattr__(self, item: str):
92
+ try:
93
+ return self.data[item]
94
+ except KeyError:
95
+ raise AttributeError
96
+
97
+ def __getstate__(self):
98
+ return {"data": self.data}
99
+
100
+ def __setstate__(self, state):
101
+ if "data" in state:
102
+ self.data = state["data"]
103
+
104
+ def _get_is_as_tensor_fns(self, tensor_type: Optional[Union[str, TensorType]] = None):
105
+ if tensor_type is None:
106
+ return None, None
107
+
108
+ # Convert to TensorType
109
+ if not isinstance(tensor_type, TensorType):
110
+ tensor_type = TensorType(tensor_type)
111
+
112
+ # Get a function reference for the correct framework
113
+ if tensor_type == TensorType.TENSORFLOW:
114
+ logger.warning_once(
115
+ "TensorFlow and JAX classes are deprecated and will be removed in Transformers v5. We "
116
+ "recommend migrating to PyTorch classes or pinning your version of Transformers."
117
+ )
118
+ if not is_tf_available():
119
+ raise ImportError(
120
+ "Unable to convert output to TensorFlow tensors format, TensorFlow is not installed."
121
+ )
122
+ import tensorflow as tf
123
+
124
+ as_tensor = tf.constant
125
+ is_tensor = tf.is_tensor
126
+ elif tensor_type == TensorType.PYTORCH:
127
+ if not is_torch_available():
128
+ raise ImportError("Unable to convert output to PyTorch tensors format, PyTorch is not installed.")
129
+ import torch
130
+
131
+ def as_tensor(value):
132
+ if isinstance(value, (list, tuple)) and len(value) > 0:
133
+ if isinstance(value[0], np.ndarray):
134
+ value = np.array(value)
135
+ elif (
136
+ isinstance(value[0], (list, tuple))
137
+ and len(value[0]) > 0
138
+ and isinstance(value[0][0], np.ndarray)
139
+ ):
140
+ value = np.array(value)
141
+ if isinstance(value, np.ndarray):
142
+ return torch.from_numpy(value)
143
+ else:
144
+ return torch.tensor(value)
145
+
146
+ is_tensor = torch.is_tensor
147
+ elif tensor_type == TensorType.JAX:
148
+ logger.warning_once(
149
+ "TensorFlow and JAX classes are deprecated and will be removed in Transformers v5. We "
150
+ "recommend migrating to PyTorch classes or pinning your version of Transformers."
151
+ )
152
+ if not is_flax_available():
153
+ raise ImportError("Unable to convert output to JAX tensors format, JAX is not installed.")
154
+ import jax.numpy as jnp # noqa: F811
155
+
156
+ as_tensor = jnp.array
157
+ is_tensor = is_jax_tensor
158
+ else:
159
+
160
+ def as_tensor(value, dtype=None):
161
+ if isinstance(value, (list, tuple)) and isinstance(value[0], (list, tuple, np.ndarray)):
162
+ value_lens = [len(val) for val in value]
163
+ if len(set(value_lens)) > 1 and dtype is None:
164
+ # we have a ragged list so handle explicitly
165
+ value = as_tensor([np.asarray(val) for val in value], dtype=object)
166
+ return np.asarray(value, dtype=dtype)
167
+
168
+ is_tensor = is_numpy_array
169
+ return is_tensor, as_tensor
170
+
171
+ def convert_to_tensors(self, tensor_type: Optional[Union[str, TensorType]] = None):
172
+ """
173
+ Convert the inner content to tensors.
174
+
175
+ Args:
176
+ tensor_type (`str` or [`~utils.TensorType`], *optional*):
177
+ The type of tensors to use. If `str`, should be one of the values of the enum [`~utils.TensorType`]. If
178
+ `None`, no modification is done.
179
+ """
180
+ if tensor_type is None:
181
+ return self
182
+
183
+ is_tensor, as_tensor = self._get_is_as_tensor_fns(tensor_type)
184
+
185
+ # Do the tensor conversion in batch
186
+ for key, value in self.items():
187
+ try:
188
+ if not is_tensor(value):
189
+ tensor = as_tensor(value)
190
+
191
+ self[key] = tensor
192
+ except: # noqa E722
193
+ if key == "overflowing_values":
194
+ raise ValueError("Unable to create tensor returning overflowing values of different lengths. ")
195
+ raise ValueError(
196
+ "Unable to create tensor, you should probably activate padding "
197
+ "with 'padding=True' to have batched tensors with the same length."
198
+ )
199
+
200
+ return self
201
+
202
+ def to(self, *args, **kwargs) -> "BatchFeature":
203
+ """
204
+ Send all values to device by calling `v.to(*args, **kwargs)` (PyTorch only). This should support casting in
205
+ different `dtypes` and sending the `BatchFeature` to a different `device`.
206
+
207
+ Args:
208
+ args (`Tuple`):
209
+ Will be passed to the `to(...)` function of the tensors.
210
+ kwargs (`Dict`, *optional*):
211
+ Will be passed to the `to(...)` function of the tensors.
212
+ To enable asynchronous data transfer, set the `non_blocking` flag in `kwargs` (defaults to `False`).
213
+
214
+ Returns:
215
+ [`BatchFeature`]: The same instance after modification.
216
+ """
217
+ requires_backends(self, ["torch"])
218
+ import torch
219
+
220
+ device = kwargs.get("device")
221
+ non_blocking = kwargs.get("non_blocking", False)
222
+ # Check if the args are a device or a dtype
223
+ if device is None and len(args) > 0:
224
+ # device should be always the first argument
225
+ arg = args[0]
226
+ if is_torch_dtype(arg):
227
+ # The first argument is a dtype
228
+ pass
229
+ elif isinstance(arg, str) or is_torch_device(arg) or isinstance(arg, int):
230
+ device = arg
231
+ else:
232
+ # it's something else
233
+ raise ValueError(f"Attempting to cast a BatchFeature to type {str(arg)}. This is not supported.")
234
+
235
+ # We cast only floating point tensors to avoid issues with tokenizers casting `LongTensor` to `FloatTensor`
236
+ def maybe_to(v):
237
+ # check if v is a floating point
238
+ if isinstance(v, torch.Tensor) and torch.is_floating_point(v):
239
+ # cast and send to device
240
+ return v.to(*args, **kwargs)
241
+ elif isinstance(v, torch.Tensor) and device is not None:
242
+ return v.to(device=device, non_blocking=non_blocking)
243
+ else:
244
+ return v
245
+
246
+ self.data = {k: maybe_to(v) for k, v in self.items()}
247
+ return self
248
+
249
+
250
+ class FeatureExtractionMixin(PushToHubMixin):
251
+ """
252
+ This is a feature extraction mixin used to provide saving/loading functionality for sequential and image feature
253
+ extractors.
254
+ """
255
+
256
+ _auto_class = None
257
+
258
+ def __init__(self, **kwargs):
259
+ """Set elements of `kwargs` as attributes."""
260
+ # Pop "processor_class" as it should be saved as private attribute
261
+ self._processor_class = kwargs.pop("processor_class", None)
262
+ # Additional attributes without default values
263
+ for key, value in kwargs.items():
264
+ try:
265
+ setattr(self, key, value)
266
+ except AttributeError as err:
267
+ logger.error(f"Can't set {key} with value {value} for {self}")
268
+ raise err
269
+
270
+ def _set_processor_class(self, processor_class: str):
271
+ """Sets processor class as an attribute."""
272
+ self._processor_class = processor_class
273
+
274
+ @classmethod
275
+ def from_pretrained(
276
+ cls: type[SpecificFeatureExtractorType],
277
+ pretrained_model_name_or_path: Union[str, os.PathLike],
278
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
279
+ force_download: bool = False,
280
+ local_files_only: bool = False,
281
+ token: Optional[Union[str, bool]] = None,
282
+ revision: str = "main",
283
+ **kwargs,
284
+ ) -> SpecificFeatureExtractorType:
285
+ r"""
286
+ Instantiate a type of [`~feature_extraction_utils.FeatureExtractionMixin`] from a feature extractor, *e.g.* a
287
+ derived class of [`SequenceFeatureExtractor`].
288
+
289
+ Args:
290
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
291
+ This can be either:
292
+
293
+ - a string, the *model id* of a pretrained feature_extractor hosted inside a model repo on
294
+ huggingface.co.
295
+ - a path to a *directory* containing a feature extractor file saved using the
296
+ [`~feature_extraction_utils.FeatureExtractionMixin.save_pretrained`] method, e.g.,
297
+ `./my_model_directory/`.
298
+ - a path or url to a saved feature extractor JSON *file*, e.g.,
299
+ `./my_model_directory/preprocessor_config.json`.
300
+ cache_dir (`str` or `os.PathLike`, *optional*):
301
+ Path to a directory in which a downloaded pretrained model feature extractor should be cached if the
302
+ standard cache should not be used.
303
+ force_download (`bool`, *optional*, defaults to `False`):
304
+ Whether or not to force to (re-)download the feature extractor files and override the cached versions
305
+ if they exist.
306
+ resume_download:
307
+ Deprecated and ignored. All downloads are now resumed by default when possible.
308
+ Will be removed in v5 of Transformers.
309
+ proxies (`dict[str, str]`, *optional*):
310
+ A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
311
+ 'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.
312
+ token (`str` or `bool`, *optional*):
313
+ The token to use as HTTP bearer authorization for remote files. If `True`, or not specified, will use
314
+ the token generated when running `hf auth login` (stored in `~/.huggingface`).
315
+ revision (`str`, *optional*, defaults to `"main"`):
316
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
317
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
318
+ identifier allowed by git.
319
+
320
+
321
+ <Tip>
322
+
323
+ To test a pull request you made on the Hub, you can pass `revision="refs/pr/<pr_number>"`.
324
+
325
+ </Tip>
326
+
327
+ return_unused_kwargs (`bool`, *optional*, defaults to `False`):
328
+ If `False`, then this function returns just the final feature extractor object. If `True`, then this
329
+ functions returns a `Tuple(feature_extractor, unused_kwargs)` where *unused_kwargs* is a dictionary
330
+ consisting of the key/value pairs whose keys are not feature extractor attributes: i.e., the part of
331
+ `kwargs` which has not been used to update `feature_extractor` and is otherwise ignored.
332
+ kwargs (`dict[str, Any]`, *optional*):
333
+ The values in kwargs of any keys which are feature extractor attributes will be used to override the
334
+ loaded values. Behavior concerning key/value pairs whose keys are *not* feature extractor attributes is
335
+ controlled by the `return_unused_kwargs` keyword parameter.
336
+
337
+ Returns:
338
+ A feature extractor of type [`~feature_extraction_utils.FeatureExtractionMixin`].
339
+
340
+ Examples:
341
+
342
+ ```python
343
+ # We can't instantiate directly the base class *FeatureExtractionMixin* nor *SequenceFeatureExtractor* so let's show the examples on a
344
+ # derived class: *Wav2Vec2FeatureExtractor*
345
+ feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(
346
+ "facebook/wav2vec2-base-960h"
347
+ ) # Download feature_extraction_config from huggingface.co and cache.
348
+ feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(
349
+ "./test/saved_model/"
350
+ ) # E.g. feature_extractor (or model) was saved using *save_pretrained('./test/saved_model/')*
351
+ feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained("./test/saved_model/preprocessor_config.json")
352
+ feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(
353
+ "facebook/wav2vec2-base-960h", return_attention_mask=False, foo=False
354
+ )
355
+ assert feature_extractor.return_attention_mask is False
356
+ feature_extractor, unused_kwargs = Wav2Vec2FeatureExtractor.from_pretrained(
357
+ "facebook/wav2vec2-base-960h", return_attention_mask=False, foo=False, return_unused_kwargs=True
358
+ )
359
+ assert feature_extractor.return_attention_mask is False
360
+ assert unused_kwargs == {"foo": False}
361
+ ```"""
362
+ kwargs["cache_dir"] = cache_dir
363
+ kwargs["force_download"] = force_download
364
+ kwargs["local_files_only"] = local_files_only
365
+ kwargs["revision"] = revision
366
+
367
+ use_auth_token = kwargs.pop("use_auth_token", None)
368
+ if use_auth_token is not None:
369
+ warnings.warn(
370
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
371
+ FutureWarning,
372
+ )
373
+ if token is not None:
374
+ raise ValueError(
375
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
376
+ )
377
+ token = use_auth_token
378
+
379
+ if token is not None:
380
+ kwargs["token"] = token
381
+
382
+ feature_extractor_dict, kwargs = cls.get_feature_extractor_dict(pretrained_model_name_or_path, **kwargs)
383
+
384
+ return cls.from_dict(feature_extractor_dict, **kwargs)
385
+
386
+ def save_pretrained(self, save_directory: Union[str, os.PathLike], push_to_hub: bool = False, **kwargs):
387
+ """
388
+ Save a feature_extractor object to the directory `save_directory`, so that it can be re-loaded using the
389
+ [`~feature_extraction_utils.FeatureExtractionMixin.from_pretrained`] class method.
390
+
391
+ Args:
392
+ save_directory (`str` or `os.PathLike`):
393
+ Directory where the feature extractor JSON file will be saved (will be created if it does not exist).
394
+ push_to_hub (`bool`, *optional*, defaults to `False`):
395
+ Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the
396
+ repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
397
+ namespace).
398
+ kwargs (`dict[str, Any]`, *optional*):
399
+ Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.
400
+ """
401
+ use_auth_token = kwargs.pop("use_auth_token", None)
402
+
403
+ if use_auth_token is not None:
404
+ warnings.warn(
405
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
406
+ FutureWarning,
407
+ )
408
+ if kwargs.get("token") is not None:
409
+ raise ValueError(
410
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
411
+ )
412
+ kwargs["token"] = use_auth_token
413
+
414
+ if os.path.isfile(save_directory):
415
+ raise AssertionError(f"Provided path ({save_directory}) should be a directory, not a file")
416
+
417
+ os.makedirs(save_directory, exist_ok=True)
418
+
419
+ if push_to_hub:
420
+ commit_message = kwargs.pop("commit_message", None)
421
+ repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])
422
+ repo_id = self._create_repo(repo_id, **kwargs)
423
+ files_timestamps = self._get_files_timestamps(save_directory)
424
+
425
+ # If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be
426
+ # loaded from the Hub.
427
+ if self._auto_class is not None:
428
+ custom_object_save(self, save_directory, config=self)
429
+
430
+ # If we save using the predefined names, we can load using `from_pretrained`
431
+ output_feature_extractor_file = os.path.join(save_directory, FEATURE_EXTRACTOR_NAME)
432
+
433
+ self.to_json_file(output_feature_extractor_file)
434
+ logger.info(f"Feature extractor saved in {output_feature_extractor_file}")
435
+
436
+ if push_to_hub:
437
+ self._upload_modified_files(
438
+ save_directory,
439
+ repo_id,
440
+ files_timestamps,
441
+ commit_message=commit_message,
442
+ token=kwargs.get("token"),
443
+ )
444
+
445
+ return [output_feature_extractor_file]
446
+
447
+ @classmethod
448
+ def get_feature_extractor_dict(
449
+ cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs
450
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
451
+ """
452
+ From a `pretrained_model_name_or_path`, resolve to a dictionary of parameters, to be used for instantiating a
453
+ feature extractor of type [`~feature_extraction_utils.FeatureExtractionMixin`] using `from_dict`.
454
+
455
+ Parameters:
456
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
457
+ The identifier of the pre-trained checkpoint from which we want the dictionary of parameters.
458
+
459
+ Returns:
460
+ `tuple[Dict, Dict]`: The dictionary(ies) that will be used to instantiate the feature extractor object.
461
+ """
462
+ cache_dir = kwargs.pop("cache_dir", None)
463
+ force_download = kwargs.pop("force_download", False)
464
+ resume_download = kwargs.pop("resume_download", None)
465
+ proxies = kwargs.pop("proxies", None)
466
+ subfolder = kwargs.pop("subfolder", None)
467
+ token = kwargs.pop("token", None)
468
+ use_auth_token = kwargs.pop("use_auth_token", None)
469
+ local_files_only = kwargs.pop("local_files_only", False)
470
+ revision = kwargs.pop("revision", None)
471
+
472
+ if use_auth_token is not None:
473
+ warnings.warn(
474
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
475
+ FutureWarning,
476
+ )
477
+ if token is not None:
478
+ raise ValueError(
479
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
480
+ )
481
+ token = use_auth_token
482
+
483
+ from_pipeline = kwargs.pop("_from_pipeline", None)
484
+ from_auto_class = kwargs.pop("_from_auto", False)
485
+
486
+ user_agent = {"file_type": "feature extractor", "from_auto_class": from_auto_class}
487
+ if from_pipeline is not None:
488
+ user_agent["using_pipeline"] = from_pipeline
489
+
490
+ if is_offline_mode() and not local_files_only:
491
+ logger.info("Offline mode: forcing local_files_only=True")
492
+ local_files_only = True
493
+
494
+ pretrained_model_name_or_path = str(pretrained_model_name_or_path)
495
+ is_local = os.path.isdir(pretrained_model_name_or_path)
496
+ if os.path.isdir(pretrained_model_name_or_path):
497
+ feature_extractor_file = os.path.join(pretrained_model_name_or_path, FEATURE_EXTRACTOR_NAME)
498
+ if os.path.isfile(pretrained_model_name_or_path):
499
+ resolved_feature_extractor_file = pretrained_model_name_or_path
500
+ is_local = True
501
+ elif is_remote_url(pretrained_model_name_or_path):
502
+ feature_extractor_file = pretrained_model_name_or_path
503
+ resolved_feature_extractor_file = download_url(pretrained_model_name_or_path)
504
+ else:
505
+ feature_extractor_file = FEATURE_EXTRACTOR_NAME
506
+ try:
507
+ # Load from local folder or from cache or download from model Hub and cache
508
+ resolved_feature_extractor_files = [
509
+ resolved_file
510
+ for filename in [feature_extractor_file, PROCESSOR_NAME]
511
+ if (
512
+ resolved_file := cached_file(
513
+ pretrained_model_name_or_path,
514
+ filename=filename,
515
+ cache_dir=cache_dir,
516
+ force_download=force_download,
517
+ proxies=proxies,
518
+ resume_download=resume_download,
519
+ local_files_only=local_files_only,
520
+ subfolder=subfolder,
521
+ token=token,
522
+ user_agent=user_agent,
523
+ revision=revision,
524
+ _raise_exceptions_for_missing_entries=False,
525
+ )
526
+ )
527
+ is not None
528
+ ]
529
+ resolved_feature_extractor_file = resolved_feature_extractor_files[0]
530
+ except OSError:
531
+ # Raise any environment error raise by `cached_file`. It will have a helpful error message adapted to
532
+ # the original exception.
533
+ raise
534
+ except Exception:
535
+ # For any other exception, we throw a generic error.
536
+ raise OSError(
537
+ f"Can't load feature extractor for '{pretrained_model_name_or_path}'. If you were trying to load"
538
+ " it from 'https://huggingface.co/models', make sure you don't have a local directory with the"
539
+ f" same name. Otherwise, make sure '{pretrained_model_name_or_path}' is the correct path to a"
540
+ f" directory containing a {FEATURE_EXTRACTOR_NAME} file"
541
+ )
542
+
543
+ try:
544
+ # Load feature_extractor dict
545
+ with open(resolved_feature_extractor_file, encoding="utf-8") as reader:
546
+ text = reader.read()
547
+ feature_extractor_dict = json.loads(text)
548
+ feature_extractor_dict = feature_extractor_dict.get("feature_extractor", feature_extractor_dict)
549
+
550
+ except json.JSONDecodeError:
551
+ raise OSError(
552
+ f"It looks like the config file at '{resolved_feature_extractor_file}' is not a valid JSON file."
553
+ )
554
+
555
+ if is_local:
556
+ logger.info(f"loading configuration file {resolved_feature_extractor_file}")
557
+ else:
558
+ logger.info(
559
+ f"loading configuration file {feature_extractor_file} from cache at {resolved_feature_extractor_file}"
560
+ )
561
+
562
+ return feature_extractor_dict, kwargs
563
+
564
+ @classmethod
565
+ def from_dict(
566
+ cls, feature_extractor_dict: dict[str, Any], **kwargs
567
+ ) -> Union["FeatureExtractionMixin", tuple["FeatureExtractionMixin", dict[str, Any]]]:
568
+ """
569
+ Instantiates a type of [`~feature_extraction_utils.FeatureExtractionMixin`] from a Python dictionary of
570
+ parameters.
571
+
572
+ Args:
573
+ feature_extractor_dict (`dict[str, Any]`):
574
+ Dictionary that will be used to instantiate the feature extractor object. Such a dictionary can be
575
+ retrieved from a pretrained checkpoint by leveraging the
576
+ [`~feature_extraction_utils.FeatureExtractionMixin.to_dict`] method.
577
+ kwargs (`dict[str, Any]`):
578
+ Additional parameters from which to initialize the feature extractor object.
579
+
580
+ Returns:
581
+ [`~feature_extraction_utils.FeatureExtractionMixin`]: The feature extractor object instantiated from those
582
+ parameters.
583
+ """
584
+ return_unused_kwargs = kwargs.pop("return_unused_kwargs", False)
585
+
586
+ # Update feature_extractor with kwargs if needed
587
+ to_remove = []
588
+ for key, value in kwargs.items():
589
+ if key in feature_extractor_dict:
590
+ feature_extractor_dict[key] = value
591
+ to_remove.append(key)
592
+ for key in to_remove:
593
+ kwargs.pop(key, None)
594
+
595
+ feature_extractor = cls(**feature_extractor_dict)
596
+
597
+ logger.info(f"Feature extractor {feature_extractor}")
598
+ if return_unused_kwargs:
599
+ return feature_extractor, kwargs
600
+ else:
601
+ return feature_extractor
602
+
603
+ def to_dict(self) -> dict[str, Any]:
604
+ """
605
+ Serializes this instance to a Python dictionary. Returns:
606
+ `dict[str, Any]`: Dictionary of all the attributes that make up this configuration instance.
607
+ """
608
+ output = copy.deepcopy(self.__dict__)
609
+ output["feature_extractor_type"] = self.__class__.__name__
610
+ if "mel_filters" in output:
611
+ del output["mel_filters"]
612
+ if "window" in output:
613
+ del output["window"]
614
+ return output
615
+
616
+ @classmethod
617
+ def from_json_file(cls, json_file: Union[str, os.PathLike]) -> "FeatureExtractionMixin":
618
+ """
619
+ Instantiates a feature extractor of type [`~feature_extraction_utils.FeatureExtractionMixin`] from the path to
620
+ a JSON file of parameters.
621
+
622
+ Args:
623
+ json_file (`str` or `os.PathLike`):
624
+ Path to the JSON file containing the parameters.
625
+
626
+ Returns:
627
+ A feature extractor of type [`~feature_extraction_utils.FeatureExtractionMixin`]: The feature_extractor
628
+ object instantiated from that JSON file.
629
+ """
630
+ with open(json_file, encoding="utf-8") as reader:
631
+ text = reader.read()
632
+ feature_extractor_dict = json.loads(text)
633
+ return cls(**feature_extractor_dict)
634
+
635
+ def to_json_string(self) -> str:
636
+ """
637
+ Serializes this instance to a JSON string.
638
+
639
+ Returns:
640
+ `str`: String containing all the attributes that make up this feature_extractor instance in JSON format.
641
+ """
642
+ dictionary = self.to_dict()
643
+
644
+ for key, value in dictionary.items():
645
+ if isinstance(value, np.ndarray):
646
+ dictionary[key] = value.tolist()
647
+
648
+ # make sure private name "_processor_class" is correctly
649
+ # saved as "processor_class"
650
+ _processor_class = dictionary.pop("_processor_class", None)
651
+ if _processor_class is not None:
652
+ dictionary["processor_class"] = _processor_class
653
+
654
+ return json.dumps(dictionary, indent=2, sort_keys=True) + "\n"
655
+
656
+ def to_json_file(self, json_file_path: Union[str, os.PathLike]):
657
+ """
658
+ Save this instance to a JSON file.
659
+
660
+ Args:
661
+ json_file_path (`str` or `os.PathLike`):
662
+ Path to the JSON file in which this feature_extractor instance's parameters will be saved.
663
+ """
664
+ with open(json_file_path, "w", encoding="utf-8") as writer:
665
+ writer.write(self.to_json_string())
666
+
667
+ def __repr__(self):
668
+ return f"{self.__class__.__name__} {self.to_json_string()}"
669
+
670
+ @classmethod
671
+ def register_for_auto_class(cls, auto_class="AutoFeatureExtractor"):
672
+ """
673
+ Register this class with a given auto class. This should only be used for custom feature extractors as the ones
674
+ in the library are already mapped with `AutoFeatureExtractor`.
675
+
676
+
677
+
678
+ Args:
679
+ auto_class (`str` or `type`, *optional*, defaults to `"AutoFeatureExtractor"`):
680
+ The auto class to register this new feature extractor with.
681
+ """
682
+ if not isinstance(auto_class, str):
683
+ auto_class = auto_class.__name__
684
+
685
+ import transformers.models.auto as auto_module
686
+
687
+ if not hasattr(auto_module, auto_class):
688
+ raise ValueError(f"{auto_class} is not a valid auto class.")
689
+
690
+ cls._auto_class = auto_class
691
+
692
+
693
+ FeatureExtractionMixin.push_to_hub = copy_func(FeatureExtractionMixin.push_to_hub)
694
+ if FeatureExtractionMixin.push_to_hub.__doc__ is not None:
695
+ FeatureExtractionMixin.push_to_hub.__doc__ = FeatureExtractionMixin.push_to_hub.__doc__.format(
696
+ object="feature extractor", object_class="AutoFeatureExtractor", object_files="feature extractor file"
697
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/file_utils.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ File utilities: utilities related to download and cache models
16
+
17
+ This module should not be update anymore and is only left for backward compatibility.
18
+ """
19
+
20
+ from huggingface_hub import get_full_repo_name # for backward compatibility
21
+ from huggingface_hub.constants import HF_HUB_DISABLE_TELEMETRY as DISABLE_TELEMETRY # for backward compatibility
22
+
23
+ from . import __version__
24
+
25
+ # Backward compatibility imports, to make sure all those objects can be found in file_utils
26
+ from .utils import (
27
+ CLOUDFRONT_DISTRIB_PREFIX,
28
+ CONFIG_NAME,
29
+ DUMMY_INPUTS,
30
+ DUMMY_MASK,
31
+ ENV_VARS_TRUE_AND_AUTO_VALUES,
32
+ ENV_VARS_TRUE_VALUES,
33
+ FEATURE_EXTRACTOR_NAME,
34
+ FLAX_WEIGHTS_NAME,
35
+ HF_MODULES_CACHE,
36
+ HUGGINGFACE_CO_PREFIX,
37
+ HUGGINGFACE_CO_RESOLVE_ENDPOINT,
38
+ MODEL_CARD_NAME,
39
+ MULTIPLE_CHOICE_DUMMY_INPUTS,
40
+ PYTORCH_PRETRAINED_BERT_CACHE,
41
+ PYTORCH_TRANSFORMERS_CACHE,
42
+ S3_BUCKET_PREFIX,
43
+ SENTENCEPIECE_UNDERLINE,
44
+ SPIECE_UNDERLINE,
45
+ TF2_WEIGHTS_NAME,
46
+ TF_WEIGHTS_NAME,
47
+ TORCH_FX_REQUIRED_VERSION,
48
+ TRANSFORMERS_CACHE,
49
+ TRANSFORMERS_DYNAMIC_MODULE_NAME,
50
+ USE_JAX,
51
+ USE_TF,
52
+ USE_TORCH,
53
+ WEIGHTS_INDEX_NAME,
54
+ WEIGHTS_NAME,
55
+ ContextManagers,
56
+ DummyObject,
57
+ EntryNotFoundError,
58
+ ExplicitEnum,
59
+ ModelOutput,
60
+ PaddingStrategy,
61
+ PushToHubMixin,
62
+ RepositoryNotFoundError,
63
+ RevisionNotFoundError,
64
+ TensorType,
65
+ _LazyModule,
66
+ add_code_sample_docstrings,
67
+ add_end_docstrings,
68
+ add_start_docstrings,
69
+ add_start_docstrings_to_model_forward,
70
+ copy_func,
71
+ default_cache_path,
72
+ define_sagemaker_information,
73
+ get_torch_version,
74
+ has_file,
75
+ http_user_agent,
76
+ is_apex_available,
77
+ is_bs4_available,
78
+ is_coloredlogs_available,
79
+ is_datasets_available,
80
+ is_detectron2_available,
81
+ is_faiss_available,
82
+ is_flax_available,
83
+ is_ftfy_available,
84
+ is_g2p_en_available,
85
+ is_in_notebook,
86
+ is_ipex_available,
87
+ is_librosa_available,
88
+ is_offline_mode,
89
+ is_onnx_available,
90
+ is_pandas_available,
91
+ is_phonemizer_available,
92
+ is_protobuf_available,
93
+ is_psutil_available,
94
+ is_py3nvml_available,
95
+ is_pyctcdecode_available,
96
+ is_pytesseract_available,
97
+ is_pytorch_quantization_available,
98
+ is_rjieba_available,
99
+ is_sagemaker_dp_enabled,
100
+ is_sagemaker_mp_enabled,
101
+ is_scipy_available,
102
+ is_sentencepiece_available,
103
+ is_seqio_available,
104
+ is_sklearn_available,
105
+ is_soundfile_available,
106
+ is_spacy_available,
107
+ is_speech_available,
108
+ is_tensor,
109
+ is_tensorflow_probability_available,
110
+ is_tf2onnx_available,
111
+ is_tf_available,
112
+ is_timm_available,
113
+ is_tokenizers_available,
114
+ is_torch_available,
115
+ is_torch_bf16_available,
116
+ is_torch_cuda_available,
117
+ is_torch_fx_available,
118
+ is_torch_fx_proxy,
119
+ is_torch_mps_available,
120
+ is_torch_tf32_available,
121
+ is_torch_xla_available,
122
+ is_torchaudio_available,
123
+ is_training_run_on_sagemaker,
124
+ is_vision_available,
125
+ replace_return_docstrings,
126
+ requires_backends,
127
+ to_numpy,
128
+ to_py_obj,
129
+ torch_only_method,
130
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/hyperparameter_search.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-present the HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from typing import Optional
15
+
16
+ from .integrations import (
17
+ is_optuna_available,
18
+ is_ray_tune_available,
19
+ is_sigopt_available,
20
+ is_wandb_available,
21
+ run_hp_search_optuna,
22
+ run_hp_search_ray,
23
+ run_hp_search_sigopt,
24
+ run_hp_search_wandb,
25
+ )
26
+ from .trainer_utils import (
27
+ HPSearchBackend,
28
+ default_hp_space_optuna,
29
+ default_hp_space_ray,
30
+ default_hp_space_sigopt,
31
+ default_hp_space_wandb,
32
+ )
33
+ from .utils import logging
34
+
35
+
36
+ logger = logging.get_logger(__name__)
37
+
38
+
39
+ class HyperParamSearchBackendBase:
40
+ name: str
41
+ pip_package: Optional[str] = None
42
+
43
+ @staticmethod
44
+ def is_available():
45
+ raise NotImplementedError
46
+
47
+ def run(self, trainer, n_trials: int, direction: str, **kwargs):
48
+ raise NotImplementedError
49
+
50
+ def default_hp_space(self, trial):
51
+ raise NotImplementedError
52
+
53
+ def ensure_available(self):
54
+ if not self.is_available():
55
+ raise RuntimeError(
56
+ f"You picked the {self.name} backend, but it is not installed. Run {self.pip_install()}."
57
+ )
58
+
59
+ @classmethod
60
+ def pip_install(cls):
61
+ return f"`pip install {cls.pip_package or cls.name}`"
62
+
63
+
64
+ class OptunaBackend(HyperParamSearchBackendBase):
65
+ name = "optuna"
66
+
67
+ @staticmethod
68
+ def is_available():
69
+ return is_optuna_available()
70
+
71
+ def run(self, trainer, n_trials: int, direction: str, **kwargs):
72
+ return run_hp_search_optuna(trainer, n_trials, direction, **kwargs)
73
+
74
+ def default_hp_space(self, trial):
75
+ return default_hp_space_optuna(trial)
76
+
77
+
78
+ class RayTuneBackend(HyperParamSearchBackendBase):
79
+ name = "ray"
80
+ pip_package = "'ray[tune]'"
81
+
82
+ @staticmethod
83
+ def is_available():
84
+ return is_ray_tune_available()
85
+
86
+ def run(self, trainer, n_trials: int, direction: str, **kwargs):
87
+ return run_hp_search_ray(trainer, n_trials, direction, **kwargs)
88
+
89
+ def default_hp_space(self, trial):
90
+ return default_hp_space_ray(trial)
91
+
92
+
93
+ class SigOptBackend(HyperParamSearchBackendBase):
94
+ name = "sigopt"
95
+
96
+ @staticmethod
97
+ def is_available():
98
+ return is_sigopt_available()
99
+
100
+ def run(self, trainer, n_trials: int, direction: str, **kwargs):
101
+ return run_hp_search_sigopt(trainer, n_trials, direction, **kwargs)
102
+
103
+ def default_hp_space(self, trial):
104
+ return default_hp_space_sigopt(trial)
105
+
106
+
107
+ class WandbBackend(HyperParamSearchBackendBase):
108
+ name = "wandb"
109
+
110
+ @staticmethod
111
+ def is_available():
112
+ return is_wandb_available()
113
+
114
+ def run(self, trainer, n_trials: int, direction: str, **kwargs):
115
+ return run_hp_search_wandb(trainer, n_trials, direction, **kwargs)
116
+
117
+ def default_hp_space(self, trial):
118
+ return default_hp_space_wandb(trial)
119
+
120
+
121
+ ALL_HYPERPARAMETER_SEARCH_BACKENDS = {
122
+ HPSearchBackend(backend.name): backend for backend in [OptunaBackend, RayTuneBackend, SigOptBackend, WandbBackend]
123
+ }
124
+
125
+
126
+ def default_hp_search_backend() -> str:
127
+ available_backends = [backend for backend in ALL_HYPERPARAMETER_SEARCH_BACKENDS.values() if backend.is_available()]
128
+ if len(available_backends) > 0:
129
+ name = available_backends[0].name
130
+ if len(available_backends) > 1:
131
+ logger.info(
132
+ f"{len(available_backends)} hyperparameter search backends available. Using {name} as the default."
133
+ )
134
+ return name
135
+ raise RuntimeError(
136
+ "No hyperparameter search backend available.\n"
137
+ + "\n".join(
138
+ f" - To install {backend.name} run {backend.pip_install()}"
139
+ for backend in ALL_HYPERPARAMETER_SEARCH_BACKENDS.values()
140
+ )
141
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_processing_base.py ADDED
@@ -0,0 +1,543 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ import copy
17
+ import json
18
+ import os
19
+ import warnings
20
+ from typing import Any, Optional, TypeVar, Union
21
+
22
+ import numpy as np
23
+
24
+ from .dynamic_module_utils import custom_object_save
25
+ from .feature_extraction_utils import BatchFeature as BaseBatchFeature
26
+ from .image_utils import is_valid_image, load_image
27
+ from .utils import (
28
+ IMAGE_PROCESSOR_NAME,
29
+ PROCESSOR_NAME,
30
+ PushToHubMixin,
31
+ copy_func,
32
+ download_url,
33
+ is_offline_mode,
34
+ is_remote_url,
35
+ logging,
36
+ )
37
+ from .utils.hub import cached_file
38
+
39
+
40
+ ImageProcessorType = TypeVar("ImageProcessorType", bound="ImageProcessingMixin")
41
+
42
+
43
+ logger = logging.get_logger(__name__)
44
+
45
+
46
+ # TODO: Move BatchFeature to be imported by both image_processing_utils and image_processing_utils_fast
47
+ # We override the class string here, but logic is the same.
48
+ class BatchFeature(BaseBatchFeature):
49
+ r"""
50
+ Holds the output of the image processor specific `__call__` methods.
51
+
52
+ This class is derived from a python dictionary and can be used as a dictionary.
53
+
54
+ Args:
55
+ data (`dict`):
56
+ Dictionary of lists/arrays/tensors returned by the __call__ method ('pixel_values', etc.).
57
+ tensor_type (`Union[None, str, TensorType]`, *optional*):
58
+ You can give a tensor_type here to convert the lists of integers in PyTorch/TensorFlow/Numpy Tensors at
59
+ initialization.
60
+ """
61
+
62
+
63
+ # TODO: (Amy) - factor out the common parts of this and the feature extractor
64
+ class ImageProcessingMixin(PushToHubMixin):
65
+ """
66
+ This is an image processor mixin used to provide saving/loading functionality for sequential and image feature
67
+ extractors.
68
+ """
69
+
70
+ _auto_class = None
71
+
72
+ def __init__(self, **kwargs):
73
+ """Set elements of `kwargs` as attributes."""
74
+ # This key was saved while we still used `XXXFeatureExtractor` for image processing. Now we use
75
+ # `XXXImageProcessor`, this attribute and its value are misleading.
76
+ kwargs.pop("feature_extractor_type", None)
77
+ # Pop "processor_class" as it should be saved as private attribute
78
+ self._processor_class = kwargs.pop("processor_class", None)
79
+ # Additional attributes without default values
80
+ for key, value in kwargs.items():
81
+ try:
82
+ setattr(self, key, value)
83
+ except AttributeError as err:
84
+ logger.error(f"Can't set {key} with value {value} for {self}")
85
+ raise err
86
+
87
+ def _set_processor_class(self, processor_class: str):
88
+ """Sets processor class as an attribute."""
89
+ self._processor_class = processor_class
90
+
91
+ @classmethod
92
+ def from_pretrained(
93
+ cls: type[ImageProcessorType],
94
+ pretrained_model_name_or_path: Union[str, os.PathLike],
95
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
96
+ force_download: bool = False,
97
+ local_files_only: bool = False,
98
+ token: Optional[Union[str, bool]] = None,
99
+ revision: str = "main",
100
+ **kwargs,
101
+ ) -> ImageProcessorType:
102
+ r"""
103
+ Instantiate a type of [`~image_processing_utils.ImageProcessingMixin`] from an image processor.
104
+
105
+ Args:
106
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
107
+ This can be either:
108
+
109
+ - a string, the *model id* of a pretrained image_processor hosted inside a model repo on
110
+ huggingface.co.
111
+ - a path to a *directory* containing a image processor file saved using the
112
+ [`~image_processing_utils.ImageProcessingMixin.save_pretrained`] method, e.g.,
113
+ `./my_model_directory/`.
114
+ - a path or url to a saved image processor JSON *file*, e.g.,
115
+ `./my_model_directory/preprocessor_config.json`.
116
+ cache_dir (`str` or `os.PathLike`, *optional*):
117
+ Path to a directory in which a downloaded pretrained model image processor should be cached if the
118
+ standard cache should not be used.
119
+ force_download (`bool`, *optional*, defaults to `False`):
120
+ Whether or not to force to (re-)download the image processor files and override the cached versions if
121
+ they exist.
122
+ resume_download:
123
+ Deprecated and ignored. All downloads are now resumed by default when possible.
124
+ Will be removed in v5 of Transformers.
125
+ proxies (`dict[str, str]`, *optional*):
126
+ A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
127
+ 'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.
128
+ token (`str` or `bool`, *optional*):
129
+ The token to use as HTTP bearer authorization for remote files. If `True`, or not specified, will use
130
+ the token generated when running `hf auth login` (stored in `~/.huggingface`).
131
+ revision (`str`, *optional*, defaults to `"main"`):
132
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
133
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
134
+ identifier allowed by git.
135
+
136
+
137
+ <Tip>
138
+
139
+ To test a pull request you made on the Hub, you can pass `revision="refs/pr/<pr_number>"`.
140
+
141
+ </Tip>
142
+
143
+ return_unused_kwargs (`bool`, *optional*, defaults to `False`):
144
+ If `False`, then this function returns just the final image processor object. If `True`, then this
145
+ functions returns a `Tuple(image_processor, unused_kwargs)` where *unused_kwargs* is a dictionary
146
+ consisting of the key/value pairs whose keys are not image processor attributes: i.e., the part of
147
+ `kwargs` which has not been used to update `image_processor` and is otherwise ignored.
148
+ subfolder (`str`, *optional*, defaults to `""`):
149
+ In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can
150
+ specify the folder name here.
151
+ kwargs (`dict[str, Any]`, *optional*):
152
+ The values in kwargs of any keys which are image processor attributes will be used to override the
153
+ loaded values. Behavior concerning key/value pairs whose keys are *not* image processor attributes is
154
+ controlled by the `return_unused_kwargs` keyword parameter.
155
+
156
+ Returns:
157
+ A image processor of type [`~image_processing_utils.ImageProcessingMixin`].
158
+
159
+ Examples:
160
+
161
+ ```python
162
+ # We can't instantiate directly the base class *ImageProcessingMixin* so let's show the examples on a
163
+ # derived class: *CLIPImageProcessor*
164
+ image_processor = CLIPImageProcessor.from_pretrained(
165
+ "openai/clip-vit-base-patch32"
166
+ ) # Download image_processing_config from huggingface.co and cache.
167
+ image_processor = CLIPImageProcessor.from_pretrained(
168
+ "./test/saved_model/"
169
+ ) # E.g. image processor (or model) was saved using *save_pretrained('./test/saved_model/')*
170
+ image_processor = CLIPImageProcessor.from_pretrained("./test/saved_model/preprocessor_config.json")
171
+ image_processor = CLIPImageProcessor.from_pretrained(
172
+ "openai/clip-vit-base-patch32", do_normalize=False, foo=False
173
+ )
174
+ assert image_processor.do_normalize is False
175
+ image_processor, unused_kwargs = CLIPImageProcessor.from_pretrained(
176
+ "openai/clip-vit-base-patch32", do_normalize=False, foo=False, return_unused_kwargs=True
177
+ )
178
+ assert image_processor.do_normalize is False
179
+ assert unused_kwargs == {"foo": False}
180
+ ```"""
181
+ kwargs["cache_dir"] = cache_dir
182
+ kwargs["force_download"] = force_download
183
+ kwargs["local_files_only"] = local_files_only
184
+ kwargs["revision"] = revision
185
+
186
+ use_auth_token = kwargs.pop("use_auth_token", None)
187
+ if use_auth_token is not None:
188
+ warnings.warn(
189
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
190
+ FutureWarning,
191
+ )
192
+ if token is not None:
193
+ raise ValueError(
194
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
195
+ )
196
+ token = use_auth_token
197
+
198
+ if token is not None:
199
+ kwargs["token"] = token
200
+
201
+ image_processor_dict, kwargs = cls.get_image_processor_dict(pretrained_model_name_or_path, **kwargs)
202
+
203
+ return cls.from_dict(image_processor_dict, **kwargs)
204
+
205
+ def save_pretrained(self, save_directory: Union[str, os.PathLike], push_to_hub: bool = False, **kwargs):
206
+ """
207
+ Save an image processor object to the directory `save_directory`, so that it can be re-loaded using the
208
+ [`~image_processing_utils.ImageProcessingMixin.from_pretrained`] class method.
209
+
210
+ Args:
211
+ save_directory (`str` or `os.PathLike`):
212
+ Directory where the image processor JSON file will be saved (will be created if it does not exist).
213
+ push_to_hub (`bool`, *optional*, defaults to `False`):
214
+ Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the
215
+ repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
216
+ namespace).
217
+ kwargs (`dict[str, Any]`, *optional*):
218
+ Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.
219
+ """
220
+ use_auth_token = kwargs.pop("use_auth_token", None)
221
+
222
+ if use_auth_token is not None:
223
+ warnings.warn(
224
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
225
+ FutureWarning,
226
+ )
227
+ if kwargs.get("token") is not None:
228
+ raise ValueError(
229
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
230
+ )
231
+ kwargs["token"] = use_auth_token
232
+
233
+ if os.path.isfile(save_directory):
234
+ raise AssertionError(f"Provided path ({save_directory}) should be a directory, not a file")
235
+
236
+ os.makedirs(save_directory, exist_ok=True)
237
+
238
+ if push_to_hub:
239
+ commit_message = kwargs.pop("commit_message", None)
240
+ repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])
241
+ repo_id = self._create_repo(repo_id, **kwargs)
242
+ files_timestamps = self._get_files_timestamps(save_directory)
243
+
244
+ # If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be
245
+ # loaded from the Hub.
246
+ if self._auto_class is not None:
247
+ custom_object_save(self, save_directory, config=self)
248
+
249
+ # If we save using the predefined names, we can load using `from_pretrained`
250
+ output_image_processor_file = os.path.join(save_directory, IMAGE_PROCESSOR_NAME)
251
+
252
+ self.to_json_file(output_image_processor_file)
253
+ logger.info(f"Image processor saved in {output_image_processor_file}")
254
+
255
+ if push_to_hub:
256
+ self._upload_modified_files(
257
+ save_directory,
258
+ repo_id,
259
+ files_timestamps,
260
+ commit_message=commit_message,
261
+ token=kwargs.get("token"),
262
+ )
263
+
264
+ return [output_image_processor_file]
265
+
266
+ @classmethod
267
+ def get_image_processor_dict(
268
+ cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs
269
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
270
+ """
271
+ From a `pretrained_model_name_or_path`, resolve to a dictionary of parameters, to be used for instantiating a
272
+ image processor of type [`~image_processor_utils.ImageProcessingMixin`] using `from_dict`.
273
+
274
+ Parameters:
275
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
276
+ The identifier of the pre-trained checkpoint from which we want the dictionary of parameters.
277
+ subfolder (`str`, *optional*, defaults to `""`):
278
+ In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can
279
+ specify the folder name here.
280
+ image_processor_filename (`str`, *optional*, defaults to `"config.json"`):
281
+ The name of the file in the model directory to use for the image processor config.
282
+
283
+ Returns:
284
+ `tuple[Dict, Dict]`: The dictionary(ies) that will be used to instantiate the image processor object.
285
+ """
286
+ cache_dir = kwargs.pop("cache_dir", None)
287
+ force_download = kwargs.pop("force_download", False)
288
+ resume_download = kwargs.pop("resume_download", None)
289
+ proxies = kwargs.pop("proxies", None)
290
+ token = kwargs.pop("token", None)
291
+ use_auth_token = kwargs.pop("use_auth_token", None)
292
+ local_files_only = kwargs.pop("local_files_only", False)
293
+ revision = kwargs.pop("revision", None)
294
+ subfolder = kwargs.pop("subfolder", "")
295
+ image_processor_filename = kwargs.pop("image_processor_filename", IMAGE_PROCESSOR_NAME)
296
+
297
+ from_pipeline = kwargs.pop("_from_pipeline", None)
298
+ from_auto_class = kwargs.pop("_from_auto", False)
299
+
300
+ if use_auth_token is not None:
301
+ warnings.warn(
302
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
303
+ FutureWarning,
304
+ )
305
+ if token is not None:
306
+ raise ValueError(
307
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
308
+ )
309
+ token = use_auth_token
310
+
311
+ user_agent = {"file_type": "image processor", "from_auto_class": from_auto_class}
312
+ if from_pipeline is not None:
313
+ user_agent["using_pipeline"] = from_pipeline
314
+
315
+ if is_offline_mode() and not local_files_only:
316
+ logger.info("Offline mode: forcing local_files_only=True")
317
+ local_files_only = True
318
+
319
+ pretrained_model_name_or_path = str(pretrained_model_name_or_path)
320
+ is_local = os.path.isdir(pretrained_model_name_or_path)
321
+ if os.path.isdir(pretrained_model_name_or_path):
322
+ image_processor_file = os.path.join(pretrained_model_name_or_path, image_processor_filename)
323
+ if os.path.isfile(pretrained_model_name_or_path):
324
+ resolved_image_processor_file = pretrained_model_name_or_path
325
+ is_local = True
326
+ elif is_remote_url(pretrained_model_name_or_path):
327
+ image_processor_file = pretrained_model_name_or_path
328
+ resolved_image_processor_file = download_url(pretrained_model_name_or_path)
329
+ else:
330
+ image_processor_file = image_processor_filename
331
+ try:
332
+ # Load from local folder or from cache or download from model Hub and cache
333
+ resolved_image_processor_files = [
334
+ resolved_file
335
+ for filename in [image_processor_file, PROCESSOR_NAME]
336
+ if (
337
+ resolved_file := cached_file(
338
+ pretrained_model_name_or_path,
339
+ filename=filename,
340
+ cache_dir=cache_dir,
341
+ force_download=force_download,
342
+ proxies=proxies,
343
+ resume_download=resume_download,
344
+ local_files_only=local_files_only,
345
+ token=token,
346
+ user_agent=user_agent,
347
+ revision=revision,
348
+ subfolder=subfolder,
349
+ _raise_exceptions_for_missing_entries=False,
350
+ )
351
+ )
352
+ is not None
353
+ ]
354
+ resolved_image_processor_file = resolved_image_processor_files[0]
355
+ except OSError:
356
+ # Raise any environment error raise by `cached_file`. It will have a helpful error message adapted to
357
+ # the original exception.
358
+ raise
359
+ except Exception:
360
+ # For any other exception, we throw a generic error.
361
+ raise OSError(
362
+ f"Can't load image processor for '{pretrained_model_name_or_path}'. If you were trying to load"
363
+ " it from 'https://huggingface.co/models', make sure you don't have a local directory with the"
364
+ f" same name. Otherwise, make sure '{pretrained_model_name_or_path}' is the correct path to a"
365
+ f" directory containing a {image_processor_filename} file"
366
+ )
367
+
368
+ try:
369
+ # Load image_processor dict
370
+ with open(resolved_image_processor_file, encoding="utf-8") as reader:
371
+ text = reader.read()
372
+ image_processor_dict = json.loads(text)
373
+ image_processor_dict = image_processor_dict.get("image_processor", image_processor_dict)
374
+
375
+ except json.JSONDecodeError:
376
+ raise OSError(
377
+ f"It looks like the config file at '{resolved_image_processor_file}' is not a valid JSON file."
378
+ )
379
+
380
+ if is_local:
381
+ logger.info(f"loading configuration file {resolved_image_processor_file}")
382
+ else:
383
+ logger.info(
384
+ f"loading configuration file {image_processor_file} from cache at {resolved_image_processor_file}"
385
+ )
386
+
387
+ return image_processor_dict, kwargs
388
+
389
+ @classmethod
390
+ def from_dict(cls, image_processor_dict: dict[str, Any], **kwargs):
391
+ """
392
+ Instantiates a type of [`~image_processing_utils.ImageProcessingMixin`] from a Python dictionary of parameters.
393
+
394
+ Args:
395
+ image_processor_dict (`dict[str, Any]`):
396
+ Dictionary that will be used to instantiate the image processor object. Such a dictionary can be
397
+ retrieved from a pretrained checkpoint by leveraging the
398
+ [`~image_processing_utils.ImageProcessingMixin.to_dict`] method.
399
+ kwargs (`dict[str, Any]`):
400
+ Additional parameters from which to initialize the image processor object.
401
+
402
+ Returns:
403
+ [`~image_processing_utils.ImageProcessingMixin`]: The image processor object instantiated from those
404
+ parameters.
405
+ """
406
+ image_processor_dict = image_processor_dict.copy()
407
+ return_unused_kwargs = kwargs.pop("return_unused_kwargs", False)
408
+
409
+ # The `size` parameter is a dict and was previously an int or tuple in feature extractors.
410
+ # We set `size` here directly to the `image_processor_dict` so that it is converted to the appropriate
411
+ # dict within the image processor and isn't overwritten if `size` is passed in as a kwarg.
412
+ if "size" in kwargs and "size" in image_processor_dict:
413
+ image_processor_dict["size"] = kwargs.pop("size")
414
+ if "crop_size" in kwargs and "crop_size" in image_processor_dict:
415
+ image_processor_dict["crop_size"] = kwargs.pop("crop_size")
416
+
417
+ image_processor = cls(**image_processor_dict)
418
+
419
+ # Update image_processor with kwargs if needed
420
+ to_remove = []
421
+ for key, value in kwargs.items():
422
+ if hasattr(image_processor, key):
423
+ setattr(image_processor, key, value)
424
+ to_remove.append(key)
425
+ for key in to_remove:
426
+ kwargs.pop(key, None)
427
+
428
+ logger.info(f"Image processor {image_processor}")
429
+ if return_unused_kwargs:
430
+ return image_processor, kwargs
431
+ else:
432
+ return image_processor
433
+
434
+ def to_dict(self) -> dict[str, Any]:
435
+ """
436
+ Serializes this instance to a Python dictionary.
437
+
438
+ Returns:
439
+ `dict[str, Any]`: Dictionary of all the attributes that make up this image processor instance.
440
+ """
441
+ output = copy.deepcopy(self.__dict__)
442
+ output["image_processor_type"] = self.__class__.__name__
443
+
444
+ return output
445
+
446
+ @classmethod
447
+ def from_json_file(cls, json_file: Union[str, os.PathLike]):
448
+ """
449
+ Instantiates a image processor of type [`~image_processing_utils.ImageProcessingMixin`] from the path to a JSON
450
+ file of parameters.
451
+
452
+ Args:
453
+ json_file (`str` or `os.PathLike`):
454
+ Path to the JSON file containing the parameters.
455
+
456
+ Returns:
457
+ A image processor of type [`~image_processing_utils.ImageProcessingMixin`]: The image_processor object
458
+ instantiated from that JSON file.
459
+ """
460
+ with open(json_file, encoding="utf-8") as reader:
461
+ text = reader.read()
462
+ image_processor_dict = json.loads(text)
463
+ return cls(**image_processor_dict)
464
+
465
+ def to_json_string(self) -> str:
466
+ """
467
+ Serializes this instance to a JSON string.
468
+
469
+ Returns:
470
+ `str`: String containing all the attributes that make up this feature_extractor instance in JSON format.
471
+ """
472
+ dictionary = self.to_dict()
473
+
474
+ for key, value in dictionary.items():
475
+ if isinstance(value, np.ndarray):
476
+ dictionary[key] = value.tolist()
477
+
478
+ # make sure private name "_processor_class" is correctly
479
+ # saved as "processor_class"
480
+ _processor_class = dictionary.pop("_processor_class", None)
481
+ if _processor_class is not None:
482
+ dictionary["processor_class"] = _processor_class
483
+
484
+ return json.dumps(dictionary, indent=2, sort_keys=True) + "\n"
485
+
486
+ def to_json_file(self, json_file_path: Union[str, os.PathLike]):
487
+ """
488
+ Save this instance to a JSON file.
489
+
490
+ Args:
491
+ json_file_path (`str` or `os.PathLike`):
492
+ Path to the JSON file in which this image_processor instance's parameters will be saved.
493
+ """
494
+ with open(json_file_path, "w", encoding="utf-8") as writer:
495
+ writer.write(self.to_json_string())
496
+
497
+ def __repr__(self):
498
+ return f"{self.__class__.__name__} {self.to_json_string()}"
499
+
500
+ @classmethod
501
+ def register_for_auto_class(cls, auto_class="AutoImageProcessor"):
502
+ """
503
+ Register this class with a given auto class. This should only be used for custom image processors as the ones
504
+ in the library are already mapped with `AutoImageProcessor `.
505
+
506
+
507
+
508
+ Args:
509
+ auto_class (`str` or `type`, *optional*, defaults to `"AutoImageProcessor "`):
510
+ The auto class to register this new image processor with.
511
+ """
512
+ if not isinstance(auto_class, str):
513
+ auto_class = auto_class.__name__
514
+
515
+ import transformers.models.auto as auto_module
516
+
517
+ if not hasattr(auto_module, auto_class):
518
+ raise ValueError(f"{auto_class} is not a valid auto class.")
519
+
520
+ cls._auto_class = auto_class
521
+
522
+ def fetch_images(self, image_url_or_urls: Union[str, list[str], list[list[str]]]):
523
+ """
524
+ Convert a single or a list of urls into the corresponding `PIL.Image` objects.
525
+
526
+ If a single url is passed, the return value will be a single object. If a list is passed a list of objects is
527
+ returned.
528
+ """
529
+ if isinstance(image_url_or_urls, list):
530
+ return [self.fetch_images(x) for x in image_url_or_urls]
531
+ elif isinstance(image_url_or_urls, str):
532
+ return load_image(image_url_or_urls)
533
+ elif is_valid_image(image_url_or_urls):
534
+ return image_url_or_urls
535
+ else:
536
+ raise TypeError(f"only a single or a list of entries is supported but got type={type(image_url_or_urls)}")
537
+
538
+
539
+ ImageProcessingMixin.push_to_hub = copy_func(ImageProcessingMixin.push_to_hub)
540
+ if ImageProcessingMixin.push_to_hub.__doc__ is not None:
541
+ ImageProcessingMixin.push_to_hub.__doc__ = ImageProcessingMixin.push_to_hub.__doc__.format(
542
+ object="image processor", object_class="AutoImageProcessor", object_files="image processor file"
543
+ )
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_processing_utils.py ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import math
16
+ from collections.abc import Iterable
17
+ from typing import Optional, Union
18
+
19
+ import numpy as np
20
+
21
+ from .image_processing_base import BatchFeature, ImageProcessingMixin
22
+ from .image_transforms import center_crop, normalize, rescale
23
+ from .image_utils import ChannelDimension, get_image_size
24
+ from .utils import logging
25
+ from .utils.import_utils import requires
26
+
27
+
28
+ logger = logging.get_logger(__name__)
29
+
30
+
31
+ INIT_SERVICE_KWARGS = [
32
+ "processor_class",
33
+ "image_processor_type",
34
+ ]
35
+
36
+
37
+ @requires(backends=("vision",))
38
+ class BaseImageProcessor(ImageProcessingMixin):
39
+ def __init__(self, **kwargs):
40
+ super().__init__(**kwargs)
41
+
42
+ @property
43
+ def is_fast(self) -> bool:
44
+ """
45
+ `bool`: Whether or not this image processor is a fast processor (backed by PyTorch and TorchVision).
46
+ """
47
+ return False
48
+
49
+ def __call__(self, images, **kwargs) -> BatchFeature:
50
+ """Preprocess an image or a batch of images."""
51
+ return self.preprocess(images, **kwargs)
52
+
53
+ def preprocess(self, images, **kwargs) -> BatchFeature:
54
+ raise NotImplementedError("Each image processor must implement its own preprocess method")
55
+
56
+ def rescale(
57
+ self,
58
+ image: np.ndarray,
59
+ scale: float,
60
+ data_format: Optional[Union[str, ChannelDimension]] = None,
61
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
62
+ **kwargs,
63
+ ) -> np.ndarray:
64
+ """
65
+ Rescale an image by a scale factor. image = image * scale.
66
+
67
+ Args:
68
+ image (`np.ndarray`):
69
+ Image to rescale.
70
+ scale (`float`):
71
+ The scaling factor to rescale pixel values by.
72
+ data_format (`str` or `ChannelDimension`, *optional*):
73
+ The channel dimension format for the output image. If unset, the channel dimension format of the input
74
+ image is used. Can be one of:
75
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
76
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
77
+ input_data_format (`ChannelDimension` or `str`, *optional*):
78
+ The channel dimension format for the input image. If unset, the channel dimension format is inferred
79
+ from the input image. Can be one of:
80
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
81
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
82
+
83
+ Returns:
84
+ `np.ndarray`: The rescaled image.
85
+ """
86
+ return rescale(image, scale=scale, data_format=data_format, input_data_format=input_data_format, **kwargs)
87
+
88
+ def normalize(
89
+ self,
90
+ image: np.ndarray,
91
+ mean: Union[float, Iterable[float]],
92
+ std: Union[float, Iterable[float]],
93
+ data_format: Optional[Union[str, ChannelDimension]] = None,
94
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
95
+ **kwargs,
96
+ ) -> np.ndarray:
97
+ """
98
+ Normalize an image. image = (image - image_mean) / image_std.
99
+
100
+ Args:
101
+ image (`np.ndarray`):
102
+ Image to normalize.
103
+ mean (`float` or `Iterable[float]`):
104
+ Image mean to use for normalization.
105
+ std (`float` or `Iterable[float]`):
106
+ Image standard deviation to use for normalization.
107
+ data_format (`str` or `ChannelDimension`, *optional*):
108
+ The channel dimension format for the output image. If unset, the channel dimension format of the input
109
+ image is used. Can be one of:
110
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
111
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
112
+ input_data_format (`ChannelDimension` or `str`, *optional*):
113
+ The channel dimension format for the input image. If unset, the channel dimension format is inferred
114
+ from the input image. Can be one of:
115
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
116
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
117
+
118
+ Returns:
119
+ `np.ndarray`: The normalized image.
120
+ """
121
+ return normalize(
122
+ image, mean=mean, std=std, data_format=data_format, input_data_format=input_data_format, **kwargs
123
+ )
124
+
125
+ def center_crop(
126
+ self,
127
+ image: np.ndarray,
128
+ size: dict[str, int],
129
+ data_format: Optional[Union[str, ChannelDimension]] = None,
130
+ input_data_format: Optional[Union[str, ChannelDimension]] = None,
131
+ **kwargs,
132
+ ) -> np.ndarray:
133
+ """
134
+ Center crop an image to `(size["height"], size["width"])`. If the input size is smaller than `crop_size` along
135
+ any edge, the image is padded with 0's and then center cropped.
136
+
137
+ Args:
138
+ image (`np.ndarray`):
139
+ Image to center crop.
140
+ size (`dict[str, int]`):
141
+ Size of the output image.
142
+ data_format (`str` or `ChannelDimension`, *optional*):
143
+ The channel dimension format for the output image. If unset, the channel dimension format of the input
144
+ image is used. Can be one of:
145
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
146
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
147
+ input_data_format (`ChannelDimension` or `str`, *optional*):
148
+ The channel dimension format for the input image. If unset, the channel dimension format is inferred
149
+ from the input image. Can be one of:
150
+ - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.
151
+ - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.
152
+ """
153
+ size = get_size_dict(size)
154
+ if "height" not in size or "width" not in size:
155
+ raise ValueError(f"The size dictionary must have keys 'height' and 'width'. Got {size.keys()}")
156
+ return center_crop(
157
+ image,
158
+ size=(size["height"], size["width"]),
159
+ data_format=data_format,
160
+ input_data_format=input_data_format,
161
+ **kwargs,
162
+ )
163
+
164
+ def to_dict(self):
165
+ encoder_dict = super().to_dict()
166
+ encoder_dict.pop("_valid_processor_keys", None)
167
+ return encoder_dict
168
+
169
+
170
+ VALID_SIZE_DICT_KEYS = (
171
+ {"height", "width"},
172
+ {"shortest_edge"},
173
+ {"shortest_edge", "longest_edge"},
174
+ {"longest_edge"},
175
+ {"max_height", "max_width"},
176
+ )
177
+
178
+
179
+ def is_valid_size_dict(size_dict):
180
+ if not isinstance(size_dict, dict):
181
+ return False
182
+
183
+ size_dict_keys = set(size_dict.keys())
184
+ for allowed_keys in VALID_SIZE_DICT_KEYS:
185
+ if size_dict_keys == allowed_keys:
186
+ return True
187
+ return False
188
+
189
+
190
+ def convert_to_size_dict(
191
+ size, max_size: Optional[int] = None, default_to_square: bool = True, height_width_order: bool = True
192
+ ):
193
+ # By default, if size is an int we assume it represents a tuple of (size, size).
194
+ if isinstance(size, int) and default_to_square:
195
+ if max_size is not None:
196
+ raise ValueError("Cannot specify both size as an int, with default_to_square=True and max_size")
197
+ return {"height": size, "width": size}
198
+ # In other configs, if size is an int and default_to_square is False, size represents the length of
199
+ # the shortest edge after resizing.
200
+ elif isinstance(size, int) and not default_to_square:
201
+ size_dict = {"shortest_edge": size}
202
+ if max_size is not None:
203
+ size_dict["longest_edge"] = max_size
204
+ return size_dict
205
+ # Otherwise, if size is a tuple it's either (height, width) or (width, height)
206
+ elif isinstance(size, (tuple, list)) and height_width_order:
207
+ return {"height": size[0], "width": size[1]}
208
+ elif isinstance(size, (tuple, list)) and not height_width_order:
209
+ return {"height": size[1], "width": size[0]}
210
+ elif size is None and max_size is not None:
211
+ if default_to_square:
212
+ raise ValueError("Cannot specify both default_to_square=True and max_size")
213
+ return {"longest_edge": max_size}
214
+
215
+ raise ValueError(f"Could not convert size input to size dict: {size}")
216
+
217
+
218
+ def get_size_dict(
219
+ size: Optional[Union[int, Iterable[int], dict[str, int]]] = None,
220
+ max_size: Optional[int] = None,
221
+ height_width_order: bool = True,
222
+ default_to_square: bool = True,
223
+ param_name="size",
224
+ ) -> dict:
225
+ """
226
+ Converts the old size parameter in the config into the new dict expected in the config. This is to ensure backwards
227
+ compatibility with the old image processor configs and removes ambiguity over whether the tuple is in (height,
228
+ width) or (width, height) format.
229
+
230
+ - If `size` is tuple, it is converted to `{"height": size[0], "width": size[1]}` or `{"height": size[1], "width":
231
+ size[0]}` if `height_width_order` is `False`.
232
+ - If `size` is an int, and `default_to_square` is `True`, it is converted to `{"height": size, "width": size}`.
233
+ - If `size` is an int and `default_to_square` is False, it is converted to `{"shortest_edge": size}`. If `max_size`
234
+ is set, it is added to the dict as `{"longest_edge": max_size}`.
235
+
236
+ Args:
237
+ size (`Union[int, Iterable[int], dict[str, int]]`, *optional*):
238
+ The `size` parameter to be cast into a size dictionary.
239
+ max_size (`Optional[int]`, *optional*):
240
+ The `max_size` parameter to be cast into a size dictionary.
241
+ height_width_order (`bool`, *optional*, defaults to `True`):
242
+ If `size` is a tuple, whether it's in (height, width) or (width, height) order.
243
+ default_to_square (`bool`, *optional*, defaults to `True`):
244
+ If `size` is an int, whether to default to a square image or not.
245
+ """
246
+ if not isinstance(size, dict):
247
+ size_dict = convert_to_size_dict(size, max_size, default_to_square, height_width_order)
248
+ logger.info(
249
+ f"{param_name} should be a dictionary on of the following set of keys: {VALID_SIZE_DICT_KEYS}, got {size}."
250
+ f" Converted to {size_dict}.",
251
+ )
252
+ else:
253
+ size_dict = size
254
+
255
+ if not is_valid_size_dict(size_dict):
256
+ raise ValueError(
257
+ f"{param_name} must have one of the following set of keys: {VALID_SIZE_DICT_KEYS}, got {size_dict.keys()}"
258
+ )
259
+ return size_dict
260
+
261
+
262
+ def select_best_resolution(original_size: tuple, possible_resolutions: list) -> tuple:
263
+ """
264
+ Selects the best resolution from a list of possible resolutions based on the original size.
265
+
266
+ This is done by calculating the effective and wasted resolution for each possible resolution.
267
+
268
+ The best fit resolution is the one that maximizes the effective resolution and minimizes the wasted resolution.
269
+
270
+ Args:
271
+ original_size (tuple):
272
+ The original size of the image in the format (height, width).
273
+ possible_resolutions (list):
274
+ A list of possible resolutions in the format [(height1, width1), (height2, width2), ...].
275
+
276
+ Returns:
277
+ tuple: The best fit resolution in the format (height, width).
278
+ """
279
+ original_height, original_width = original_size
280
+ best_fit = None
281
+ max_effective_resolution = 0
282
+ min_wasted_resolution = float("inf")
283
+
284
+ for height, width in possible_resolutions:
285
+ scale = min(width / original_width, height / original_height)
286
+ downscaled_width, downscaled_height = int(original_width * scale), int(original_height * scale)
287
+ effective_resolution = min(downscaled_width * downscaled_height, original_width * original_height)
288
+ wasted_resolution = (width * height) - effective_resolution
289
+
290
+ if effective_resolution > max_effective_resolution or (
291
+ effective_resolution == max_effective_resolution and wasted_resolution < min_wasted_resolution
292
+ ):
293
+ max_effective_resolution = effective_resolution
294
+ min_wasted_resolution = wasted_resolution
295
+ best_fit = (height, width)
296
+
297
+ return best_fit
298
+
299
+
300
+ def get_patch_output_size(image, target_resolution, input_data_format):
301
+ """
302
+ Given an image and a target resolution, calculate the output size of the image after cropping to the target
303
+ """
304
+ original_height, original_width = get_image_size(image, channel_dim=input_data_format)
305
+ target_height, target_width = target_resolution
306
+
307
+ scale_w = target_width / original_width
308
+ scale_h = target_height / original_height
309
+
310
+ if scale_w < scale_h:
311
+ new_width = target_width
312
+ new_height = min(math.ceil(original_height * scale_w), target_height)
313
+ else:
314
+ new_height = target_height
315
+ new_width = min(math.ceil(original_width * scale_h), target_width)
316
+
317
+ return new_height, new_width
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/image_utils.py ADDED
@@ -0,0 +1,969 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import base64
16
+ import os
17
+ from collections.abc import Iterable
18
+ from dataclasses import dataclass
19
+ from io import BytesIO
20
+ from typing import Optional, Union
21
+
22
+ import numpy as np
23
+ import requests
24
+
25
+ from .utils import (
26
+ ExplicitEnum,
27
+ is_jax_tensor,
28
+ is_numpy_array,
29
+ is_tf_tensor,
30
+ is_torch_available,
31
+ is_torch_tensor,
32
+ is_torchvision_available,
33
+ is_vision_available,
34
+ logging,
35
+ requires_backends,
36
+ to_numpy,
37
+ )
38
+ from .utils.constants import ( # noqa: F401
39
+ IMAGENET_DEFAULT_MEAN,
40
+ IMAGENET_DEFAULT_STD,
41
+ IMAGENET_STANDARD_MEAN,
42
+ IMAGENET_STANDARD_STD,
43
+ OPENAI_CLIP_MEAN,
44
+ OPENAI_CLIP_STD,
45
+ )
46
+
47
+
48
+ if is_vision_available():
49
+ import PIL.Image
50
+ import PIL.ImageOps
51
+
52
+ PILImageResampling = PIL.Image.Resampling
53
+
54
+ if is_torchvision_available():
55
+ from torchvision.transforms import InterpolationMode
56
+
57
+ pil_torch_interpolation_mapping = {
58
+ PILImageResampling.NEAREST: InterpolationMode.NEAREST_EXACT,
59
+ PILImageResampling.BOX: InterpolationMode.BOX,
60
+ PILImageResampling.BILINEAR: InterpolationMode.BILINEAR,
61
+ PILImageResampling.HAMMING: InterpolationMode.HAMMING,
62
+ PILImageResampling.BICUBIC: InterpolationMode.BICUBIC,
63
+ PILImageResampling.LANCZOS: InterpolationMode.LANCZOS,
64
+ }
65
+ else:
66
+ pil_torch_interpolation_mapping = {}
67
+
68
+
69
+ if is_torch_available():
70
+ import torch
71
+
72
+
73
+ logger = logging.get_logger(__name__)
74
+
75
+
76
+ ImageInput = Union[
77
+ "PIL.Image.Image", np.ndarray, "torch.Tensor", list["PIL.Image.Image"], list[np.ndarray], list["torch.Tensor"]
78
+ ]
79
+
80
+
81
+ class ChannelDimension(ExplicitEnum):
82
+ FIRST = "channels_first"
83
+ LAST = "channels_last"
84
+
85
+
86
+ class AnnotationFormat(ExplicitEnum):
87
+ COCO_DETECTION = "coco_detection"
88
+ COCO_PANOPTIC = "coco_panoptic"
89
+
90
+
91
+ class AnnotionFormat(ExplicitEnum):
92
+ COCO_DETECTION = AnnotationFormat.COCO_DETECTION.value
93
+ COCO_PANOPTIC = AnnotationFormat.COCO_PANOPTIC.value
94
+
95
+
96
+ AnnotationType = dict[str, Union[int, str, list[dict]]]
97
+
98
+
99
+ def is_pil_image(img):
100
+ return is_vision_available() and isinstance(img, PIL.Image.Image)
101
+
102
+
103
+ class ImageType(ExplicitEnum):
104
+ PIL = "pillow"
105
+ TORCH = "torch"
106
+ NUMPY = "numpy"
107
+ TENSORFLOW = "tensorflow"
108
+ JAX = "jax"
109
+
110
+
111
+ def get_image_type(image):
112
+ if is_pil_image(image):
113
+ return ImageType.PIL
114
+ if is_torch_tensor(image):
115
+ return ImageType.TORCH
116
+ if is_numpy_array(image):
117
+ return ImageType.NUMPY
118
+ if is_tf_tensor(image):
119
+ return ImageType.TENSORFLOW
120
+ if is_jax_tensor(image):
121
+ return ImageType.JAX
122
+ raise ValueError(f"Unrecognized image type {type(image)}")
123
+
124
+
125
+ def is_valid_image(img):
126
+ return is_pil_image(img) or is_numpy_array(img) or is_torch_tensor(img) or is_tf_tensor(img) or is_jax_tensor(img)
127
+
128
+
129
+ def is_valid_list_of_images(images: list):
130
+ return images and all(is_valid_image(image) for image in images)
131
+
132
+
133
+ def concatenate_list(input_list):
134
+ if isinstance(input_list[0], list):
135
+ return [item for sublist in input_list for item in sublist]
136
+ elif isinstance(input_list[0], np.ndarray):
137
+ return np.concatenate(input_list, axis=0)
138
+ elif isinstance(input_list[0], torch.Tensor):
139
+ return torch.cat(input_list, dim=0)
140
+
141
+
142
+ def valid_images(imgs):
143
+ # If we have an list of images, make sure every image is valid
144
+ if isinstance(imgs, (list, tuple)):
145
+ for img in imgs:
146
+ if not valid_images(img):
147
+ return False
148
+ # If not a list of tuple, we have been given a single image or batched tensor of images
149
+ elif not is_valid_image(imgs):
150
+ return False
151
+ return True
152
+
153
+
154
+ def is_batched(img):
155
+ if isinstance(img, (list, tuple)):
156
+ return is_valid_image(img[0])
157
+ return False
158
+
159
+
160
+ def is_scaled_image(image: np.ndarray) -> bool:
161
+ """
162
+ Checks to see whether the pixel values have already been rescaled to [0, 1].
163
+ """
164
+ if image.dtype == np.uint8:
165
+ return False
166
+
167
+ # It's possible the image has pixel values in [0, 255] but is of floating type
168
+ return np.min(image) >= 0 and np.max(image) <= 1
169
+
170
+
171
+ def make_list_of_images(images, expected_ndims: int = 3) -> list[ImageInput]:
172
+ """
173
+ Ensure that the output is a list of images. If the input is a single image, it is converted to a list of length 1.
174
+ If the input is a batch of images, it is converted to a list of images.
175
+
176
+ Args:
177
+ images (`ImageInput`):
178
+ Image of images to turn into a list of images.
179
+ expected_ndims (`int`, *optional*, defaults to 3):
180
+ Expected number of dimensions for a single input image. If the input image has a different number of
181
+ dimensions, an error is raised.
182
+ """
183
+ if is_batched(images):
184
+ return images
185
+
186
+ # Either the input is a single image, in which case we create a list of length 1
187
+ if is_pil_image(images):
188
+ # PIL images are never batched
189
+ return [images]
190
+
191
+ if is_valid_image(images):
192
+ if images.ndim == expected_ndims + 1:
193
+ # Batch of images
194
+ images = list(images)
195
+ elif images.ndim == expected_ndims:
196
+ # Single image
197
+ images = [images]
198
+ else:
199
+ raise ValueError(
200
+ f"Invalid image shape. Expected either {expected_ndims + 1} or {expected_ndims} dimensions, but got"
201
+ f" {images.ndim} dimensions."
202
+ )
203
+ return images
204
+ raise ValueError(
205
+ "Invalid image type. Expected either PIL.Image.Image, numpy.ndarray, torch.Tensor, tf.Tensor or "
206
+ f"jax.ndarray, but got {type(images)}."
207
+ )
208
+
209
+
210
+ def make_flat_list_of_images(
211
+ images: Union[list[ImageInput], ImageInput],
212
+ expected_ndims: int = 3,
213
+ ) -> ImageInput:
214
+ """
215
+ Ensure that the output is a flat list of images. If the input is a single image, it is converted to a list of length 1.
216
+ If the input is a nested list of images, it is converted to a flat list of images.
217
+ Args:
218
+ images (`Union[list[ImageInput], ImageInput]`):
219
+ The input image.
220
+ expected_ndims (`int`, *optional*, defaults to 3):
221
+ The expected number of dimensions for a single input image.
222
+ Returns:
223
+ list: A list of images or a 4d array of images.
224
+ """
225
+ # If the input is a nested list of images, we flatten it
226
+ if (
227
+ isinstance(images, (list, tuple))
228
+ and all(isinstance(images_i, (list, tuple)) for images_i in images)
229
+ and all(is_valid_list_of_images(images_i) or not images_i for images_i in images)
230
+ ):
231
+ return [img for img_list in images for img in img_list]
232
+
233
+ if isinstance(images, (list, tuple)) and is_valid_list_of_images(images):
234
+ if is_pil_image(images[0]) or images[0].ndim == expected_ndims:
235
+ return images
236
+ if images[0].ndim == expected_ndims + 1:
237
+ return [img for img_list in images for img in img_list]
238
+
239
+ if is_valid_image(images):
240
+ if is_pil_image(images) or images.ndim == expected_ndims:
241
+ return [images]
242
+ if images.ndim == expected_ndims + 1:
243
+ return list(images)
244
+
245
+ raise ValueError(f"Could not make a flat list of images from {images}")
246
+
247
+
248
+ def make_nested_list_of_images(
249
+ images: Union[list[ImageInput], ImageInput],
250
+ expected_ndims: int = 3,
251
+ ) -> list[ImageInput]:
252
+ """
253
+ Ensure that the output is a nested list of images.
254
+ Args:
255
+ images (`Union[list[ImageInput], ImageInput]`):
256
+ The input image.
257
+ expected_ndims (`int`, *optional*, defaults to 3):
258
+ The expected number of dimensions for a single input image.
259
+ Returns:
260
+ list: A list of list of images or a list of 4d array of images.
261
+ """
262
+ # If it's a list of batches, it's already in the right format
263
+ if (
264
+ isinstance(images, (list, tuple))
265
+ and all(isinstance(images_i, (list, tuple)) for images_i in images)
266
+ and all(is_valid_list_of_images(images_i) or not images_i for images_i in images)
267
+ ):
268
+ return images
269
+
270
+ # If it's a list of images, it's a single batch, so convert it to a list of lists
271
+ if isinstance(images, (list, tuple)) and is_valid_list_of_images(images):
272
+ if is_pil_image(images[0]) or images[0].ndim == expected_ndims:
273
+ return [images]
274
+ if images[0].ndim == expected_ndims + 1:
275
+ return [list(image) for image in images]
276
+
277
+ # If it's a single image, convert it to a list of lists
278
+ if is_valid_image(images):
279
+ if is_pil_image(images) or images.ndim == expected_ndims:
280
+ return [[images]]
281
+ if images.ndim == expected_ndims + 1:
282
+ return [list(images)]
283
+
284
+ raise ValueError("Invalid input type. Must be a single image, a list of images, or a list of batches of images.")
285
+
286
+
287
+ def to_numpy_array(img) -> np.ndarray:
288
+ if not is_valid_image(img):
289
+ raise ValueError(f"Invalid image type: {type(img)}")
290
+
291
+ if is_vision_available() and isinstance(img, PIL.Image.Image):
292
+ return np.array(img)
293
+ return to_numpy(img)
294
+
295
+
296
+ def infer_channel_dimension_format(
297
+ image: np.ndarray, num_channels: Optional[Union[int, tuple[int, ...]]] = None
298
+ ) -> ChannelDimension:
299
+ """
300
+ Infers the channel dimension format of `image`.
301
+
302
+ Args:
303
+ image (`np.ndarray`):
304
+ The image to infer the channel dimension of.
305
+ num_channels (`int` or `tuple[int, ...]`, *optional*, defaults to `(1, 3)`):
306
+ The number of channels of the image.
307
+
308
+ Returns:
309
+ The channel dimension of the image.
310
+ """
311
+ num_channels = num_channels if num_channels is not None else (1, 3)
312
+ num_channels = (num_channels,) if isinstance(num_channels, int) else num_channels
313
+
314
+ if image.ndim == 3:
315
+ first_dim, last_dim = 0, 2
316
+ elif image.ndim == 4:
317
+ first_dim, last_dim = 1, 3
318
+ elif image.ndim == 5:
319
+ first_dim, last_dim = 2, 4
320
+ else:
321
+ raise ValueError(f"Unsupported number of image dimensions: {image.ndim}")
322
+
323
+ if image.shape[first_dim] in num_channels and image.shape[last_dim] in num_channels:
324
+ logger.warning(
325
+ f"The channel dimension is ambiguous. Got image shape {image.shape}. Assuming channels are the first dimension. Use the [input_data_format](https://huggingface.co/docs/transformers/main/internal/image_processing_utils#transformers.image_transforms.rescale.input_data_format) parameter to assign the channel dimension."
326
+ )
327
+ return ChannelDimension.FIRST
328
+ elif image.shape[first_dim] in num_channels:
329
+ return ChannelDimension.FIRST
330
+ elif image.shape[last_dim] in num_channels:
331
+ return ChannelDimension.LAST
332
+ raise ValueError("Unable to infer channel dimension format")
333
+
334
+
335
+ def get_channel_dimension_axis(
336
+ image: np.ndarray, input_data_format: Optional[Union[ChannelDimension, str]] = None
337
+ ) -> int:
338
+ """
339
+ Returns the channel dimension axis of the image.
340
+
341
+ Args:
342
+ image (`np.ndarray`):
343
+ The image to get the channel dimension axis of.
344
+ input_data_format (`ChannelDimension` or `str`, *optional*):
345
+ The channel dimension format of the image. If `None`, will infer the channel dimension from the image.
346
+
347
+ Returns:
348
+ The channel dimension axis of the image.
349
+ """
350
+ if input_data_format is None:
351
+ input_data_format = infer_channel_dimension_format(image)
352
+ if input_data_format == ChannelDimension.FIRST:
353
+ return image.ndim - 3
354
+ elif input_data_format == ChannelDimension.LAST:
355
+ return image.ndim - 1
356
+ raise ValueError(f"Unsupported data format: {input_data_format}")
357
+
358
+
359
+ def get_image_size(image: np.ndarray, channel_dim: Optional[ChannelDimension] = None) -> tuple[int, int]:
360
+ """
361
+ Returns the (height, width) dimensions of the image.
362
+
363
+ Args:
364
+ image (`np.ndarray`):
365
+ The image to get the dimensions of.
366
+ channel_dim (`ChannelDimension`, *optional*):
367
+ Which dimension the channel dimension is in. If `None`, will infer the channel dimension from the image.
368
+
369
+ Returns:
370
+ A tuple of the image's height and width.
371
+ """
372
+ if channel_dim is None:
373
+ channel_dim = infer_channel_dimension_format(image)
374
+
375
+ if channel_dim == ChannelDimension.FIRST:
376
+ return image.shape[-2], image.shape[-1]
377
+ elif channel_dim == ChannelDimension.LAST:
378
+ return image.shape[-3], image.shape[-2]
379
+ else:
380
+ raise ValueError(f"Unsupported data format: {channel_dim}")
381
+
382
+
383
+ def get_image_size_for_max_height_width(
384
+ image_size: tuple[int, int],
385
+ max_height: int,
386
+ max_width: int,
387
+ ) -> tuple[int, int]:
388
+ """
389
+ Computes the output image size given the input image and the maximum allowed height and width. Keep aspect ratio.
390
+ Important, even if image_height < max_height and image_width < max_width, the image will be resized
391
+ to at least one of the edges be equal to max_height or max_width.
392
+
393
+ For example:
394
+ - input_size: (100, 200), max_height: 50, max_width: 50 -> output_size: (25, 50)
395
+ - input_size: (100, 200), max_height: 200, max_width: 500 -> output_size: (200, 400)
396
+
397
+ Args:
398
+ image_size (`tuple[int, int]`):
399
+ The image to resize.
400
+ max_height (`int`):
401
+ The maximum allowed height.
402
+ max_width (`int`):
403
+ The maximum allowed width.
404
+ """
405
+ height, width = image_size
406
+ height_scale = max_height / height
407
+ width_scale = max_width / width
408
+ min_scale = min(height_scale, width_scale)
409
+ new_height = int(height * min_scale)
410
+ new_width = int(width * min_scale)
411
+ return new_height, new_width
412
+
413
+
414
+ def is_valid_annotation_coco_detection(annotation: dict[str, Union[list, tuple]]) -> bool:
415
+ if (
416
+ isinstance(annotation, dict)
417
+ and "image_id" in annotation
418
+ and "annotations" in annotation
419
+ and isinstance(annotation["annotations"], (list, tuple))
420
+ and (
421
+ # an image can have no annotations
422
+ len(annotation["annotations"]) == 0 or isinstance(annotation["annotations"][0], dict)
423
+ )
424
+ ):
425
+ return True
426
+ return False
427
+
428
+
429
+ def is_valid_annotation_coco_panoptic(annotation: dict[str, Union[list, tuple]]) -> bool:
430
+ if (
431
+ isinstance(annotation, dict)
432
+ and "image_id" in annotation
433
+ and "segments_info" in annotation
434
+ and "file_name" in annotation
435
+ and isinstance(annotation["segments_info"], (list, tuple))
436
+ and (
437
+ # an image can have no segments
438
+ len(annotation["segments_info"]) == 0 or isinstance(annotation["segments_info"][0], dict)
439
+ )
440
+ ):
441
+ return True
442
+ return False
443
+
444
+
445
+ def valid_coco_detection_annotations(annotations: Iterable[dict[str, Union[list, tuple]]]) -> bool:
446
+ return all(is_valid_annotation_coco_detection(ann) for ann in annotations)
447
+
448
+
449
+ def valid_coco_panoptic_annotations(annotations: Iterable[dict[str, Union[list, tuple]]]) -> bool:
450
+ return all(is_valid_annotation_coco_panoptic(ann) for ann in annotations)
451
+
452
+
453
+ def load_image(image: Union[str, "PIL.Image.Image"], timeout: Optional[float] = None) -> "PIL.Image.Image":
454
+ """
455
+ Loads `image` to a PIL Image.
456
+
457
+ Args:
458
+ image (`str` or `PIL.Image.Image`):
459
+ The image to convert to the PIL Image format.
460
+ timeout (`float`, *optional*):
461
+ The timeout value in seconds for the URL request.
462
+
463
+ Returns:
464
+ `PIL.Image.Image`: A PIL Image.
465
+ """
466
+ requires_backends(load_image, ["vision"])
467
+ if isinstance(image, str):
468
+ if image.startswith("http://") or image.startswith("https://"):
469
+ # We need to actually check for a real protocol, otherwise it's impossible to use a local file
470
+ # like http_huggingface_co.png
471
+ image = PIL.Image.open(BytesIO(requests.get(image, timeout=timeout).content))
472
+ elif os.path.isfile(image):
473
+ image = PIL.Image.open(image)
474
+ else:
475
+ if image.startswith("data:image/"):
476
+ image = image.split(",")[1]
477
+
478
+ # Try to load as base64
479
+ try:
480
+ b64 = base64.decodebytes(image.encode())
481
+ image = PIL.Image.open(BytesIO(b64))
482
+ except Exception as e:
483
+ raise ValueError(
484
+ f"Incorrect image source. Must be a valid URL starting with `http://` or `https://`, a valid path to an image file, or a base64 encoded string. Got {image}. Failed with {e}"
485
+ )
486
+ elif not isinstance(image, PIL.Image.Image):
487
+ raise TypeError(
488
+ "Incorrect format used for image. Should be an url linking to an image, a base64 string, a local path, or a PIL image."
489
+ )
490
+ image = PIL.ImageOps.exif_transpose(image)
491
+ image = image.convert("RGB")
492
+ return image
493
+
494
+
495
+ def load_images(
496
+ images: Union[list, tuple, str, "PIL.Image.Image"], timeout: Optional[float] = None
497
+ ) -> Union["PIL.Image.Image", list["PIL.Image.Image"], list[list["PIL.Image.Image"]]]:
498
+ """Loads images, handling different levels of nesting.
499
+
500
+ Args:
501
+ images: A single image, a list of images, or a list of lists of images to load.
502
+ timeout: Timeout for loading images.
503
+
504
+ Returns:
505
+ A single image, a list of images, a list of lists of images.
506
+ """
507
+ if isinstance(images, (list, tuple)):
508
+ if len(images) and isinstance(images[0], (list, tuple)):
509
+ return [[load_image(image, timeout=timeout) for image in image_group] for image_group in images]
510
+ else:
511
+ return [load_image(image, timeout=timeout) for image in images]
512
+ else:
513
+ return load_image(images, timeout=timeout)
514
+
515
+
516
+ def validate_preprocess_arguments(
517
+ do_rescale: Optional[bool] = None,
518
+ rescale_factor: Optional[float] = None,
519
+ do_normalize: Optional[bool] = None,
520
+ image_mean: Optional[Union[float, list[float]]] = None,
521
+ image_std: Optional[Union[float, list[float]]] = None,
522
+ do_pad: Optional[bool] = None,
523
+ pad_size: Optional[Union[dict[str, int], int]] = None,
524
+ do_center_crop: Optional[bool] = None,
525
+ crop_size: Optional[dict[str, int]] = None,
526
+ do_resize: Optional[bool] = None,
527
+ size: Optional[dict[str, int]] = None,
528
+ resample: Optional["PILImageResampling"] = None,
529
+ interpolation: Optional["InterpolationMode"] = None,
530
+ ):
531
+ """
532
+ Checks validity of typically used arguments in an `ImageProcessor` `preprocess` method.
533
+ Raises `ValueError` if arguments incompatibility is caught.
534
+ Many incompatibilities are model-specific. `do_pad` sometimes needs `size_divisor`,
535
+ sometimes `size_divisibility`, and sometimes `size`. New models and processors added should follow
536
+ existing arguments when possible.
537
+
538
+ """
539
+ if do_rescale and rescale_factor is None:
540
+ raise ValueError("`rescale_factor` must be specified if `do_rescale` is `True`.")
541
+
542
+ if do_pad and pad_size is None:
543
+ # Processors pad images using different args depending on the model, so the below check is pointless
544
+ # but we keep it for BC for now. TODO: remove in v5
545
+ # Usually padding can be called with:
546
+ # - "pad_size/size" if we're padding to specific values
547
+ # - "size_divisor" if we're padding to any value divisible by X
548
+ # - "None" if we're padding to the maximum size image in batch
549
+ raise ValueError(
550
+ "Depending on the model, `size_divisor` or `pad_size` or `size` must be specified if `do_pad` is `True`."
551
+ )
552
+
553
+ if do_normalize and (image_mean is None or image_std is None):
554
+ raise ValueError("`image_mean` and `image_std` must both be specified if `do_normalize` is `True`.")
555
+
556
+ if do_center_crop and crop_size is None:
557
+ raise ValueError("`crop_size` must be specified if `do_center_crop` is `True`.")
558
+
559
+ if interpolation is not None and resample is not None:
560
+ raise ValueError(
561
+ "Only one of `interpolation` and `resample` should be specified, depending on image processor type."
562
+ )
563
+
564
+ if do_resize and not (size is not None and (resample is not None or interpolation is not None)):
565
+ raise ValueError("`size` and `resample/interpolation` must be specified if `do_resize` is `True`.")
566
+
567
+
568
+ # In the future we can add a TF implementation here when we have TF models.
569
+ class ImageFeatureExtractionMixin:
570
+ """
571
+ Mixin that contain utilities for preparing image features.
572
+ """
573
+
574
+ def _ensure_format_supported(self, image):
575
+ if not isinstance(image, (PIL.Image.Image, np.ndarray)) and not is_torch_tensor(image):
576
+ raise ValueError(
577
+ f"Got type {type(image)} which is not supported, only `PIL.Image.Image`, `np.ndarray` and "
578
+ "`torch.Tensor` are."
579
+ )
580
+
581
+ def to_pil_image(self, image, rescale=None):
582
+ """
583
+ Converts `image` to a PIL Image. Optionally rescales it and puts the channel dimension back as the last axis if
584
+ needed.
585
+
586
+ Args:
587
+ image (`PIL.Image.Image` or `numpy.ndarray` or `torch.Tensor`):
588
+ The image to convert to the PIL Image format.
589
+ rescale (`bool`, *optional*):
590
+ Whether or not to apply the scaling factor (to make pixel values integers between 0 and 255). Will
591
+ default to `True` if the image type is a floating type, `False` otherwise.
592
+ """
593
+ self._ensure_format_supported(image)
594
+
595
+ if is_torch_tensor(image):
596
+ image = image.numpy()
597
+
598
+ if isinstance(image, np.ndarray):
599
+ if rescale is None:
600
+ # rescale default to the array being of floating type.
601
+ rescale = isinstance(image.flat[0], np.floating)
602
+ # If the channel as been moved to first dim, we put it back at the end.
603
+ if image.ndim == 3 and image.shape[0] in [1, 3]:
604
+ image = image.transpose(1, 2, 0)
605
+ if rescale:
606
+ image = image * 255
607
+ image = image.astype(np.uint8)
608
+ return PIL.Image.fromarray(image)
609
+ return image
610
+
611
+ def convert_rgb(self, image):
612
+ """
613
+ Converts `PIL.Image.Image` to RGB format.
614
+
615
+ Args:
616
+ image (`PIL.Image.Image`):
617
+ The image to convert.
618
+ """
619
+ self._ensure_format_supported(image)
620
+ if not isinstance(image, PIL.Image.Image):
621
+ return image
622
+
623
+ return image.convert("RGB")
624
+
625
+ def rescale(self, image: np.ndarray, scale: Union[float, int]) -> np.ndarray:
626
+ """
627
+ Rescale a numpy image by scale amount
628
+ """
629
+ self._ensure_format_supported(image)
630
+ return image * scale
631
+
632
+ def to_numpy_array(self, image, rescale=None, channel_first=True):
633
+ """
634
+ Converts `image` to a numpy array. Optionally rescales it and puts the channel dimension as the first
635
+ dimension.
636
+
637
+ Args:
638
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor`):
639
+ The image to convert to a NumPy array.
640
+ rescale (`bool`, *optional*):
641
+ Whether or not to apply the scaling factor (to make pixel values floats between 0. and 1.). Will
642
+ default to `True` if the image is a PIL Image or an array/tensor of integers, `False` otherwise.
643
+ channel_first (`bool`, *optional*, defaults to `True`):
644
+ Whether or not to permute the dimensions of the image to put the channel dimension first.
645
+ """
646
+ self._ensure_format_supported(image)
647
+
648
+ if isinstance(image, PIL.Image.Image):
649
+ image = np.array(image)
650
+
651
+ if is_torch_tensor(image):
652
+ image = image.numpy()
653
+
654
+ rescale = isinstance(image.flat[0], np.integer) if rescale is None else rescale
655
+
656
+ if rescale:
657
+ image = self.rescale(image.astype(np.float32), 1 / 255.0)
658
+
659
+ if channel_first and image.ndim == 3:
660
+ image = image.transpose(2, 0, 1)
661
+
662
+ return image
663
+
664
+ def expand_dims(self, image):
665
+ """
666
+ Expands 2-dimensional `image` to 3 dimensions.
667
+
668
+ Args:
669
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor`):
670
+ The image to expand.
671
+ """
672
+ self._ensure_format_supported(image)
673
+
674
+ # Do nothing if PIL image
675
+ if isinstance(image, PIL.Image.Image):
676
+ return image
677
+
678
+ if is_torch_tensor(image):
679
+ image = image.unsqueeze(0)
680
+ else:
681
+ image = np.expand_dims(image, axis=0)
682
+ return image
683
+
684
+ def normalize(self, image, mean, std, rescale=False):
685
+ """
686
+ Normalizes `image` with `mean` and `std`. Note that this will trigger a conversion of `image` to a NumPy array
687
+ if it's a PIL Image.
688
+
689
+ Args:
690
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor`):
691
+ The image to normalize.
692
+ mean (`list[float]` or `np.ndarray` or `torch.Tensor`):
693
+ The mean (per channel) to use for normalization.
694
+ std (`list[float]` or `np.ndarray` or `torch.Tensor`):
695
+ The standard deviation (per channel) to use for normalization.
696
+ rescale (`bool`, *optional*, defaults to `False`):
697
+ Whether or not to rescale the image to be between 0 and 1. If a PIL image is provided, scaling will
698
+ happen automatically.
699
+ """
700
+ self._ensure_format_supported(image)
701
+
702
+ if isinstance(image, PIL.Image.Image):
703
+ image = self.to_numpy_array(image, rescale=True)
704
+ # If the input image is a PIL image, it automatically gets rescaled. If it's another
705
+ # type it may need rescaling.
706
+ elif rescale:
707
+ if isinstance(image, np.ndarray):
708
+ image = self.rescale(image.astype(np.float32), 1 / 255.0)
709
+ elif is_torch_tensor(image):
710
+ image = self.rescale(image.float(), 1 / 255.0)
711
+
712
+ if isinstance(image, np.ndarray):
713
+ if not isinstance(mean, np.ndarray):
714
+ mean = np.array(mean).astype(image.dtype)
715
+ if not isinstance(std, np.ndarray):
716
+ std = np.array(std).astype(image.dtype)
717
+ elif is_torch_tensor(image):
718
+ import torch
719
+
720
+ if not isinstance(mean, torch.Tensor):
721
+ if isinstance(mean, np.ndarray):
722
+ mean = torch.from_numpy(mean)
723
+ else:
724
+ mean = torch.tensor(mean)
725
+ if not isinstance(std, torch.Tensor):
726
+ if isinstance(std, np.ndarray):
727
+ std = torch.from_numpy(std)
728
+ else:
729
+ std = torch.tensor(std)
730
+
731
+ if image.ndim == 3 and image.shape[0] in [1, 3]:
732
+ return (image - mean[:, None, None]) / std[:, None, None]
733
+ else:
734
+ return (image - mean) / std
735
+
736
+ def resize(self, image, size, resample=None, default_to_square=True, max_size=None):
737
+ """
738
+ Resizes `image`. Enforces conversion of input to PIL.Image.
739
+
740
+ Args:
741
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor`):
742
+ The image to resize.
743
+ size (`int` or `tuple[int, int]`):
744
+ The size to use for resizing the image. If `size` is a sequence like (h, w), output size will be
745
+ matched to this.
746
+
747
+ If `size` is an int and `default_to_square` is `True`, then image will be resized to (size, size). If
748
+ `size` is an int and `default_to_square` is `False`, then smaller edge of the image will be matched to
749
+ this number. i.e, if height > width, then image will be rescaled to (size * height / width, size).
750
+ resample (`int`, *optional*, defaults to `PILImageResampling.BILINEAR`):
751
+ The filter to user for resampling.
752
+ default_to_square (`bool`, *optional*, defaults to `True`):
753
+ How to convert `size` when it is a single int. If set to `True`, the `size` will be converted to a
754
+ square (`size`,`size`). If set to `False`, will replicate
755
+ [`torchvision.transforms.Resize`](https://pytorch.org/vision/stable/transforms.html#torchvision.transforms.Resize)
756
+ with support for resizing only the smallest edge and providing an optional `max_size`.
757
+ max_size (`int`, *optional*, defaults to `None`):
758
+ The maximum allowed for the longer edge of the resized image: if the longer edge of the image is
759
+ greater than `max_size` after being resized according to `size`, then the image is resized again so
760
+ that the longer edge is equal to `max_size`. As a result, `size` might be overruled, i.e the smaller
761
+ edge may be shorter than `size`. Only used if `default_to_square` is `False`.
762
+
763
+ Returns:
764
+ image: A resized `PIL.Image.Image`.
765
+ """
766
+ resample = resample if resample is not None else PILImageResampling.BILINEAR
767
+
768
+ self._ensure_format_supported(image)
769
+
770
+ if not isinstance(image, PIL.Image.Image):
771
+ image = self.to_pil_image(image)
772
+
773
+ if isinstance(size, list):
774
+ size = tuple(size)
775
+
776
+ if isinstance(size, int) or len(size) == 1:
777
+ if default_to_square:
778
+ size = (size, size) if isinstance(size, int) else (size[0], size[0])
779
+ else:
780
+ width, height = image.size
781
+ # specified size only for the smallest edge
782
+ short, long = (width, height) if width <= height else (height, width)
783
+ requested_new_short = size if isinstance(size, int) else size[0]
784
+
785
+ if short == requested_new_short:
786
+ return image
787
+
788
+ new_short, new_long = requested_new_short, int(requested_new_short * long / short)
789
+
790
+ if max_size is not None:
791
+ if max_size <= requested_new_short:
792
+ raise ValueError(
793
+ f"max_size = {max_size} must be strictly greater than the requested "
794
+ f"size for the smaller edge size = {size}"
795
+ )
796
+ if new_long > max_size:
797
+ new_short, new_long = int(max_size * new_short / new_long), max_size
798
+
799
+ size = (new_short, new_long) if width <= height else (new_long, new_short)
800
+
801
+ return image.resize(size, resample=resample)
802
+
803
+ def center_crop(self, image, size):
804
+ """
805
+ Crops `image` to the given size using a center crop. Note that if the image is too small to be cropped to the
806
+ size given, it will be padded (so the returned result has the size asked).
807
+
808
+ Args:
809
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor` of shape (n_channels, height, width) or (height, width, n_channels)):
810
+ The image to resize.
811
+ size (`int` or `tuple[int, int]`):
812
+ The size to which crop the image.
813
+
814
+ Returns:
815
+ new_image: A center cropped `PIL.Image.Image` or `np.ndarray` or `torch.Tensor` of shape: (n_channels,
816
+ height, width).
817
+ """
818
+ self._ensure_format_supported(image)
819
+
820
+ if not isinstance(size, tuple):
821
+ size = (size, size)
822
+
823
+ # PIL Image.size is (width, height) but NumPy array and torch Tensors have (height, width)
824
+ if is_torch_tensor(image) or isinstance(image, np.ndarray):
825
+ if image.ndim == 2:
826
+ image = self.expand_dims(image)
827
+ image_shape = image.shape[1:] if image.shape[0] in [1, 3] else image.shape[:2]
828
+ else:
829
+ image_shape = (image.size[1], image.size[0])
830
+
831
+ top = (image_shape[0] - size[0]) // 2
832
+ bottom = top + size[0] # In case size is odd, (image_shape[0] + size[0]) // 2 won't give the proper result.
833
+ left = (image_shape[1] - size[1]) // 2
834
+ right = left + size[1] # In case size is odd, (image_shape[1] + size[1]) // 2 won't give the proper result.
835
+
836
+ # For PIL Images we have a method to crop directly.
837
+ if isinstance(image, PIL.Image.Image):
838
+ return image.crop((left, top, right, bottom))
839
+
840
+ # Check if image is in (n_channels, height, width) or (height, width, n_channels) format
841
+ channel_first = image.shape[0] in [1, 3]
842
+
843
+ # Transpose (height, width, n_channels) format images
844
+ if not channel_first:
845
+ if isinstance(image, np.ndarray):
846
+ image = image.transpose(2, 0, 1)
847
+ if is_torch_tensor(image):
848
+ image = image.permute(2, 0, 1)
849
+
850
+ # Check if cropped area is within image boundaries
851
+ if top >= 0 and bottom <= image_shape[0] and left >= 0 and right <= image_shape[1]:
852
+ return image[..., top:bottom, left:right]
853
+
854
+ # Otherwise, we may need to pad if the image is too small. Oh joy...
855
+ new_shape = image.shape[:-2] + (max(size[0], image_shape[0]), max(size[1], image_shape[1]))
856
+ if isinstance(image, np.ndarray):
857
+ new_image = np.zeros_like(image, shape=new_shape)
858
+ elif is_torch_tensor(image):
859
+ new_image = image.new_zeros(new_shape)
860
+
861
+ top_pad = (new_shape[-2] - image_shape[0]) // 2
862
+ bottom_pad = top_pad + image_shape[0]
863
+ left_pad = (new_shape[-1] - image_shape[1]) // 2
864
+ right_pad = left_pad + image_shape[1]
865
+ new_image[..., top_pad:bottom_pad, left_pad:right_pad] = image
866
+
867
+ top += top_pad
868
+ bottom += top_pad
869
+ left += left_pad
870
+ right += left_pad
871
+
872
+ new_image = new_image[
873
+ ..., max(0, top) : min(new_image.shape[-2], bottom), max(0, left) : min(new_image.shape[-1], right)
874
+ ]
875
+
876
+ return new_image
877
+
878
+ def flip_channel_order(self, image):
879
+ """
880
+ Flips the channel order of `image` from RGB to BGR, or vice versa. Note that this will trigger a conversion of
881
+ `image` to a NumPy array if it's a PIL Image.
882
+
883
+ Args:
884
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor`):
885
+ The image whose color channels to flip. If `np.ndarray` or `torch.Tensor`, the channel dimension should
886
+ be first.
887
+ """
888
+ self._ensure_format_supported(image)
889
+
890
+ if isinstance(image, PIL.Image.Image):
891
+ image = self.to_numpy_array(image)
892
+
893
+ return image[::-1, :, :]
894
+
895
+ def rotate(self, image, angle, resample=None, expand=0, center=None, translate=None, fillcolor=None):
896
+ """
897
+ Returns a rotated copy of `image`. This method returns a copy of `image`, rotated the given number of degrees
898
+ counter clockwise around its centre.
899
+
900
+ Args:
901
+ image (`PIL.Image.Image` or `np.ndarray` or `torch.Tensor`):
902
+ The image to rotate. If `np.ndarray` or `torch.Tensor`, will be converted to `PIL.Image.Image` before
903
+ rotating.
904
+
905
+ Returns:
906
+ image: A rotated `PIL.Image.Image`.
907
+ """
908
+ resample = resample if resample is not None else PIL.Image.NEAREST
909
+
910
+ self._ensure_format_supported(image)
911
+
912
+ if not isinstance(image, PIL.Image.Image):
913
+ image = self.to_pil_image(image)
914
+
915
+ return image.rotate(
916
+ angle, resample=resample, expand=expand, center=center, translate=translate, fillcolor=fillcolor
917
+ )
918
+
919
+
920
+ def validate_annotations(
921
+ annotation_format: AnnotationFormat,
922
+ supported_annotation_formats: tuple[AnnotationFormat, ...],
923
+ annotations: list[dict],
924
+ ) -> None:
925
+ if annotation_format not in supported_annotation_formats:
926
+ raise ValueError(f"Unsupported annotation format: {format} must be one of {supported_annotation_formats}")
927
+
928
+ if annotation_format is AnnotationFormat.COCO_DETECTION:
929
+ if not valid_coco_detection_annotations(annotations):
930
+ raise ValueError(
931
+ "Invalid COCO detection annotations. Annotations must a dict (single image) or list of dicts "
932
+ "(batch of images) with the following keys: `image_id` and `annotations`, with the latter "
933
+ "being a list of annotations in the COCO format."
934
+ )
935
+
936
+ if annotation_format is AnnotationFormat.COCO_PANOPTIC:
937
+ if not valid_coco_panoptic_annotations(annotations):
938
+ raise ValueError(
939
+ "Invalid COCO panoptic annotations. Annotations must a dict (single image) or list of dicts "
940
+ "(batch of images) with the following keys: `image_id`, `file_name` and `segments_info`, with "
941
+ "the latter being a list of annotations in the COCO format."
942
+ )
943
+
944
+
945
+ def validate_kwargs(valid_processor_keys: list[str], captured_kwargs: list[str]):
946
+ unused_keys = set(captured_kwargs).difference(set(valid_processor_keys))
947
+ if unused_keys:
948
+ unused_key_str = ", ".join(unused_keys)
949
+ # TODO raise a warning here instead of simply logging?
950
+ logger.warning(f"Unused or unrecognized kwargs: {unused_key_str}.")
951
+
952
+
953
+ @dataclass(frozen=True)
954
+ class SizeDict:
955
+ """
956
+ Hashable dictionary to store image size information.
957
+ """
958
+
959
+ height: Optional[int] = None
960
+ width: Optional[int] = None
961
+ longest_edge: Optional[int] = None
962
+ shortest_edge: Optional[int] = None
963
+ max_height: Optional[int] = None
964
+ max_width: Optional[int] = None
965
+
966
+ def __getitem__(self, key):
967
+ if hasattr(self, key):
968
+ return getattr(self, key)
969
+ raise KeyError(f"Key {key} not found in SizeDict.")
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/keras_callbacks.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from pathlib import Path
4
+ from time import sleep
5
+ from typing import Callable, Optional, Union
6
+
7
+ import numpy as np
8
+ import tensorflow as tf
9
+ from huggingface_hub import Repository, create_repo
10
+ from packaging.version import parse
11
+
12
+ from . import IntervalStrategy, PreTrainedTokenizerBase
13
+ from .modelcard import TrainingSummary
14
+ from .modeling_tf_utils import keras
15
+
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class KerasMetricCallback(keras.callbacks.Callback):
21
+ """
22
+ Callback to compute metrics at the end of every epoch. Unlike normal Keras metrics, these do not need to be
23
+ compilable by TF. It is particularly useful for common NLP metrics like BLEU and ROUGE that require string
24
+ operations or generation loops that cannot be compiled. Predictions (or generations) will be computed on the
25
+ `eval_dataset` before being passed to the `metric_fn` in `np.ndarray` format. The `metric_fn` should compute
26
+ metrics and return a dict mapping metric names to metric values.
27
+
28
+ We provide an example of a suitable metric_fn that computes ROUGE scores for a summarization model below. Note that
29
+ this example skips some post-processing for readability and simplicity, and should probably not be used as-is!
30
+
31
+ ```py
32
+ from datasets import load_metric
33
+
34
+ rouge_metric = load_metric("rouge")
35
+
36
+
37
+ def rouge_fn(predictions, labels):
38
+ decoded_predictions = tokenizer.batch_decode(predictions, skip_special_tokens=True)
39
+ decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
40
+ result = rouge_metric.compute(predictions=decoded_predictions, references=decoded_labels)
41
+ return {key: value.mid.fmeasure * 100 for key, value in result.items()}
42
+ ```
43
+
44
+ The above function will return a dict containing values which will be logged like any other Keras metric:
45
+
46
+ ```
47
+ {'rouge1': 37.4199, 'rouge2': 13.9768, 'rougeL': 34.361, 'rougeLsum': 35.0781
48
+ ```
49
+
50
+ Args:
51
+ metric_fn (`Callable`):
52
+ Metric function provided by the user. It will be called with two arguments - `predictions` and `labels`.
53
+ These contain the model's outputs and matching labels from the dataset. It should return a dict mapping
54
+ metric names to numerical values.
55
+ eval_dataset (`tf.data.Dataset` or `dict` or `tuple` or `np.ndarray` or `tf.Tensor`):
56
+ Validation data to be used to generate predictions for the `metric_fn`.
57
+ output_cols (`list[str], *optional*):
58
+ A list of columns to be retained from the model output as the predictions. Defaults to all.
59
+ label_cols ('`list[str]`, *optional*'):
60
+ A list of columns to be retained from the input dataset as the labels. Will be autodetected if this is not
61
+ supplied.
62
+ batch_size (`int`, *optional*):
63
+ Batch size. Only used when the data is not a pre-batched `tf.data.Dataset`.
64
+ predict_with_generate (`bool`, *optional*, defaults to `False`):
65
+ Whether we should use `model.generate()` to get outputs for the model.
66
+ use_xla_generation (`bool`, *optional*, defaults to `False`):
67
+ If we're generating, whether to compile model generation with XLA. This can massively increase the speed of
68
+ generation (up to 100X speedup) but will require a new XLA compilation for each input shape. When using XLA
69
+ generation, it's a good idea to pad your inputs to the same size, or to use the `pad_to_multiple_of`
70
+ argument in your `tokenizer` or `DataCollator`, which will reduce the number of unique input shapes and
71
+ save a lot of compilation time. This option has no effect is `predict_with_generate` is `False`.
72
+ generate_kwargs (`dict`, *optional*):
73
+ Keyword arguments to pass to `model.generate()` when generating. Has no effect if `predict_with_generate`
74
+ is `False`.
75
+
76
+ """
77
+
78
+ def __init__(
79
+ self,
80
+ metric_fn: Callable,
81
+ eval_dataset: Union[tf.data.Dataset, np.ndarray, tf.Tensor, tuple, dict],
82
+ output_cols: Optional[list[str]] = None,
83
+ label_cols: Optional[list[str]] = None,
84
+ batch_size: Optional[int] = None,
85
+ predict_with_generate: bool = False,
86
+ use_xla_generation: bool = False,
87
+ generate_kwargs: Optional[dict] = None,
88
+ ):
89
+ super().__init__()
90
+ self.metric_fn = metric_fn
91
+ self.batch_size = batch_size
92
+ if not isinstance(eval_dataset, tf.data.Dataset):
93
+ if batch_size is None:
94
+ raise ValueError(
95
+ "When passing data to KerasMetricCallback that is not a pre-batched tf.data.Dataset "
96
+ "the batch_size argument must be set."
97
+ )
98
+ # Wrap a tf.data.Dataset around it
99
+ eval_dataset = tf.data.Dataset.from_tensor_slices(eval_dataset).batch(batch_size, drop_remainder=False)
100
+ self.eval_dataset = eval_dataset
101
+ self.predict_with_generate = predict_with_generate
102
+ self.output_cols = output_cols
103
+
104
+ # This next block attempts to parse out which elements of the dataset should be appended to the labels list
105
+ # that is passed to the metric_fn
106
+ if isinstance(eval_dataset.element_spec, tuple) and len(eval_dataset.element_spec) == 2:
107
+ input_spec, label_spec = eval_dataset.element_spec
108
+ else:
109
+ input_spec = eval_dataset.element_spec
110
+ label_spec = None
111
+ if label_cols is not None:
112
+ for label in label_cols:
113
+ if label not in input_spec:
114
+ raise ValueError(f"Label {label} is in label_cols but could not be found in the dataset inputs!")
115
+ self.label_cols = label_cols
116
+ self.use_keras_label = False
117
+ elif label_spec is not None:
118
+ # If the dataset inputs are split into a 2-tuple of inputs and labels,
119
+ # assume the second element is the labels
120
+ self.label_cols = None
121
+ self.use_keras_label = True
122
+ elif "labels" in input_spec:
123
+ self.label_cols = ["labels"]
124
+ self.use_keras_label = False
125
+ logging.warning("No label_cols specified for KerasMetricCallback, assuming you want the 'labels' key.")
126
+ elif "start_positions" in input_spec and "end_positions" in input_spec:
127
+ self.label_cols = ["start_positions", "end_positions"]
128
+ self.use_keras_label = False
129
+ logging.warning(
130
+ "No label_cols specified for KerasMetricCallback, assuming you want the "
131
+ "start_positions and end_positions keys."
132
+ )
133
+ else:
134
+ raise ValueError("Could not autodetect label_cols for KerasMetricCallback, please specify them!")
135
+ if parse(tf.__version__) < parse("2.7"):
136
+ logging.warning("TF versions less than 2.7 may encounter issues with KerasMetricCallback!")
137
+
138
+ self.use_xla_generation = use_xla_generation
139
+ self.generate_kwargs = {} if generate_kwargs is None else generate_kwargs
140
+
141
+ self.generation_function = None
142
+
143
+ @staticmethod
144
+ def _concatenate_batches(batches, padding_index=-100):
145
+ # If all batches are unidimensional or same length, do a simple concatenation
146
+ if batches[0].ndim == 1 or all(batch.shape[1] == batches[0].shape[1] for batch in batches):
147
+ return np.concatenate(batches, axis=0)
148
+
149
+ # Welp, they're not the same length. Let's do some padding
150
+ max_len = max([batch.shape[1] for batch in batches])
151
+ num_samples = sum([batch.shape[0] for batch in batches])
152
+ output = np.full_like(
153
+ batches[0], fill_value=padding_index, shape=[num_samples, max_len] + list(batches[0].shape[2:])
154
+ )
155
+ # i keeps track of which part of the concatenated array we're writing the next batch to
156
+ i = 0
157
+ for batch in batches:
158
+ output[i : i + len(batch), : batch.shape[1]] = batch
159
+ i += len(batch)
160
+ return output
161
+
162
+ def _postprocess_predictions_or_labels(self, inputs):
163
+ if isinstance(inputs[0], dict):
164
+ outputs = {}
165
+ for key in inputs[0]:
166
+ outputs[key] = self._concatenate_batches([batch[key] for batch in inputs])
167
+ # If it's a dict with only one key, just return the array
168
+ if len(outputs) == 1:
169
+ outputs = list(outputs.values())[0]
170
+ elif isinstance(inputs[0], (tuple, list)):
171
+ outputs = []
172
+ for input_list in zip(*inputs):
173
+ outputs.append(self._concatenate_batches(input_list))
174
+ if len(outputs) == 1:
175
+ outputs = outputs[0] # If it's a list with only one element, just return the array
176
+ elif isinstance(inputs[0], np.ndarray):
177
+ outputs = self._concatenate_batches(inputs)
178
+ elif isinstance(inputs[0], tf.Tensor):
179
+ outputs = self._concatenate_batches([tensor.numpy() for tensor in inputs])
180
+ else:
181
+ raise TypeError(f"Couldn't handle batch of type {type(inputs[0])}!")
182
+ return outputs
183
+
184
+ def on_epoch_end(self, epoch, logs=None):
185
+ if hasattr(self.model, "config"):
186
+ ignore_keys = getattr(self.model.config, "keys_to_ignore_at_inference", [])
187
+ else:
188
+ ignore_keys = []
189
+
190
+ main_input_name = None
191
+ if self.predict_with_generate:
192
+ # This dense conditional recognizes the case where we have an encoder-decoder model, but
193
+ # avoids getting tangled up when we just have a model with a layer called 'encoder'
194
+ if hasattr(self.model, "encoder") and hasattr(self.model.encoder, "main_input_name"):
195
+ main_input_name = self.model.encoder.main_input_name
196
+ else:
197
+ main_input_name = getattr(self.model, "main_input_name", "input_ids")
198
+
199
+ if self.use_xla_generation and self.generation_function is None:
200
+
201
+ def generation_function(inputs, attention_mask):
202
+ return self.model.generate(inputs, attention_mask=attention_mask, **self.generate_kwargs)
203
+
204
+ self.generation_function = tf.function(generation_function, jit_compile=True)
205
+
206
+ prediction_list = []
207
+ label_list = []
208
+
209
+ # The whole predict/generate loop is handled inside this method
210
+ for batch in self.eval_dataset:
211
+ if isinstance(batch, tuple):
212
+ batch, labels = batch
213
+ else:
214
+ labels = None
215
+ if self.predict_with_generate:
216
+ if isinstance(batch, dict):
217
+ generation_inputs = batch[main_input_name]
218
+ attention_mask = batch.get("attention_mask", None)
219
+ else:
220
+ generation_inputs = batch
221
+ attention_mask = None
222
+ if self.use_xla_generation:
223
+ predictions = self.generation_function(generation_inputs, attention_mask=attention_mask)
224
+ else:
225
+ predictions = self.model.generate(
226
+ generation_inputs, attention_mask=attention_mask, **self.generate_kwargs
227
+ )
228
+ else:
229
+ predictions = self.model.predict_on_batch(batch)
230
+ if isinstance(predictions, dict):
231
+ # This converts any dict-subclass to a regular dict
232
+ # Keras REALLY doesn't like it when we pass around a BatchEncoding or other derived class
233
+ predictions = dict(predictions)
234
+ if self.output_cols is not None:
235
+ predictions = {key: predictions[key] for key in self.output_cols}
236
+ else:
237
+ predictions = {
238
+ key: val for key, val in predictions.items() if key not in ignore_keys + ["loss"]
239
+ }
240
+ prediction_list.append(predictions)
241
+ if not self.use_keras_label:
242
+ labels = {key: batch[key].numpy() for key in self.label_cols}
243
+ elif isinstance(labels, dict):
244
+ labels = {key: array.numpy() for key, array in labels.items()}
245
+ elif isinstance(labels, (list, tuple)):
246
+ labels = [array.numpy() for array in labels]
247
+ elif isinstance(labels, tf.Tensor):
248
+ labels = labels.numpy()
249
+ else:
250
+ raise TypeError(f"Confused by labels of type {type(labels)}")
251
+ label_list.append(labels)
252
+
253
+ all_preds = self._postprocess_predictions_or_labels(prediction_list)
254
+ all_labels = self._postprocess_predictions_or_labels(label_list)
255
+
256
+ metric_output = self.metric_fn((all_preds, all_labels))
257
+ if not isinstance(metric_output, dict):
258
+ raise TypeError(
259
+ f"metric_fn should return a dict mapping metric names to values but instead returned {metric_output}"
260
+ )
261
+ # This is the critical bit - Keras passes a dict containing the loss and standard metric values for this epoch
262
+ # in the logs argument. Ordinarily, this is so the callback can read them, but in this case we write a bunch of
263
+ # new keys in there, which will then get read by the History callback and treated like any other metric value.
264
+ # I promise that I have it in writing from Chollet that this is okay.
265
+ logs.update(metric_output)
266
+
267
+
268
+ class PushToHubCallback(keras.callbacks.Callback):
269
+ """
270
+ Callback that will save and push the model to the Hub regularly. By default, it pushes once per epoch, but this can
271
+ be changed with the `save_strategy` argument. Pushed models can be accessed like any other model on the hub, such
272
+ as with the `from_pretrained` method.
273
+
274
+ ```py
275
+ from transformers.keras_callbacks import PushToHubCallback
276
+
277
+ push_to_hub_callback = PushToHubCallback(
278
+ output_dir="./model_save",
279
+ tokenizer=tokenizer,
280
+ hub_model_id="gpt5-7xlarge",
281
+ )
282
+
283
+ model.fit(train_dataset, callbacks=[push_to_hub_callback])
284
+ ```
285
+
286
+ Args:
287
+ output_dir (`str`):
288
+ The output directory where the model predictions and checkpoints will be written and synced with the
289
+ repository on the Hub.
290
+ save_strategy (`str` or [`~trainer_utils.IntervalStrategy`], *optional*, defaults to `"epoch"`):
291
+ The checkpoint save strategy to adopt during training. Possible values are:
292
+
293
+ - `"no"`: Save is done at the end of training.
294
+ - `"epoch"`: Save is done at the end of each epoch.
295
+ - `"steps"`: Save is done every `save_steps`
296
+ save_steps (`int`, *optional*):
297
+ The number of steps between saves when using the "steps" `save_strategy`.
298
+ tokenizer (`PreTrainedTokenizerBase`, *optional*):
299
+ The tokenizer used by the model. If supplied, will be uploaded to the repo alongside the weights.
300
+ hub_model_id (`str`, *optional*):
301
+ The name of the repository to keep in sync with the local `output_dir`. It can be a simple model ID in
302
+ which case the model will be pushed in your namespace. Otherwise it should be the whole repository name,
303
+ for instance `"user_name/model"`, which allows you to push to an organization you are a member of with
304
+ `"organization_name/model"`.
305
+
306
+ Will default to the name of `output_dir`.
307
+ hub_token (`str`, *optional*):
308
+ The token to use to push the model to the Hub. Will default to the token in the cache folder obtained with
309
+ `hf auth login`.
310
+ checkpoint (`bool`, *optional*, defaults to `False`):
311
+ Whether to save full training checkpoints (including epoch and optimizer state) to allow training to be
312
+ resumed. Only usable when `save_strategy` is `"epoch"`.
313
+ """
314
+
315
+ def __init__(
316
+ self,
317
+ output_dir: Union[str, Path],
318
+ save_strategy: Union[str, IntervalStrategy] = "epoch",
319
+ save_steps: Optional[int] = None,
320
+ tokenizer: Optional[PreTrainedTokenizerBase] = None,
321
+ hub_model_id: Optional[str] = None,
322
+ hub_token: Optional[str] = None,
323
+ checkpoint: bool = False,
324
+ **model_card_args,
325
+ ):
326
+ super().__init__()
327
+ if checkpoint and save_strategy != "epoch":
328
+ raise ValueError("Cannot save checkpoints when save_strategy is not 'epoch'!")
329
+ if isinstance(save_strategy, str):
330
+ save_strategy = IntervalStrategy(save_strategy.lower())
331
+ self.save_strategy = save_strategy
332
+ if self.save_strategy == IntervalStrategy.STEPS and (not isinstance(save_steps, int) or save_steps <= 0):
333
+ raise ValueError("Please supply a positive integer argument for save_steps when save_strategy == 'steps'!")
334
+ self.save_steps = save_steps
335
+ output_dir = Path(output_dir)
336
+
337
+ # Create repo and retrieve repo_id
338
+ if hub_model_id is None:
339
+ hub_model_id = output_dir.absolute().name
340
+ self.hub_model_id = create_repo(repo_id=hub_model_id, exist_ok=True, token=hub_token).repo_id
341
+
342
+ self.output_dir = output_dir
343
+ self.repo = Repository(str(self.output_dir), clone_from=self.hub_model_id, token=hub_token)
344
+
345
+ self.tokenizer = tokenizer
346
+ self.last_job = None
347
+ self.checkpoint = checkpoint
348
+ self.training_history = None
349
+ self.model_card_args = model_card_args
350
+
351
+ def on_train_begin(self, logs=None):
352
+ # Although we can access model.history, we have no guarantees that the History callback will fire before this
353
+ # one, so we keep track of it here too
354
+ self.training_history = []
355
+
356
+ def on_train_batch_end(self, batch, logs=None):
357
+ if self.save_strategy == IntervalStrategy.STEPS and (batch + 1) % self.save_steps == 0:
358
+ if self.last_job is not None and not self.last_job.is_done:
359
+ return # The last upload is still running, don't start another
360
+ self.model.save_pretrained(self.output_dir)
361
+ if self.tokenizer is not None:
362
+ self.tokenizer.save_pretrained(self.output_dir)
363
+ _, self.last_job = self.repo.push_to_hub(
364
+ commit_message=f"Training in progress steps {batch}", blocking=False
365
+ )
366
+
367
+ def on_epoch_end(self, epoch, logs=None):
368
+ logs = logs.copy() # Don't accidentally write things that Keras will read later
369
+ if "epoch" not in logs:
370
+ logs["epoch"] = epoch
371
+ self.training_history.append(logs)
372
+ if self.save_strategy == IntervalStrategy.EPOCH:
373
+ if self.last_job is not None and not self.last_job.is_done:
374
+ return # The last upload is still running, don't start another
375
+ self.model.save_pretrained(self.output_dir)
376
+ if self.tokenizer is not None:
377
+ self.tokenizer.save_pretrained(self.output_dir)
378
+ if self.checkpoint:
379
+ checkpoint_dir = os.path.join(self.output_dir, "checkpoint")
380
+ self.model._save_checkpoint(checkpoint_dir, epoch)
381
+ train_summary = TrainingSummary.from_keras(
382
+ model=self.model,
383
+ model_name=self.hub_model_id,
384
+ keras_history=self.training_history,
385
+ **self.model_card_args,
386
+ )
387
+ model_card = train_summary.to_model_card()
388
+ with (self.output_dir / "README.md").open("w") as f:
389
+ f.write(model_card)
390
+ _, self.last_job = self.repo.push_to_hub(
391
+ commit_message=f"Training in progress epoch {epoch}", blocking=False
392
+ )
393
+
394
+ def on_train_end(self, logs=None):
395
+ # Makes sure the latest version of the model is uploaded
396
+ if self.last_job is not None and not self.last_job.is_done:
397
+ logging.info("Pushing the last epoch to the Hub, this may take a while...")
398
+ while not self.last_job.is_done:
399
+ sleep(1)
400
+ else:
401
+ self.model.save_pretrained(self.output_dir)
402
+ if self.tokenizer is not None:
403
+ self.tokenizer.save_pretrained(self.output_dir)
404
+ train_summary = TrainingSummary.from_keras(
405
+ model=self.model,
406
+ model_name=self.hub_model_id,
407
+ keras_history=self.training_history,
408
+ **self.model_card_args,
409
+ )
410
+ model_card = train_summary.to_model_card()
411
+ with (self.output_dir / "README.md").open("w") as f:
412
+ f.write(model_card)
413
+ self.repo.push_to_hub(commit_message="End of training", blocking=True)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/model_debugging_utils.py ADDED
@@ -0,0 +1,456 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 The HuggingFace Inc. team.
2
+ # All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import functools
17
+ import json
18
+ import os
19
+ import re
20
+ from contextlib import contextmanager, redirect_stdout
21
+ from io import StringIO
22
+ from typing import Optional
23
+
24
+ from .utils import logging
25
+ from .utils.import_utils import is_torch_available, requires
26
+
27
+
28
+ if is_torch_available():
29
+ import torch
30
+ from safetensors.torch import save_file
31
+
32
+ _torch_distributed_available = False
33
+ # Note to code inspectors: this toolbox is intended for people who add models to `transformers`.
34
+ if torch.distributed.is_available():
35
+ import torch.distributed.tensor
36
+
37
+ _torch_distributed_available = True
38
+ else:
39
+ _torch_distributed_available = False
40
+
41
+
42
+ logger = logging.get_logger(__name__)
43
+
44
+
45
+ def _is_rank_zero():
46
+ """Return True if rank=0 or we aren't running distributed."""
47
+ if not (_torch_distributed_available and torch.distributed.is_initialized()):
48
+ return True
49
+ return torch.distributed.get_rank() == 0
50
+
51
+
52
+ MEMORY_ADDRESS_REGEX = re.compile(r"object at 0x[0-9A-Fa-f]+")
53
+
54
+
55
+ def _sanitize_repr_for_diff(x_str: str) -> str:
56
+ """
57
+ Replace memory addresses in an object's repr with a stable placeholder
58
+ so that beautiful JSON diffs won't be ruined by ephemeral addresses.
59
+ """
60
+ return MEMORY_ADDRESS_REGEX.sub("object at 0xXXXXXXXX", x_str)
61
+
62
+
63
+ def _dtensor_repr(x):
64
+ """Return a stable string representation for a DTensor-like object."""
65
+ if _is_rank_zero():
66
+ return f"DTensor (rank0) -> {repr(x._local_tensor)}"
67
+ return "DTensor(non-rank0)"
68
+
69
+
70
+ def _serialize_tensor_like_io(
71
+ value, debug_path: Optional[str] = None, use_repr: bool = True, path_to_value: Optional[str] = None
72
+ ):
73
+ """
74
+ Converts Tensors and DTensors to a JSON-serializable dictionary representation.
75
+
76
+ Args:
77
+ value: Any Python object, often including torch Tensors, lists, dicts, etc.
78
+ debug_path (`str`, *optional*, defaults to `None`): Directory to dump debug JSON and SafeTensors files.
79
+ use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensor as the
80
+ `value` property in the asscoiated FULL_TENSORS.json file, or to store the full tensors in separate
81
+ SafeTensors file and store the relative path to that file in the `value` property in the dictionary.
82
+ path_to_value (`str`, *optional*, defaults to `None`): The file name for the SafeTensors file holding the full
83
+ tensor value if `use_repr=False`.
84
+
85
+ Returns:
86
+ A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
87
+ """
88
+ torch.set_printoptions(sci_mode=True)
89
+
90
+ if use_repr:
91
+ value_out = _repr_to_list(value)
92
+ elif path_to_value:
93
+ if not path_to_value.endswith(".safetensors"):
94
+ path_to_value += ".safetensors"
95
+
96
+ filepath = os.path.join(debug_path, path_to_value) if debug_path else path_to_value
97
+ save_file({"data": value.contiguous().detach().cpu()}, filepath)
98
+ value_out = f"./{path_to_value}"
99
+ else:
100
+ raise ValueError(f"{use_repr=} and {path_to_value=} cannot both be falsy.")
101
+
102
+ out = {
103
+ "shape": repr(value.shape),
104
+ "dtype": repr(value.dtype),
105
+ "value": value_out,
106
+ }
107
+ if value.dtype in {torch.float16, torch.float32, torch.bfloat16}:
108
+ out.update(
109
+ {
110
+ "mean": _sanitize_repr_for_diff(repr(value.mean())),
111
+ "std": _sanitize_repr_for_diff(repr(value.std())),
112
+ "min": _sanitize_repr_for_diff(repr(value.min())),
113
+ "max": _sanitize_repr_for_diff(repr(value.max())),
114
+ }
115
+ )
116
+ return out
117
+
118
+
119
+ def _serialize_io(value, debug_path: Optional[str] = None, use_repr: bool = True, path_to_value: Optional[str] = None):
120
+ """
121
+ Recursively build a JSON-serializable Python structure from `value`.
122
+ Tensors and DTensors become either sanitized repr strings, or are saved to disk as SafeTensors files and their
123
+ relative paths are recorded in the returned Python structure.
124
+ Lists/tuples/dicts are recursed into.
125
+ All memory addresses are replaced with a stable placeholder.
126
+
127
+ Args:
128
+ value: Any Python object, often including torch Tensors, lists, dicts, etc.
129
+ debug_path (`str`, *optional*, defaults to `None`): Directory to dump debug JSON and SafeTensors files.
130
+ use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensors as the
131
+ `value` property in the asscoiated FULL_TENSORS.json file, or to store full tensors in separate SafeTensors
132
+ files and store the relative path to that file in the `value` property.
133
+ path_to_value (`str`, *optional*, defaults to `None`): The file name for the SafeTensors file holding the full
134
+ tensor value if `use_repr=False`.
135
+
136
+ Returns:
137
+ A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
138
+ """
139
+ if isinstance(value, (list, tuple)):
140
+ return [
141
+ _serialize_io(v, debug_path=debug_path, use_repr=use_repr, path_to_value=f"{path_to_value}_{i}")
142
+ for i, v in enumerate(value)
143
+ ]
144
+
145
+ if isinstance(value, dict):
146
+ return {
147
+ k: _serialize_io(v, debug_path=debug_path, use_repr=use_repr, path_to_value=f"{path_to_value}_{k}")
148
+ for k, v in value.items()
149
+ }
150
+
151
+ if hasattr(value, "_local_tensor"):
152
+ return _serialize_tensor_like_io(
153
+ value._local_tensor, debug_path=debug_path, use_repr=use_repr, path_to_value=path_to_value
154
+ )
155
+
156
+ if isinstance(value, torch.Tensor):
157
+ return _serialize_tensor_like_io(value, debug_path=debug_path, use_repr=use_repr, path_to_value=path_to_value)
158
+
159
+ return _sanitize_repr_for_diff(repr(value))
160
+
161
+
162
+ def _repr_to_list(value: torch.Tensor):
163
+ """
164
+ Converts a tensor into a sanitized multi-line string representation.
165
+
166
+ Args:
167
+ value (`torch.Tensor`): The tensor to represent.
168
+
169
+ Returns:
170
+ `list[str]`: List of string lines representing the tensor.
171
+ """
172
+ torch.set_printoptions(sci_mode=True, linewidth=120)
173
+ with StringIO() as buf, redirect_stdout(buf):
174
+ print(value) # to redirected stdout to avoid line splits
175
+ raw = buf.getvalue()
176
+ return _sanitize_repr_for_diff(raw).splitlines()
177
+
178
+
179
+ def prune_outputs_if_children(node):
180
+ # if there are children, remove this node's "outputs"
181
+ # so we only see outputs at the leaf level
182
+ if node.get("children"):
183
+ node.pop("outputs", None)
184
+ for child in node["children"]:
185
+ prune_outputs_if_children(child)
186
+
187
+
188
+ LAYER_SUFFIX_RE = re.compile(r"(.*)\.(\d+)$") # should be generic enough, ends with a number
189
+
190
+
191
+ def is_layer_block(node):
192
+ """
193
+ Checks whether a node represents a layer block with submodules.
194
+
195
+ Args:
196
+ node (`dict`): A node from the call tree.
197
+
198
+ Returns:
199
+ `bool`: Whether the node is a layer block.
200
+ """
201
+ match = LAYER_SUFFIX_RE.match(node.get("module_path", ""))
202
+ if not match or not node.get("children"):
203
+ return False
204
+ number = match.group(2)
205
+ return any(f".{number}." in child.get("module_path", "") for child in node["children"])
206
+
207
+
208
+ def prune_intermediate_layers(node):
209
+ """
210
+ Recursively removes intermediate layers from the tree to improve readability.
211
+ Keeps at least the first and last layers if many consecutive layers are present.
212
+
213
+ Args:
214
+ node (`dict`): The root or subnode to prune recursively.
215
+ """
216
+ if not node.get("children"):
217
+ return
218
+ layer_blocks = [(i, child) for i, child in enumerate(node["children"]) if is_layer_block(child)]
219
+
220
+ if len(layer_blocks) > 2:
221
+ to_remove = [i for i, _ in layer_blocks[1:-1]]
222
+ node["children"] = [child for i, child in enumerate(node["children"]) if i not in to_remove]
223
+
224
+ for child in node["children"]:
225
+ prune_intermediate_layers(child)
226
+
227
+
228
+ def log_model_debug_trace(debug_path: Optional[str], model):
229
+ if debug_path:
230
+ try:
231
+ os.makedirs(debug_path, exist_ok=True)
232
+ base = os.path.join(debug_path, model._debugger_module_dump_name + "_debug_tree")
233
+ except Exception as e:
234
+ raise ValueError(f"Unexpected or existing debug_path={debug_path}.") from e
235
+ else:
236
+ base = model._debugger_module_dump_name + "_debug_tree"
237
+
238
+ logger.info(f"Writing model trace at {base}.json")
239
+ full_path = base + "_FULL_TENSORS.json"
240
+ summary_path = base + "_SUMMARY.json"
241
+
242
+ prune_outputs_if_children(model._call_tree)
243
+
244
+ with open(full_path, "w") as f:
245
+ json.dump(model._call_tree, f, indent=2)
246
+
247
+ # summary-only version for readability - traversing the tree again #TODO optimize?
248
+ def strip_values(node):
249
+ def clean(val):
250
+ if isinstance(val, dict):
251
+ val.pop("value", None)
252
+ for v in val.values():
253
+ clean(v)
254
+ elif isinstance(val, list):
255
+ for item in val:
256
+ clean(item)
257
+
258
+ clean(node.get("inputs", {}))
259
+ clean(node.get("outputs", {}))
260
+
261
+ for child in node.get("children", []):
262
+ strip_values(child)
263
+
264
+ tree_copy = json.loads(json.dumps(model._call_tree)) # deep copy
265
+ strip_values(tree_copy)
266
+
267
+ with open(summary_path, "w") as f:
268
+ json.dump(tree_copy, f, indent=2)
269
+
270
+
271
+ def _attach_debugger_logic(
272
+ model,
273
+ debug_path: str = ".",
274
+ do_prune_layers: bool = True,
275
+ use_repr: bool = True,
276
+ ):
277
+ """
278
+ Attaches a debugging wrapper to every module in the model.
279
+
280
+ This records structured inputs and outputs during the forward pass into a call tree.
281
+
282
+ Args:
283
+ model (`PreTrainedModel`, `nn.Module`): Model to wrap.
284
+ debug_path (`str`): Optional directory to dump debug JSON files.
285
+ do_prune_layers (`bool`, *optional*, defaults to `True`): Whether to prune intermediate layers.
286
+ use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensors as the
287
+ `value` property in the associated FULL_TENSORS.json file, or to store full tensors in separate SafeTensors
288
+ files and store the relative path to that file in the `value` property.
289
+ """
290
+ class_name = model.__class__.__name__
291
+
292
+ # Prepare data structures on the model object
293
+ model._call_tree = {"module_path": class_name, "inputs": None, "outputs": None, "children": []}
294
+ model._debugger_model_call_stack = []
295
+ model._debugger_module_dump_name = class_name # used for final JSON filename
296
+
297
+ if debug_path:
298
+ try:
299
+ os.makedirs(debug_path, exist_ok=True)
300
+ except Exception as e:
301
+ raise ValueError(f"Unexpected or existing debug_path={debug_path}.") from e
302
+
303
+ def wrap_forward(module, full_path):
304
+ orig_forward = module.forward
305
+
306
+ @functools.wraps(orig_forward)
307
+ def wrapped_forward(*inps, **kws):
308
+ if _is_rank_zero():
309
+ dict_inputs = {"args": inps, "kwargs": kws}
310
+ dict_inputs = {k: dict_inputs[k] for k in dict_inputs if len(dict_inputs[k]) > 0}
311
+ node = {
312
+ "module_path": full_path,
313
+ "inputs": _serialize_io(
314
+ dict_inputs,
315
+ debug_path=debug_path,
316
+ use_repr=use_repr,
317
+ path_to_value=f"{full_path}_inputs",
318
+ ),
319
+ "outputs": None,
320
+ "children": [],
321
+ }
322
+ model._debugger_model_call_stack.append(node)
323
+ with torch.no_grad():
324
+ out = orig_forward(*inps, **kws)
325
+
326
+ if _is_rank_zero():
327
+ if sum(1 for _ in module.named_children()) > 0:
328
+ node["outputs"] = None
329
+ else:
330
+ node["outputs"] = _serialize_io(
331
+ out,
332
+ debug_path=debug_path,
333
+ use_repr=use_repr,
334
+ path_to_value=f"{full_path}_outputs",
335
+ )
336
+
337
+ finished = model._debugger_model_call_stack.pop()
338
+ # prune empty vertices here as well (mostly empty children nodes)
339
+ if not finished["children"]:
340
+ finished.pop("children")
341
+
342
+ if model._debugger_model_call_stack:
343
+ model._debugger_model_call_stack[-1]["children"].append(finished)
344
+ return out
345
+
346
+ module.forward = wrapped_forward
347
+
348
+ # wrap all submodules
349
+ for name, submodule in model.named_modules():
350
+ if name == "":
351
+ continue
352
+ wrap_forward(submodule, f"{class_name}.{name}")
353
+
354
+ # wrap top-level forward
355
+ real_top_forward = model.forward
356
+
357
+ @functools.wraps(real_top_forward)
358
+ def top_wrapped_forward(*inps, **kws):
359
+ if _is_rank_zero():
360
+ top_node = {
361
+ "module_path": f"{class_name} (top-level)",
362
+ "inputs": _serialize_io(
363
+ {"args": inps, "kwargs": kws},
364
+ debug_path=debug_path,
365
+ use_repr=use_repr,
366
+ path_to_value=f"{class_name}_inputs",
367
+ ),
368
+ "outputs": None,
369
+ "children": [],
370
+ }
371
+ model._debugger_model_call_stack.append(top_node)
372
+
373
+ out = real_top_forward(*inps, **kws)
374
+ if _is_rank_zero() and model._debugger_model_call_stack:
375
+ top_node["outputs"] = _serialize_io(
376
+ out,
377
+ debug_path=debug_path,
378
+ use_repr=use_repr,
379
+ path_to_value=f"{class_name}_outputs",
380
+ )
381
+ finished = model._debugger_model_call_stack.pop()
382
+ model._call_tree["inputs"] = finished["inputs"]
383
+ model._call_tree["outputs"] = finished["outputs"]
384
+ model._call_tree["children"] = finished["children"]
385
+ # prune empty stuff for visibility
386
+ [model._call_tree.pop(k, None) for k in list(model._call_tree.keys()) if not model._call_tree[k]]
387
+
388
+ # prune layers that are not 0 or last
389
+ if do_prune_layers:
390
+ prune_intermediate_layers(model._call_tree)
391
+ # Write final JSON trace here
392
+ log_model_debug_trace(debug_path=debug_path, model=model)
393
+ return out
394
+
395
+ model.forward = top_wrapped_forward
396
+
397
+
398
+ @requires(backends=("torch",))
399
+ @contextmanager
400
+ def model_addition_debugger_context(
401
+ model,
402
+ debug_path: Optional[str] = None,
403
+ do_prune_layers: bool = True,
404
+ use_repr: bool = True,
405
+ ):
406
+ """
407
+ # Model addition debugger - context manager for model adders
408
+ This context manager is a power user tool intended for model adders.
409
+
410
+ It tracks all forward calls within a model forward and logs a slice of each input and output on a nested JSON file.
411
+ If `use_repr=True` (the default), the JSON file will record a `repr()`-ized version of the tensors as a list of
412
+ strings. If `use_repr=False`, the full tensors will be stored in separate SafeTensors files and the JSON file will
413
+ provide a relative path to that file.
414
+
415
+ To note, this context manager enforces `torch.no_grad()`.
416
+
417
+ ## Usage
418
+
419
+ add the context manager to a model to debug
420
+
421
+ ```python
422
+ import torch
423
+
424
+ from PIL import Image
425
+ from transformers import LlavaProcessor, LlavaForConditionalGeneration, model_addition_debugger_context
426
+
427
+ torch.random.manual_seed(673)
428
+
429
+ # load pretrained model and processor
430
+ model_id = "llava-hf/llava-1.5-7b-hf"
431
+ processor = LlavaProcessor.from_pretrained(model_id)
432
+ model = LlavaForConditionalGeneration.from_pretrained(model_id)
433
+
434
+ # create random image input
435
+ random_image = Image.fromarray(torch.randint(0, 256, (224, 224, 3), dtype=torch.uint8).numpy())
436
+
437
+ # prompt
438
+ prompt = "<image>Describe this image."
439
+
440
+ # process inputs
441
+ inputs = processor(text=prompt, images=random_image, return_tensors="pt")
442
+
443
+ # call forward method (not .generate!)
444
+ with model_addition_debugger_context(model, debug_path="Your_debug_path", do_prune_layers=False):
445
+ output = model.forward(**inputs)
446
+ ```
447
+
448
+ """
449
+ orig_forwards = {m: m.forward for _, m in model.named_modules()}
450
+ orig_forwards[model] = model.forward
451
+ _attach_debugger_logic(model, debug_path, do_prune_layers, use_repr)
452
+ try:
453
+ yield model
454
+ finally:
455
+ for module_instance, forward_method in orig_forwards.items():
456
+ module_instance.forward = forward_method
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modelcard.py ADDED
@@ -0,0 +1,914 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2018 The HuggingFace Inc. team.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Configuration base class and utilities."""
15
+
16
+ import copy
17
+ import json
18
+ import os
19
+ import warnings
20
+ from dataclasses import dataclass
21
+ from pathlib import Path
22
+ from typing import Any, Optional, Union
23
+
24
+ import requests
25
+ import yaml
26
+ from huggingface_hub import model_info
27
+ from huggingface_hub.errors import OfflineModeIsEnabled
28
+ from huggingface_hub.utils import HFValidationError
29
+
30
+ from . import __version__
31
+ from .models.auto.modeling_auto import (
32
+ MODEL_FOR_AUDIO_CLASSIFICATION_MAPPING_NAMES,
33
+ MODEL_FOR_CAUSAL_LM_MAPPING_NAMES,
34
+ MODEL_FOR_CTC_MAPPING_NAMES,
35
+ MODEL_FOR_IMAGE_CLASSIFICATION_MAPPING_NAMES,
36
+ MODEL_FOR_IMAGE_SEGMENTATION_MAPPING_NAMES,
37
+ MODEL_FOR_IMAGE_TEXT_TO_TEXT_MAPPING_NAMES,
38
+ MODEL_FOR_MASKED_LM_MAPPING_NAMES,
39
+ MODEL_FOR_OBJECT_DETECTION_MAPPING_NAMES,
40
+ MODEL_FOR_QUESTION_ANSWERING_MAPPING_NAMES,
41
+ MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING_NAMES,
42
+ MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING_NAMES,
43
+ MODEL_FOR_SPEECH_SEQ_2_SEQ_MAPPING_NAMES,
44
+ MODEL_FOR_TABLE_QUESTION_ANSWERING_MAPPING_NAMES,
45
+ MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING_NAMES,
46
+ MODEL_FOR_ZERO_SHOT_IMAGE_CLASSIFICATION_MAPPING_NAMES,
47
+ )
48
+ from .training_args import ParallelMode
49
+ from .utils import (
50
+ MODEL_CARD_NAME,
51
+ cached_file,
52
+ is_datasets_available,
53
+ is_offline_mode,
54
+ is_tf_available,
55
+ is_tokenizers_available,
56
+ is_torch_available,
57
+ logging,
58
+ )
59
+
60
+
61
+ TASK_MAPPING = {
62
+ "text-generation": MODEL_FOR_CAUSAL_LM_MAPPING_NAMES,
63
+ "image-classification": MODEL_FOR_IMAGE_CLASSIFICATION_MAPPING_NAMES,
64
+ "image-segmentation": MODEL_FOR_IMAGE_SEGMENTATION_MAPPING_NAMES,
65
+ "fill-mask": MODEL_FOR_MASKED_LM_MAPPING_NAMES,
66
+ "object-detection": MODEL_FOR_OBJECT_DETECTION_MAPPING_NAMES,
67
+ "question-answering": MODEL_FOR_QUESTION_ANSWERING_MAPPING_NAMES,
68
+ "text2text-generation": MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING_NAMES,
69
+ "text-classification": MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING_NAMES,
70
+ "table-question-answering": MODEL_FOR_TABLE_QUESTION_ANSWERING_MAPPING_NAMES,
71
+ "token-classification": MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING_NAMES,
72
+ "audio-classification": MODEL_FOR_AUDIO_CLASSIFICATION_MAPPING_NAMES,
73
+ "automatic-speech-recognition": {**MODEL_FOR_CTC_MAPPING_NAMES, **MODEL_FOR_SPEECH_SEQ_2_SEQ_MAPPING_NAMES},
74
+ "zero-shot-image-classification": MODEL_FOR_ZERO_SHOT_IMAGE_CLASSIFICATION_MAPPING_NAMES,
75
+ "image-text-to-text": MODEL_FOR_IMAGE_TEXT_TO_TEXT_MAPPING_NAMES,
76
+ }
77
+
78
+ logger = logging.get_logger(__name__)
79
+
80
+
81
+ class ModelCard:
82
+ r"""
83
+ Structured Model Card class. Store model card as well as methods for loading/downloading/saving model cards.
84
+
85
+ Please read the following paper for details and explanation on the sections: "Model Cards for Model Reporting" by
86
+ Margaret Mitchell, Simone Wu, Andrew Zaldivar, Parker Barnes, Lucy Vasserman, Ben Hutchinson, Elena Spitzer,
87
+ Inioluwa Deborah Raji and Timnit Gebru for the proposal behind model cards. Link: https://huggingface.co/papers/1810.03993
88
+
89
+ Note: A model card can be loaded and saved to disk.
90
+ """
91
+
92
+ def __init__(self, **kwargs):
93
+ warnings.warn(
94
+ "The class `ModelCard` is deprecated and will be removed in version 5 of Transformers", FutureWarning
95
+ )
96
+ # Recommended attributes from https://huggingface.co/papers/1810.03993 (see papers)
97
+ self.model_details = kwargs.pop("model_details", {})
98
+ self.intended_use = kwargs.pop("intended_use", {})
99
+ self.factors = kwargs.pop("factors", {})
100
+ self.metrics = kwargs.pop("metrics", {})
101
+ self.evaluation_data = kwargs.pop("evaluation_data", {})
102
+ self.training_data = kwargs.pop("training_data", {})
103
+ self.quantitative_analyses = kwargs.pop("quantitative_analyses", {})
104
+ self.ethical_considerations = kwargs.pop("ethical_considerations", {})
105
+ self.caveats_and_recommendations = kwargs.pop("caveats_and_recommendations", {})
106
+
107
+ # Open additional attributes
108
+ for key, value in kwargs.items():
109
+ try:
110
+ setattr(self, key, value)
111
+ except AttributeError as err:
112
+ logger.error(f"Can't set {key} with value {value} for {self}")
113
+ raise err
114
+
115
+ def save_pretrained(self, save_directory_or_file):
116
+ """Save a model card object to the directory or file `save_directory_or_file`."""
117
+ if os.path.isdir(save_directory_or_file):
118
+ # If we save using the predefined names, we can load using `from_pretrained`
119
+ output_model_card_file = os.path.join(save_directory_or_file, MODEL_CARD_NAME)
120
+ else:
121
+ output_model_card_file = save_directory_or_file
122
+
123
+ self.to_json_file(output_model_card_file)
124
+ logger.info(f"Model card saved in {output_model_card_file}")
125
+
126
+ @classmethod
127
+ def from_pretrained(cls, pretrained_model_name_or_path, **kwargs):
128
+ r"""
129
+ Instantiate a [`ModelCard`] from a pre-trained model model card.
130
+
131
+ Parameters:
132
+ pretrained_model_name_or_path: either:
133
+
134
+ - a string, the *model id* of a pretrained model card hosted inside a model repo on huggingface.co.
135
+ - a path to a *directory* containing a model card file saved using the [`~ModelCard.save_pretrained`]
136
+ method, e.g.: `./my_model_directory/`.
137
+ - a path or url to a saved model card JSON *file*, e.g.: `./my_model_directory/modelcard.json`.
138
+
139
+ cache_dir: (*optional*) string:
140
+ Path to a directory in which a downloaded pre-trained model card should be cached if the standard cache
141
+ should not be used.
142
+
143
+ kwargs: (*optional*) dict: key/value pairs with which to update the ModelCard object after loading.
144
+
145
+ - The values in kwargs of any keys which are model card attributes will be used to override the loaded
146
+ values.
147
+ - Behavior concerning key/value pairs whose keys are *not* model card attributes is controlled by the
148
+ *return_unused_kwargs* keyword parameter.
149
+
150
+ proxies: (*optional*) dict, default None:
151
+ A dictionary of proxy servers to use by protocol or endpoint, e.g.: {'http': 'foo.bar:3128',
152
+ 'http://hostname': 'foo.bar:4012'}. The proxies are used on each request.
153
+
154
+ return_unused_kwargs: (*optional*) bool:
155
+
156
+ - If False, then this function returns just the final model card object.
157
+ - If True, then this functions returns a tuple *(model card, unused_kwargs)* where *unused_kwargs* is a
158
+ dictionary consisting of the key/value pairs whose keys are not model card attributes: ie the part of
159
+ kwargs which has not been used to update *ModelCard* and is otherwise ignored.
160
+
161
+ Examples:
162
+
163
+ ```python
164
+ # Download model card from huggingface.co and cache.
165
+ modelcard = ModelCard.from_pretrained("google-bert/bert-base-uncased")
166
+ # Model card was saved using *save_pretrained('./test/saved_model/')*
167
+ modelcard = ModelCard.from_pretrained("./test/saved_model/")
168
+ modelcard = ModelCard.from_pretrained("./test/saved_model/modelcard.json")
169
+ modelcard = ModelCard.from_pretrained("google-bert/bert-base-uncased", output_attentions=True, foo=False)
170
+ ```"""
171
+ cache_dir = kwargs.pop("cache_dir", None)
172
+ proxies = kwargs.pop("proxies", None)
173
+ return_unused_kwargs = kwargs.pop("return_unused_kwargs", False)
174
+ from_pipeline = kwargs.pop("_from_pipeline", None)
175
+
176
+ user_agent = {"file_type": "model_card"}
177
+ if from_pipeline is not None:
178
+ user_agent["using_pipeline"] = from_pipeline
179
+
180
+ is_local = os.path.isdir(pretrained_model_name_or_path)
181
+ if os.path.isfile(pretrained_model_name_or_path):
182
+ resolved_model_card_file = pretrained_model_name_or_path
183
+ is_local = True
184
+ else:
185
+ try:
186
+ # Load from URL or cache if already cached
187
+ resolved_model_card_file = cached_file(
188
+ pretrained_model_name_or_path,
189
+ filename=MODEL_CARD_NAME,
190
+ cache_dir=cache_dir,
191
+ proxies=proxies,
192
+ user_agent=user_agent,
193
+ )
194
+ if is_local:
195
+ logger.info(f"loading model card file {resolved_model_card_file}")
196
+ else:
197
+ logger.info(f"loading model card file {MODEL_CARD_NAME} from cache at {resolved_model_card_file}")
198
+ # Load model card
199
+ modelcard = cls.from_json_file(resolved_model_card_file)
200
+
201
+ except (OSError, json.JSONDecodeError):
202
+ # We fall back on creating an empty model card
203
+ modelcard = cls()
204
+
205
+ # Update model card with kwargs if needed
206
+ to_remove = []
207
+ for key, value in kwargs.items():
208
+ if hasattr(modelcard, key):
209
+ setattr(modelcard, key, value)
210
+ to_remove.append(key)
211
+ for key in to_remove:
212
+ kwargs.pop(key, None)
213
+
214
+ logger.info(f"Model card: {modelcard}")
215
+ if return_unused_kwargs:
216
+ return modelcard, kwargs
217
+ else:
218
+ return modelcard
219
+
220
+ @classmethod
221
+ def from_dict(cls, json_object):
222
+ """Constructs a `ModelCard` from a Python dictionary of parameters."""
223
+ return cls(**json_object)
224
+
225
+ @classmethod
226
+ def from_json_file(cls, json_file):
227
+ """Constructs a `ModelCard` from a json file of parameters."""
228
+ with open(json_file, encoding="utf-8") as reader:
229
+ text = reader.read()
230
+ dict_obj = json.loads(text)
231
+ return cls(**dict_obj)
232
+
233
+ def __eq__(self, other):
234
+ return self.__dict__ == other.__dict__
235
+
236
+ def __repr__(self):
237
+ return str(self.to_json_string())
238
+
239
+ def to_dict(self):
240
+ """Serializes this instance to a Python dictionary."""
241
+ output = copy.deepcopy(self.__dict__)
242
+ return output
243
+
244
+ def to_json_string(self):
245
+ """Serializes this instance to a JSON string."""
246
+ return json.dumps(self.to_dict(), indent=2, sort_keys=True) + "\n"
247
+
248
+ def to_json_file(self, json_file_path):
249
+ """Save this instance to a json file."""
250
+ with open(json_file_path, "w", encoding="utf-8") as writer:
251
+ writer.write(self.to_json_string())
252
+
253
+
254
+ AUTOGENERATED_TRAINER_COMMENT = """
255
+ <!-- This model card has been generated automatically according to the information the Trainer had access to. You
256
+ should probably proofread and complete it, then remove this comment. -->
257
+ """
258
+
259
+ AUTOGENERATED_KERAS_COMMENT = """
260
+ <!-- This model card has been generated automatically according to the information Keras had access to. You should
261
+ probably proofread and complete it, then remove this comment. -->
262
+ """
263
+
264
+
265
+ TASK_TAG_TO_NAME_MAPPING = {
266
+ "fill-mask": "Masked Language Modeling",
267
+ "image-classification": "Image Classification",
268
+ "image-segmentation": "Image Segmentation",
269
+ "multiple-choice": "Multiple Choice",
270
+ "object-detection": "Object Detection",
271
+ "question-answering": "Question Answering",
272
+ "summarization": "Summarization",
273
+ "table-question-answering": "Table Question Answering",
274
+ "text-classification": "Text Classification",
275
+ "text-generation": "Causal Language Modeling",
276
+ "text2text-generation": "Sequence-to-sequence Language Modeling",
277
+ "token-classification": "Token Classification",
278
+ "translation": "Translation",
279
+ "zero-shot-classification": "Zero Shot Classification",
280
+ "automatic-speech-recognition": "Automatic Speech Recognition",
281
+ "audio-classification": "Audio Classification",
282
+ }
283
+
284
+
285
+ METRIC_TAGS = [
286
+ "accuracy",
287
+ "bleu",
288
+ "f1",
289
+ "matthews_correlation",
290
+ "pearsonr",
291
+ "precision",
292
+ "recall",
293
+ "rouge",
294
+ "sacrebleu",
295
+ "spearmanr",
296
+ "wer",
297
+ ]
298
+
299
+
300
+ def _listify(obj):
301
+ if obj is None:
302
+ return []
303
+ elif isinstance(obj, str):
304
+ return [obj]
305
+ else:
306
+ return obj
307
+
308
+
309
+ def _insert_values_as_list(metadata, name, values):
310
+ if values is None:
311
+ return metadata
312
+ if isinstance(values, str):
313
+ values = [values]
314
+ values = [v for v in values if v is not None]
315
+ if len(values) == 0:
316
+ return metadata
317
+ metadata[name] = values
318
+ return metadata
319
+
320
+
321
+ def infer_metric_tags_from_eval_results(eval_results):
322
+ if eval_results is None:
323
+ return {}
324
+ result = {}
325
+ for key in eval_results:
326
+ if key.lower().replace(" ", "_") in METRIC_TAGS:
327
+ result[key.lower().replace(" ", "_")] = key
328
+ elif key.lower() == "rouge1":
329
+ result["rouge"] = key
330
+ return result
331
+
332
+
333
+ def _insert_value(metadata, name, value):
334
+ if value is None:
335
+ return metadata
336
+ metadata[name] = value
337
+ return metadata
338
+
339
+
340
+ def is_hf_dataset(dataset):
341
+ if not is_datasets_available():
342
+ return False
343
+
344
+ from datasets import Dataset, IterableDataset
345
+
346
+ return isinstance(dataset, (Dataset, IterableDataset))
347
+
348
+
349
+ def _get_mapping_values(mapping):
350
+ result = []
351
+ for v in mapping.values():
352
+ if isinstance(v, (tuple, list)):
353
+ result += list(v)
354
+ else:
355
+ result.append(v)
356
+ return result
357
+
358
+
359
+ @dataclass
360
+ class TrainingSummary:
361
+ model_name: str
362
+ language: Optional[Union[str, list[str]]] = None
363
+ license: Optional[str] = None
364
+ tags: Optional[Union[str, list[str]]] = None
365
+ finetuned_from: Optional[str] = None
366
+ tasks: Optional[Union[str, list[str]]] = None
367
+ dataset: Optional[Union[str, list[str]]] = None
368
+ dataset_tags: Optional[Union[str, list[str]]] = None
369
+ dataset_args: Optional[Union[str, list[str]]] = None
370
+ dataset_metadata: Optional[dict[str, Any]] = None
371
+ eval_results: Optional[dict[str, float]] = None
372
+ eval_lines: Optional[list[str]] = None
373
+ hyperparameters: Optional[dict[str, Any]] = None
374
+ source: Optional[str] = "trainer"
375
+
376
+ def __post_init__(self):
377
+ # Infer default license from the checkpoint used, if possible.
378
+ if (
379
+ self.license is None
380
+ and not is_offline_mode()
381
+ and self.finetuned_from is not None
382
+ and len(self.finetuned_from) > 0
383
+ ):
384
+ try:
385
+ info = model_info(self.finetuned_from)
386
+ for tag in info.tags:
387
+ if tag.startswith("license:"):
388
+ self.license = tag[8:]
389
+ except (
390
+ requests.exceptions.HTTPError,
391
+ requests.exceptions.ConnectionError,
392
+ HFValidationError,
393
+ OfflineModeIsEnabled,
394
+ ):
395
+ pass
396
+
397
+ def create_model_index(self, metric_mapping):
398
+ model_index = {"name": self.model_name}
399
+
400
+ # Dataset mapping tag -> name
401
+ dataset_names = _listify(self.dataset)
402
+ dataset_tags = _listify(self.dataset_tags)
403
+ dataset_args = _listify(self.dataset_args)
404
+ dataset_metadata = _listify(self.dataset_metadata)
405
+ if len(dataset_args) < len(dataset_tags):
406
+ dataset_args = dataset_args + [None] * (len(dataset_tags) - len(dataset_args))
407
+ dataset_mapping = dict(zip(dataset_tags, dataset_names))
408
+ dataset_arg_mapping = dict(zip(dataset_tags, dataset_args))
409
+ dataset_metadata_mapping = dict(zip(dataset_tags, dataset_metadata))
410
+
411
+ task_mapping = {
412
+ task: TASK_TAG_TO_NAME_MAPPING[task] for task in _listify(self.tasks) if task in TASK_TAG_TO_NAME_MAPPING
413
+ }
414
+
415
+ model_index["results"] = []
416
+
417
+ if len(task_mapping) == 0 and len(dataset_mapping) == 0:
418
+ return [model_index]
419
+ if len(task_mapping) == 0:
420
+ task_mapping = {None: None}
421
+ if len(dataset_mapping) == 0:
422
+ dataset_mapping = {None: None}
423
+
424
+ # One entry per dataset and per task
425
+ all_possibilities = [(task_tag, ds_tag) for task_tag in task_mapping for ds_tag in dataset_mapping]
426
+ for task_tag, ds_tag in all_possibilities:
427
+ result = {}
428
+ if task_tag is not None:
429
+ result["task"] = {"name": task_mapping[task_tag], "type": task_tag}
430
+
431
+ if ds_tag is not None:
432
+ metadata = dataset_metadata_mapping.get(ds_tag, {})
433
+ result["dataset"] = {
434
+ "name": dataset_mapping[ds_tag],
435
+ "type": ds_tag,
436
+ **metadata,
437
+ }
438
+ if dataset_arg_mapping[ds_tag] is not None:
439
+ result["dataset"]["args"] = dataset_arg_mapping[ds_tag]
440
+
441
+ if len(metric_mapping) > 0:
442
+ result["metrics"] = []
443
+ for metric_tag, metric_name in metric_mapping.items():
444
+ result["metrics"].append(
445
+ {
446
+ "name": metric_name,
447
+ "type": metric_tag,
448
+ "value": self.eval_results[metric_name],
449
+ }
450
+ )
451
+
452
+ # Remove partial results to avoid the model card being rejected.
453
+ if "task" in result and "dataset" in result and "metrics" in result:
454
+ model_index["results"].append(result)
455
+ else:
456
+ logger.info(f"Dropping the following result as it does not have all the necessary fields:\n{result}")
457
+
458
+ return [model_index]
459
+
460
+ def create_metadata(self):
461
+ metric_mapping = infer_metric_tags_from_eval_results(self.eval_results)
462
+
463
+ metadata = {}
464
+ metadata = _insert_value(metadata, "library_name", "transformers")
465
+ metadata = _insert_values_as_list(metadata, "language", self.language)
466
+ metadata = _insert_value(metadata, "license", self.license)
467
+ if self.finetuned_from is not None and isinstance(self.finetuned_from, str) and len(self.finetuned_from) > 0:
468
+ metadata = _insert_value(metadata, "base_model", self.finetuned_from)
469
+ metadata = _insert_values_as_list(metadata, "tags", self.tags)
470
+ metadata = _insert_values_as_list(metadata, "datasets", self.dataset_tags)
471
+ metadata = _insert_values_as_list(metadata, "metrics", list(metric_mapping.keys()))
472
+ metadata["model-index"] = self.create_model_index(metric_mapping)
473
+
474
+ return metadata
475
+
476
+ def to_model_card(self):
477
+ model_card = ""
478
+
479
+ metadata = yaml.dump(self.create_metadata(), sort_keys=False)
480
+ if len(metadata) > 0:
481
+ model_card = f"---\n{metadata}---\n"
482
+
483
+ # Now the model card for realsies.
484
+ if self.source == "trainer":
485
+ model_card += AUTOGENERATED_TRAINER_COMMENT
486
+ else:
487
+ model_card += AUTOGENERATED_KERAS_COMMENT
488
+
489
+ model_card += f"\n# {self.model_name}\n\n"
490
+
491
+ if self.finetuned_from is None:
492
+ model_card += "This model was trained from scratch on "
493
+ else:
494
+ model_card += (
495
+ "This model is a fine-tuned version of"
496
+ f" [{self.finetuned_from}](https://huggingface.co/{self.finetuned_from}) on "
497
+ )
498
+
499
+ if self.dataset is None or (isinstance(self.dataset, list) and len(self.dataset) == 0):
500
+ model_card += "an unknown dataset."
501
+ else:
502
+ if isinstance(self.dataset, str):
503
+ model_card += f"the {self.dataset} dataset."
504
+ elif isinstance(self.dataset, (tuple, list)) and len(self.dataset) == 1:
505
+ model_card += f"the {self.dataset[0]} dataset."
506
+ else:
507
+ model_card += (
508
+ ", ".join([f"the {ds}" for ds in self.dataset[:-1]]) + f" and the {self.dataset[-1]} datasets."
509
+ )
510
+
511
+ if self.eval_results is not None:
512
+ model_card += "\nIt achieves the following results on the evaluation set:\n"
513
+ model_card += "\n".join([f"- {name}: {_maybe_round(value)}" for name, value in self.eval_results.items()])
514
+ model_card += "\n"
515
+
516
+ model_card += "\n## Model description\n\nMore information needed\n"
517
+ model_card += "\n## Intended uses & limitations\n\nMore information needed\n"
518
+ model_card += "\n## Training and evaluation data\n\nMore information needed\n"
519
+
520
+ model_card += "\n## Training procedure\n"
521
+ model_card += "\n### Training hyperparameters\n"
522
+ if self.hyperparameters is not None:
523
+ model_card += "\nThe following hyperparameters were used during training:\n"
524
+ model_card += "\n".join([f"- {name}: {value}" for name, value in self.hyperparameters.items()])
525
+ model_card += "\n"
526
+ else:
527
+ model_card += "\nMore information needed\n"
528
+
529
+ if self.eval_lines is not None:
530
+ model_card += "\n### Training results\n\n"
531
+ model_card += make_markdown_table(self.eval_lines)
532
+ model_card += "\n"
533
+
534
+ model_card += "\n### Framework versions\n\n"
535
+ model_card += f"- Transformers {__version__}\n"
536
+
537
+ if self.source == "trainer" and is_torch_available():
538
+ import torch
539
+
540
+ model_card += f"- Pytorch {torch.__version__}\n"
541
+ elif self.source == "keras" and is_tf_available():
542
+ import tensorflow as tf
543
+
544
+ model_card += f"- TensorFlow {tf.__version__}\n"
545
+ if is_datasets_available():
546
+ import datasets
547
+
548
+ model_card += f"- Datasets {datasets.__version__}\n"
549
+ if is_tokenizers_available():
550
+ import tokenizers
551
+
552
+ model_card += f"- Tokenizers {tokenizers.__version__}\n"
553
+
554
+ return model_card
555
+
556
+ @classmethod
557
+ def from_trainer(
558
+ cls,
559
+ trainer,
560
+ language=None,
561
+ license=None,
562
+ tags=None,
563
+ model_name=None,
564
+ finetuned_from=None,
565
+ tasks=None,
566
+ dataset_tags=None,
567
+ dataset_metadata=None,
568
+ dataset=None,
569
+ dataset_args=None,
570
+ ):
571
+ # Infer default from dataset
572
+ one_dataset = trainer.eval_dataset if trainer.eval_dataset is not None else trainer.train_dataset
573
+ if is_hf_dataset(one_dataset) and (dataset_tags is None or dataset_args is None or dataset_metadata is None):
574
+ default_tag = one_dataset.builder_name
575
+ # Those are not real datasets from the Hub so we exclude them.
576
+ if default_tag not in ["csv", "json", "pandas", "parquet", "text"]:
577
+ if dataset_metadata is None:
578
+ dataset_metadata = [{"config": one_dataset.config_name, "split": str(one_dataset.split)}]
579
+ if dataset_tags is None:
580
+ dataset_tags = [default_tag]
581
+ if dataset_args is None:
582
+ dataset_args = [one_dataset.config_name]
583
+
584
+ if dataset is None and dataset_tags is not None:
585
+ dataset = dataset_tags
586
+
587
+ # Infer default finetuned_from
588
+ if (
589
+ finetuned_from is None
590
+ and hasattr(trainer.model.config, "_name_or_path")
591
+ and not os.path.isdir(trainer.model.config._name_or_path)
592
+ ):
593
+ finetuned_from = trainer.model.config._name_or_path
594
+
595
+ # Infer default task tag:
596
+ if tasks is None:
597
+ model_class_name = trainer.model.__class__.__name__
598
+ for task, mapping in TASK_MAPPING.items():
599
+ if model_class_name in _get_mapping_values(mapping):
600
+ tasks = task
601
+
602
+ if model_name is None:
603
+ model_name = Path(trainer.args.output_dir).name
604
+ if len(model_name) == 0:
605
+ model_name = finetuned_from
606
+
607
+ # Add `generated_from_trainer` to the tags
608
+ if tags is None:
609
+ tags = ["generated_from_trainer"]
610
+ elif isinstance(tags, str) and tags != "generated_from_trainer":
611
+ tags = [tags, "generated_from_trainer"]
612
+ elif "generated_from_trainer" not in tags:
613
+ tags.append("generated_from_trainer")
614
+
615
+ _, eval_lines, eval_results = parse_log_history(trainer.state.log_history)
616
+ hyperparameters = extract_hyperparameters_from_trainer(trainer)
617
+
618
+ return cls(
619
+ language=language,
620
+ license=license,
621
+ tags=tags,
622
+ model_name=model_name,
623
+ finetuned_from=finetuned_from,
624
+ tasks=tasks,
625
+ dataset=dataset,
626
+ dataset_tags=dataset_tags,
627
+ dataset_args=dataset_args,
628
+ dataset_metadata=dataset_metadata,
629
+ eval_results=eval_results,
630
+ eval_lines=eval_lines,
631
+ hyperparameters=hyperparameters,
632
+ )
633
+
634
+ @classmethod
635
+ def from_keras(
636
+ cls,
637
+ model,
638
+ model_name,
639
+ keras_history=None,
640
+ language=None,
641
+ license=None,
642
+ tags=None,
643
+ finetuned_from=None,
644
+ tasks=None,
645
+ dataset_tags=None,
646
+ dataset=None,
647
+ dataset_args=None,
648
+ ):
649
+ # Infer default from dataset
650
+ if dataset is not None:
651
+ if is_hf_dataset(dataset) and (dataset_tags is None or dataset_args is None):
652
+ default_tag = dataset.builder_name
653
+ # Those are not real datasets from the Hub so we exclude them.
654
+ if default_tag not in ["csv", "json", "pandas", "parquet", "text"]:
655
+ if dataset_tags is None:
656
+ dataset_tags = [default_tag]
657
+ if dataset_args is None:
658
+ dataset_args = [dataset.config_name]
659
+
660
+ if dataset is None and dataset_tags is not None:
661
+ dataset = dataset_tags
662
+
663
+ # Infer default finetuned_from
664
+ if (
665
+ finetuned_from is None
666
+ and hasattr(model.config, "_name_or_path")
667
+ and not os.path.isdir(model.config._name_or_path)
668
+ ):
669
+ finetuned_from = model.config._name_or_path
670
+
671
+ # Infer default task tag:
672
+ if tasks is None:
673
+ model_class_name = model.__class__.__name__
674
+ for task, mapping in TASK_MAPPING.items():
675
+ if model_class_name in _get_mapping_values(mapping):
676
+ tasks = task
677
+
678
+ # Add `generated_from_keras_callback` to the tags
679
+ if tags is None:
680
+ tags = ["generated_from_keras_callback"]
681
+ elif isinstance(tags, str) and tags != "generated_from_keras_callback":
682
+ tags = [tags, "generated_from_keras_callback"]
683
+ elif "generated_from_keras_callback" not in tags:
684
+ tags.append("generated_from_keras_callback")
685
+
686
+ if keras_history is not None:
687
+ _, eval_lines, eval_results = parse_keras_history(keras_history)
688
+ else:
689
+ eval_lines = []
690
+ eval_results = {}
691
+ hyperparameters = extract_hyperparameters_from_keras(model)
692
+
693
+ return cls(
694
+ language=language,
695
+ license=license,
696
+ tags=tags,
697
+ model_name=model_name,
698
+ finetuned_from=finetuned_from,
699
+ tasks=tasks,
700
+ dataset_tags=dataset_tags,
701
+ dataset=dataset,
702
+ dataset_args=dataset_args,
703
+ eval_results=eval_results,
704
+ eval_lines=eval_lines,
705
+ hyperparameters=hyperparameters,
706
+ source="keras",
707
+ )
708
+
709
+
710
+ def parse_keras_history(logs):
711
+ """
712
+ Parse the `logs` of either a `keras.History` object returned by `model.fit()` or an accumulated logs `dict`
713
+ passed to the `PushToHubCallback`. Returns lines and logs compatible with those returned by `parse_log_history`.
714
+ """
715
+ if hasattr(logs, "history"):
716
+ # This looks like a `History` object
717
+ if not hasattr(logs, "epoch"):
718
+ # This history looks empty, return empty results
719
+ return None, [], {}
720
+ logs.history["epoch"] = logs.epoch
721
+ logs = logs.history
722
+ else:
723
+ # Training logs is a list of dicts, let's invert it to a dict of lists to match a History object
724
+ logs = {log_key: [single_dict[log_key] for single_dict in logs] for log_key in logs[0]}
725
+
726
+ lines = []
727
+ for i in range(len(logs["epoch"])):
728
+ epoch_dict = {log_key: log_value_list[i] for log_key, log_value_list in logs.items()}
729
+ values = {}
730
+ for k, v in epoch_dict.items():
731
+ if k.startswith("val_"):
732
+ k = "validation_" + k[4:]
733
+ elif k != "epoch":
734
+ k = "train_" + k
735
+ splits = k.split("_")
736
+ name = " ".join([part.capitalize() for part in splits])
737
+ values[name] = v
738
+ lines.append(values)
739
+
740
+ eval_results = lines[-1]
741
+
742
+ return logs, lines, eval_results
743
+
744
+
745
+ def parse_log_history(log_history):
746
+ """
747
+ Parse the `log_history` of a Trainer to get the intermediate and final evaluation results.
748
+ """
749
+ idx = 0
750
+ while idx < len(log_history) and "train_runtime" not in log_history[idx]:
751
+ idx += 1
752
+
753
+ # If there are no training logs
754
+ if idx == len(log_history):
755
+ idx -= 1
756
+ while idx >= 0 and "eval_loss" not in log_history[idx]:
757
+ idx -= 1
758
+
759
+ if idx >= 0:
760
+ return None, None, log_history[idx]
761
+ else:
762
+ return None, None, None
763
+
764
+ # From now one we can assume we have training logs:
765
+ train_log = log_history[idx]
766
+ lines = []
767
+ training_loss = "No log"
768
+ for i in range(idx):
769
+ if "loss" in log_history[i]:
770
+ training_loss = log_history[i]["loss"]
771
+ if "eval_loss" in log_history[i]:
772
+ metrics = log_history[i].copy()
773
+ _ = metrics.pop("total_flos", None)
774
+ epoch = metrics.pop("epoch", None)
775
+ step = metrics.pop("step", None)
776
+ _ = metrics.pop("eval_runtime", None)
777
+ _ = metrics.pop("eval_samples_per_second", None)
778
+ _ = metrics.pop("eval_steps_per_second", None)
779
+ _ = metrics.pop("eval_jit_compilation_time", None)
780
+ values = {"Training Loss": training_loss, "Epoch": epoch, "Step": step}
781
+ for k, v in metrics.items():
782
+ if k == "eval_loss":
783
+ values["Validation Loss"] = v
784
+ else:
785
+ splits = k.split("_")
786
+ name = " ".join([part.capitalize() for part in splits[1:]])
787
+ values[name] = v
788
+ lines.append(values)
789
+
790
+ idx = len(log_history) - 1
791
+ while idx >= 0 and "eval_loss" not in log_history[idx]:
792
+ idx -= 1
793
+
794
+ if idx > 0:
795
+ eval_results = {}
796
+ for key, value in log_history[idx].items():
797
+ key = key.removeprefix("eval_")
798
+ if key not in ["runtime", "samples_per_second", "steps_per_second", "epoch", "step"]:
799
+ camel_cased_key = " ".join([part.capitalize() for part in key.split("_")])
800
+ eval_results[camel_cased_key] = value
801
+ return train_log, lines, eval_results
802
+ else:
803
+ return train_log, lines, None
804
+
805
+
806
+ def extract_hyperparameters_from_keras(model):
807
+ from .modeling_tf_utils import keras
808
+
809
+ hyperparameters = {}
810
+ if hasattr(model, "optimizer") and model.optimizer is not None:
811
+ hyperparameters["optimizer"] = model.optimizer.get_config()
812
+ else:
813
+ hyperparameters["optimizer"] = None
814
+ hyperparameters["training_precision"] = keras.mixed_precision.global_policy().name
815
+
816
+ return hyperparameters
817
+
818
+
819
+ def _maybe_round(v, decimals=4):
820
+ if isinstance(v, float) and len(str(v).split(".")) > 1 and len(str(v).split(".")[1]) > decimals:
821
+ return f"{v:.{decimals}f}"
822
+ return str(v)
823
+
824
+
825
+ def _regular_table_line(values, col_widths):
826
+ values_with_space = [f"| {v}" + " " * (w - len(v) + 1) for v, w in zip(values, col_widths)]
827
+ return "".join(values_with_space) + "|\n"
828
+
829
+
830
+ def _second_table_line(col_widths):
831
+ values = ["|:" + "-" * w + ":" for w in col_widths]
832
+ return "".join(values) + "|\n"
833
+
834
+
835
+ def make_markdown_table(lines):
836
+ """
837
+ Create a nice Markdown table from the results in `lines`.
838
+ """
839
+ if lines is None or len(lines) == 0:
840
+ return ""
841
+ col_widths = {key: len(str(key)) for key in lines[0]}
842
+ for line in lines:
843
+ for key, value in line.items():
844
+ if col_widths[key] < len(_maybe_round(value)):
845
+ col_widths[key] = len(_maybe_round(value))
846
+
847
+ table = _regular_table_line(list(lines[0].keys()), list(col_widths.values()))
848
+ table += _second_table_line(list(col_widths.values()))
849
+ for line in lines:
850
+ table += _regular_table_line([_maybe_round(v) for v in line.values()], list(col_widths.values()))
851
+ return table
852
+
853
+
854
+ _TRAINING_ARGS_KEYS = [
855
+ "learning_rate",
856
+ "train_batch_size",
857
+ "eval_batch_size",
858
+ "seed",
859
+ ]
860
+
861
+
862
+ def extract_hyperparameters_from_trainer(trainer):
863
+ hyperparameters = {k: getattr(trainer.args, k) for k in _TRAINING_ARGS_KEYS}
864
+
865
+ if trainer.args.parallel_mode not in [ParallelMode.NOT_PARALLEL, ParallelMode.NOT_DISTRIBUTED]:
866
+ hyperparameters["distributed_type"] = (
867
+ "multi-GPU" if trainer.args.parallel_mode == ParallelMode.DISTRIBUTED else trainer.args.parallel_mode.value
868
+ )
869
+ if trainer.args.world_size > 1:
870
+ hyperparameters["num_devices"] = trainer.args.world_size
871
+ if trainer.args.gradient_accumulation_steps > 1:
872
+ hyperparameters["gradient_accumulation_steps"] = trainer.args.gradient_accumulation_steps
873
+
874
+ total_train_batch_size = (
875
+ trainer.args.train_batch_size * trainer.args.world_size * trainer.args.gradient_accumulation_steps
876
+ )
877
+ if total_train_batch_size != hyperparameters["train_batch_size"]:
878
+ hyperparameters["total_train_batch_size"] = total_train_batch_size
879
+ total_eval_batch_size = trainer.args.eval_batch_size * trainer.args.world_size
880
+ if total_eval_batch_size != hyperparameters["eval_batch_size"]:
881
+ hyperparameters["total_eval_batch_size"] = total_eval_batch_size
882
+
883
+ if trainer.args.optim:
884
+ optimizer_name = trainer.args.optim
885
+ optimizer_args = trainer.args.optim_args if trainer.args.optim_args else "No additional optimizer arguments"
886
+
887
+ if "adam" in optimizer_name.lower():
888
+ hyperparameters["optimizer"] = (
889
+ f"Use {optimizer_name} with betas=({trainer.args.adam_beta1},{trainer.args.adam_beta2}) and"
890
+ f" epsilon={trainer.args.adam_epsilon} and optimizer_args={optimizer_args}"
891
+ )
892
+ else:
893
+ hyperparameters["optimizer"] = f"Use {optimizer_name} and the args are:\n{optimizer_args}"
894
+
895
+ hyperparameters["lr_scheduler_type"] = trainer.args.lr_scheduler_type.value
896
+ if trainer.args.warmup_ratio != 0.0:
897
+ hyperparameters["lr_scheduler_warmup_ratio"] = trainer.args.warmup_ratio
898
+ if trainer.args.warmup_steps != 0.0:
899
+ hyperparameters["lr_scheduler_warmup_steps"] = trainer.args.warmup_steps
900
+ if trainer.args.max_steps != -1:
901
+ hyperparameters["training_steps"] = trainer.args.max_steps
902
+ else:
903
+ hyperparameters["num_epochs"] = trainer.args.num_train_epochs
904
+
905
+ if trainer.args.fp16:
906
+ if trainer.use_apex:
907
+ hyperparameters["mixed_precision_training"] = f"Apex, opt level {trainer.args.fp16_opt_level}"
908
+ else:
909
+ hyperparameters["mixed_precision_training"] = "Native AMP"
910
+
911
+ if trainer.args.label_smoothing_factor != 0.0:
912
+ hyperparameters["label_smoothing_factor"] = trainer.args.label_smoothing_factor
913
+
914
+ return hyperparameters
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_attn_mask_utils.py ADDED
@@ -0,0 +1,487 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ IMPORTANT NOTICE: Every class and function in this file is deprecated in favor of using the much more general
16
+ `masking_utils.py` primitives. New code should not rely on it, it is only kept for backward compatibility for now,
17
+ and will be removed in the future.
18
+ """
19
+
20
+ from dataclasses import dataclass
21
+ from typing import Optional, Union
22
+
23
+ import torch
24
+
25
+ from .utils.import_utils import is_torchdynamo_compiling
26
+
27
+
28
+ @dataclass
29
+ class AttentionMaskConverter:
30
+ """
31
+ A utility attention mask class that allows one to:
32
+ - Create a causal 4d mask
33
+ - Create a causal 4d mask with slided window
34
+ - Convert a 2d attention mask (batch_size, query_length) to a 4d attention mask (batch_size, 1, query_length,
35
+ key_value_length) that can be multiplied with attention scores
36
+
37
+ Examples:
38
+
39
+ ```python
40
+ >>> import torch
41
+ >>> from transformers.modeling_attn_mask_utils import AttentionMaskConverter
42
+
43
+ >>> converter = AttentionMaskConverter(True)
44
+ >>> converter.to_4d(torch.tensor([[0, 0, 0, 1, 1]]), 5, key_value_length=5, dtype=torch.float32)
45
+ tensor([[[[-3.4028e+38, -3.4028e+38, -3.4028e+38, -3.4028e+38, -3.4028e+38],
46
+ [-3.4028e+38, -3.4028e+38, -3.4028e+38, -3.4028e+38, -3.4028e+38],
47
+ [-3.4028e+38, -3.4028e+38, -3.4028e+38, -3.4028e+38, -3.4028e+38],
48
+ [-3.4028e+38, -3.4028e+38, -3.4028e+38, 0.0000e+00, -3.4028e+38],
49
+ [-3.4028e+38, -3.4028e+38, -3.4028e+38, 0.0000e+00, 0.0000e+00]]]])
50
+ ```
51
+
52
+ Parameters:
53
+ is_causal (`bool`):
54
+ Whether the attention mask should be a uni-directional (causal) or bi-directional mask.
55
+
56
+ sliding_window (`int`, *optional*):
57
+ Optionally, the sliding window masks can be created if `sliding_window` is defined to a positive integer.
58
+ """
59
+
60
+ is_causal: bool
61
+ sliding_window: int
62
+
63
+ def __init__(self, is_causal: bool, sliding_window: Optional[int] = None):
64
+ self.is_causal = is_causal
65
+ self.sliding_window = sliding_window
66
+
67
+ if self.sliding_window is not None and self.sliding_window <= 0:
68
+ raise ValueError(
69
+ f"Make sure that when passing `sliding_window` that its value is a strictly positive integer, not `{self.sliding_window}`"
70
+ )
71
+
72
+ def to_causal_4d(
73
+ self,
74
+ batch_size: int,
75
+ query_length: int,
76
+ key_value_length: int,
77
+ dtype: torch.dtype,
78
+ device: Union[torch.device, "str"] = "cpu",
79
+ ) -> Optional[torch.Tensor]:
80
+ """
81
+ Creates a causal 4D mask of (bsz, head_dim=1, query_length, key_value_length) shape and adds large negative
82
+ bias to upper right hand triangular matrix (causal mask).
83
+ """
84
+ if not self.is_causal:
85
+ raise ValueError(f"Please use `to_causal_4d` only if {self.__class__} has `is_causal` set to True.")
86
+
87
+ # If shape is not cached, create a new causal mask and cache it
88
+ input_shape = (batch_size, query_length)
89
+ past_key_values_length = key_value_length - query_length
90
+
91
+ # create causal mask
92
+ # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
93
+ causal_4d_mask = None
94
+ if input_shape[-1] > 1 or self.sliding_window is not None:
95
+ causal_4d_mask = self._make_causal_mask(
96
+ input_shape,
97
+ dtype,
98
+ device=device,
99
+ past_key_values_length=past_key_values_length,
100
+ sliding_window=self.sliding_window,
101
+ )
102
+
103
+ return causal_4d_mask
104
+
105
+ def to_4d(
106
+ self,
107
+ attention_mask_2d: torch.Tensor,
108
+ query_length: int,
109
+ dtype: torch.dtype,
110
+ key_value_length: Optional[int] = None,
111
+ ) -> torch.Tensor:
112
+ """
113
+ Converts 2D attention mask to 4D attention mask by expanding mask to (bsz, head_dim=1, query_length,
114
+ key_value_length) shape and by adding a large negative bias to not-attended positions. If attention_mask is
115
+ causal, a causal mask will be added.
116
+ """
117
+ input_shape = (attention_mask_2d.shape[0], query_length)
118
+
119
+ # create causal mask
120
+ # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
121
+ causal_4d_mask = None
122
+ if (input_shape[-1] > 1 or self.sliding_window is not None) and self.is_causal:
123
+ if key_value_length is None:
124
+ raise ValueError(
125
+ "This attention mask converter is causal. Make sure to pass `key_value_length` to correctly create a causal mask."
126
+ )
127
+
128
+ past_key_values_length = key_value_length - query_length
129
+ causal_4d_mask = self._make_causal_mask(
130
+ input_shape,
131
+ dtype,
132
+ device=attention_mask_2d.device,
133
+ past_key_values_length=past_key_values_length,
134
+ sliding_window=self.sliding_window,
135
+ )
136
+ elif self.sliding_window is not None:
137
+ raise NotImplementedError("Sliding window is currently only implemented for causal masking")
138
+
139
+ # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len]
140
+ expanded_attn_mask = self._expand_mask(attention_mask_2d, dtype, tgt_len=input_shape[-1]).to(
141
+ attention_mask_2d.device
142
+ )
143
+
144
+ if causal_4d_mask is not None:
145
+ expanded_attn_mask = causal_4d_mask.masked_fill(expanded_attn_mask.bool(), torch.finfo(dtype).min)
146
+
147
+ # expanded_attn_mask + causal_4d_mask can cause some overflow
148
+ expanded_4d_mask = expanded_attn_mask
149
+
150
+ return expanded_4d_mask
151
+
152
+ @staticmethod
153
+ def _make_causal_mask(
154
+ input_ids_shape: torch.Size,
155
+ dtype: torch.dtype,
156
+ device: torch.device,
157
+ past_key_values_length: int = 0,
158
+ sliding_window: Optional[int] = None,
159
+ ):
160
+ """
161
+ Make causal mask used for bi-directional self-attention.
162
+ """
163
+ bsz, tgt_len = input_ids_shape
164
+ mask = torch.full((tgt_len, tgt_len), torch.finfo(dtype).min, device=device)
165
+ mask_cond = torch.arange(mask.size(-1), device=device)
166
+ mask.masked_fill_(mask_cond < (mask_cond + 1).view(mask.size(-1), 1), 0)
167
+
168
+ mask = mask.to(dtype)
169
+
170
+ if past_key_values_length > 0:
171
+ mask = torch.cat([torch.zeros(tgt_len, past_key_values_length, dtype=dtype, device=device), mask], dim=-1)
172
+
173
+ # add lower triangular sliding window mask if necessary
174
+ if sliding_window is not None:
175
+ diagonal = past_key_values_length - sliding_window - 1
176
+
177
+ context_mask = torch.tril(torch.ones_like(mask, dtype=torch.bool), diagonal=diagonal)
178
+ # Recent changes in PyTorch prevent mutations on tensors converted with aten::_to_copy
179
+ # See https://github.com/pytorch/pytorch/issues/127571
180
+ if is_torchdynamo_compiling():
181
+ mask = mask.clone()
182
+ mask.masked_fill_(context_mask, torch.finfo(dtype).min)
183
+
184
+ return mask[None, None, :, :].expand(bsz, 1, tgt_len, tgt_len + past_key_values_length)
185
+
186
+ @staticmethod
187
+ def _expand_mask(mask: torch.Tensor, dtype: torch.dtype, tgt_len: Optional[int] = None):
188
+ """
189
+ Expands attention_mask from `[bsz, seq_len]` to `[bsz, 1, tgt_seq_len, src_seq_len]`.
190
+ """
191
+ bsz, src_len = mask.size()
192
+ tgt_len = tgt_len if tgt_len is not None else src_len
193
+
194
+ expanded_mask = mask[:, None, None, :].expand(bsz, 1, tgt_len, src_len).to(dtype)
195
+
196
+ inverted_mask = torch.tensor(1.0, dtype=dtype) - expanded_mask
197
+
198
+ return inverted_mask.masked_fill(inverted_mask.to(torch.bool), torch.finfo(dtype).min)
199
+
200
+ @staticmethod
201
+ def _unmask_unattended(
202
+ expanded_mask: torch.FloatTensor,
203
+ min_dtype: float,
204
+ ):
205
+ # fmt: off
206
+ """
207
+ Attend to all tokens in masked rows from the expanded attention mask, for example the relevant first rows when
208
+ using left padding. This is required by F.scaled_dot_product_attention memory-efficient attention path.
209
+ Details: https://github.com/pytorch/pytorch/issues/110213
210
+
211
+ `expanded_mask` is [bsz, num_masks, tgt_seq_len, src_seq_len] or [bsz, tgt_seq_len, src_seq_len].
212
+ `attention_mask` is [bsz, src_seq_len].
213
+
214
+ The dimension num_masks of `expanded_mask` is most often 1, but it can also be the number of heads in the case of alibi attention bias.
215
+
216
+ For example, if `expanded_mask` is (e.g. here left-padding case)
217
+ ```
218
+ [[[[0, 0, 0],
219
+ [0, 0, 0],
220
+ [0, 0, 1]]],
221
+ [[[1, 0, 0],
222
+ [1, 1, 0],
223
+ [1, 1, 1]]],
224
+ [[[0, 0, 0],
225
+ [0, 1, 0],
226
+ [0, 1, 1]]]]
227
+ ```
228
+ then the modified `expanded_mask` will be
229
+ ```
230
+ [[[[1, 1, 1], <-- modified
231
+ [1, 1, 1], <-- modified
232
+ [0, 0, 1]]],
233
+ [[[1, 0, 0],
234
+ [1, 1, 0],
235
+ [1, 1, 1]]],
236
+ [[[1, 1, 1], <-- modified
237
+ [0, 1, 0],
238
+ [0, 1, 1]]]]
239
+ ```
240
+ """
241
+ # fmt: on
242
+ if expanded_mask.dtype == torch.bool:
243
+ raise ValueError(
244
+ "AttentionMaskConverter._unmask_unattended expects a float `expanded_mask`, got a BoolTensor."
245
+ )
246
+
247
+ return expanded_mask.mul(~torch.all(expanded_mask == min_dtype, dim=-1, keepdim=True))
248
+
249
+ @staticmethod
250
+ def _ignore_causal_mask_sdpa(
251
+ attention_mask: Optional[torch.Tensor],
252
+ inputs_embeds: torch.Tensor,
253
+ past_key_values_length: int,
254
+ sliding_window: Optional[int] = None,
255
+ is_training: bool = False,
256
+ ) -> bool:
257
+ """
258
+ Detects whether the optional user-specified attention_mask & the automatically created causal mask can be
259
+ ignored in case PyTorch's SDPA is used, rather relying on SDPA's `is_causal` argument.
260
+
261
+ In case no token is masked in the `attention_mask` argument, if `query_length == 1` or
262
+ `key_value_length == query_length`, we rather rely on SDPA `is_causal` argument to use causal/non-causal masks,
263
+ allowing to dispatch to the flash attention kernel (that can otherwise not be used if a custom `attn_mask` is
264
+ passed).
265
+ """
266
+
267
+ _, query_length = inputs_embeds.shape[0], inputs_embeds.shape[1]
268
+ key_value_length = query_length + past_key_values_length
269
+
270
+ is_tracing = torch.jit.is_tracing() or isinstance(inputs_embeds, torch.fx.Proxy) or is_torchdynamo_compiling()
271
+
272
+ ignore_causal_mask = False
273
+
274
+ if attention_mask is None:
275
+ # TODO: When tracing with TorchDynamo with fullgraph=True, the model is recompiled depending on the input
276
+ # shape, thus SDPA's `is_causal` argument is rightfully updated
277
+ # (see https://gist.github.com/fxmarty/1313f39037fc1c112508989628c57363). However, when using
278
+ # `torch.export` or `torch.onnx.dynamo_export`, we must pass an example input, and `is_causal` behavior is
279
+ # hard-coded. If a user exports a model with q_len > 1, the exported model will hard-code `is_causal=True`
280
+ # which is in general wrong (see https://github.com/pytorch/pytorch/issues/108108).
281
+ # Thus, we only set `ignore_causal_mask = True` if the model is set to training.
282
+ #
283
+ # Besides, jit.trace can not handle the `q_len > 1` condition for `is_causal`
284
+ # ("TypeError: scaled_dot_product_attention(): argument 'is_causal' must be bool, not Tensor").
285
+ if (
286
+ (is_training or not is_tracing)
287
+ and (query_length == 1 or key_value_length == query_length)
288
+ and (sliding_window is None or key_value_length < sliding_window)
289
+ ):
290
+ ignore_causal_mask = True
291
+ elif sliding_window is None or key_value_length < sliding_window:
292
+ if len(attention_mask.shape) == 4:
293
+ return False
294
+ elif not is_tracing and torch.all(attention_mask == 1):
295
+ if query_length == 1 or key_value_length == query_length:
296
+ # For query_length == 1, causal attention and bi-directional attention are the same.
297
+ ignore_causal_mask = True
298
+
299
+ # Unfortunately, for query_length > 1 and key_value_length != query_length, we cannot generally ignore
300
+ # the attention mask, as SDPA causal mask generation may be wrong. We will set `is_causal=False` in
301
+ # SDPA and rely on Transformers attention_mask instead, hence not setting it to None here.
302
+ # Reference: https://github.com/pytorch/pytorch/issues/108108
303
+ # TODO: maybe revisit this with https://github.com/pytorch/pytorch/pull/114823 in PyTorch 2.3.
304
+
305
+ return ignore_causal_mask
306
+
307
+
308
+ def _prepare_4d_causal_attention_mask(
309
+ attention_mask: Optional[torch.Tensor],
310
+ input_shape: Union[torch.Size, tuple, list],
311
+ inputs_embeds: torch.Tensor,
312
+ past_key_values_length: int,
313
+ sliding_window: Optional[int] = None,
314
+ ):
315
+ """
316
+ Creates a causal 4D mask of shape `(batch_size, 1, query_length, key_value_length)` from a 2D mask of shape
317
+ `(batch_size, key_value_length)`
318
+
319
+ Args:
320
+ attention_mask (`torch.Tensor` or `None`):
321
+ A 2D attention mask of shape `(batch_size, key_value_length)`
322
+ input_shape (`tuple(int)` or `list(int)` or `torch.Size`):
323
+ The input shape should be a tuple that defines `(batch_size, query_length)`.
324
+ inputs_embeds (`torch.Tensor`):
325
+ The embedded inputs as a torch Tensor.
326
+ past_key_values_length (`int`):
327
+ The length of the key value cache.
328
+ sliding_window (`int`, *optional*):
329
+ If the model uses windowed attention, a sliding window should be passed.
330
+ """
331
+ attn_mask_converter = AttentionMaskConverter(is_causal=True, sliding_window=sliding_window)
332
+
333
+ key_value_length = input_shape[-1] + past_key_values_length
334
+
335
+ # 4d mask is passed through the layers
336
+ if attention_mask is not None and len(attention_mask.shape) == 2:
337
+ attention_mask = attn_mask_converter.to_4d(
338
+ attention_mask, input_shape[-1], key_value_length=key_value_length, dtype=inputs_embeds.dtype
339
+ )
340
+ elif attention_mask is not None and len(attention_mask.shape) == 4:
341
+ expected_shape = (input_shape[0], 1, input_shape[1], key_value_length)
342
+ if tuple(attention_mask.shape) != expected_shape:
343
+ raise ValueError(
344
+ f"Incorrect 4D attention_mask shape: {tuple(attention_mask.shape)}; expected: {expected_shape}."
345
+ )
346
+ else:
347
+ # if the 4D mask has correct shape - invert it and fill with negative infinity
348
+ inverted_mask = 1.0 - attention_mask
349
+ attention_mask = inverted_mask.masked_fill(
350
+ inverted_mask.to(torch.bool), torch.finfo(inputs_embeds.dtype).min
351
+ )
352
+ else:
353
+ attention_mask = attn_mask_converter.to_causal_4d(
354
+ input_shape[0], input_shape[-1], key_value_length, dtype=inputs_embeds.dtype, device=inputs_embeds.device
355
+ )
356
+
357
+ return attention_mask
358
+
359
+
360
+ # Adapted from _prepare_4d_causal_attention_mask
361
+ def _prepare_4d_causal_attention_mask_for_sdpa(
362
+ attention_mask: Optional[torch.Tensor],
363
+ input_shape: Union[torch.Size, tuple, list],
364
+ inputs_embeds: torch.Tensor,
365
+ past_key_values_length: int,
366
+ sliding_window: Optional[int] = None,
367
+ ):
368
+ """
369
+ Prepares the correct `attn_mask` argument to be used by `torch.nn.functional.scaled_dot_product_attention`.
370
+
371
+ In case no token is masked in the `attention_mask` argument, we simply set it to `None` for the cases `query_length == 1` and
372
+ `key_value_length == query_length`, and rely instead on SDPA `is_causal` argument to use causal/non-causal masks,
373
+ allowing to dispatch to the flash attention kernel (that can otherwise not be used if a custom `attn_mask` is passed).
374
+ """
375
+ attn_mask_converter = AttentionMaskConverter(is_causal=True, sliding_window=sliding_window)
376
+
377
+ key_value_length = input_shape[-1] + past_key_values_length
378
+
379
+ # torch.jit.trace, symbolic_trace and torchdynamo with fullgraph=True are unable to capture the controlflow `is_causal=attention_mask is None and q_len > 1`
380
+ # used as an SDPA argument. We keep compatibility with these tracing tools by always using SDPA's `attn_mask` argument in case we are tracing.
381
+ # TODO: For dynamo, rather use a check on fullgraph=True once this is possible (https://github.com/pytorch/pytorch/pull/120400).
382
+ is_tracing = torch.jit.is_tracing() or isinstance(inputs_embeds, torch.fx.Proxy) or is_torchdynamo_compiling()
383
+
384
+ ignore_causal_mask = AttentionMaskConverter._ignore_causal_mask_sdpa(
385
+ attention_mask=attention_mask,
386
+ inputs_embeds=inputs_embeds,
387
+ past_key_values_length=past_key_values_length,
388
+ sliding_window=sliding_window,
389
+ )
390
+
391
+ if ignore_causal_mask:
392
+ expanded_4d_mask = None
393
+ elif attention_mask is None:
394
+ expanded_4d_mask = attn_mask_converter.to_causal_4d(
395
+ input_shape[0], input_shape[-1], key_value_length, dtype=inputs_embeds.dtype, device=inputs_embeds.device
396
+ )
397
+ else:
398
+ if attention_mask.dim() == 4:
399
+ expanded_4d_mask = attention_mask
400
+ else:
401
+ expanded_4d_mask = attn_mask_converter.to_4d(
402
+ attention_mask,
403
+ input_shape[-1],
404
+ dtype=inputs_embeds.dtype,
405
+ key_value_length=key_value_length,
406
+ )
407
+
408
+ # Attend to all tokens in masked rows from the causal_mask, for example the relevant first rows when
409
+ # using left padding. This is required by F.scaled_dot_product_attention memory-efficient attention path.
410
+ # Details: https://github.com/pytorch/pytorch/issues/110213
411
+ if not is_tracing and expanded_4d_mask.device.type == "cuda":
412
+ expanded_4d_mask = AttentionMaskConverter._unmask_unattended(
413
+ expanded_4d_mask, min_dtype=torch.finfo(inputs_embeds.dtype).min
414
+ )
415
+
416
+ return expanded_4d_mask
417
+
418
+
419
+ def _prepare_4d_attention_mask(mask: torch.Tensor, dtype: torch.dtype, tgt_len: Optional[int] = None):
420
+ """
421
+ Creates a non-causal 4D mask of shape `(batch_size, 1, query_length, key_value_length)` from a 2D mask of shape
422
+ `(batch_size, key_value_length)`
423
+
424
+ Args:
425
+ mask (`torch.Tensor`):
426
+ A 2D attention mask of shape `(batch_size, key_value_length)`
427
+ dtype (`torch.dtype`):
428
+ The torch dtype the created mask shall have.
429
+ tgt_len (`int`):
430
+ The target length or query length the created mask shall have.
431
+ """
432
+ return AttentionMaskConverter._expand_mask(mask=mask, dtype=dtype, tgt_len=tgt_len)
433
+
434
+
435
+ def _prepare_4d_attention_mask_for_sdpa(mask: torch.Tensor, dtype: torch.dtype, tgt_len: Optional[int] = None):
436
+ """
437
+ Creates a non-causal 4D mask of shape `(batch_size, 1, query_length, key_value_length)` from a 2D mask of shape
438
+ `(batch_size, key_value_length)`
439
+
440
+ Args:
441
+ mask (`torch.Tensor`):
442
+ A 2D attention mask of shape `(batch_size, key_value_length)`
443
+ dtype (`torch.dtype`):
444
+ The torch dtype the created mask shall have.
445
+ tgt_len (`int`):
446
+ The target length or query length the created mask shall have.
447
+ """
448
+ _, key_value_length = mask.shape
449
+ tgt_len = tgt_len if tgt_len is not None else key_value_length
450
+
451
+ is_tracing = torch.jit.is_tracing() or isinstance(mask, torch.fx.Proxy) or is_torchdynamo_compiling()
452
+
453
+ # torch.jit.trace, symbolic_trace and torchdynamo with fullgraph=True are unable to capture data-dependent controlflows.
454
+ if not is_tracing and torch.all(mask == 1):
455
+ return None
456
+ else:
457
+ return AttentionMaskConverter._expand_mask(mask=mask, dtype=dtype, tgt_len=tgt_len)
458
+
459
+
460
+ def _create_4d_causal_attention_mask(
461
+ input_shape: Union[torch.Size, tuple, list],
462
+ dtype: torch.dtype,
463
+ device: torch.device,
464
+ past_key_values_length: int = 0,
465
+ sliding_window: Optional[int] = None,
466
+ ) -> Optional[torch.Tensor]:
467
+ """
468
+ Creates a causal 4D mask of shape `(batch_size, 1, query_length, key_value_length)`
469
+
470
+ Args:
471
+ input_shape (`tuple(int)` or `list(int)` or `torch.Size`):
472
+ The input shape should be a tuple that defines `(batch_size, query_length)`.
473
+ dtype (`torch.dtype`):
474
+ The torch dtype the created mask shall have.
475
+ device (`int`):
476
+ The torch device the created mask shall have.
477
+ sliding_window (`int`, *optional*):
478
+ If the model uses windowed attention, a sliding window should be passed.
479
+ """
480
+ attn_mask_converter = AttentionMaskConverter(is_causal=True, sliding_window=sliding_window)
481
+
482
+ key_value_length = past_key_values_length + input_shape[-1]
483
+ attention_mask = attn_mask_converter.to_causal_4d(
484
+ input_shape[0], input_shape[-1], key_value_length, dtype=dtype, device=device
485
+ )
486
+
487
+ return attention_mask
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flash_attention_utils.py ADDED
@@ -0,0 +1,668 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 The Fairseq Authors and the HuggingFace Inc. team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import inspect
15
+ import os
16
+ from functools import partial
17
+ from typing import Optional, TypedDict
18
+
19
+ import torch
20
+ import torch.nn.functional as F
21
+
22
+ from .utils import (
23
+ is_flash_attn_2_available,
24
+ is_flash_attn_3_available,
25
+ is_flash_attn_greater_or_equal_2_10,
26
+ is_torch_npu_available,
27
+ logging,
28
+ )
29
+
30
+
31
+ logger = logging.get_logger(__name__)
32
+
33
+
34
+ # TODO Deprecate when all models have the attention interface
35
+ def flash_attn_supports_top_left_mask():
36
+ if is_flash_attn_3_available():
37
+ return False
38
+ if is_flash_attn_2_available():
39
+ return not is_flash_attn_greater_or_equal_2_10()
40
+
41
+ from .integrations.npu_flash_attention import is_npu_fa2_top_left_aligned_causal_mask
42
+
43
+ return is_npu_fa2_top_left_aligned_causal_mask()
44
+
45
+
46
+ # TODO Deprecate when all models have the attention interface
47
+ def is_flash_attn_available():
48
+ return is_flash_attn_3_available() or is_flash_attn_2_available() or is_torch_npu_available()
49
+
50
+
51
+ # `globals()` is not compatible with dynamo, hence we have do define them in global scope ourselves
52
+ _flash_fn = None
53
+ _flash_varlen_fn = None
54
+ _pad_fn = None
55
+ _unpad_fn = None
56
+
57
+ # function that processes kwargs, generalized to handle any supported kwarg within the function
58
+ _process_flash_kwargs_fn = None
59
+ # exceptions where hf API doesn't match the original flash attention API
60
+ _hf_api_to_flash_mapping = {
61
+ "dropout": "dropout_p",
62
+ "sliding_window": "window_size",
63
+ }
64
+
65
+
66
+ def _lazy_imports(implementation: Optional[str]):
67
+ """
68
+ Lazy loads the respective flash attention implementations.
69
+
70
+ Return:
71
+ flash_attn_func: The base flash attention function.
72
+ flash_attn_varlen_func: The flash attention function supporting variable sequence lengths,
73
+ e.g. for padding-free training.
74
+ pad_input: The function to pad inputs into one sequence and returning the respective kwargs.
75
+ unpad_input: The function to unpad outputs based on the kwargs (from pad_input).
76
+ """
77
+ is_fa2 = is_flash_attn_2_available()
78
+ is_fa3 = is_flash_attn_3_available()
79
+
80
+ pad_input, unpad_input = _pad_input, _unpad_input
81
+
82
+ if (implementation == "flash_attention_2" and is_fa2) or (implementation is None and is_fa2 and not is_fa3):
83
+ from flash_attn import flash_attn_func, flash_attn_varlen_func
84
+ from flash_attn.bert_padding import pad_input, unpad_input
85
+ elif is_torch_npu_available():
86
+ # Package `flash-attn` is unavailable on Ascend NPU, which will cause ImportError
87
+ # Flash-Attention2 related apis for Ascend NPU must be imported from `.integrations.npu_flash_attention` module
88
+ from .integrations.npu_flash_attention import npu_flash_attn_func as flash_attn_func
89
+ from .integrations.npu_flash_attention import npu_flash_attn_varlen_func as flash_attn_varlen_func
90
+ else:
91
+ if implementation == "flash_attention_3" or (implementation is None and is_fa3):
92
+ from flash_attn_interface import flash_attn_func, flash_attn_varlen_func
93
+ # Kernels fallback
94
+ else:
95
+ flash_attn_func = getattr(implementation, "flash_attn_func", None)
96
+ flash_attn_varlen_func = getattr(implementation, "flash_attn_varlen_func", None)
97
+ if flash_attn_varlen_func is None or flash_attn_func is None:
98
+ raise ValueError(
99
+ f"Could not find the currently requested flash attention implementation at `{implementation}`."
100
+ f"Make sure that you request a valid kernel from the hub, e.g. `kernels-community/flash-attn`."
101
+ )
102
+
103
+ return flash_attn_func, flash_attn_varlen_func, pad_input, unpad_input
104
+
105
+
106
+ def _lazy_define_process_function(flash_function):
107
+ """
108
+ Depending on the version and kernel some features are not supported. Due to limitations in
109
+ `torch.compile`, we opt to statically type which (optional) kwarg parameters are supported
110
+ within `_process_flash_attention_kwargs`.
111
+
112
+ NOTE: While all supported kwargs are marked as `True`, everything else is marked as `False`.
113
+ This might be confusing for kwargs that we use in any case, e.g. `is_causal`.
114
+ """
115
+
116
+ flash_parameters = inspect.signature(flash_function).parameters
117
+ process_parameters = inspect.signature(_process_flash_attention_kwargs).parameters
118
+
119
+ supports_mapping = {}
120
+ for param in process_parameters:
121
+ fa_param = _hf_api_to_flash_mapping.get(param, param)
122
+ supports_mapping[fa_param] = fa_param in flash_parameters
123
+
124
+ return partial(_process_flash_attention_kwargs, supports_mapping=supports_mapping)
125
+
126
+
127
+ def lazy_import_flash_attention(implementation: Optional[str], force_import: Optional[bool] = False):
128
+ """
129
+ Lazily import flash attention and return the respective functions + flags.
130
+
131
+ NOTE: For fullgraph, this needs to be called before compile, while no fullgraph can
132
+ work without preloading. See `load_and_register_kernel` in `integrations.hub_kernels`.
133
+ """
134
+ global _flash_fn, _flash_varlen_fn, _pad_fn, _unpad_fn
135
+ if force_import or any(k is None for k in [_flash_fn, _flash_varlen_fn, _pad_fn, _unpad_fn]):
136
+ _flash_fn, _flash_varlen_fn, _pad_fn, _unpad_fn = _lazy_imports(implementation)
137
+
138
+ global _process_flash_kwargs_fn
139
+ if force_import or _process_flash_kwargs_fn is None:
140
+ _process_flash_kwargs_fn = _lazy_define_process_function(_flash_varlen_fn)
141
+
142
+ return (_flash_fn, _flash_varlen_fn, _pad_fn, _unpad_fn), _process_flash_kwargs_fn
143
+
144
+
145
+ def _index_first_axis(tensor, indices):
146
+ """
147
+ A local implementation of the PyTorch indexing operation `tensor[indices]` on the first axis,
148
+ after flattening the first two dimensions of the tensor. This is functionally equivalent to
149
+ FA2's `index_first_axis` and replaces the need to import it.
150
+ """
151
+ # The input tensor is expected to be of shape (batch, seq_len, ...). We flatten the first
152
+ # two dimensions to get (total_tokens, ...) before indexing.
153
+ reshaped_tensor = tensor.reshape(-1, *tensor.shape[2:])
154
+ return reshaped_tensor[indices]
155
+
156
+
157
+ def _unpad_input(hidden_states, attention_mask, unused_mask=None):
158
+ """
159
+ unpad_input function for flash attention variants that do not have them within their pkg themselves, e.g. fa3.
160
+
161
+ Arguments:
162
+ hidden_states: (batch, seqlen, ...)
163
+ attention_mask: (batch, seqlen), bool / int, 1 means valid and 0 means not valid.
164
+ unused_mask: (batch, seqlen), bool / int, 1 means the element is allocated but unused.
165
+
166
+ Return:
167
+ hidden_states: (total_nnz, ...), where total_nnz = number of tokens selected in attention_mask + unused_mask.
168
+ indices: (total_nnz), the indices of masked tokens from the flattened input sequence.
169
+ cu_seqlens: (batch + 1), the cumulative sequence lengths, used to index into hidden_states.
170
+ max_seqlen_in_batch: int
171
+ seqused: (batch), returns the number of tokens selected in attention_mask + unused_mask.
172
+ """
173
+ all_masks = (attention_mask + unused_mask) if unused_mask is not None else attention_mask
174
+ seqlens_in_batch = all_masks.sum(dim=-1, dtype=torch.int32)
175
+ used_seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32)
176
+ indices = torch.nonzero(all_masks.flatten(), as_tuple=False).flatten()
177
+ max_seqlen_in_batch = seqlens_in_batch.max().item()
178
+ cu_seqlens = F.pad(torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.int32), (1, 0))
179
+
180
+ return (
181
+ _index_first_axis(hidden_states, indices),
182
+ indices,
183
+ cu_seqlens,
184
+ max_seqlen_in_batch,
185
+ used_seqlens_in_batch,
186
+ )
187
+
188
+
189
+ def _pad_input(hidden_states, indices, batch, seqlen):
190
+ """
191
+ pad_input function for flash attention variants that do not have them within their pkg themselves, e.g. fa3.
192
+
193
+ Arguments:
194
+ hidden_states: (total_nnz, ...), where total_nnz = number of tokens in selected in attention_mask.
195
+ indices: (total_nnz), the indices that represent the non-masked tokens of the original padded input sequence.
196
+ batch: int, batch size for the padded sequence.
197
+ seqlen: int, maximum sequence length for the padded sequence.
198
+
199
+ Return:
200
+ hidden_states: (batch, seqlen, ...)
201
+ """
202
+ dim = hidden_states.shape[1:]
203
+ output = torch.zeros((batch * seqlen), *dim, device=hidden_states.device, dtype=hidden_states.dtype)
204
+ output[indices] = hidden_states
205
+ return output.view(batch, seqlen, *dim)
206
+
207
+
208
+ def _get_unpad_data(attention_mask: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, int]:
209
+ """
210
+ Retrieves indexing data required to repad unpadded (ragged) tensors.
211
+
212
+ Arguments:
213
+ attention_mask (`torch.Tensor`):
214
+ Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
215
+
216
+ Return:
217
+ indices (`torch.Tensor`):
218
+ The indices of non-masked tokens from the flattened input sequence.
219
+ cu_seqlens (`torch.Tensor`):
220
+ The cumulative sequence lengths, used to index into ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
221
+ max_seqlen_in_batch (`int`):
222
+ Maximum sequence length in batch.
223
+ """
224
+ seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32)
225
+ indices = torch.nonzero(attention_mask.flatten(), as_tuple=False).flatten()
226
+ # NOTE: Similar to the `.item()` in prepare_fa2_from_position_ids, with torch compile,
227
+ # this might cause a graph break
228
+ max_seqlen_in_batch = seqlens_in_batch.max().item()
229
+ cu_seqlens = F.pad(torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.int32), (1, 0))
230
+ return (
231
+ indices,
232
+ cu_seqlens,
233
+ max_seqlen_in_batch,
234
+ )
235
+
236
+
237
+ def _upad_input(
238
+ query_layer: torch.Tensor,
239
+ key_layer: torch.Tensor,
240
+ value_layer: torch.Tensor,
241
+ attention_mask: torch.Tensor,
242
+ query_length: int,
243
+ unpad_input_func,
244
+ ):
245
+ """
246
+ Unpads query, key, and values tensors, using a single dimension for all tokens even though they belong to different batches.
247
+ This function is used instead of `flash_attn.bert_padding.unpad_input` in order to avoid the recomputation of the same intermediary
248
+ tensors for query, key, value tensors.
249
+
250
+ Arguments:
251
+ query_layer (`torch.Tensor`):
252
+ Query state with padding. Shape: (batch_size, query_length, num_heads, head_dim).
253
+ key_layer (`torch.Tensor`):
254
+ Key state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
255
+ value_layer (`torch.Tensor`):
256
+ Value state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
257
+ attention_mask (`torch.Tensor`):
258
+ Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
259
+ query_length (`int`):
260
+ Target length.
261
+ unpad_input_func:
262
+ The function to use for unpadding the input tensors.
263
+
264
+ Return:
265
+ query_layer (`torch.Tensor`):
266
+ Query state without padding. Shape: (total_target_length, num_heads, head_dim).
267
+ key_layer (`torch.Tensor`):
268
+ Key state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
269
+ value_layer (`torch.Tensor`):
270
+ Value state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
271
+ indices_q (`torch.Tensor`):
272
+ The indices of non-masked tokens from the flattened input target sequence.
273
+ (cu_seqlens_q, cu_seqlens_k) (`tuple[int]`):
274
+ The cumulative sequence lengths for the target (query) and source (key, value), used to index into ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
275
+ (max_seqlen_in_batch_q, max_seqlen_in_batch_k) (`tuple[int]`):
276
+ Maximum sequence length in batch (`max_seqlen_in_batch_q` for the target sequence i.e. query, `max_seqlen_in_batch_k` for the source sequence i.e. key/value).
277
+ """
278
+ indices_k, cu_seqlens_k, max_seqlen_in_batch_k = _get_unpad_data(attention_mask)
279
+
280
+ # With static caches, the k/v states may be larger than the mask -> we need to slice them to avoid generating garbage
281
+ # It's a bit of an anti-pattern, but otherwise we silently compute wrong attentions scores
282
+ if key_layer.shape[1] > (seq_len := attention_mask.shape[-1]):
283
+ key_layer, value_layer = key_layer[:, :seq_len, :, :], value_layer[:, :seq_len, :, :]
284
+
285
+ batch_size, kv_seq_len, num_key_value_heads, head_dim = key_layer.shape
286
+
287
+ key_layer = _index_first_axis(key_layer, indices_k)
288
+ value_layer = _index_first_axis(value_layer, indices_k)
289
+ if query_length == kv_seq_len:
290
+ query_layer = _index_first_axis(query_layer, indices_k)
291
+ cu_seqlens_q = cu_seqlens_k
292
+ max_seqlen_in_batch_q = max_seqlen_in_batch_k
293
+ indices_q = indices_k
294
+ elif query_length == 1:
295
+ max_seqlen_in_batch_q = 1
296
+ cu_seqlens_q = torch.arange(
297
+ batch_size + 1, dtype=torch.int32, device=query_layer.device
298
+ ) # There is a memcpy here, that is very bad.
299
+ indices_q = cu_seqlens_q[:-1]
300
+ query_layer = query_layer.squeeze(1)
301
+ else:
302
+ # The -q_len: slice assumes left padding.
303
+ attention_mask = attention_mask[:, -query_length:]
304
+ query_layer, indices_q, cu_seqlens_q, max_seqlen_in_batch_q, *_ = unpad_input_func(query_layer, attention_mask)
305
+
306
+ return (
307
+ query_layer,
308
+ key_layer,
309
+ value_layer,
310
+ indices_q,
311
+ (cu_seqlens_q, cu_seqlens_k),
312
+ (max_seqlen_in_batch_q, max_seqlen_in_batch_k),
313
+ )
314
+
315
+
316
+ def prepare_fa_kwargs_from_position_ids(position_ids):
317
+ """
318
+ This function returns all the necessary kwargs to call `flash_attn_varlen_func` extracted from position_ids.
319
+
320
+ Arguments:
321
+ position_ids (`torch.Tensor`):
322
+ Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
323
+
324
+ Return:
325
+ (cu_seqlens_q, cu_seqlens_k) (`tuple[int]`):
326
+ The cumulative sequence lengths for the target (query) and source (key, value), used to index into
327
+ ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
328
+ (max_seqlen_in_batch_q, max_seqlen_in_batch_k) (`tuple[int]`):
329
+ Maximum sequence length in batch (`max_seqlen_in_batch_q` for the target sequence i.e. query,
330
+ `max_seqlen_in_batch_k` for the source sequence i.e. key/value).
331
+ """
332
+ tensor_kwargs = {"dtype": torch.int32, "device": position_ids.device}
333
+
334
+ position_ids = position_ids.view(-1)
335
+ indices_q = (position_ids == 0).nonzero().view(-1)
336
+
337
+ cu_seq_lens_q = torch.cat(
338
+ (
339
+ indices_q.to(**tensor_kwargs),
340
+ torch.tensor(position_ids.size(), **tensor_kwargs),
341
+ )
342
+ )
343
+ cu_seq_lens_k = cu_seq_lens_q
344
+
345
+ # https://github.com/Dao-AILab/flash-attention/blob/2dd8078adc1d9b74e315ee99718c0dea0de8eeb6/flash_attn/flash_attn_interface.py#L1423-L1424
346
+ # We should use cu_seq_lens instead of position_ids to get the max length since position_ids is not always increasing
347
+ # for some models (e.g. qwen2-vl).
348
+ max_length_q = cu_seq_lens_q.diff().max()
349
+ # NOTE: With torch compile, this will cause a graph break if you don't set
350
+ # `TORCHDYNAMO_CAPTURE_SCALAR_OUTPUTS=1` in the environment or call
351
+ # `torch._dynamo.config.capture_scalar_outputs = True` before doing the forward pass.
352
+ # This is a limitation of flash attention API, as the function `flash_attn_varlen_func`
353
+ # requires `max_length_q`, `max_length_k` to be passed as `int` and not `torch.Tensor`.
354
+ max_length_q = max_length_q.item()
355
+ max_length_k = max_length_q
356
+
357
+ return (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k)
358
+
359
+
360
+ def _prepare_from_posids(query, key, value, position_ids):
361
+ """
362
+ This function returns necessary arguments to call `flash_attn_varlen_func`.
363
+ All three query, key, value states will be flattened.
364
+ Cumulative lengths of each examples in the batch will be extracted from position_ids.
365
+ NOTE: ideally cumulative lengths should be prepared at the data collator stage
366
+
367
+ Arguments:
368
+ query (`torch.Tensor`):
369
+ Query state with padding. Shape: (batch_size, query_length, num_heads, head_dim).
370
+ key (`torch.Tensor`):
371
+ Key state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
372
+ value (`torch.Tensor`):
373
+ Value state with padding. Shape: (batch_size, kv_seq_len, num_key_value_heads, head_dim).
374
+ position_ids (`torch.Tensor`):
375
+ Boolean or int tensor of shape (batch_size, sequence_length), 1 means valid and 0 means not valid.
376
+
377
+ Return:
378
+ query (`torch.Tensor`):
379
+ Query state without padding. Shape: (total_target_length, num_heads, head_dim).
380
+ key (`torch.Tensor`):
381
+ Key state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
382
+ value (`torch.Tensor`):
383
+ Value state with padding. Shape: (total_source_length, num_key_value_heads, head_dim).
384
+ (cu_seqlens_q, cu_seqlens_k) (`tuple[int]`):
385
+ The cumulative sequence lengths for the target (query) and source (key, value), used to index into ragged (unpadded) tensors. `cu_seqlens` shape is (batch_size + 1,).
386
+ (max_seqlen_in_batch_q, max_seqlen_in_batch_k) (`tuple[int]`):
387
+ Maximum sequence length in batch (`max_seqlen_in_batch_q` for the target sequence i.e. query, `max_seqlen_in_batch_k` for the source sequence i.e. key/value).
388
+ """
389
+ query = query.contiguous().view(-1, query.size(-2), query.size(-1))
390
+ key = key.contiguous().view(-1, key.size(-2), key.size(-1))
391
+ value = value.contiguous().view(-1, value.size(-2), value.size(-1))
392
+
393
+ (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k) = prepare_fa_kwargs_from_position_ids(position_ids)
394
+
395
+ return (query, key, value, (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k))
396
+
397
+
398
+ def _is_packed_sequence(position_ids, batch_size):
399
+ """
400
+ Check the position ids whether packed sequences are indicated or not
401
+ 1. Position ids exist
402
+ 2. Flattened sequences only are supported
403
+ 3. Compile-friendly `not (torch.diff(position_ids, dim=-1) >= 0).all()`, i.e. we have multiple increasing sequences
404
+ """
405
+ if position_ids is None:
406
+ return False
407
+
408
+ increasing_position_sequences = (
409
+ torch.arange(position_ids.shape[1], device=position_ids.device) + position_ids.min()
410
+ )
411
+ return batch_size == 1 and (increasing_position_sequences - position_ids).abs().sum().bool()
412
+
413
+
414
+ def fa_peft_integration_check(
415
+ q: torch.Tensor,
416
+ k: torch.Tensor,
417
+ v: torch.Tensor,
418
+ target_dtype: Optional[torch.dtype] = None,
419
+ ):
420
+ """
421
+ PEFT usually casts the layer norms in float32 for training stability reasons
422
+ therefore the input hidden states gets silently casted in float32. Hence, we need
423
+ cast them back in float16 / bfloat16 just to be sure everything works as expected.
424
+ This might slowdown training & inference so it is recommended to not cast the LayerNorms!
425
+ """
426
+ if target_dtype and q.dtype == torch.float32:
427
+ logger.warning_once(f"Casting fp32 inputs back to {target_dtype} for flash-attn compatibility.")
428
+ q, k, v = q.to(target_dtype), k.to(target_dtype), v.to(target_dtype)
429
+ return q, k, v
430
+
431
+
432
+ class FlashAttentionKwargs(TypedDict, total=False):
433
+ """
434
+ Keyword arguments for Flash Attention with Compile.
435
+
436
+ Attributes:
437
+ cu_seq_lens_q (`torch.LongTensor`, *optional*)
438
+ Gets cumulative sequence length for query state.
439
+ cu_seq_lens_k (`torch.LongTensor`, *optional*)
440
+ Gets cumulative sequence length for key state.
441
+ max_length_q (`int`, *optional*):
442
+ Maximum sequence length for query state.
443
+ max_length_k (`int`, *optional*):
444
+ Maximum sequence length for key state.
445
+ """
446
+
447
+ cu_seq_lens_q: Optional[torch.LongTensor]
448
+ cu_seq_lens_k: Optional[torch.LongTensor]
449
+ max_length_q: Optional[int]
450
+ max_length_k: Optional[int]
451
+
452
+
453
+ def _process_flash_attention_kwargs(
454
+ query_length: int,
455
+ key_length: int,
456
+ is_causal: bool,
457
+ dropout: float = 0.0,
458
+ softmax_scale: Optional[float] = None,
459
+ sliding_window: Optional[int] = None,
460
+ use_top_left_mask: bool = False,
461
+ softcap: Optional[float] = None,
462
+ deterministic: Optional[bool] = None,
463
+ s_aux: Optional[torch.Tensor] = None,
464
+ supports_mapping: Optional[dict[str, bool]] = None,
465
+ **kwargs,
466
+ ):
467
+ """
468
+ Returns a set of kwargs that are passed down to the according flash attention function based on
469
+ requested features and whether it is supported - depends on the version and kernel implementation
470
+ which is dynamically configured at `lazy_import_flash_attention`. The (un)supported features can be
471
+ inspected in `supports_mapping`, see `_lazy_define_process_function` for more details.
472
+
473
+ Args:
474
+ query_length (`int`):
475
+ Length of the query states
476
+ key_length (`int`):
477
+ Length of the key states
478
+ is_causal (`bool`):
479
+ Whether we perform causal (decoder) attention or full attention.
480
+ dropout (`float`):
481
+ Attention dropout.
482
+ softmax_scale (`float`, *optional*):
483
+ The scaling of QK^T before applying softmax. Default to `1 / sqrt(head_dim)`.
484
+ sliding_window (`int`, *optional*):
485
+ The size of the sliding window, i.e. we look at a max of `sliding_window` tokens back.
486
+ use_top_left_mask (`bool`):
487
+ Deprecated behavior of older versions of flash attention requiring different masking.
488
+ softcap (`float`, *optional*):
489
+ Softcap for the attention logits, used e.g. in gemma2.
490
+ deterministic (`bool`, *optional*):
491
+ Determines if the deterministic option introduced in flash_attn>=2.4.1 is enabled.
492
+ s_aux (`torch.Tensor`, *optional*):
493
+ Attention sink auxiliary that adds a `bias` to the attention calculation via an additional head.
494
+ Return:
495
+ flash_kwargs (`dict`):
496
+ A dict of kwargs that are requested and supported.
497
+ """
498
+ flash_kwargs = {
499
+ "causal": is_causal and not (use_top_left_mask and query_length == 1),
500
+ "softmax_scale": softmax_scale,
501
+ }
502
+
503
+ if supports_mapping["dropout_p"]:
504
+ flash_kwargs["dropout_p"] = dropout
505
+
506
+ if supports_mapping["window_size"] and sliding_window is not None and key_length > sliding_window:
507
+ # The flash attention API sets inclusive boundaries, i.e. (4, 0) would take 4 tokens to the left
508
+ # and the current token for a total size of 5. However, we usually define our window sizes by
509
+ # their total window size (when causal). Encoder models as of now seldom use SWA and when they
510
+ # do, they have a custom workaround (e.g. ModernBERT) which would align with this symmetric logic, i.e.
511
+ # for a total of `2*sliding_window + 1`.
512
+ flash_kwargs["window_size"] = (sliding_window - 1, sliding_window - 1)
513
+
514
+ if supports_mapping["deterministic"]:
515
+ flash_kwargs["deterministic"] = (
516
+ deterministic if deterministic is not None else os.getenv("FLASH_ATTENTION_DETERMINISTIC", "0") == "1"
517
+ )
518
+
519
+ if supports_mapping["softcap"] and softcap is not None:
520
+ flash_kwargs["softcap"] = softcap
521
+
522
+ # Only within kernel implementation atm
523
+ if supports_mapping["s_aux"] and s_aux is not None:
524
+ flash_kwargs["s_aux"] = s_aux
525
+
526
+ return flash_kwargs
527
+
528
+
529
+ def _flash_attention_forward(
530
+ query_states: torch.Tensor,
531
+ key_states: torch.Tensor,
532
+ value_states: torch.Tensor,
533
+ attention_mask: Optional[torch.Tensor],
534
+ query_length: int,
535
+ is_causal: bool,
536
+ dropout: float = 0.0,
537
+ position_ids: Optional[torch.Tensor] = None,
538
+ softmax_scale: Optional[float] = None,
539
+ sliding_window: Optional[int] = None,
540
+ use_top_left_mask: bool = False,
541
+ softcap: Optional[float] = None,
542
+ deterministic: Optional[bool] = None,
543
+ cu_seq_lens_q: Optional[torch.LongTensor] = None,
544
+ cu_seq_lens_k: Optional[torch.LongTensor] = None,
545
+ max_length_q: Optional[int] = None,
546
+ max_length_k: Optional[int] = None,
547
+ target_dtype: Optional[torch.dtype] = None,
548
+ implementation: Optional[str] = None,
549
+ **kwargs,
550
+ ):
551
+ """
552
+ Calls the forward method of Flash Attention - if the input hidden states contain at least one padding token
553
+ first unpad the input, then computes the attention scores and pad the final attention scores.
554
+
555
+ (Optional) kwargs are described further in `_process_flash_attention_kwargs` and `FlashAttentionKwargs`.
556
+
557
+ Args:
558
+ query_states (`torch.Tensor`):
559
+ Input query states to be passed to Flash Attention API
560
+ key_states (`torch.Tensor`):
561
+ Input key states to be passed to Flash Attention API
562
+ value_states (`torch.Tensor`):
563
+ Input value states to be passed to Flash Attention API
564
+ attention_mask (`torch.Tensor`, *optional*):
565
+ The padding mask - corresponds to a tensor of size `(batch_size, seq_len)` where 0 stands for the
566
+ position of padding tokens and 1 for the position of non-padding tokens.
567
+ implementation (`str`, *optional*):
568
+ The attention implementation to use. If None, will default to the one based on the environment.
569
+ """
570
+ (flash_fn, flash_varlen_fn, pad_fn, unpad_fn), process_flash_kwargs_fn = lazy_import_flash_attention(
571
+ implementation
572
+ )
573
+
574
+ # PEFT possibly silently casts tensors to fp32, this potentially reconverts to correct dtype or is a no op
575
+ query_states, key_states, value_states = fa_peft_integration_check(
576
+ query_states, key_states, value_states, target_dtype
577
+ )
578
+
579
+ # Extract the flash attention kwargs that have been requested (and are supported by the implementation)
580
+ flash_kwargs = process_flash_kwargs_fn(
581
+ query_length=query_length,
582
+ key_length=key_states.size(1),
583
+ is_causal=is_causal,
584
+ dropout=dropout,
585
+ softmax_scale=softmax_scale,
586
+ sliding_window=sliding_window,
587
+ use_top_left_mask=use_top_left_mask,
588
+ softcap=softcap,
589
+ deterministic=deterministic,
590
+ **kwargs,
591
+ )
592
+
593
+ # We will use `flash_varlen_fn` to prevent cross-example attention and also allow padding free approach under two cases:
594
+ # Case 1. If position ids is provided and the position ids indicate packed sequences, see `_is_packed_sequence`.
595
+ # Case 2. Some models pass directly pre-computed `cu_seqlens` so we don't need to infer it from position ids. It is safe to
596
+ # use `flash_varlen_fn` knowing we already have all necessary the kwargs.
597
+ #
598
+ # NOTE: it is user's responsibility to take care of flattening `position_ids` if that's needed by the model.
599
+ # See #39121 for more information.
600
+ is_fa_with_position_ids = _is_packed_sequence(position_ids, batch_size=query_states.size(0))
601
+ is_fa_with_varlen_kwargs = all(
602
+ kwarg is not None for kwarg in (cu_seq_lens_q, cu_seq_lens_k, max_length_q, max_length_k)
603
+ )
604
+
605
+ # Contains at least one padding token in the sequence
606
+ if attention_mask is not None:
607
+ q, k, v, indices_q, (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k) = _upad_input(
608
+ query_states, key_states, value_states, attention_mask, query_length, unpad_fn
609
+ )
610
+
611
+ # TODO for now this is required to work with
612
+ # https://huggingface.co/kernels-community/metal-flash-sdpa/blob/main/torch-ext/metal_flash_sdpa/__init__.py
613
+ if "mps" in str(q.device):
614
+ cu_seq_lens_k = cu_seq_lens_k.clone()
615
+
616
+ out_unpad = flash_varlen_fn(
617
+ q,
618
+ k,
619
+ v,
620
+ cu_seqlens_q=cu_seq_lens_q,
621
+ cu_seqlens_k=cu_seq_lens_k,
622
+ max_seqlen_q=max_length_q,
623
+ max_seqlen_k=max_length_k,
624
+ **flash_kwargs,
625
+ )
626
+ if isinstance(out_unpad, tuple):
627
+ out_unpad = out_unpad[0]
628
+
629
+ out = pad_fn(out_unpad, indices_q, query_states.size(0), query_length)
630
+
631
+ # Padding free, i.e. sequences flattened into one total sequence
632
+ elif is_fa_with_varlen_kwargs or is_fa_with_position_ids:
633
+ if cu_seq_lens_q is None or cu_seq_lens_k is None:
634
+ q, k, v, (cu_seq_lens_q, cu_seq_lens_k), (max_length_q, max_length_k) = _prepare_from_posids(
635
+ query_states, key_states, value_states, position_ids
636
+ )
637
+ else:
638
+ q = query_states.reshape(-1, query_states.size(-2), query_states.size(-1))
639
+ k = key_states.reshape(-1, key_states.size(-2), key_states.size(-1))
640
+ v = value_states.reshape(-1, value_states.size(-2), value_states.size(-1))
641
+
642
+ # TODO for now this is required to work with
643
+ # https://huggingface.co/kernels-community/metal-flash-sdpa/blob/main/torch-ext/metal_flash_sdpa/__init__.py
644
+ if "mps" in str(q.device):
645
+ cu_seq_lens_k = cu_seq_lens_k.clone()
646
+
647
+ out = flash_varlen_fn(
648
+ q,
649
+ k,
650
+ v,
651
+ cu_seqlens_q=cu_seq_lens_q,
652
+ cu_seqlens_k=cu_seq_lens_k,
653
+ max_seqlen_q=max_length_q,
654
+ max_seqlen_k=max_length_k,
655
+ **flash_kwargs,
656
+ )
657
+ if isinstance(out, tuple):
658
+ out = out[0]
659
+
660
+ out = out.view(query_states.size(0), -1, out.size(-2), out.size(-1))
661
+
662
+ # No padding
663
+ else:
664
+ out = flash_fn(query_states, key_states, value_states, **flash_kwargs)
665
+ if isinstance(out, tuple):
666
+ out = out[0]
667
+
668
+ return out
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flax_outputs.py ADDED
@@ -0,0 +1,700 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from typing import Optional
15
+
16
+ import flax
17
+ import jax.numpy as jnp
18
+
19
+ from .utils import ModelOutput
20
+
21
+
22
+ @flax.struct.dataclass
23
+ class FlaxBaseModelOutput(ModelOutput):
24
+ """
25
+ Base class for model's outputs, with potential hidden states and attentions.
26
+
27
+ Args:
28
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
29
+ Sequence of hidden-states at the output of the last layer of the model.
30
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
31
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
32
+ `(batch_size, sequence_length, hidden_size)`.
33
+
34
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
35
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
36
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
37
+ sequence_length)`.
38
+
39
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
40
+ heads.
41
+ """
42
+
43
+ last_hidden_state: Optional[jnp.ndarray] = None
44
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
45
+ attentions: Optional[tuple[jnp.ndarray]] = None
46
+
47
+
48
+ @flax.struct.dataclass
49
+ class FlaxBaseModelOutputWithNoAttention(ModelOutput):
50
+ """
51
+ Base class for model's outputs, with potential hidden states.
52
+
53
+ Args:
54
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, num_channels, height, width)`):
55
+ Sequence of hidden-states at the output of the last layer of the model.
56
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
57
+ Tuple of `jnp.ndarray` (one for the output of the embeddings, if the model has an embedding layer, + one
58
+ for the output of each layer) of shape `(batch_size, num_channels, height, width)`. Hidden-states of the
59
+ model at the output of each layer plus the optional initial embedding outputs.
60
+ """
61
+
62
+ last_hidden_state: Optional[jnp.ndarray] = None
63
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
64
+
65
+
66
+ @flax.struct.dataclass
67
+ class FlaxBaseModelOutputWithPoolingAndNoAttention(ModelOutput):
68
+ """
69
+ Base class for model's outputs that also contains a pooling of the last hidden states.
70
+
71
+ Args:
72
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, num_channels, height, width)`):
73
+ Sequence of hidden-states at the output of the last layer of the model.
74
+ pooler_output (`jnp.ndarray` of shape `(batch_size, hidden_size)`):
75
+ Last layer hidden-state after a pooling operation on the spatial dimensions.
76
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
77
+ Tuple of `jnp.ndarray` (one for the output of the embeddings, if the model has an embedding layer, + one
78
+ for the output of each layer) of shape `(batch_size, num_channels, height, width)`. Hidden-states of the
79
+ model at the output of each layer plus the optional initial embedding outputs.
80
+ """
81
+
82
+ last_hidden_state: Optional[jnp.ndarray] = None
83
+ pooler_output: Optional[jnp.ndarray] = None
84
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
85
+
86
+
87
+ @flax.struct.dataclass
88
+ class FlaxImageClassifierOutputWithNoAttention(ModelOutput):
89
+ """
90
+ Base class for outputs of image classification models.
91
+
92
+ Args:
93
+ logits (`jnp.ndarray` of shape `(batch_size, config.num_labels)`):
94
+ Classification (or regression if config.num_labels==1) scores (before SoftMax).
95
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when
96
+ `config.output_hidden_states=True`):
97
+ Tuple of `jnp.ndarray` (one for the output of the embeddings, if the model has an embedding layer, + one
98
+ for the output of each stage) of shape `(batch_size, num_channels, height, width)`. Hidden-states (also
99
+ called feature maps) of the model at the output of each stage.
100
+ """
101
+
102
+ logits: Optional[jnp.ndarray] = None
103
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
104
+
105
+
106
+ @flax.struct.dataclass
107
+ class FlaxBaseModelOutputWithPast(ModelOutput):
108
+ """
109
+ Base class for model's outputs, with potential hidden states and attentions.
110
+
111
+ Args:
112
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
113
+ Sequence of hidden-states at the output of the last layer of the model.
114
+ past_key_values (`dict[str, jnp.ndarray]`):
115
+ Dictionary of pre-computed hidden-states (key and values in the attention blocks) that can be used for fast
116
+ auto-regressive decoding. Pre-computed key and value hidden-states are of shape *[batch_size, max_length]*.
117
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
118
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
119
+ `(batch_size, sequence_length, hidden_size)`.
120
+
121
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
122
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
123
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
124
+ sequence_length)`.
125
+
126
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
127
+ heads.
128
+ """
129
+
130
+ last_hidden_state: Optional[jnp.ndarray] = None
131
+ past_key_values: Optional[dict[str, jnp.ndarray]] = None
132
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
133
+ attentions: Optional[tuple[jnp.ndarray]] = None
134
+
135
+
136
+ @flax.struct.dataclass
137
+ class FlaxBaseModelOutputWithPooling(ModelOutput):
138
+ """
139
+ Base class for model's outputs that also contains a pooling of the last hidden states.
140
+
141
+ Args:
142
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
143
+ Sequence of hidden-states at the output of the last layer of the model.
144
+ pooler_output (`jnp.ndarray` of shape `(batch_size, hidden_size)`):
145
+ Last layer hidden-state of the first token of the sequence (classification token) further processed by a
146
+ Linear layer and a Tanh activation function. The Linear layer weights are trained from the next sentence
147
+ prediction (classification) objective during pretraining.
148
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
149
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
150
+ `(batch_size, sequence_length, hidden_size)`.
151
+
152
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
153
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
154
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
155
+ sequence_length)`.
156
+
157
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
158
+ heads.
159
+ """
160
+
161
+ last_hidden_state: Optional[jnp.ndarray] = None
162
+ pooler_output: Optional[jnp.ndarray] = None
163
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
164
+ attentions: Optional[tuple[jnp.ndarray]] = None
165
+
166
+
167
+ @flax.struct.dataclass
168
+ class FlaxBaseModelOutputWithPoolingAndCrossAttentions(ModelOutput):
169
+ """
170
+ Base class for model's outputs that also contains a pooling of the last hidden states.
171
+
172
+ Args:
173
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
174
+ Sequence of hidden-states at the output of the last layer of the model.
175
+ pooler_output (`jnp.ndarray` of shape `(batch_size, hidden_size)`):
176
+ Last layer hidden-state of the first token of the sequence (classification token) after further processing
177
+ through the layers used for the auxiliary pretraining task. E.g. for BERT-family of models, this returns
178
+ the classification token after processing through a linear layer and a tanh activation function. The linear
179
+ layer weights are trained from the next sentence prediction (classification) objective during pretraining.
180
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
181
+ Tuple of `jnp.ndarray` (one for the output of the embeddings, if the model has an embedding layer, + one
182
+ for the output of each layer) of shape `(batch_size, sequence_length, hidden_size)`.
183
+
184
+ Hidden-states of the model at the output of each layer plus the optional initial embedding outputs.
185
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
186
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
187
+ sequence_length)`.
188
+
189
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
190
+ heads.
191
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` and `config.add_cross_attention=True` is passed or when `config.output_attentions=True`):
192
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
193
+ sequence_length)`.
194
+
195
+ Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the
196
+ weighted average in the cross-attention heads.
197
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
198
+ Tuple of `tuple(jnp.ndarray)` of length `config.n_layers`, with each tuple having 2 tensors of shape
199
+ `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and optionally if
200
+ `config.is_encoder_decoder=True` 2 additional tensors of shape `(batch_size, num_heads,
201
+ encoder_sequence_length, embed_size_per_head)`.
202
+
203
+ Contains pre-computed hidden-states (key and values in the self-attention blocks and optionally if
204
+ `config.is_encoder_decoder=True` in the cross-attention blocks) that can be used (see `past_key_values`
205
+ input) to speed up sequential decoding.
206
+ """
207
+
208
+ last_hidden_state: Optional[jnp.ndarray] = None
209
+ pooler_output: Optional[jnp.ndarray] = None
210
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
211
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
212
+ attentions: Optional[tuple[jnp.ndarray]] = None
213
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
214
+
215
+
216
+ @flax.struct.dataclass
217
+ class FlaxBaseModelOutputWithPastAndCrossAttentions(ModelOutput):
218
+ """
219
+ Base class for model's outputs that may also contain a past key/values (to speed up sequential decoding).
220
+
221
+ Args:
222
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
223
+ Sequence of hidden-states at the output of the last layer of the model.
224
+
225
+ If `past_key_values` is used only the last hidden-state of the sequences of shape `(batch_size, 1,
226
+ hidden_size)` is output.
227
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
228
+ Tuple of `tuple(jnp.ndarray)` of length `config.n_layers`, with each tuple having 2 tensors of shape
229
+ `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and optionally if
230
+ `config.is_encoder_decoder=True` 2 additional tensors of shape `(batch_size, num_heads,
231
+ encoder_sequence_length, embed_size_per_head)`.
232
+
233
+ Contains pre-computed hidden-states (key and values in the self-attention blocks and optionally if
234
+ `config.is_encoder_decoder=True` in the cross-attention blocks) that can be used (see `past_key_values`
235
+ input) to speed up sequential decoding.
236
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
237
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
238
+ `(batch_size, sequence_length, hidden_size)`.
239
+
240
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
241
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
242
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
243
+ sequence_length)`.
244
+
245
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
246
+ heads.
247
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` and `config.add_cross_attention=True` is passed or when `config.output_attentions=True`):
248
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
249
+ sequence_length)`.
250
+
251
+ Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the
252
+ weighted average in the cross-attention heads.
253
+ """
254
+
255
+ last_hidden_state: Optional[jnp.ndarray] = None
256
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
257
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
258
+ attentions: Optional[tuple[jnp.ndarray]] = None
259
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
260
+
261
+
262
+ @flax.struct.dataclass
263
+ class FlaxSeq2SeqModelOutput(ModelOutput):
264
+ """
265
+ Base class for model encoder's outputs that also contains : pre-computed hidden states that can speed up sequential
266
+ decoding.
267
+
268
+ Args:
269
+ last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`):
270
+ Sequence of hidden-states at the output of the last layer of the decoder of the model.
271
+
272
+ If `past_key_values` is used only the last hidden-state of the sequences of shape `(batch_size, 1,
273
+ hidden_size)` is output.
274
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
275
+ Tuple of `tuple(jnp.ndarray)` of length `config.n_layers`, with each tuple having 2 tensors of shape
276
+ `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
277
+ `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.
278
+
279
+ Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
280
+ blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.
281
+ decoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
282
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
283
+ `(batch_size, sequence_length, hidden_size)`.
284
+
285
+ Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.
286
+ decoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
287
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
288
+ sequence_length)`.
289
+
290
+ Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the
291
+ self-attention heads.
292
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
293
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
294
+ sequence_length)`.
295
+
296
+ Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the
297
+ weighted average in the cross-attention heads.
298
+ encoder_last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
299
+ Sequence of hidden-states at the output of the last layer of the encoder of the model.
300
+ encoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
301
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
302
+ `(batch_size, sequence_length, hidden_size)`.
303
+
304
+ Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.
305
+ encoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
306
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
307
+ sequence_length)`.
308
+
309
+ Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the
310
+ self-attention heads.
311
+ """
312
+
313
+ last_hidden_state: Optional[jnp.ndarray] = None
314
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
315
+ decoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
316
+ decoder_attentions: Optional[tuple[jnp.ndarray]] = None
317
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
318
+ encoder_last_hidden_state: Optional[jnp.ndarray] = None
319
+ encoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
320
+ encoder_attentions: Optional[tuple[jnp.ndarray]] = None
321
+
322
+
323
+ @flax.struct.dataclass
324
+ class FlaxCausalLMOutputWithCrossAttentions(ModelOutput):
325
+ """
326
+ Base class for causal language model (or autoregressive) outputs.
327
+
328
+ Args:
329
+ logits (`jnp.ndarray` of shape `(batch_size, sequence_length, config.vocab_size)`):
330
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
331
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
332
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
333
+ `(batch_size, sequence_length, hidden_size)`.
334
+
335
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
336
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
337
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
338
+ sequence_length)`.
339
+
340
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
341
+ heads.
342
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
343
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
344
+ sequence_length)`.
345
+
346
+ Cross attentions weights after the attention softmax, used to compute the weighted average in the
347
+ cross-attention heads.
348
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
349
+ Tuple of `jnp.ndarray` tuples of length `config.n_layers`, with each tuple containing the cached key, value
350
+ states of the self-attention and the cross-attention layers if model is used in encoder-decoder setting.
351
+ Only relevant if `config.is_decoder = True`.
352
+
353
+ Contains pre-computed hidden-states (key and values in the attention blocks) that can be used (see
354
+ `past_key_values` input) to speed up sequential decoding.
355
+ """
356
+
357
+ logits: Optional[jnp.ndarray] = None
358
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
359
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
360
+ attentions: Optional[tuple[jnp.ndarray]] = None
361
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
362
+
363
+
364
+ @flax.struct.dataclass
365
+ class FlaxMaskedLMOutput(ModelOutput):
366
+ """
367
+ Base class for masked language models outputs.
368
+
369
+ Args:
370
+ logits (`jnp.ndarray` of shape `(batch_size, sequence_length, config.vocab_size)`):
371
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
372
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
373
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
374
+ `(batch_size, sequence_length, hidden_size)`.
375
+
376
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
377
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
378
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
379
+ sequence_length)`.
380
+
381
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
382
+ heads.
383
+ """
384
+
385
+ logits: Optional[jnp.ndarray] = None
386
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
387
+ attentions: Optional[tuple[jnp.ndarray]] = None
388
+
389
+
390
+ FlaxCausalLMOutput = FlaxMaskedLMOutput
391
+
392
+
393
+ @flax.struct.dataclass
394
+ class FlaxSeq2SeqLMOutput(ModelOutput):
395
+ """
396
+ Base class for sequence-to-sequence language models outputs.
397
+
398
+ Args:
399
+ logits (`jnp.ndarray` of shape `(batch_size, sequence_length, config.vocab_size)`):
400
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
401
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
402
+ Tuple of `tuple(jnp.ndarray)` of length `config.n_layers`, with each tuple having 2 tensors of shape
403
+ `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
404
+ `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.
405
+
406
+ Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
407
+ blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.
408
+ decoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
409
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
410
+ `(batch_size, sequence_length, hidden_size)`.
411
+
412
+ Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.
413
+ decoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
414
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
415
+ sequence_length)`.
416
+
417
+ Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the
418
+ self-attention heads.
419
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
420
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
421
+ sequence_length)`.
422
+
423
+ Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the
424
+ weighted average in the cross-attention heads.
425
+ encoder_last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
426
+ Sequence of hidden-states at the output of the last layer of the encoder of the model.
427
+ encoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
428
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
429
+ `(batch_size, sequence_length, hidden_size)`.
430
+
431
+ Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.
432
+ encoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
433
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
434
+ sequence_length)`.
435
+
436
+ Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the
437
+ self-attention heads.
438
+ """
439
+
440
+ logits: Optional[jnp.ndarray] = None
441
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
442
+ decoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
443
+ decoder_attentions: Optional[tuple[jnp.ndarray]] = None
444
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
445
+ encoder_last_hidden_state: Optional[jnp.ndarray] = None
446
+ encoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
447
+ encoder_attentions: Optional[tuple[jnp.ndarray]] = None
448
+
449
+
450
+ @flax.struct.dataclass
451
+ class FlaxNextSentencePredictorOutput(ModelOutput):
452
+ """
453
+ Base class for outputs of models predicting if two sentences are consecutive or not.
454
+
455
+ Args:
456
+ logits (`jnp.ndarray` of shape `(batch_size, 2)`):
457
+ Prediction scores of the next sequence prediction (classification) head (scores of True/False continuation
458
+ before SoftMax).
459
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
460
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
461
+ `(batch_size, sequence_length, hidden_size)`.
462
+
463
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
464
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
465
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
466
+ sequence_length)`.
467
+
468
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
469
+ heads.
470
+ """
471
+
472
+ logits: Optional[jnp.ndarray] = None
473
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
474
+ attentions: Optional[tuple[jnp.ndarray]] = None
475
+
476
+
477
+ @flax.struct.dataclass
478
+ class FlaxSequenceClassifierOutput(ModelOutput):
479
+ """
480
+ Base class for outputs of sentence classification models.
481
+
482
+ Args:
483
+ logits (`jnp.ndarray` of shape `(batch_size, config.num_labels)`):
484
+ Classification (or regression if config.num_labels==1) scores (before SoftMax).
485
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
486
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
487
+ `(batch_size, sequence_length, hidden_size)`.
488
+
489
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
490
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
491
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
492
+ sequence_length)`.
493
+
494
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
495
+ heads.
496
+ """
497
+
498
+ logits: Optional[jnp.ndarray] = None
499
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
500
+ attentions: Optional[tuple[jnp.ndarray]] = None
501
+
502
+
503
+ @flax.struct.dataclass
504
+ class FlaxSeq2SeqSequenceClassifierOutput(ModelOutput):
505
+ """
506
+ Base class for outputs of sequence-to-sequence sentence classification models.
507
+
508
+ Args:
509
+ logits (`jnp.ndarray` of shape `(batch_size, config.num_labels)`):
510
+ Classification (or regression if config.num_labels==1) scores (before SoftMax).
511
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
512
+ Tuple of `tuple(jnp.ndarray)` of length `config.n_layers`, with each tuple having 2 tensors of shape
513
+ `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
514
+ `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.
515
+
516
+ Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
517
+ blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.
518
+ decoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
519
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
520
+ `(batch_size, sequence_length, hidden_size)`.
521
+
522
+ Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.
523
+ decoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
524
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
525
+ sequence_length)`.
526
+
527
+ Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the
528
+ self-attention heads.
529
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
530
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
531
+ sequence_length)`.
532
+
533
+ Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the
534
+ weighted average in the cross-attention heads.
535
+ encoder_last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
536
+ Sequence of hidden-states at the output of the last layer of the encoder of the model.
537
+ encoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
538
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
539
+ `(batch_size, sequence_length, hidden_size)`.
540
+
541
+ Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.
542
+ encoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
543
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
544
+ sequence_length)`.
545
+
546
+ Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the
547
+ self-attention heads.
548
+ """
549
+
550
+ logits: Optional[jnp.ndarray] = None
551
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
552
+ decoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
553
+ decoder_attentions: Optional[tuple[jnp.ndarray]] = None
554
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
555
+ encoder_last_hidden_state: Optional[jnp.ndarray] = None
556
+ encoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
557
+ encoder_attentions: Optional[tuple[jnp.ndarray]] = None
558
+
559
+
560
+ @flax.struct.dataclass
561
+ class FlaxMultipleChoiceModelOutput(ModelOutput):
562
+ """
563
+ Base class for outputs of multiple choice models.
564
+
565
+ Args:
566
+ logits (`jnp.ndarray` of shape `(batch_size, num_choices)`):
567
+ *num_choices* is the second dimension of the input tensors. (see *input_ids* above).
568
+
569
+ Classification scores (before SoftMax).
570
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
571
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
572
+ `(batch_size, sequence_length, hidden_size)`.
573
+
574
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
575
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
576
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
577
+ sequence_length)`.
578
+
579
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
580
+ heads.
581
+ """
582
+
583
+ logits: Optional[jnp.ndarray] = None
584
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
585
+ attentions: Optional[tuple[jnp.ndarray]] = None
586
+
587
+
588
+ @flax.struct.dataclass
589
+ class FlaxTokenClassifierOutput(ModelOutput):
590
+ """
591
+ Base class for outputs of token classification models.
592
+
593
+ Args:
594
+ logits (`jnp.ndarray` of shape `(batch_size, sequence_length, config.num_labels)`):
595
+ Classification scores (before SoftMax).
596
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
597
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
598
+ `(batch_size, sequence_length, hidden_size)`.
599
+
600
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
601
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
602
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
603
+ sequence_length)`.
604
+
605
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
606
+ heads.
607
+ """
608
+
609
+ logits: Optional[jnp.ndarray] = None
610
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
611
+ attentions: Optional[tuple[jnp.ndarray]] = None
612
+
613
+
614
+ @flax.struct.dataclass
615
+ class FlaxQuestionAnsweringModelOutput(ModelOutput):
616
+ """
617
+ Base class for outputs of question answering models.
618
+
619
+ Args:
620
+ start_logits (`jnp.ndarray` of shape `(batch_size, sequence_length)`):
621
+ Span-start scores (before SoftMax).
622
+ end_logits (`jnp.ndarray` of shape `(batch_size, sequence_length)`):
623
+ Span-end scores (before SoftMax).
624
+ hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
625
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
626
+ `(batch_size, sequence_length, hidden_size)`.
627
+
628
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
629
+ attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
630
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
631
+ sequence_length)`.
632
+
633
+ Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
634
+ heads.
635
+ """
636
+
637
+ start_logits: Optional[jnp.ndarray] = None
638
+ end_logits: Optional[jnp.ndarray] = None
639
+ hidden_states: Optional[tuple[jnp.ndarray]] = None
640
+ attentions: Optional[tuple[jnp.ndarray]] = None
641
+
642
+
643
+ @flax.struct.dataclass
644
+ class FlaxSeq2SeqQuestionAnsweringModelOutput(ModelOutput):
645
+ """
646
+ Base class for outputs of sequence-to-sequence question answering models.
647
+
648
+ Args:
649
+ start_logits (`jnp.ndarray` of shape `(batch_size, sequence_length)`):
650
+ Span-start scores (before SoftMax).
651
+ end_logits (`jnp.ndarray` of shape `(batch_size, sequence_length)`):
652
+ Span-end scores (before SoftMax).
653
+ past_key_values (`tuple(tuple(jnp.ndarray))`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
654
+ Tuple of `tuple(jnp.ndarray)` of length `config.n_layers`, with each tuple having 2 tensors of shape
655
+ `(batch_size, num_heads, sequence_length, embed_size_per_head)`) and 2 additional tensors of shape
656
+ `(batch_size, num_heads, encoder_sequence_length, embed_size_per_head)`.
657
+
658
+ Contains pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
659
+ blocks) that can be used (see `past_key_values` input) to speed up sequential decoding.
660
+ decoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
661
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
662
+ `(batch_size, sequence_length, hidden_size)`.
663
+
664
+ Hidden-states of the decoder at the output of each layer plus the initial embedding outputs.
665
+ decoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
666
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
667
+ sequence_length)`.
668
+
669
+ Attentions weights of the decoder, after the attention softmax, used to compute the weighted average in the
670
+ self-attention heads.
671
+ cross_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
672
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
673
+ sequence_length)`.
674
+
675
+ Attentions weights of the decoder's cross-attention layer, after the attention softmax, used to compute the
676
+ weighted average in the cross-attention heads.
677
+ encoder_last_hidden_state (`jnp.ndarray` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
678
+ Sequence of hidden-states at the output of the last layer of the encoder of the model.
679
+ encoder_hidden_states (`tuple(jnp.ndarray)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
680
+ Tuple of `jnp.ndarray` (one for the output of the embeddings + one for the output of each layer) of shape
681
+ `(batch_size, sequence_length, hidden_size)`.
682
+
683
+ Hidden-states of the encoder at the output of each layer plus the initial embedding outputs.
684
+ encoder_attentions (`tuple(jnp.ndarray)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
685
+ Tuple of `jnp.ndarray` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
686
+ sequence_length)`.
687
+
688
+ Attentions weights of the encoder, after the attention softmax, used to compute the weighted average in the
689
+ self-attention heads.
690
+ """
691
+
692
+ start_logits: Optional[jnp.ndarray] = None
693
+ end_logits: Optional[jnp.ndarray] = None
694
+ past_key_values: Optional[tuple[tuple[jnp.ndarray]]] = None
695
+ decoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
696
+ decoder_attentions: Optional[tuple[jnp.ndarray]] = None
697
+ cross_attentions: Optional[tuple[jnp.ndarray]] = None
698
+ encoder_last_hidden_state: Optional[jnp.ndarray] = None
699
+ encoder_hidden_states: Optional[tuple[jnp.ndarray]] = None
700
+ encoder_attentions: Optional[tuple[jnp.ndarray]] = None
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_flax_utils.py ADDED
@@ -0,0 +1,1274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2021 The Google Flax Team Authors and The HuggingFace Inc. team.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+
17
+ import gc
18
+ import json
19
+ import os
20
+ import warnings
21
+ from functools import partial
22
+ from pickle import UnpicklingError
23
+ from typing import Any, Optional, Union
24
+
25
+ import flax.linen as nn
26
+ import jax
27
+ import jax.numpy as jnp
28
+ import msgpack.exceptions
29
+ from flax.core.frozen_dict import FrozenDict, unfreeze
30
+ from flax.serialization import from_bytes, to_bytes
31
+ from flax.traverse_util import flatten_dict, unflatten_dict
32
+ from jax.random import PRNGKey
33
+
34
+ from .configuration_utils import PretrainedConfig
35
+ from .dynamic_module_utils import custom_object_save
36
+ from .generation import FlaxGenerationMixin, GenerationConfig
37
+ from .modeling_flax_pytorch_utils import load_pytorch_checkpoint_in_flax_state_dict
38
+ from .utils import (
39
+ FLAX_WEIGHTS_INDEX_NAME,
40
+ FLAX_WEIGHTS_NAME,
41
+ SAFE_WEIGHTS_INDEX_NAME,
42
+ SAFE_WEIGHTS_NAME,
43
+ WEIGHTS_INDEX_NAME,
44
+ WEIGHTS_NAME,
45
+ PushToHubMixin,
46
+ add_code_sample_docstrings,
47
+ add_start_docstrings_to_model_forward,
48
+ cached_file,
49
+ copy_func,
50
+ download_url,
51
+ has_file,
52
+ is_offline_mode,
53
+ is_remote_url,
54
+ logging,
55
+ replace_return_docstrings,
56
+ )
57
+ from .utils.hub import convert_file_size_to_int, get_checkpoint_shard_files
58
+ from .utils.import_utils import is_safetensors_available
59
+
60
+
61
+ if is_safetensors_available():
62
+ from safetensors import safe_open
63
+ from safetensors.flax import load_file as safe_load_file
64
+ from safetensors.flax import save_file as safe_save_file
65
+
66
+ logger = logging.get_logger(__name__)
67
+
68
+
69
+ def quick_gelu(x):
70
+ return x * jax.nn.sigmoid(1.702 * x)
71
+
72
+
73
+ ACT2FN = {
74
+ "gelu": partial(nn.gelu, approximate=False),
75
+ "relu": nn.relu,
76
+ "silu": nn.swish,
77
+ "swish": nn.swish,
78
+ "gelu_new": partial(nn.gelu, approximate=True),
79
+ "quick_gelu": quick_gelu,
80
+ "gelu_pytorch_tanh": partial(nn.gelu, approximate=True),
81
+ "tanh": nn.tanh,
82
+ }
83
+
84
+
85
+ def flax_shard_checkpoint(params, max_shard_size="10GB"):
86
+ """
87
+ Splits a model state dictionary in sub-checkpoints so that the final size of each sub-checkpoint does not exceed a
88
+ given size. The sub-checkpoints are determined by iterating through the `state_dict` in the order of its keys, so
89
+ there is no optimization made to make each sub-checkpoint as close as possible to the maximum size passed. For
90
+ example, if the limit is 10GB and we have weights of sizes [6GB, 6GB, 2GB, 6GB, 2GB, 2GB] they will get sharded as
91
+ [6GB], [6+2GB], [6+2+2GB] and not [6+2+2GB], [6+2GB], [6GB].
92
+
93
+ <Tip warning={true}>
94
+
95
+ If one of the model's weight is bigger that `max_shard_size`, it will end up in its own sub-checkpoint which will
96
+ have a size greater than `max_shard_size`.
97
+
98
+ </Tip>
99
+
100
+ Args:
101
+ params (`Union[Dict, FrozenDict]`): A `PyTree` of model parameters.
102
+ max_shard_size (`int` or `str`, *optional*, defaults to `"10GB"`):
103
+ The maximum size of each sub-checkpoint. If expressed as a string, needs to be digits followed by a unit
104
+ (like `"5MB"`).
105
+ """
106
+ max_shard_size = convert_file_size_to_int(max_shard_size)
107
+
108
+ sharded_state_dicts = []
109
+ current_block = {}
110
+ current_block_size = 0
111
+ total_size = 0
112
+
113
+ # flatten the weights to chunk
114
+ weights = flatten_dict(params, sep="/")
115
+ for item in weights:
116
+ weight_size = weights[item].size * weights[item].dtype.itemsize
117
+
118
+ # If this weight is going to tip up over the maximal size, we split.
119
+ if current_block_size + weight_size > max_shard_size:
120
+ sharded_state_dicts.append(current_block)
121
+ current_block = {}
122
+ current_block_size = 0
123
+
124
+ current_block[item] = weights[item]
125
+ current_block_size += weight_size
126
+ total_size += weight_size
127
+
128
+ # Add the last block
129
+ sharded_state_dicts.append(current_block)
130
+
131
+ # If we only have one shard, we return it
132
+ if len(sharded_state_dicts) == 1:
133
+ return {FLAX_WEIGHTS_NAME: sharded_state_dicts[0]}, None
134
+
135
+ # Otherwise, let's build the index
136
+ weight_map = {}
137
+ shards = {}
138
+ for idx, shard in enumerate(sharded_state_dicts):
139
+ shard_file = FLAX_WEIGHTS_NAME.replace(".msgpack", f"-{idx + 1:05d}-of-{len(sharded_state_dicts):05d}.msgpack")
140
+ shards[shard_file] = shard
141
+ for weight_name in shard:
142
+ weight_map[weight_name] = shard_file
143
+
144
+ # Add the metadata
145
+ metadata = {"total_size": total_size}
146
+ index = {"metadata": metadata, "weight_map": weight_map}
147
+ return shards, index
148
+
149
+
150
+ class FlaxPreTrainedModel(PushToHubMixin, FlaxGenerationMixin):
151
+ r"""
152
+ Base class for all models.
153
+
154
+ [`FlaxPreTrainedModel`] takes care of storing the configuration of the models and handles methods for loading,
155
+ downloading and saving models.
156
+
157
+ Class attributes (overridden by derived classes):
158
+
159
+ - **config_class** ([`PretrainedConfig`]) -- A subclass of [`PretrainedConfig`] to use as configuration class
160
+ for this model architecture.
161
+ - **base_model_prefix** (`str`) -- A string indicating the attribute associated to the base model in derived
162
+ classes of the same architecture adding modules on top of the base model.
163
+ - **main_input_name** (`str`) -- The name of the principal input to the model (often `input_ids` for NLP
164
+ models, `pixel_values` for vision models and `input_values` for speech models).
165
+ """
166
+
167
+ config_class = None
168
+ base_model_prefix = ""
169
+ main_input_name = "input_ids"
170
+ _auto_class = None
171
+ _missing_keys = set()
172
+
173
+ def __init__(
174
+ self,
175
+ config: PretrainedConfig,
176
+ module: nn.Module,
177
+ input_shape: tuple = (1, 1),
178
+ seed: int = 0,
179
+ dtype: jnp.dtype = jnp.float32,
180
+ _do_init: bool = True,
181
+ ):
182
+ logger.warning_once(
183
+ "TensorFlow and JAX classes are deprecated and will be removed in Transformers v5. We "
184
+ "recommend migrating to PyTorch classes or pinning your version of Transformers."
185
+ )
186
+ if config is None:
187
+ raise ValueError("config cannot be None")
188
+
189
+ if module is None:
190
+ raise ValueError("module cannot be None")
191
+
192
+ # Those are private to be exposed as typed property on derived classes.
193
+ self._config = config
194
+ self._module = module
195
+
196
+ # Those are public as their type is generic to every derived classes.
197
+ self.key = PRNGKey(seed)
198
+ self.dtype = dtype
199
+ self.input_shape = input_shape
200
+ self.generation_config = GenerationConfig.from_model_config(config) if self.can_generate() else None
201
+
202
+ # To check if the model was initialized automatically.
203
+ self._is_initialized = _do_init
204
+
205
+ if _do_init:
206
+ # randomly initialized parameters
207
+ random_params = self.init_weights(self.key, input_shape)
208
+ params_shape_tree = jax.eval_shape(lambda params: params, random_params)
209
+ else:
210
+ init_fn = partial(self.init_weights, input_shape=input_shape)
211
+ params_shape_tree = jax.eval_shape(init_fn, self.key)
212
+
213
+ logger.info(
214
+ "Model weights are not initialized as `_do_init` is set to `False`. "
215
+ f"Make sure to call `{self.__class__.__name__}.init_weights` manually to initialize the weights."
216
+ )
217
+
218
+ # get the shape of the parameters
219
+ self._params_shape_tree = params_shape_tree
220
+
221
+ # save required_params as set
222
+ self._required_params = set(flatten_dict(unfreeze(params_shape_tree)).keys())
223
+
224
+ # initialize the parameters
225
+ if _do_init:
226
+ self.params = random_params
227
+
228
+ def init_weights(self, rng: jax.random.PRNGKey, input_shape: tuple, params: FrozenDict = None) -> dict:
229
+ raise NotImplementedError(f"init method has to be implemented for {self}")
230
+
231
+ def enable_gradient_checkpointing(self):
232
+ raise NotImplementedError(f"gradient checkpointing method has to be implemented for {self}")
233
+
234
+ @classmethod
235
+ def _from_config(cls, config, **kwargs):
236
+ """
237
+ All context managers that the model should be initialized under go here.
238
+ """
239
+ return cls(config, **kwargs)
240
+
241
+ @property
242
+ def framework(self) -> str:
243
+ """
244
+ :str: Identifies that this is a Flax model.
245
+ """
246
+ return "flax"
247
+
248
+ @property
249
+ def config(self) -> PretrainedConfig:
250
+ return self._config
251
+
252
+ @property
253
+ def module(self) -> nn.Module:
254
+ return self._module
255
+
256
+ @property
257
+ def params(self) -> Union[dict, FrozenDict]:
258
+ if not self._is_initialized:
259
+ raise ValueError(
260
+ "`params` cannot be accessed from model when the model is created with `_do_init=False`. "
261
+ "You must call `init_weights` manually and store the params outside of the model and "
262
+ "pass it explicitly where needed."
263
+ )
264
+ return self._params
265
+
266
+ @property
267
+ def required_params(self) -> set:
268
+ return self._required_params
269
+
270
+ @property
271
+ def params_shape_tree(self) -> dict:
272
+ return self._params_shape_tree
273
+
274
+ @params.setter
275
+ def params(self, params: Union[dict, FrozenDict]):
276
+ # don't set params if the model is not initialized
277
+ if not self._is_initialized:
278
+ raise ValueError(
279
+ "`params` cannot be set from model when the model is created with `_do_init=False`. "
280
+ "You store the params outside of the model."
281
+ )
282
+
283
+ if isinstance(params, FrozenDict):
284
+ params = unfreeze(params)
285
+ param_keys = set(flatten_dict(params).keys())
286
+ if len(self.required_params - param_keys) > 0:
287
+ raise ValueError(
288
+ "Some parameters are missing. Make sure that `params` include the following "
289
+ f"parameters {self.required_params - param_keys}"
290
+ )
291
+ self._params = params
292
+
293
+ def _cast_floating_to(self, params: Union[dict, FrozenDict], dtype: jnp.dtype, mask: Any = None) -> Any:
294
+ """
295
+ Helper method to cast floating-point values of given parameter `PyTree` to given `dtype`.
296
+ """
297
+
298
+ # taken from https://github.com/deepmind/jmp/blob/3a8318abc3292be38582794dbf7b094e6583b192/jmp/_src/policy.py#L27
299
+ def conditional_cast(param):
300
+ if isinstance(param, jnp.ndarray) and jnp.issubdtype(param.dtype, jnp.floating):
301
+ param = param.astype(dtype)
302
+ return param
303
+
304
+ if mask is None:
305
+ return jax.tree_util.tree_map(conditional_cast, params)
306
+
307
+ flat_params = flatten_dict(params)
308
+ flat_mask, _ = jax.tree_util.tree_flatten(mask)
309
+
310
+ for masked, key in zip(flat_mask, sorted(flat_params.keys())):
311
+ if masked:
312
+ flat_params[key] = conditional_cast(flat_params[key])
313
+
314
+ return unflatten_dict(flat_params)
315
+
316
+ def to_bf16(self, params: Union[dict, FrozenDict], mask: Any = None):
317
+ r"""
318
+ Cast the floating-point `params` to `jax.numpy.bfloat16`. This returns a new `params` tree and does not cast
319
+ the `params` in place.
320
+
321
+ This method can be used on TPU to explicitly convert the model parameters to bfloat16 precision to do full
322
+ half-precision training or to save weights in bfloat16 for inference in order to save memory and improve speed.
323
+
324
+ Arguments:
325
+ params (`Union[Dict, FrozenDict]`):
326
+ A `PyTree` of model parameters.
327
+ mask (`Union[Dict, FrozenDict]`):
328
+ A `PyTree` with same structure as the `params` tree. The leaves should be booleans, `True` for params
329
+ you want to cast, and should be `False` for those you want to skip.
330
+
331
+ Examples:
332
+
333
+ ```python
334
+ >>> from transformers import FlaxBertModel
335
+
336
+ >>> # load model
337
+ >>> model = FlaxBertModel.from_pretrained("google-bert/bert-base-cased")
338
+ >>> # By default, the model parameters will be in fp32 precision, to cast these to bfloat16 precision
339
+ >>> model.params = model.to_bf16(model.params)
340
+ >>> # If you want don't want to cast certain parameters (for example layer norm bias and scale)
341
+ >>> # then pass the mask as follows
342
+ >>> from flax import traverse_util
343
+
344
+ >>> model = FlaxBertModel.from_pretrained("google-bert/bert-base-cased")
345
+ >>> flat_params = traverse_util.flatten_dict(model.params)
346
+ >>> mask = {
347
+ ... path: (path[-2] != ("LayerNorm", "bias") and path[-2:] != ("LayerNorm", "scale"))
348
+ ... for path in flat_params
349
+ ... }
350
+ >>> mask = traverse_util.unflatten_dict(mask)
351
+ >>> model.params = model.to_bf16(model.params, mask)
352
+ ```"""
353
+ return self._cast_floating_to(params, jnp.bfloat16, mask)
354
+
355
+ def to_fp32(self, params: Union[dict, FrozenDict], mask: Any = None):
356
+ r"""
357
+ Cast the floating-point `params` to `jax.numpy.float32`. This method can be used to explicitly convert the
358
+ model parameters to fp32 precision. This returns a new `params` tree and does not cast the `params` in place.
359
+
360
+ Arguments:
361
+ params (`Union[Dict, FrozenDict]`):
362
+ A `PyTree` of model parameters.
363
+ mask (`Union[Dict, FrozenDict]`):
364
+ A `PyTree` with same structure as the `params` tree. The leaves should be booleans, `True` for params
365
+ you want to cast, and should be `False` for those you want to skip
366
+
367
+ Examples:
368
+
369
+ ```python
370
+ >>> from transformers import FlaxBertModel
371
+
372
+ >>> # Download model and configuration from huggingface.co
373
+ >>> model = FlaxBertModel.from_pretrained("google-bert/bert-base-cased")
374
+ >>> # By default, the model params will be in fp32, to illustrate the use of this method,
375
+ >>> # we'll first cast to fp16 and back to fp32
376
+ >>> model.params = model.to_f16(model.params)
377
+ >>> # now cast back to fp32
378
+ >>> model.params = model.to_fp32(model.params)
379
+ ```"""
380
+ return self._cast_floating_to(params, jnp.float32, mask)
381
+
382
+ def to_fp16(self, params: Union[dict, FrozenDict], mask: Any = None):
383
+ r"""
384
+ Cast the floating-point `params` to `jax.numpy.float16`. This returns a new `params` tree and does not cast the
385
+ `params` in place.
386
+
387
+ This method can be used on GPU to explicitly convert the model parameters to float16 precision to do full
388
+ half-precision training or to save weights in float16 for inference in order to save memory and improve speed.
389
+
390
+ Arguments:
391
+ params (`Union[Dict, FrozenDict]`):
392
+ A `PyTree` of model parameters.
393
+ mask (`Union[Dict, FrozenDict]`):
394
+ A `PyTree` with same structure as the `params` tree. The leaves should be booleans, `True` for params
395
+ you want to cast, and should be `False` for those you want to skip
396
+
397
+ Examples:
398
+
399
+ ```python
400
+ >>> from transformers import FlaxBertModel
401
+
402
+ >>> # load model
403
+ >>> model = FlaxBertModel.from_pretrained("google-bert/bert-base-cased")
404
+ >>> # By default, the model params will be in fp32, to cast these to float16
405
+ >>> model.params = model.to_fp16(model.params)
406
+ >>> # If you want don't want to cast certain parameters (for example layer norm bias and scale)
407
+ >>> # then pass the mask as follows
408
+ >>> from flax import traverse_util
409
+
410
+ >>> model = FlaxBertModel.from_pretrained("google-bert/bert-base-cased")
411
+ >>> flat_params = traverse_util.flatten_dict(model.params)
412
+ >>> mask = {
413
+ ... path: (path[-2] != ("LayerNorm", "bias") and path[-2:] != ("LayerNorm", "scale"))
414
+ ... for path in flat_params
415
+ ... }
416
+ >>> mask = traverse_util.unflatten_dict(mask)
417
+ >>> model.params = model.to_fp16(model.params, mask)
418
+ ```"""
419
+ return self._cast_floating_to(params, jnp.float16, mask)
420
+
421
+ @classmethod
422
+ def load_flax_weights(cls, resolved_archive_file):
423
+ try:
424
+ if resolved_archive_file.endswith(".safetensors"):
425
+ state = safe_load_file(resolved_archive_file)
426
+ state = unflatten_dict(state, sep=".")
427
+ else:
428
+ with open(resolved_archive_file, "rb") as state_f:
429
+ state = from_bytes(cls, state_f.read())
430
+ except (UnpicklingError, msgpack.exceptions.ExtraData) as e:
431
+ try:
432
+ with open(resolved_archive_file) as f:
433
+ if f.read().startswith("version"):
434
+ raise OSError(
435
+ "You seem to have cloned a repository without having git-lfs installed. Please"
436
+ " install git-lfs and run `git lfs install` followed by `git lfs pull` in the"
437
+ " folder you cloned."
438
+ )
439
+ else:
440
+ raise ValueError from e
441
+ except (UnicodeDecodeError, ValueError):
442
+ raise OSError(f"Unable to convert {resolved_archive_file} to Flax deserializable object. ")
443
+
444
+ return state
445
+
446
+ @classmethod
447
+ def load_flax_sharded_weights(cls, shard_files):
448
+ """
449
+ This is the same as [`flax.serialization.from_bytes`]
450
+ (https:lax.readthedocs.io/en/latest/_modules/flax/serialization.html#from_bytes) but for a sharded checkpoint.
451
+
452
+ This load is performed efficiently: each checkpoint shard is loaded one by one in RAM and deleted after being
453
+ loaded in the model.
454
+
455
+ Args:
456
+ shard_files (`list[str]`:
457
+ The list of shard files to load.
458
+
459
+ Returns:
460
+ `Dict`: A nested dictionary of the model parameters, in the expected format for flax models : `{'model':
461
+ {'params': {'...'}}}`.
462
+ """
463
+
464
+ # Load the index
465
+ state_sharded_dict = {}
466
+
467
+ for shard_file in shard_files:
468
+ # load using msgpack utils
469
+ try:
470
+ with open(shard_file, "rb") as state_f:
471
+ state = from_bytes(cls, state_f.read())
472
+ except (UnpicklingError, msgpack.exceptions.ExtraData) as e:
473
+ with open(shard_file) as f:
474
+ if f.read().startswith("version"):
475
+ raise OSError(
476
+ "You seem to have cloned a repository without having git-lfs installed. Please"
477
+ " install git-lfs and run `git lfs install` followed by `git lfs pull` in the"
478
+ " folder you cloned."
479
+ )
480
+ else:
481
+ raise ValueError from e
482
+ except (UnicodeDecodeError, ValueError):
483
+ raise OSError(f"Unable to convert {shard_file} to Flax deserializable object. ")
484
+
485
+ state = flatten_dict(state, sep="/")
486
+ state_sharded_dict.update(state)
487
+ del state
488
+ gc.collect()
489
+
490
+ # the state dict is unflattened to the match the format of model.params
491
+ return unflatten_dict(state_sharded_dict, sep="/")
492
+
493
+ @classmethod
494
+ def can_generate(cls) -> bool:
495
+ """
496
+ Returns whether this model can generate sequences with `.generate()`. Returns:
497
+ `bool`: Whether this model can generate sequences with `.generate()`.
498
+ """
499
+ # Detects whether `prepare_inputs_for_generation` has been overwritten, which is a requirement for generation.
500
+ # Alternatively, the model can also have a custom `generate` function.
501
+ if "GenerationMixin" in str(cls.prepare_inputs_for_generation) and "GenerationMixin" in str(cls.generate):
502
+ return False
503
+ return True
504
+
505
+ @classmethod
506
+ def from_pretrained(
507
+ cls,
508
+ pretrained_model_name_or_path: Union[str, os.PathLike],
509
+ dtype: jnp.dtype = jnp.float32,
510
+ *model_args,
511
+ config: Optional[Union[PretrainedConfig, str, os.PathLike]] = None,
512
+ cache_dir: Optional[Union[str, os.PathLike]] = None,
513
+ ignore_mismatched_sizes: bool = False,
514
+ force_download: bool = False,
515
+ local_files_only: bool = False,
516
+ token: Optional[Union[str, bool]] = None,
517
+ revision: str = "main",
518
+ **kwargs,
519
+ ):
520
+ r"""
521
+ Instantiate a pretrained flax model from a pre-trained model configuration.
522
+
523
+ The warning *Weights from XXX not initialized from pretrained model* means that the weights of XXX do not come
524
+ pretrained with the rest of the model. It is up to you to train those weights with a downstream fine-tuning
525
+ task.
526
+
527
+ The warning *Weights from XXX not used in YYY* means that the layer XXX is not used by YYY, therefore those
528
+ weights are discarded.
529
+
530
+ Parameters:
531
+ pretrained_model_name_or_path (`str` or `os.PathLike`):
532
+ Can be either:
533
+
534
+ - A string, the *model id* of a pretrained model hosted inside a model repo on huggingface.co.
535
+ - A path to a *directory* containing model weights saved using
536
+ [`~FlaxPreTrainedModel.save_pretrained`], e.g., `./my_model_directory/`.
537
+ - A path or url to a *pt index checkpoint file* (e.g, `./tf_model/model.ckpt.index`). In this case,
538
+ `from_pt` should be set to `True`.
539
+ dtype (`jax.numpy.dtype`, *optional*, defaults to `jax.numpy.float32`):
540
+ The data type of the computation. Can be one of `jax.numpy.float32`, `jax.numpy.float16` (on GPUs) and
541
+ `jax.numpy.bfloat16` (on TPUs).
542
+
543
+ This can be used to enable mixed-precision training or half-precision inference on GPUs or TPUs. If
544
+ specified all the computation will be performed with the given `dtype`.
545
+
546
+ **Note that this only specifies the dtype of the computation and does not influence the dtype of model
547
+ parameters.**
548
+
549
+ If you wish to change the dtype of the model parameters, see [`~FlaxPreTrainedModel.to_fp16`] and
550
+ [`~FlaxPreTrainedModel.to_bf16`].
551
+ model_args (sequence of positional arguments, *optional*):
552
+ All remaining positional arguments will be passed to the underlying model's `__init__` method.
553
+ config (`Union[PretrainedConfig, str, os.PathLike]`, *optional*):
554
+ Can be either:
555
+
556
+ - an instance of a class derived from [`PretrainedConfig`],
557
+ - a string or path valid as input to [`~PretrainedConfig.from_pretrained`].
558
+
559
+ Configuration for the model to use instead of an automatically loaded configuration. Configuration can
560
+ be automatically loaded when:
561
+
562
+ - The model is a model provided by the library (loaded with the *model id* string of a pretrained
563
+ model).
564
+ - The model was saved using [`~PreTrainedModel.save_pretrained`] and is reloaded by supplying the
565
+ save directory.
566
+ - The model is loaded by supplying a local directory as `pretrained_model_name_or_path` and a
567
+ configuration JSON file named *config.json* is found in the directory.
568
+ cache_dir (`Union[str, os.PathLike]`, *optional*):
569
+ Path to a directory in which a downloaded pretrained model configuration should be cached if the
570
+ standard cache should not be used.
571
+ from_pt (`bool`, *optional*, defaults to `False`):
572
+ Load the model weights from a PyTorch checkpoint save file (see docstring of
573
+ `pretrained_model_name_or_path` argument).
574
+ ignore_mismatched_sizes (`bool`, *optional*, defaults to `False`):
575
+ Whether or not to raise an error if some of the weights from the checkpoint do not have the same size
576
+ as the weights of the model (if for instance, you are instantiating a model with 10 labels from a
577
+ checkpoint with 3 labels).
578
+ force_download (`bool`, *optional*, defaults to `False`):
579
+ Whether or not to force the (re-)download of the model weights and configuration files, overriding the
580
+ cached versions if they exist.
581
+ resume_download:
582
+ Deprecated and ignored. All downloads are now resumed by default when possible.
583
+ Will be removed in v5 of Transformers.
584
+ proxies (`dict[str, str]`, *optional*):
585
+ A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
586
+ 'http://hostname': 'foo.bar:4012'}`. The proxies are used on each request.
587
+ local_files_only(`bool`, *optional*, defaults to `False`):
588
+ Whether or not to only look at local files (i.e., do not try to download the model).
589
+ token (`str` or `bool`, *optional*):
590
+ The token to use as HTTP bearer authorization for remote files. If `True`, or not specified, will use
591
+ the token generated when running `hf auth login` (stored in `~/.huggingface`).
592
+ revision (`str`, *optional*, defaults to `"main"`):
593
+ The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a
594
+ git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any
595
+ identifier allowed by git.
596
+
597
+
598
+ <Tip>
599
+
600
+ To test a pull request you made on the Hub, you can pass `revision="refs/pr/<pr_number>"`.
601
+
602
+ </Tip>
603
+
604
+ subfolder (`str`, *optional*, defaults to `""`):
605
+ In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can
606
+ specify the folder name here.
607
+ kwargs (remaining dictionary of keyword arguments, *optional*):
608
+ Can be used to update the configuration object (after it being loaded) and initiate the model (e.g.,
609
+ `output_attentions=True`). Behaves differently depending on whether a `config` is provided or
610
+ automatically loaded:
611
+
612
+ - If a configuration is provided with `config`, `**kwargs` will be directly passed to the
613
+ underlying model's `__init__` method (we assume all relevant updates to the configuration have
614
+ already been done)
615
+ - If a configuration is not provided, `kwargs` will be first passed to the configuration class
616
+ initialization function ([`~PretrainedConfig.from_pretrained`]). Each key of `kwargs` that
617
+ corresponds to a configuration attribute will be used to override said attribute with the
618
+ supplied `kwargs` value. Remaining keys that do not correspond to any configuration attribute
619
+ will be passed to the underlying model's `__init__` function.
620
+
621
+ Examples:
622
+
623
+ ```python
624
+ >>> from transformers import BertConfig, FlaxBertModel
625
+
626
+ >>> # Download model and configuration from huggingface.co and cache.
627
+ >>> model = FlaxBertModel.from_pretrained("google-bert/bert-base-cased")
628
+ >>> # Model was saved using *save_pretrained('./test/saved_model/')* (for example purposes, not runnable).
629
+ >>> model = FlaxBertModel.from_pretrained("./test/saved_model/")
630
+ >>> # Loading from a PyTorch checkpoint file instead of a PyTorch model (slower, for example purposes, not runnable).
631
+ >>> config = BertConfig.from_json_file("./pt_model/config.json")
632
+ >>> model = FlaxBertModel.from_pretrained("./pt_model/pytorch_model.bin", from_pt=True, config=config)
633
+ ```"""
634
+ from_pt = kwargs.pop("from_pt", False)
635
+ resume_download = kwargs.pop("resume_download", None)
636
+ proxies = kwargs.pop("proxies", None)
637
+ use_auth_token = kwargs.pop("use_auth_token", None)
638
+ trust_remote_code = kwargs.pop("trust_remote_code", None)
639
+ from_pipeline = kwargs.pop("_from_pipeline", None)
640
+ from_auto_class = kwargs.pop("_from_auto", False)
641
+ _do_init = kwargs.pop("_do_init", True)
642
+ subfolder = kwargs.pop("subfolder", "")
643
+ commit_hash = kwargs.pop("_commit_hash", None)
644
+
645
+ # Not relevant for Flax Models
646
+ _ = kwargs.pop("adapter_kwargs", None)
647
+
648
+ if use_auth_token is not None:
649
+ warnings.warn(
650
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
651
+ FutureWarning,
652
+ )
653
+ if token is not None:
654
+ raise ValueError(
655
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
656
+ )
657
+ token = use_auth_token
658
+
659
+ if trust_remote_code is True:
660
+ logger.warning(
661
+ "The argument `trust_remote_code` is to be used with Auto classes. It has no effect here and is"
662
+ " ignored."
663
+ )
664
+
665
+ user_agent = {"file_type": "model", "framework": "flax", "from_auto_class": from_auto_class}
666
+ if from_pipeline is not None:
667
+ user_agent["using_pipeline"] = from_pipeline
668
+
669
+ if is_offline_mode() and not local_files_only:
670
+ logger.info("Offline mode: forcing local_files_only=True")
671
+ local_files_only = True
672
+
673
+ # Load config if we don't provide a configuration
674
+ if not isinstance(config, PretrainedConfig):
675
+ config_path = config if config is not None else pretrained_model_name_or_path
676
+ config, model_kwargs = cls.config_class.from_pretrained(
677
+ config_path,
678
+ cache_dir=cache_dir,
679
+ return_unused_kwargs=True,
680
+ force_download=force_download,
681
+ resume_download=resume_download,
682
+ proxies=proxies,
683
+ local_files_only=local_files_only,
684
+ token=token,
685
+ revision=revision,
686
+ subfolder=subfolder,
687
+ _from_auto=from_auto_class,
688
+ _from_pipeline=from_pipeline,
689
+ _commit_hash=commit_hash,
690
+ **kwargs,
691
+ )
692
+ else:
693
+ model_kwargs = kwargs.copy()
694
+
695
+ if commit_hash is None:
696
+ commit_hash = getattr(config, "_commit_hash", None)
697
+
698
+ # Add the dtype to model_kwargs
699
+ model_kwargs["dtype"] = dtype
700
+
701
+ # This variable will flag if we're loading a sharded checkpoint. In this case the archive file is just the
702
+ # index of the files.
703
+ is_sharded = False
704
+
705
+ # Load model
706
+ if pretrained_model_name_or_path is not None:
707
+ pretrained_model_name_or_path = str(pretrained_model_name_or_path)
708
+ is_local = os.path.isdir(pretrained_model_name_or_path)
709
+ if is_local:
710
+ if os.path.isfile(os.path.join(pretrained_model_name_or_path, subfolder, FLAX_WEIGHTS_NAME)):
711
+ # Load from a Flax checkpoint
712
+ archive_file = os.path.join(pretrained_model_name_or_path, subfolder, FLAX_WEIGHTS_NAME)
713
+ elif os.path.isfile(os.path.join(pretrained_model_name_or_path, subfolder, FLAX_WEIGHTS_INDEX_NAME)):
714
+ # Load from a sharded Flax checkpoint
715
+ archive_file = os.path.join(pretrained_model_name_or_path, subfolder, FLAX_WEIGHTS_INDEX_NAME)
716
+ is_sharded = True
717
+ elif is_safetensors_available() and os.path.isfile(
718
+ os.path.join(pretrained_model_name_or_path, subfolder, SAFE_WEIGHTS_NAME)
719
+ ):
720
+ # Load from a safetensors checkpoint
721
+ archive_file = os.path.join(pretrained_model_name_or_path, subfolder, SAFE_WEIGHTS_NAME)
722
+ elif is_safetensors_available() and os.path.isfile(
723
+ os.path.join(pretrained_model_name_or_path, SAFE_WEIGHTS_NAME)
724
+ ):
725
+ # Load from a safetensors checkpoint
726
+ archive_file = os.path.join(pretrained_model_name_or_path, SAFE_WEIGHTS_NAME)
727
+ elif from_pt and os.path.isfile(os.path.join(pretrained_model_name_or_path, subfolder, WEIGHTS_NAME)):
728
+ # Load from a PyTorch checkpoint
729
+ archive_file = os.path.join(pretrained_model_name_or_path, subfolder, WEIGHTS_NAME)
730
+ elif from_pt and os.path.isfile(
731
+ os.path.join(pretrained_model_name_or_path, subfolder, WEIGHTS_INDEX_NAME)
732
+ ):
733
+ # Load from a sharded pytorch checkpoint
734
+ archive_file = os.path.join(pretrained_model_name_or_path, subfolder, WEIGHTS_INDEX_NAME)
735
+ is_sharded = True
736
+ # At this stage we don't have a weight file so we will raise an error.
737
+ elif is_safetensors_available() and os.path.isfile(
738
+ os.path.join(pretrained_model_name_or_path, SAFE_WEIGHTS_INDEX_NAME)
739
+ ):
740
+ # Load from a sharded safetensors checkpoint
741
+ archive_file = os.path.join(pretrained_model_name_or_path, SAFE_WEIGHTS_INDEX_NAME)
742
+ is_sharded = True
743
+ raise NotImplementedError("Support for sharded checkpoints using safetensors is coming soon!")
744
+ elif os.path.isfile(os.path.join(pretrained_model_name_or_path, subfolder, WEIGHTS_NAME)):
745
+ raise OSError(
746
+ f"Error no file named {FLAX_WEIGHTS_NAME} found in directory {pretrained_model_name_or_path} "
747
+ "but there is a file for PyTorch weights. Use `from_pt=True` to load this model from those "
748
+ "weights."
749
+ )
750
+ else:
751
+ raise OSError(
752
+ f"Error no file named {FLAX_WEIGHTS_NAME} or {WEIGHTS_NAME} found in directory "
753
+ f"{pretrained_model_name_or_path}."
754
+ )
755
+ elif os.path.isfile(os.path.join(subfolder, pretrained_model_name_or_path)):
756
+ archive_file = pretrained_model_name_or_path
757
+ is_local = True
758
+ elif is_remote_url(pretrained_model_name_or_path):
759
+ filename = pretrained_model_name_or_path
760
+ resolved_archive_file = download_url(pretrained_model_name_or_path)
761
+ else:
762
+ if from_pt:
763
+ filename = WEIGHTS_NAME
764
+ else:
765
+ filename = FLAX_WEIGHTS_NAME
766
+
767
+ try:
768
+ # Load from URL or cache if already cached
769
+ cached_file_kwargs = {
770
+ "cache_dir": cache_dir,
771
+ "force_download": force_download,
772
+ "proxies": proxies,
773
+ "resume_download": resume_download,
774
+ "local_files_only": local_files_only,
775
+ "token": token,
776
+ "user_agent": user_agent,
777
+ "revision": revision,
778
+ "subfolder": subfolder,
779
+ "_raise_exceptions_for_gated_repo": False,
780
+ "_raise_exceptions_for_missing_entries": False,
781
+ "_commit_hash": commit_hash,
782
+ }
783
+ resolved_archive_file = cached_file(pretrained_model_name_or_path, filename, **cached_file_kwargs)
784
+
785
+ # Maybe the checkpoint is sharded, we try to grab the index name in this case.
786
+ if resolved_archive_file is None and filename == FLAX_WEIGHTS_NAME:
787
+ resolved_archive_file = cached_file(
788
+ pretrained_model_name_or_path, FLAX_WEIGHTS_INDEX_NAME, **cached_file_kwargs
789
+ )
790
+ if resolved_archive_file is not None:
791
+ is_sharded = True
792
+
793
+ # Maybe the checkpoint is pytorch sharded, we try to grab the pytorch index name in this case.
794
+ if resolved_archive_file is None and from_pt:
795
+ resolved_archive_file = cached_file(
796
+ pretrained_model_name_or_path, WEIGHTS_INDEX_NAME, **cached_file_kwargs
797
+ )
798
+ if resolved_archive_file is not None:
799
+ is_sharded = True
800
+
801
+ # If we still haven't found anything, look for `safetensors`.
802
+ if resolved_archive_file is None:
803
+ # No support for sharded safetensors yet, so we'll raise an error if that's all we find.
804
+ filename = SAFE_WEIGHTS_NAME
805
+ resolved_archive_file = cached_file(
806
+ pretrained_model_name_or_path, SAFE_WEIGHTS_NAME, **cached_file_kwargs
807
+ )
808
+
809
+ # Since we set _raise_exceptions_for_missing_entries=False, we don't get an exception but a None
810
+ # result when internet is up, the repo and revision exist, but the file does not.
811
+ if resolved_archive_file is None:
812
+ # Otherwise, maybe there is a TF or Torch model file. We try those to give a helpful error
813
+ # message.
814
+ has_file_kwargs = {
815
+ "revision": revision,
816
+ "proxies": proxies,
817
+ "token": token,
818
+ "cache_dir": cache_dir,
819
+ "local_files_only": local_files_only,
820
+ }
821
+ if has_file(pretrained_model_name_or_path, SAFE_WEIGHTS_INDEX_NAME, **has_file_kwargs):
822
+ is_sharded = True
823
+ raise NotImplementedError(
824
+ "Support for sharded checkpoints using safetensors is coming soon!"
825
+ )
826
+ elif has_file(pretrained_model_name_or_path, WEIGHTS_NAME, **has_file_kwargs):
827
+ raise OSError(
828
+ f"{pretrained_model_name_or_path} does not appear to have a file named"
829
+ f" {FLAX_WEIGHTS_NAME} but there is a file for PyTorch weights. Use `from_pt=True` to"
830
+ " load this model from those weights."
831
+ )
832
+ elif has_file(pretrained_model_name_or_path, WEIGHTS_INDEX_NAME, **has_file_kwargs):
833
+ raise OSError(
834
+ f"{pretrained_model_name_or_path} does not appear to have a file named"
835
+ f" {FLAX_WEIGHTS_INDEX_NAME} but there is a sharded file for PyTorch weights. Use"
836
+ " `from_pt=True` to load this model from those weights."
837
+ )
838
+ else:
839
+ raise OSError(
840
+ f"{pretrained_model_name_or_path} does not appear to have a file named"
841
+ f" {FLAX_WEIGHTS_NAME} or {WEIGHTS_NAME}."
842
+ )
843
+ except OSError:
844
+ # Raise any environment error raise by `cached_file`. It will have a helpful error message adapted
845
+ # to the original exception.
846
+ raise
847
+ except Exception:
848
+ # For any other exception, we throw a generic error.
849
+ raise OSError(
850
+ f"Can't load the model for '{pretrained_model_name_or_path}'. If you were trying to load it"
851
+ " from 'https://huggingface.co/models', make sure you don't have a local directory with the"
852
+ f" same name. Otherwise, make sure '{pretrained_model_name_or_path}' is the correct path to a"
853
+ f" directory containing a file named {FLAX_WEIGHTS_NAME} or {WEIGHTS_NAME}."
854
+ )
855
+
856
+ if is_local:
857
+ logger.info(f"loading weights file {archive_file}")
858
+ resolved_archive_file = archive_file
859
+ filename = resolved_archive_file.split(os.path.sep)[-1]
860
+ else:
861
+ logger.info(f"loading weights file {filename} from cache at {resolved_archive_file}")
862
+ else:
863
+ resolved_archive_file = None
864
+
865
+ # We'll need to download and cache each checkpoint shard if the checkpoint is sharded.
866
+ if is_sharded:
867
+ # resolved_archive_file becomes a list of files that point to the different checkpoint shards in this case.
868
+ resolved_archive_file, _ = get_checkpoint_shard_files(
869
+ pretrained_model_name_or_path,
870
+ resolved_archive_file,
871
+ cache_dir=cache_dir,
872
+ force_download=force_download,
873
+ proxies=proxies,
874
+ resume_download=resume_download,
875
+ local_files_only=local_files_only,
876
+ token=token,
877
+ user_agent=user_agent,
878
+ revision=revision,
879
+ subfolder=subfolder,
880
+ _commit_hash=commit_hash,
881
+ )
882
+
883
+ safetensors_from_pt = False
884
+ if filename == SAFE_WEIGHTS_NAME:
885
+ with safe_open(resolved_archive_file, framework="flax") as f:
886
+ safetensors_metadata = f.metadata()
887
+ if safetensors_metadata is None or safetensors_metadata.get("format") not in ["pt", "tf", "flax"]:
888
+ raise OSError(
889
+ f"The safetensors archive passed at {resolved_archive_file} does not contain the valid metadata."
890
+ " Make sure you save your model with the `save_pretrained` method."
891
+ )
892
+ safetensors_from_pt = safetensors_metadata.get("format") == "pt"
893
+
894
+ # init random models
895
+ model = cls(config, *model_args, _do_init=_do_init, **model_kwargs)
896
+
897
+ if from_pt or safetensors_from_pt:
898
+ state = load_pytorch_checkpoint_in_flax_state_dict(model, resolved_archive_file, is_sharded)
899
+ else:
900
+ if is_sharded:
901
+ state = cls.load_flax_sharded_weights(resolved_archive_file)
902
+ else:
903
+ state = cls.load_flax_weights(resolved_archive_file)
904
+ # make sure all arrays are stored as jnp.arrays
905
+ # NOTE: This is to prevent a bug this will be fixed in Flax >= v0.3.4:
906
+ # https://github.com/google/flax/issues/1261
907
+ if _do_init:
908
+ state = jax.tree_util.tree_map(jnp.array, state)
909
+ else:
910
+ # keep the params on CPU if we don't want to initialize
911
+ state = jax.tree_util.tree_map(lambda x: jax.device_put(x, jax.local_devices(backend="cpu")[0]), state)
912
+
913
+ if "batch_stats" in state: # if flax model contains batch norm layers
914
+ # if model is base model only use model_prefix key
915
+ if (
916
+ cls.base_model_prefix not in dict(model.params_shape_tree["params"])
917
+ and cls.base_model_prefix in state["params"]
918
+ ):
919
+ state["params"] = state["params"][cls.base_model_prefix]
920
+ state["batch_stats"] = state["batch_stats"][cls.base_model_prefix]
921
+
922
+ # if model is head model and we are loading weights from base model
923
+ # we initialize new params dict with base_model_prefix
924
+ if (
925
+ cls.base_model_prefix in dict(model.params_shape_tree["params"])
926
+ and cls.base_model_prefix not in state["params"]
927
+ ):
928
+ state = {
929
+ "params": {cls.base_model_prefix: state["params"]},
930
+ "batch_stats": {cls.base_model_prefix: state["batch_stats"]},
931
+ }
932
+
933
+ else:
934
+ # if model is base model only use model_prefix key
935
+ if cls.base_model_prefix not in dict(model.params_shape_tree) and cls.base_model_prefix in state:
936
+ state = state[cls.base_model_prefix]
937
+
938
+ # if model is head model and we are loading weights from base model
939
+ # we initialize new params dict with base_model_prefix
940
+ if cls.base_model_prefix in dict(model.params_shape_tree) and cls.base_model_prefix not in state:
941
+ state = {cls.base_model_prefix: state}
942
+
943
+ # flatten dicts
944
+ state = flatten_dict(state)
945
+
946
+ random_state = flatten_dict(unfreeze(model.params if _do_init else model.params_shape_tree))
947
+
948
+ missing_keys = model.required_params - set(state.keys())
949
+ unexpected_keys = set(state.keys()) - model.required_params
950
+
951
+ # Disabling warning when porting pytorch weights to flax, flax does not uses num_batches_tracked
952
+ for unexpected_key in unexpected_keys.copy():
953
+ if "num_batches_tracked" in unexpected_key[-1]:
954
+ unexpected_keys.remove(unexpected_key)
955
+
956
+ if missing_keys and not _do_init:
957
+ logger.warning(
958
+ f"The checkpoint {pretrained_model_name_or_path} is missing required keys: {missing_keys}. "
959
+ "Make sure to call model.init_weights to initialize the missing weights."
960
+ )
961
+ cls._missing_keys = missing_keys
962
+
963
+ # Mismatched keys contains tuples key/shape1/shape2 of weights in the checkpoint that have a shape not
964
+ # matching the weights in the model.
965
+ mismatched_keys = []
966
+ for key in state:
967
+ if key in random_state and state[key].shape != random_state[key].shape:
968
+ if ignore_mismatched_sizes:
969
+ mismatched_keys.append((key, state[key].shape, random_state[key].shape))
970
+ state[key] = random_state[key]
971
+ else:
972
+ raise ValueError(
973
+ f"Trying to load the pretrained weight for {key} failed: checkpoint has shape "
974
+ f"{state[key].shape} which is incompatible with the model shape {random_state[key].shape}. "
975
+ "Using `ignore_mismatched_sizes=True` if you really want to load this checkpoint inside this "
976
+ "model."
977
+ )
978
+
979
+ # add missing keys as random parameters if we are initializing
980
+ if missing_keys and _do_init:
981
+ for missing_key in missing_keys:
982
+ state[missing_key] = random_state[missing_key]
983
+
984
+ # remove unexpected keys to not be saved again
985
+ for unexpected_key in unexpected_keys:
986
+ del state[unexpected_key]
987
+
988
+ if len(unexpected_keys) > 0:
989
+ logger.warning(
990
+ f"Some weights of the model checkpoint at {pretrained_model_name_or_path} were not used when"
991
+ f" initializing {model.__class__.__name__}: {unexpected_keys}\n- This IS expected if you are"
992
+ f" initializing {model.__class__.__name__} from the checkpoint of a model trained on another task or"
993
+ " with another architecture (e.g. initializing a BertForSequenceClassification model from a"
994
+ " BertForPreTraining model).\n- This IS NOT expected if you are initializing"
995
+ f" {model.__class__.__name__} from the checkpoint of a model that you expect to be exactly identical"
996
+ " (initializing a BertForSequenceClassification model from a BertForSequenceClassification model)."
997
+ )
998
+ else:
999
+ logger.info(f"All model checkpoint weights were used when initializing {model.__class__.__name__}.\n")
1000
+
1001
+ if len(missing_keys) > 0:
1002
+ logger.warning(
1003
+ f"Some weights of {model.__class__.__name__} were not initialized from the model checkpoint at"
1004
+ f" {pretrained_model_name_or_path} and are newly initialized: {missing_keys}\nYou should probably"
1005
+ " TRAIN this model on a down-stream task to be able to use it for predictions and inference."
1006
+ )
1007
+ elif len(mismatched_keys) == 0:
1008
+ logger.info(
1009
+ f"All the weights of {model.__class__.__name__} were initialized from the model checkpoint at"
1010
+ f" {pretrained_model_name_or_path}.\nIf your task is similar to the task the model of the checkpoint"
1011
+ f" was trained on, you can already use {model.__class__.__name__} for predictions without further"
1012
+ " training."
1013
+ )
1014
+ if len(mismatched_keys) > 0:
1015
+ mismatched_warning = "\n".join(
1016
+ [
1017
+ f"- {key}: found shape {shape1} in the checkpoint and {shape2} in the model instantiated"
1018
+ for key, shape1, shape2 in mismatched_keys
1019
+ ]
1020
+ )
1021
+ logger.warning(
1022
+ f"Some weights of {model.__class__.__name__} were not initialized from the model checkpoint at"
1023
+ f" {pretrained_model_name_or_path} and are newly initialized because the shapes did not"
1024
+ f" match:\n{mismatched_warning}\nYou should probably TRAIN this model on a down-stream task to be able"
1025
+ " to use it for predictions and inference."
1026
+ )
1027
+
1028
+ # dictionary of key: dtypes for the model params
1029
+ param_dtypes = jax.tree_util.tree_map(lambda x: x.dtype, state)
1030
+ # extract keys of parameters not in jnp.float32
1031
+ fp16_params = [k for k in param_dtypes if param_dtypes[k] == jnp.float16]
1032
+ bf16_params = [k for k in param_dtypes if param_dtypes[k] == jnp.bfloat16]
1033
+
1034
+ # raise a warning if any of the parameters are not in jnp.float32
1035
+ if len(fp16_params) > 0:
1036
+ logger.warning(
1037
+ f"Some of the weights of {model.__class__.__name__} were initialized in float16 precision from "
1038
+ f"the model checkpoint at {pretrained_model_name_or_path}:\n{fp16_params}\n"
1039
+ "You should probably UPCAST the model weights to float32 if this was not intended. "
1040
+ "See [`~FlaxPreTrainedModel.to_fp32`] for further information on how to do this."
1041
+ )
1042
+
1043
+ if len(bf16_params) > 0:
1044
+ logger.warning(
1045
+ f"Some of the weights of {model.__class__.__name__} were initialized in bfloat16 precision from "
1046
+ f"the model checkpoint at {pretrained_model_name_or_path}:\n{bf16_params}\n"
1047
+ "You should probably UPCAST the model weights to float32 if this was not intended. "
1048
+ "See [`~FlaxPreTrainedModel.to_fp32`] for further information on how to do this."
1049
+ )
1050
+
1051
+ # If it is a model with generation capabilities, attempt to load the generation config
1052
+ if model.can_generate():
1053
+ try:
1054
+ model.generation_config = GenerationConfig.from_pretrained(
1055
+ pretrained_model_name_or_path,
1056
+ cache_dir=cache_dir,
1057
+ force_download=force_download,
1058
+ resume_download=resume_download,
1059
+ proxies=proxies,
1060
+ local_files_only=local_files_only,
1061
+ token=token,
1062
+ revision=revision,
1063
+ subfolder=subfolder,
1064
+ _from_auto=from_auto_class,
1065
+ _from_pipeline=from_pipeline,
1066
+ **kwargs,
1067
+ )
1068
+ except OSError:
1069
+ logger.info(
1070
+ "Generation config file not found, using a generation config created from the model config."
1071
+ )
1072
+ pass
1073
+
1074
+ if _do_init:
1075
+ # set correct parameters
1076
+ model.params = unflatten_dict(state)
1077
+ return model
1078
+ else:
1079
+ return model, unflatten_dict(state)
1080
+
1081
+ def save_pretrained(
1082
+ self,
1083
+ save_directory: Union[str, os.PathLike],
1084
+ params=None,
1085
+ push_to_hub=False,
1086
+ max_shard_size="10GB",
1087
+ token: Optional[Union[str, bool]] = None,
1088
+ safe_serialization: bool = False,
1089
+ **kwargs,
1090
+ ):
1091
+ """
1092
+ Save a model and its configuration file to a directory, so that it can be re-loaded using the
1093
+ `[`~FlaxPreTrainedModel.from_pretrained`]` class method
1094
+
1095
+ Arguments:
1096
+ save_directory (`str` or `os.PathLike`):
1097
+ Directory to which to save. Will be created if it doesn't exist.
1098
+ push_to_hub (`bool`, *optional*, defaults to `False`):
1099
+ Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the
1100
+ repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
1101
+ namespace).
1102
+ max_shard_size (`int` or `str`, *optional*, defaults to `"10GB"`):
1103
+ The maximum size for a checkpoint before being sharded. Checkpoints shard will then be each of size
1104
+ lower than this size. If expressed as a string, needs to be digits followed by a unit (like `"5MB"`).
1105
+
1106
+ <Tip warning={true}>
1107
+
1108
+ If a single weight of the model is bigger than `max_shard_size`, it will be in its own checkpoint shard
1109
+ which will be bigger than `max_shard_size`.
1110
+
1111
+ </Tip>
1112
+
1113
+ token (`str` or `bool`, *optional*):
1114
+ The token to use as HTTP bearer authorization for remote files. If `True`, or not specified, will use
1115
+ the token generated when running `hf auth login` (stored in `~/.huggingface`).
1116
+ kwargs (`dict[str, Any]`, *optional*):
1117
+ Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.
1118
+ safe_serialization (`bool`, *optional*, defaults to `False`):
1119
+ Whether to save the model using `safetensors` or through msgpack.
1120
+ """
1121
+ use_auth_token = kwargs.pop("use_auth_token", None)
1122
+
1123
+ if use_auth_token is not None:
1124
+ warnings.warn(
1125
+ "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",
1126
+ FutureWarning,
1127
+ )
1128
+ if token is not None:
1129
+ raise ValueError(
1130
+ "`token` and `use_auth_token` are both specified. Please set only the argument `token`."
1131
+ )
1132
+ token = use_auth_token
1133
+
1134
+ if token is not None:
1135
+ kwargs["token"] = token
1136
+
1137
+ if os.path.isfile(save_directory):
1138
+ logger.error(f"Provided path ({save_directory}) should be a directory, not a file")
1139
+ return
1140
+
1141
+ os.makedirs(save_directory, exist_ok=True)
1142
+
1143
+ if push_to_hub:
1144
+ commit_message = kwargs.pop("commit_message", None)
1145
+ repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])
1146
+ repo_id = self._create_repo(repo_id, **kwargs)
1147
+ files_timestamps = self._get_files_timestamps(save_directory)
1148
+
1149
+ # get abs dir
1150
+ save_directory = os.path.abspath(save_directory)
1151
+ # save config as well
1152
+ self.config.architectures = [self.__class__.__name__[4:]]
1153
+
1154
+ # If we have a custom model, we copy the file defining it in the folder and set the attributes so it can be
1155
+ # loaded from the Hub.
1156
+ if self._auto_class is not None:
1157
+ custom_object_save(self, save_directory, config=self.config)
1158
+
1159
+ self.config.save_pretrained(save_directory)
1160
+ if self.can_generate():
1161
+ self.generation_config.save_pretrained(save_directory)
1162
+
1163
+ # save model
1164
+ weights_name = SAFE_WEIGHTS_NAME if safe_serialization else FLAX_WEIGHTS_NAME
1165
+ output_model_file = os.path.join(save_directory, weights_name)
1166
+
1167
+ shards, index = flax_shard_checkpoint(params if params is not None else self.params, max_shard_size)
1168
+ # Clean the folder from a previous save
1169
+ for filename in os.listdir(save_directory):
1170
+ full_filename = os.path.join(save_directory, filename)
1171
+ weights_no_suffix = weights_name.replace(".bin", "").replace(".safetensors", "")
1172
+ if filename.startswith(weights_no_suffix) and os.path.isfile(full_filename) and filename not in shards:
1173
+ os.remove(full_filename)
1174
+
1175
+ if index is None:
1176
+ if safe_serialization:
1177
+ params = params if params is not None else self.params
1178
+ flat_dict = flatten_dict(params, sep=".")
1179
+ safe_save_file(flat_dict, output_model_file, metadata={"format": "flax"})
1180
+ else:
1181
+ with open(output_model_file, "wb") as f:
1182
+ params = params if params is not None else self.params
1183
+ model_bytes = to_bytes(params)
1184
+ f.write(model_bytes)
1185
+
1186
+ else:
1187
+ save_index_file = os.path.join(save_directory, FLAX_WEIGHTS_INDEX_NAME)
1188
+ # Save the index as well
1189
+ with open(save_index_file, "w", encoding="utf-8") as f:
1190
+ content = json.dumps(index, indent=2, sort_keys=True) + "\n"
1191
+ f.write(content)
1192
+ logger.info(
1193
+ f"The model is bigger than the maximum size per checkpoint ({max_shard_size}) and is going to be "
1194
+ f"split in {len(shards)} checkpoint shards. You can find where each parameters has been saved in the "
1195
+ f"index located at {save_index_file}."
1196
+ )
1197
+ for shard_file, shard in shards.items():
1198
+ # the shard item are unflattened, to save them we need to flatten them again
1199
+ with open(os.path.join(save_directory, shard_file), mode="wb") as f:
1200
+ params = unflatten_dict(shard, sep="/")
1201
+ shard_bytes = to_bytes(params)
1202
+ f.write(shard_bytes)
1203
+
1204
+ logger.info(f"Model weights saved in {output_model_file}")
1205
+
1206
+ if push_to_hub:
1207
+ self._upload_modified_files(
1208
+ save_directory,
1209
+ repo_id,
1210
+ files_timestamps,
1211
+ commit_message=commit_message,
1212
+ token=token,
1213
+ )
1214
+
1215
+ @classmethod
1216
+ def register_for_auto_class(cls, auto_class="FlaxAutoModel"):
1217
+ """
1218
+ Register this class with a given auto class. This should only be used for custom models as the ones in the
1219
+ library are already mapped with an auto class.
1220
+
1221
+
1222
+
1223
+ Args:
1224
+ auto_class (`str` or `type`, *optional*, defaults to `"FlaxAutoModel"`):
1225
+ The auto class to register this new model with.
1226
+ """
1227
+ if not isinstance(auto_class, str):
1228
+ auto_class = auto_class.__name__
1229
+
1230
+ import transformers.models.auto as auto_module
1231
+
1232
+ if not hasattr(auto_module, auto_class):
1233
+ raise ValueError(f"{auto_class} is not a valid auto class.")
1234
+
1235
+ cls._auto_class = auto_class
1236
+
1237
+
1238
+ # To update the docstring, we need to copy the method, otherwise we change the original docstring.
1239
+ FlaxPreTrainedModel.push_to_hub = copy_func(FlaxPreTrainedModel.push_to_hub)
1240
+ if FlaxPreTrainedModel.push_to_hub.__doc__ is not None:
1241
+ FlaxPreTrainedModel.push_to_hub.__doc__ = FlaxPreTrainedModel.push_to_hub.__doc__.format(
1242
+ object="model", object_class="FlaxAutoModel", object_files="model checkpoint"
1243
+ )
1244
+
1245
+
1246
+ def overwrite_call_docstring(model_class, docstring):
1247
+ # copy __call__ function to be sure docstring is changed only for this function
1248
+ model_class.__call__ = copy_func(model_class.__call__)
1249
+ # delete existing docstring
1250
+ model_class.__call__.__doc__ = None
1251
+ # set correct docstring
1252
+ model_class.__call__ = add_start_docstrings_to_model_forward(docstring)(model_class.__call__)
1253
+
1254
+
1255
+ def append_call_sample_docstring(
1256
+ model_class, checkpoint, output_type, config_class, mask=None, revision=None, real_checkpoint=None
1257
+ ):
1258
+ model_class.__call__ = copy_func(model_class.__call__)
1259
+ model_class.__call__ = add_code_sample_docstrings(
1260
+ checkpoint=checkpoint,
1261
+ output_type=output_type,
1262
+ config_class=config_class,
1263
+ model_cls=model_class.__name__,
1264
+ revision=revision,
1265
+ real_checkpoint=real_checkpoint,
1266
+ )(model_class.__call__)
1267
+
1268
+
1269
+ def append_replace_return_docstrings(model_class, output_type, config_class):
1270
+ model_class.__call__ = copy_func(model_class.__call__)
1271
+ model_class.__call__ = replace_return_docstrings(
1272
+ output_type=output_type,
1273
+ config_class=config_class,
1274
+ )(model_class.__call__)
Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/transformers/modeling_gguf_pytorch_utils.py ADDED
@@ -0,0 +1,532 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 The ggml.ai team and The HuggingFace Inc. team. and pygguf author (github.com/99991)
2
+ # https://github.com/99991/pygguf
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import re
17
+ from typing import NamedTuple, Optional
18
+
19
+ import numpy as np
20
+ from tqdm.auto import tqdm
21
+
22
+ from .integrations import (
23
+ GGUF_CONFIG_MAPPING,
24
+ GGUF_TOKENIZER_MAPPING,
25
+ _gguf_parse_value,
26
+ )
27
+ from .utils import is_torch_available
28
+ from .utils.import_utils import is_gguf_available
29
+ from .utils.logging import get_logger
30
+
31
+
32
+ if is_torch_available():
33
+ import torch
34
+
35
+ logger = get_logger(__name__)
36
+
37
+
38
+ GGUF_TO_TRANSFORMERS_MAPPING = {
39
+ "ignore": {
40
+ "GGUF": {
41
+ "version": "version",
42
+ "tensor_count": "tensor_count",
43
+ "kv_count": "kv_count",
44
+ },
45
+ "general": {"file_type": "file_type", "quantization_version": "quantization_version"},
46
+ },
47
+ "config": GGUF_CONFIG_MAPPING,
48
+ "tokenizer": {"tokenizer": GGUF_TOKENIZER_MAPPING["tokenizer"]},
49
+ "tokenizer_config": {"tokenizer": GGUF_TOKENIZER_MAPPING["tokenizer_config"]},
50
+ }
51
+
52
+ GGUF_SUPPORTED_ARCHITECTURES = list(GGUF_TO_TRANSFORMERS_MAPPING["config"].keys())
53
+
54
+
55
+ class GGUFTensor(NamedTuple):
56
+ weights: np.ndarray
57
+ name: str
58
+ metadata: dict
59
+
60
+
61
+ class TensorProcessor:
62
+ def __init__(self, config=None):
63
+ self.config = config or {}
64
+
65
+ def process(self, weights, name, **kwargs):
66
+ return GGUFTensor(weights, name, {})
67
+
68
+
69
+ class LlamaTensorProcessor(TensorProcessor):
70
+ def __init__(self, config=None):
71
+ super().__init__(config=config)
72
+
73
+ def process(self, weights, name, **kwargs):
74
+ if ".attn_k." in name or ".attn_q." in name:
75
+ num_heads = self.config.get("num_attention_heads")
76
+ num_kv_heads = self.config.get("num_key_value_heads")
77
+
78
+ if None in (num_heads, num_kv_heads):
79
+ return GGUFTensor(weights, name, {})
80
+ if ".attn_q." in name:
81
+ weights = self._reverse_permute_weights(weights, num_heads, num_heads)
82
+ elif ".attn_k." in name:
83
+ weights = self._reverse_permute_weights(weights, num_heads, num_kv_heads)
84
+ return GGUFTensor(weights, name, {})
85
+
86
+ def _reverse_permute_weights(
87
+ self, weights: np.ndarray, n_head: int, num_kv_heads: Optional[int] = None
88
+ ) -> np.ndarray:
89
+ # Original permutation implementation
90
+ # https://github.com/ggerganov/llama.cpp/blob/a38b884c6c4b0c256583acfaaabdf556c62fabea/convert_hf_to_gguf.py#L1402-L1408
91
+ if num_kv_heads is not None and n_head != num_kv_heads:
92
+ n_head = num_kv_heads
93
+
94
+ dim = weights.shape[0] // n_head // 2
95
+ w = weights.reshape(n_head, dim, 2, *weights.shape[1:])
96
+ return w.swapaxes(2, 1).reshape(weights.shape)
97
+
98
+
99
+ class Qwen2MoeTensorProcessor(TensorProcessor):
100
+ def __init__(self, config=None):
101
+ super().__init__(config=config)
102
+
103
+ def process(self, weights, name, **kwargs):
104
+ if "_exp" in name:
105
+ tensor_key_mapping = kwargs.get("tensor_key_mapping")
106
+ parsed_parameters = kwargs.get("parsed_parameters")
107
+ if tensor_key_mapping:
108
+ self._split_moe_expert_tensor(weights, parsed_parameters, name, tensor_key_mapping)
109
+ return GGUFTensor(weights, None, {})
110
+ if "ffn_gate_inp_shexp" in name:
111
+ # for compatibility tensor shared_expert_gate must be (1, 2048) dim,
112
+ # quantized one is (2048)
113
+ weights = np.expand_dims(weights, axis=0)
114
+ return GGUFTensor(weights, name, {})
115
+
116
+ def _split_moe_expert_tensor(
117
+ self, weights: np.ndarray, parsed_parameters: dict[str, dict], name: str, tensor_key_mapping: dict
118
+ ):
119
+ # Original merge implementation
120
+ # https://github.com/ggerganov/llama.cpp/blob/master/convert_hf_to_gguf.py#L1994-L2022
121
+ name = tensor_key_mapping[name]
122
+ w_counter = self.config.get("num_experts", 60)
123
+ for i in range(0, w_counter):
124
+ temp_name = name.replace("mlp.experts.", f"mlp.experts.{i}.")
125
+ exp_weight = weights[i]
126
+ parsed_parameters["tensors"][temp_name] = torch.from_numpy(np.copy(exp_weight))
127
+
128
+
129
+ class BloomTensorProcessor(TensorProcessor):
130
+ def __init__(self, config=None):
131
+ super().__init__(config=config)
132
+
133
+ def process(self, weights, name, **kwargs):
134
+ if "attn_qkv" in name:
135
+ num_heads = self.config["n_head"]
136
+ n_embed = self.config["hidden_size"]
137
+ if "weight" in name:
138
+ weights = self._reverse_reshape_weights(weights, num_heads, n_embed)
139
+ else:
140
+ weights = self._reverse_reshape_bias(weights, num_heads, n_embed)
141
+ return GGUFTensor(weights, name, {})
142
+
143
+ def _reverse_reshape_weights(self, weights: np.ndarray, n_head: int, n_embed: int):
144
+ # Original reshape implementation
145
+ # https://github.com/ggerganov/llama.cpp/blob/master/convert_hf_to_gguf.py#L972-L985
146
+ q, k, v = np.array_split(weights, 3, axis=0)
147
+
148
+ q = q.reshape(n_head, n_embed // n_head, n_embed)
149
+ k = k.reshape(n_head, n_embed // n_head, n_embed)
150
+ v = v.reshape(n_head, n_embed // n_head, n_embed)
151
+ qkv_weights = np.stack([q, k, v], axis=1)
152
+
153
+ return qkv_weights.reshape(n_head * 3 * (n_embed // n_head), n_embed)
154
+
155
+ def _reverse_reshape_bias(self, weights: np.ndarray, n_head: int, n_embed: int):
156
+ # Original reshape implementation
157
+ # https://github.com/ggerganov/llama.cpp/blob/master/convert_hf_to_gguf.py#L986-L998
158
+ q_bias, k_bias, v_bias = np.array_split(weights, 3)
159
+
160
+ q_bias = q_bias.reshape(n_head, n_embed // n_head)
161
+ k_bias = k_bias.reshape(n_head, n_embed // n_head)
162
+ v_bias = v_bias.reshape(n_head, n_embed // n_head)
163
+
164
+ qkv_bias = np.stack([q_bias, k_bias, v_bias], axis=1).flatten()
165
+ return qkv_bias
166
+
167
+
168
+ class T5TensorProcessor(TensorProcessor):
169
+ def __init__(self, config=None):
170
+ super().__init__(config=config)
171
+
172
+ def process(self, weights, name, **kwargs):
173
+ bid = None
174
+ for chunk in name.split("."):
175
+ if chunk.isdigit():
176
+ bid = int(chunk)
177
+ break
178
+ return GGUFTensor(weights, name, {"bid": bid})
179
+
180
+
181
+ class GPT2TensorProcessor(TensorProcessor):
182
+ def __init__(self, config=None):
183
+ super().__init__(config=config)
184
+
185
+ def process(self, weights, name, **kwargs):
186
+ # Original transpose implementation
187
+ # https://github.com/ggerganov/llama.cpp/blob/a38b884c6c4b0c256583acfaaabdf556c62fabea/convert_hf_to_gguf.py#L2060-L2061
188
+ if (
189
+ "attn_qkv.weight" in name
190
+ or "ffn_down.weight" in name
191
+ or "ffn_up.weight" in name
192
+ or "attn_output.weight" in name
193
+ ):
194
+ weights = weights.T
195
+
196
+ # Handle special case for output.weight
197
+ if name == "output.weight":
198
+ # output.weight has conflicts with attn_output.weight in name checking
199
+ # Store the tensor directly and signal to skip further processing
200
+ name = "lm_head.weight"
201
+ parsed_parameters = kwargs.get("parsed_parameters", {})
202
+ parsed_parameters["tensors"][name] = torch.from_numpy(np.copy(weights))
203
+ name = None # Signal to skip further processing
204
+ return GGUFTensor(weights, name, {})
205
+
206
+
207
+ class MambaTensorProcessor(TensorProcessor):
208
+ def __init__(self, config=None):
209
+ super().__init__(config=config)
210
+
211
+ def process(self, weights, name, **kwargs):
212
+ if "ssm_conv1d.weight" in name:
213
+ # for compatibility tensor ssm_conv1d must be (5120, 1, 4]) dim,
214
+ # quantized one is (5120, 4)
215
+ weights = np.expand_dims(weights, axis=1)
216
+ if "ssm_a" in name:
217
+ # Original exponential implementation
218
+ # https://github.com/ggerganov/llama.cpp/blob/master/convert_hf_to_gguf.py#L2975-L2977
219
+ weights = np.log(-weights)
220
+ return GGUFTensor(weights, name, {})
221
+
222
+
223
+ class NemotronTensorProcessor(TensorProcessor):
224
+ def __init__(self, config=None):
225
+ super().__init__(config=config)
226
+
227
+ # ref : https://github.com/ggerganov/llama.cpp/blob/master/convert_hf_to_gguf.py#L4666
228
+ def process(self, weights, name, **kwargs):
229
+ if "norm.weight" in name:
230
+ weights = weights - 1
231
+ return GGUFTensor(weights, name, {})
232
+
233
+
234
+ class Gemma2TensorProcessor(TensorProcessor):
235
+ def __init__(self, config=None):
236
+ super().__init__(config=config)
237
+
238
+ # ref: https://github.com/ggerganov/llama.cpp/blob/d79d8f39b4da6deca4aea8bf130c6034c482b320/convert_hf_to_gguf.py#L3191
239
+ # ref: https://github.com/huggingface/transformers/blob/fc37f38915372c15992b540dfcbbe00a916d4fc6/src/transformers/models/gemma/modeling_gemma.py#L89
240
+ def process(self, weights, name, **kwargs):
241
+ if "norm.weight" in name:
242
+ weights = weights - 1
243
+ return GGUFTensor(weights, name, {})
244
+
245
+
246
+ class Lfm2TensorProcessor(TensorProcessor):
247
+ def __init__(self, config=None):
248
+ super().__init__(config=config)
249
+
250
+ def process(self, weights, name, **kwargs):
251
+ if "shortconv.conv.weight" in name:
252
+ ## GGUF shape is [hidden_dim, L_cache], HF expects [hidden_dim, 1, L_cache]
253
+ weights = np.expand_dims(weights, axis=1) ## equivalent to unsqueeze(1)
254
+ return GGUFTensor(weights, name, {})
255
+
256
+
257
+ TENSOR_PROCESSORS = {
258
+ "llama": LlamaTensorProcessor,
259
+ "qwen2moe": Qwen2MoeTensorProcessor,
260
+ "qwen3moe": Qwen2MoeTensorProcessor,
261
+ "bloom": BloomTensorProcessor,
262
+ "t5": T5TensorProcessor,
263
+ "t5encoder": T5TensorProcessor,
264
+ "gpt2": GPT2TensorProcessor,
265
+ "mamba": MambaTensorProcessor,
266
+ "nemotron": NemotronTensorProcessor,
267
+ "gemma2": Gemma2TensorProcessor,
268
+ "gemma3": Gemma2TensorProcessor,
269
+ "lfm2": Lfm2TensorProcessor,
270
+ }
271
+
272
+
273
+ def read_field(reader, field):
274
+ if field not in reader.fields:
275
+ return []
276
+ value = reader.fields[field]
277
+ return [_gguf_parse_value(value.parts[_data_index], value.types) for _data_index in value.data]
278
+
279
+
280
+ # modified from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/model_executor/model_loader/loader.py#L1115-L1147
281
+ def get_gguf_hf_weights_map(
282
+ hf_model,
283
+ model_type: Optional[str] = None,
284
+ num_layers: Optional[int] = None,
285
+ qual_name: str = "",
286
+ ):
287
+ """
288
+ GGUF uses this naming convention for their tensors from HF checkpoint:
289
+ `blk.N.BB.weight` and `blk.N.BB.bias`
290
+ where N signifies the block number of a layer, and BB signifies the
291
+ attention/mlp layer components.
292
+ See "Standardized tensor names" in
293
+ https://github.com/ggerganov/ggml/blob/master/docs/gguf.md for details.
294
+ """
295
+ if is_gguf_available() and is_torch_available():
296
+ from gguf import MODEL_ARCH_NAMES, get_tensor_name_map
297
+ else:
298
+ logger.error(
299
+ "Loading a GGUF checkpoint in PyTorch, requires both PyTorch and GGUF>=0.10.0 to be installed. Please see "
300
+ "https://pytorch.org/ and https://github.com/ggerganov/llama.cpp/tree/master/gguf-py for installation instructions."
301
+ )
302
+ raise ImportError("Please install torch and gguf>=0.10.0 to load a GGUF checkpoint in PyTorch.")
303
+
304
+ model_type = hf_model.config.model_type if model_type is None else model_type
305
+ num_layers = hf_model.config.num_hidden_layers if num_layers is None else num_layers
306
+ # hack: ggufs have a different name for cohere
307
+ if model_type == "cohere":
308
+ model_type = "command-r"
309
+ elif model_type == "qwen2_moe":
310
+ model_type = "qwen2moe"
311
+ elif model_type == "qwen3_moe":
312
+ model_type = "qwen3moe"
313
+ elif model_type == "gemma3_text":
314
+ model_type = "gemma3"
315
+ elif model_type == "umt5":
316
+ model_type = "t5"
317
+ arch = None
318
+ for key, value in MODEL_ARCH_NAMES.items():
319
+ if value == model_type:
320
+ arch = key
321
+ break
322
+ if arch is None:
323
+ raise NotImplementedError(
324
+ f"Unknown gguf model_type: {model_type} in gguf-py. "
325
+ "This might because you're using an outdated version of gguf-py package, "
326
+ "you can install `gguf` package from source refer to "
327
+ "https://github.com/ggerganov/llama.cpp/tree/master/gguf-py#development"
328
+ )
329
+ name_map = get_tensor_name_map(arch, num_layers)
330
+
331
+ # Use a dummy conversion to get the mapping, because
332
+ # hf => gguf and gguf => hf mappings are reversed
333
+ gguf_to_hf_name_map = {}
334
+ state_dict = hf_model.state_dict()
335
+ for hf_name in state_dict:
336
+ # An exception for qwen2moe/qwen3moe model, where the expert layers are packed
337
+ if model_type in ("qwen2moe", "qwen3moe") and "mlp.experts." in hf_name:
338
+ hf_name = re.sub(r"mlp.experts.\d+.", "mlp.experts.", hf_name)
339
+
340
+ name, suffix = hf_name, ""
341
+ if hf_name.endswith(".weight") or hf_name.endswith(".bias"):
342
+ name, suffix = hf_name.rsplit(".", 1)
343
+ suffix = "." + suffix
344
+
345
+ gguf_name = name_map.get_name(name)
346
+ if gguf_name is None:
347
+ continue
348
+
349
+ gguf_to_hf_name_map[gguf_name + suffix] = qual_name + hf_name
350
+
351
+ # Some model like Bloom converted from BloomModel instead of BloomForCausalLM
352
+ # Therefore, we need to check submodule as well to get a correct mapping
353
+ if named_children := hf_model.named_children():
354
+ for name, child in named_children:
355
+ sub_map = get_gguf_hf_weights_map(child, model_type, num_layers, qual_name=f"{qual_name}{name}.")
356
+ # Ignore the keys that are already in the main map to avoid overwriting
357
+ sub_map = {k: v for k, v in sub_map.items() if k not in gguf_to_hf_name_map}
358
+ gguf_to_hf_name_map.update(sub_map)
359
+
360
+ return gguf_to_hf_name_map
361
+
362
+
363
+ def load_gguf_checkpoint(gguf_checkpoint_path, return_tensors=False, model_to_load=None):
364
+ """
365
+ Load a GGUF file and return a dictionary of parsed parameters containing tensors, the parsed
366
+ tokenizer and config attributes.
367
+
368
+ Args:
369
+ gguf_checkpoint_path (`str`):
370
+ The path the to GGUF file to load
371
+ return_tensors (`bool`, defaults to `False`):
372
+ Whether to read the tensors from the file and return them. Not doing so is faster
373
+ and only loads the metadata in memory.
374
+ """
375
+ if is_gguf_available() and is_torch_available():
376
+ from gguf import GGUFReader, dequantize
377
+ else:
378
+ logger.error(
379
+ "Loading a GGUF checkpoint in PyTorch, requires both PyTorch and GGUF>=0.10.0 to be installed. Please see "
380
+ "https://pytorch.org/ and https://github.com/ggerganov/llama.cpp/tree/master/gguf-py for installation instructions."
381
+ )
382
+ raise ImportError("Please install torch and gguf>=0.10.0 to load a GGUF checkpoint in PyTorch.")
383
+
384
+ reader = GGUFReader(gguf_checkpoint_path)
385
+ fields = reader.fields
386
+ reader_keys = list(fields.keys())
387
+
388
+ parsed_parameters = {k: {} for k in GGUF_TO_TRANSFORMERS_MAPPING}
389
+
390
+ architecture = read_field(reader, "general.architecture")[0]
391
+ # NOTE: Some GGUF checkpoints may miss `general.name` field in metadata
392
+ model_name = read_field(reader, "general.name")
393
+
394
+ updated_architecture = None
395
+ # in llama.cpp mistral models use the same architecture as llama. We need
396
+ # to add this patch to ensure things work correctly on our side.
397
+ if "llama" in architecture and "mistral" in model_name:
398
+ updated_architecture = "mistral"
399
+ # FIXME: Currently this implementation is only for flan-t5 architecture.
400
+ # It needs to be developed for supporting legacy t5.
401
+ elif "t5" in architecture or "t5encoder" in architecture:
402
+ parsed_parameters["config"]["is_gated_act"] = True
403
+ if model_name and "umt5" in model_name[0].lower():
404
+ updated_architecture = "umt5"
405
+ if "t5encoder" in architecture:
406
+ parsed_parameters["config"]["architectures"] = ["UMT5EncoderModel"]
407
+ else:
408
+ if "t5encoder" in architecture:
409
+ parsed_parameters["config"]["architectures"] = ["T5EncoderModel"]
410
+ updated_architecture = "t5"
411
+ else:
412
+ updated_architecture = architecture
413
+
414
+ if "qwen2moe" in architecture:
415
+ updated_architecture = "qwen2_moe"
416
+ elif "qwen3moe" in architecture:
417
+ updated_architecture = "qwen3_moe"
418
+
419
+ # For stablelm architecture, we need to set qkv_bias and use_parallel_residual from tensors
420
+ # If `qkv_bias=True`, qkv_proj with bias will be present in the tensors
421
+ # If `use_parallel_residual=False`, ffn_norm will be present in the tensors
422
+ if "stablelm" in architecture:
423
+ attn_bias_name = {"attn_q.bias", "attn_k.bias", "attn_v.bias"}
424
+ ffn_norm_name = "ffn_norm"
425
+ qkv_bias = any(bias_name in tensor.name for tensor in reader.tensors for bias_name in attn_bias_name)
426
+ use_parallel_residual = any(ffn_norm_name in tensor.name for tensor in reader.tensors)
427
+ parsed_parameters["config"]["use_qkv_bias"] = qkv_bias
428
+ parsed_parameters["config"]["use_parallel_residual"] = not use_parallel_residual
429
+
430
+ if architecture not in GGUF_SUPPORTED_ARCHITECTURES and updated_architecture not in GGUF_SUPPORTED_ARCHITECTURES:
431
+ raise ValueError(f"GGUF model with architecture {architecture} is not supported yet.")
432
+
433
+ # Handle tie_word_embeddings, if lm_head.weight is not present in tensors,
434
+ # tie_word_embeddings is true otherwise false
435
+ exceptions = ["falcon", "bloom"]
436
+ parsed_parameters["config"]["tie_word_embeddings"] = (
437
+ all("output.weight" != tensor.name for tensor in reader.tensors) or architecture in exceptions
438
+ )
439
+
440
+ # List all key-value pairs in a columnized format
441
+ for gguf_key, field in reader.fields.items():
442
+ gguf_key = gguf_key.replace(architecture, updated_architecture)
443
+ split = gguf_key.split(".")
444
+ prefix = split[0]
445
+ config_key = ".".join(split[1:])
446
+
447
+ value = [_gguf_parse_value(field.parts[_data_index], field.types) for _data_index in field.data]
448
+
449
+ if len(value) == 1:
450
+ value = value[0]
451
+
452
+ if isinstance(value, str) and architecture in value:
453
+ value = value.replace(architecture, updated_architecture)
454
+
455
+ for parameter, parameter_renames in GGUF_TO_TRANSFORMERS_MAPPING.items():
456
+ if prefix in parameter_renames and config_key in parameter_renames[prefix]:
457
+ renamed_config_key = parameter_renames[prefix][config_key]
458
+ if renamed_config_key == -1:
459
+ continue
460
+
461
+ if renamed_config_key is not None:
462
+ parsed_parameters[parameter][renamed_config_key] = value
463
+
464
+ if gguf_key in reader_keys:
465
+ reader_keys.remove(gguf_key)
466
+
467
+ if gguf_key in reader_keys:
468
+ logger.info(f"Some keys were not parsed and added into account {gguf_key} | {value}")
469
+
470
+ # Gemma3 GGUF checkpoint only contains weights of text backbone
471
+ if parsed_parameters["config"]["model_type"] == "gemma3":
472
+ parsed_parameters["config"]["model_type"] = "gemma3_text"
473
+
474
+ if parsed_parameters["config"]["model_type"] == "lfm2":
475
+ gguf_num_key_value_heads = parsed_parameters["config"]["num_key_value_heads"]
476
+ # LFM2 GGUF checkpoint defines num_key_value_heads as a list of integers .e.g [0, 0, 8, 0, 0, 8, 0, 0, 8, 0, 8, 0, 8, 0, 8, 0] but we need to set it to the max value for HF
477
+ parsed_parameters["config"]["num_key_value_heads"] = max(gguf_num_key_value_heads)
478
+ ## we already read the correct intermediate_size from the GGUF checkpoint so we need to set block_auto_adjust_ff_dim to False
479
+ parsed_parameters["config"]["block_auto_adjust_ff_dim"] = False
480
+
481
+ ## llama.cpp defines the layers that are full-attention by looking at num_key_value_heads
482
+ ## we need to set the full_attn_idxs to the layers that are full-attention
483
+ parsed_parameters["config"]["full_attn_idxs"] = [
484
+ i for i, num_kv_heads in enumerate(gguf_num_key_value_heads) if num_kv_heads > 0
485
+ ]
486
+
487
+ # retrieve config vocab_size from tokenizer
488
+ # Please refer to https://github.com/huggingface/transformers/issues/32526 for more details
489
+ if "vocab_size" not in parsed_parameters["config"]:
490
+ tokenizer_parameters = parsed_parameters["tokenizer"]
491
+ if "tokens" in tokenizer_parameters:
492
+ parsed_parameters["config"]["vocab_size"] = len(tokenizer_parameters["tokens"])
493
+ else:
494
+ logger.warning(
495
+ "Can't find a way to retrieve missing config vocab_size from tokenizer parameters. "
496
+ "This will use default value from model config class and cause unexpected behavior."
497
+ )
498
+
499
+ if return_tensors:
500
+ parsed_parameters["tensors"] = {}
501
+
502
+ tensor_key_mapping = get_gguf_hf_weights_map(model_to_load)
503
+ config = parsed_parameters.get("config", {})
504
+
505
+ ProcessorClass = TENSOR_PROCESSORS.get(architecture, TensorProcessor)
506
+ processor = ProcessorClass(config=config)
507
+
508
+ for tensor in tqdm(reader.tensors, desc="Converting and de-quantizing GGUF tensors..."):
509
+ name = tensor.name
510
+ weights = dequantize(tensor.data, tensor.tensor_type)
511
+
512
+ result = processor.process(
513
+ weights=weights,
514
+ name=name,
515
+ tensor_key_mapping=tensor_key_mapping,
516
+ parsed_parameters=parsed_parameters,
517
+ )
518
+
519
+ weights = result.weights
520
+ name = result.name
521
+
522
+ if name not in tensor_key_mapping:
523
+ continue
524
+
525
+ name = tensor_key_mapping[name]
526
+
527
+ parsed_parameters["tensors"][name] = torch.from_numpy(np.copy(weights))
528
+
529
+ if len(reader_keys) > 0:
530
+ logger.info(f"Some keys of the GGUF file were not considered: {reader_keys}")
531
+
532
+ return parsed_parameters