Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/sql/visitors.py: 65%
240 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:35 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:35 +0000
1# sql/visitors.py
2# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
8"""Visitor/traversal interface and library functions.
10SQLAlchemy schema and expression constructs rely on a Python-centric
11version of the classic "visitor" pattern as the primary way in which
12they apply functionality. The most common use of this pattern
13is statement compilation, where individual expression classes match
14up to rendering methods that produce a string result. Beyond this,
15the visitor system is also used to inspect expressions for various
16information and patterns, as well as for the purposes of applying
17transformations to expressions.
19Examples of how the visit system is used can be seen in the source code
20of for example the ``sqlalchemy.sql.util`` and the ``sqlalchemy.sql.compiler``
21modules. Some background on clause adaption is also at
22https://techspot.zzzeek.org/2008/01/23/expression-transformations/ .
24"""
26from collections import deque
27import itertools
28import operator
30from .. import exc
31from .. import util
32from ..util import langhelpers
33from ..util import symbol
35__all__ = [
36 "iterate",
37 "traverse_using",
38 "traverse",
39 "cloned_traverse",
40 "replacement_traverse",
41 "Traversible",
42 "TraversibleType",
43 "ExternalTraversal",
44 "InternalTraversal",
45]
48def _generate_compiler_dispatch(cls):
49 """Generate a _compiler_dispatch() external traversal on classes with a
50 __visit_name__ attribute.
52 """
53 visit_name = cls.__visit_name__
55 if "_compiler_dispatch" in cls.__dict__:
56 # class has a fixed _compiler_dispatch() method.
57 # copy it to "original" so that we can get it back if
58 # sqlalchemy.ext.compiles overrides it.
59 cls._original_compiler_dispatch = cls._compiler_dispatch
60 return
62 if not isinstance(visit_name, util.compat.string_types):
63 raise exc.InvalidRequestError(
64 "__visit_name__ on class %s must be a string at the class level"
65 % cls.__name__
66 )
68 name = "visit_%s" % visit_name
69 getter = operator.attrgetter(name)
71 def _compiler_dispatch(self, visitor, **kw):
72 """Look for an attribute named "visit_<visit_name>" on the
73 visitor, and call it with the same kw params.
75 """
76 try:
77 meth = getter(visitor)
78 except AttributeError as err:
79 return visitor.visit_unsupported_compilation(self, err, **kw)
81 else:
82 return meth(self, **kw)
84 cls._compiler_dispatch = (
85 cls._original_compiler_dispatch
86 ) = _compiler_dispatch
89class TraversibleType(type):
90 """Metaclass which assigns dispatch attributes to various kinds of
91 "visitable" classes.
93 Attributes include:
95 * The ``_compiler_dispatch`` method, corresponding to ``__visit_name__``.
96 This is called "external traversal" because the caller of each visit()
97 method is responsible for sub-traversing the inner elements of each
98 object. This is appropriate for string compilers and other traversals
99 that need to call upon the inner elements in a specific pattern.
101 * internal traversal collections ``_children_traversal``,
102 ``_cache_key_traversal``, ``_copy_internals_traversal``, generated from
103 an optional ``_traverse_internals`` collection of symbols which comes
104 from the :class:`.InternalTraversal` list of symbols. This is called
105 "internal traversal" MARKMARK
107 """
109 def __init__(cls, clsname, bases, clsdict):
110 if clsname != "Traversible":
111 if "__visit_name__" in clsdict:
112 _generate_compiler_dispatch(cls)
114 super(TraversibleType, cls).__init__(clsname, bases, clsdict)
117class Traversible(util.with_metaclass(TraversibleType)):
118 """Base class for visitable objects, applies the
119 :class:`.visitors.TraversibleType` metaclass.
121 """
123 def __class_getitem__(cls, key):
124 # allow generic classes in py3.9+
125 return cls
127 @util.preload_module("sqlalchemy.sql.traversals")
128 def get_children(self, omit_attrs=(), **kw):
129 r"""Return immediate child :class:`.visitors.Traversible`
130 elements of this :class:`.visitors.Traversible`.
132 This is used for visit traversal.
134 \**kw may contain flags that change the collection that is
135 returned, for example to return a subset of items in order to
136 cut down on larger traversals, or to return child items from a
137 different context (such as schema-level collections instead of
138 clause-level).
140 """
142 traversals = util.preloaded.sql_traversals
144 try:
145 traverse_internals = self._traverse_internals
146 except AttributeError:
147 # user-defined classes may not have a _traverse_internals
148 return []
150 dispatch = traversals._get_children.run_generated_dispatch
151 return itertools.chain.from_iterable(
152 meth(obj, **kw)
153 for attrname, obj, meth in dispatch(
154 self, traverse_internals, "_generated_get_children_traversal"
155 )
156 if attrname not in omit_attrs and obj is not None
157 )
160class _InternalTraversalType(type):
161 def __init__(cls, clsname, bases, clsdict):
162 if cls.__name__ in ("InternalTraversal", "ExtendedInternalTraversal"):
163 lookup = {}
164 for key, sym in clsdict.items():
165 if key.startswith("dp_"):
166 visit_key = key.replace("dp_", "visit_")
167 sym_name = sym.name
168 assert sym_name not in lookup, sym_name
169 lookup[sym] = lookup[sym_name] = visit_key
170 if hasattr(cls, "_dispatch_lookup"):
171 lookup.update(cls._dispatch_lookup)
172 cls._dispatch_lookup = lookup
174 super(_InternalTraversalType, cls).__init__(clsname, bases, clsdict)
177def _generate_dispatcher(visitor, internal_dispatch, method_name):
178 names = []
179 for attrname, visit_sym in internal_dispatch:
180 meth = visitor.dispatch(visit_sym)
181 if meth:
182 visit_name = ExtendedInternalTraversal._dispatch_lookup[visit_sym]
183 names.append((attrname, visit_name))
185 code = (
186 (" return [\n")
187 + (
188 ", \n".join(
189 " (%r, self.%s, visitor.%s)"
190 % (attrname, attrname, visit_name)
191 for attrname, visit_name in names
192 )
193 )
194 + ("\n ]\n")
195 )
196 meth_text = ("def %s(self, visitor):\n" % method_name) + code + "\n"
197 # print(meth_text)
198 return langhelpers._exec_code_in_env(meth_text, {}, method_name)
201class InternalTraversal(util.with_metaclass(_InternalTraversalType, object)):
202 r"""Defines visitor symbols used for internal traversal.
204 The :class:`.InternalTraversal` class is used in two ways. One is that
205 it can serve as the superclass for an object that implements the
206 various visit methods of the class. The other is that the symbols
207 themselves of :class:`.InternalTraversal` are used within
208 the ``_traverse_internals`` collection. Such as, the :class:`.Case`
209 object defines ``_traverse_internals`` as ::
211 _traverse_internals = [
212 ("value", InternalTraversal.dp_clauseelement),
213 ("whens", InternalTraversal.dp_clauseelement_tuples),
214 ("else_", InternalTraversal.dp_clauseelement),
215 ]
217 Above, the :class:`.Case` class indicates its internal state as the
218 attributes named ``value``, ``whens``, and ``else_``. They each
219 link to an :class:`.InternalTraversal` method which indicates the type
220 of datastructure referred towards.
222 Using the ``_traverse_internals`` structure, objects of type
223 :class:`.InternalTraversible` will have the following methods automatically
224 implemented:
226 * :meth:`.Traversible.get_children`
228 * :meth:`.Traversible._copy_internals`
230 * :meth:`.Traversible._gen_cache_key`
232 Subclasses can also implement these methods directly, particularly for the
233 :meth:`.Traversible._copy_internals` method, when special steps
234 are needed.
236 .. versionadded:: 1.4
238 """
240 def dispatch(self, visit_symbol):
241 """Given a method from :class:`.InternalTraversal`, return the
242 corresponding method on a subclass.
244 """
245 name = self._dispatch_lookup[visit_symbol]
246 return getattr(self, name, None)
248 def run_generated_dispatch(
249 self, target, internal_dispatch, generate_dispatcher_name
250 ):
251 try:
252 dispatcher = target.__class__.__dict__[generate_dispatcher_name]
253 except KeyError:
254 # most of the dispatchers are generated up front
255 # in sqlalchemy/sql/__init__.py ->
256 # traversals.py-> _preconfigure_traversals().
257 # this block will generate any remaining dispatchers.
258 dispatcher = self.generate_dispatch(
259 target.__class__, internal_dispatch, generate_dispatcher_name
260 )
261 return dispatcher(target, self)
263 def generate_dispatch(
264 self, target_cls, internal_dispatch, generate_dispatcher_name
265 ):
266 dispatcher = _generate_dispatcher(
267 self, internal_dispatch, generate_dispatcher_name
268 )
269 # assert isinstance(target_cls, type)
270 setattr(target_cls, generate_dispatcher_name, dispatcher)
271 return dispatcher
273 dp_has_cache_key = symbol("HC")
274 """Visit a :class:`.HasCacheKey` object."""
276 dp_has_cache_key_list = symbol("HL")
277 """Visit a list of :class:`.HasCacheKey` objects."""
279 dp_clauseelement = symbol("CE")
280 """Visit a :class:`_expression.ClauseElement` object."""
282 dp_fromclause_canonical_column_collection = symbol("FC")
283 """Visit a :class:`_expression.FromClause` object in the context of the
284 ``columns`` attribute.
286 The column collection is "canonical", meaning it is the originally
287 defined location of the :class:`.ColumnClause` objects. Right now
288 this means that the object being visited is a
289 :class:`_expression.TableClause`
290 or :class:`_schema.Table` object only.
292 """
294 dp_clauseelement_tuples = symbol("CTS")
295 """Visit a list of tuples which contain :class:`_expression.ClauseElement`
296 objects.
298 """
300 dp_clauseelement_list = symbol("CL")
301 """Visit a list of :class:`_expression.ClauseElement` objects.
303 """
305 dp_clauseelement_tuple = symbol("CT")
306 """Visit a tuple of :class:`_expression.ClauseElement` objects.
308 """
310 dp_executable_options = symbol("EO")
312 dp_with_context_options = symbol("WC")
314 dp_fromclause_ordered_set = symbol("CO")
315 """Visit an ordered set of :class:`_expression.FromClause` objects. """
317 dp_string = symbol("S")
318 """Visit a plain string value.
320 Examples include table and column names, bound parameter keys, special
321 keywords such as "UNION", "UNION ALL".
323 The string value is considered to be significant for cache key
324 generation.
326 """
328 dp_string_list = symbol("SL")
329 """Visit a list of strings."""
331 dp_anon_name = symbol("AN")
332 """Visit a potentially "anonymized" string value.
334 The string value is considered to be significant for cache key
335 generation.
337 """
339 dp_boolean = symbol("B")
340 """Visit a boolean value.
342 The boolean value is considered to be significant for cache key
343 generation.
345 """
347 dp_operator = symbol("O")
348 """Visit an operator.
350 The operator is a function from the :mod:`sqlalchemy.sql.operators`
351 module.
353 The operator value is considered to be significant for cache key
354 generation.
356 """
358 dp_type = symbol("T")
359 """Visit a :class:`.TypeEngine` object
361 The type object is considered to be significant for cache key
362 generation.
364 """
366 dp_plain_dict = symbol("PD")
367 """Visit a dictionary with string keys.
369 The keys of the dictionary should be strings, the values should
370 be immutable and hashable. The dictionary is considered to be
371 significant for cache key generation.
373 """
375 dp_dialect_options = symbol("DO")
376 """Visit a dialect options structure."""
378 dp_string_clauseelement_dict = symbol("CD")
379 """Visit a dictionary of string keys to :class:`_expression.ClauseElement`
380 objects.
382 """
384 dp_string_multi_dict = symbol("MD")
385 """Visit a dictionary of string keys to values which may either be
386 plain immutable/hashable or :class:`.HasCacheKey` objects.
388 """
390 dp_annotations_key = symbol("AK")
391 """Visit the _annotations_cache_key element.
393 This is a dictionary of additional information about a ClauseElement
394 that modifies its role. It should be included when comparing or caching
395 objects, however generating this key is relatively expensive. Visitors
396 should check the "_annotations" dict for non-None first before creating
397 this key.
399 """
401 dp_plain_obj = symbol("PO")
402 """Visit a plain python object.
404 The value should be immutable and hashable, such as an integer.
405 The value is considered to be significant for cache key generation.
407 """
409 dp_named_ddl_element = symbol("DD")
410 """Visit a simple named DDL element.
412 The current object used by this method is the :class:`.Sequence`.
414 The object is only considered to be important for cache key generation
415 as far as its name, but not any other aspects of it.
417 """
419 dp_prefix_sequence = symbol("PS")
420 """Visit the sequence represented by :class:`_expression.HasPrefixes`
421 or :class:`_expression.HasSuffixes`.
423 """
425 dp_table_hint_list = symbol("TH")
426 """Visit the ``_hints`` collection of a :class:`_expression.Select`
427 object.
429 """
431 dp_setup_join_tuple = symbol("SJ")
433 dp_memoized_select_entities = symbol("ME")
435 dp_statement_hint_list = symbol("SH")
436 """Visit the ``_statement_hints`` collection of a
437 :class:`_expression.Select`
438 object.
440 """
442 dp_unknown_structure = symbol("UK")
443 """Visit an unknown structure.
445 """
447 dp_dml_ordered_values = symbol("DML_OV")
448 """Visit the values() ordered tuple list of an
449 :class:`_expression.Update` object."""
451 dp_dml_values = symbol("DML_V")
452 """Visit the values() dictionary of a :class:`.ValuesBase`
453 (e.g. Insert or Update) object.
455 """
457 dp_dml_multi_values = symbol("DML_MV")
458 """Visit the values() multi-valued list of dictionaries of an
459 :class:`_expression.Insert` object.
461 """
463 dp_propagate_attrs = symbol("PA")
464 """Visit the propagate attrs dict. This hardcodes to the particular
465 elements we care about right now."""
468class ExtendedInternalTraversal(InternalTraversal):
469 """Defines additional symbols that are useful in caching applications.
471 Traversals for :class:`_expression.ClauseElement` objects only need to use
472 those symbols present in :class:`.InternalTraversal`. However, for
473 additional caching use cases within the ORM, symbols dealing with the
474 :class:`.HasCacheKey` class are added here.
476 """
478 dp_ignore = symbol("IG")
479 """Specify an object that should be ignored entirely.
481 This currently applies function call argument caching where some
482 arguments should not be considered to be part of a cache key.
484 """
486 dp_inspectable = symbol("IS")
487 """Visit an inspectable object where the return value is a
488 :class:`.HasCacheKey` object."""
490 dp_multi = symbol("M")
491 """Visit an object that may be a :class:`.HasCacheKey` or may be a
492 plain hashable object."""
494 dp_multi_list = symbol("MT")
495 """Visit a tuple containing elements that may be :class:`.HasCacheKey` or
496 may be a plain hashable object."""
498 dp_has_cache_key_tuples = symbol("HT")
499 """Visit a list of tuples which contain :class:`.HasCacheKey`
500 objects.
502 """
504 dp_inspectable_list = symbol("IL")
505 """Visit a list of inspectable objects which upon inspection are
506 HasCacheKey objects."""
509class ExternalTraversal(object):
510 """Base class for visitor objects which can traverse externally using
511 the :func:`.visitors.traverse` function.
513 Direct usage of the :func:`.visitors.traverse` function is usually
514 preferred.
516 """
518 __traverse_options__ = {}
520 def traverse_single(self, obj, **kw):
521 for v in self.visitor_iterator:
522 meth = getattr(v, "visit_%s" % obj.__visit_name__, None)
523 if meth:
524 return meth(obj, **kw)
526 def iterate(self, obj):
527 """Traverse the given expression structure, returning an iterator
528 of all elements.
530 """
531 return iterate(obj, self.__traverse_options__)
533 def traverse(self, obj):
534 """Traverse and visit the given expression structure."""
536 return traverse(obj, self.__traverse_options__, self._visitor_dict)
538 @util.memoized_property
539 def _visitor_dict(self):
540 visitors = {}
542 for name in dir(self):
543 if name.startswith("visit_"):
544 visitors[name[6:]] = getattr(self, name)
545 return visitors
547 @property
548 def visitor_iterator(self):
549 """Iterate through this visitor and each 'chained' visitor."""
551 v = self
552 while v:
553 yield v
554 v = getattr(v, "_next", None)
556 def chain(self, visitor):
557 """'Chain' an additional ClauseVisitor onto this ClauseVisitor.
559 The chained visitor will receive all visit events after this one.
561 """
562 tail = list(self.visitor_iterator)[-1]
563 tail._next = visitor
564 return self
567class CloningExternalTraversal(ExternalTraversal):
568 """Base class for visitor objects which can traverse using
569 the :func:`.visitors.cloned_traverse` function.
571 Direct usage of the :func:`.visitors.cloned_traverse` function is usually
572 preferred.
575 """
577 def copy_and_process(self, list_):
578 """Apply cloned traversal to the given list of elements, and return
579 the new list.
581 """
582 return [self.traverse(x) for x in list_]
584 def traverse(self, obj):
585 """Traverse and visit the given expression structure."""
587 return cloned_traverse(
588 obj, self.__traverse_options__, self._visitor_dict
589 )
592class ReplacingExternalTraversal(CloningExternalTraversal):
593 """Base class for visitor objects which can traverse using
594 the :func:`.visitors.replacement_traverse` function.
596 Direct usage of the :func:`.visitors.replacement_traverse` function is
597 usually preferred.
599 """
601 def replace(self, elem):
602 """Receive pre-copied elements during a cloning traversal.
604 If the method returns a new element, the element is used
605 instead of creating a simple copy of the element. Traversal
606 will halt on the newly returned element if it is re-encountered.
607 """
608 return None
610 def traverse(self, obj):
611 """Traverse and visit the given expression structure."""
613 def replace(elem):
614 for v in self.visitor_iterator:
615 e = v.replace(elem)
616 if e is not None:
617 return e
619 return replacement_traverse(obj, self.__traverse_options__, replace)
622# backwards compatibility
623Visitable = Traversible
624VisitableType = TraversibleType
625ClauseVisitor = ExternalTraversal
626CloningVisitor = CloningExternalTraversal
627ReplacingCloningVisitor = ReplacingExternalTraversal
630def iterate(obj, opts=util.immutabledict()):
631 r"""Traverse the given expression structure, returning an iterator.
633 Traversal is configured to be breadth-first.
635 The central API feature used by the :func:`.visitors.iterate`
636 function is the
637 :meth:`_expression.ClauseElement.get_children` method of
638 :class:`_expression.ClauseElement` objects. This method should return all
639 the :class:`_expression.ClauseElement` objects which are associated with a
640 particular :class:`_expression.ClauseElement` object. For example, a
641 :class:`.Case` structure will refer to a series of
642 :class:`_expression.ColumnElement` objects within its "whens" and "else\_"
643 member variables.
645 :param obj: :class:`_expression.ClauseElement` structure to be traversed
647 :param opts: dictionary of iteration options. This dictionary is usually
648 empty in modern usage.
650 """
651 yield obj
652 children = obj.get_children(**opts)
654 if not children:
655 return
657 stack = deque([children])
658 while stack:
659 t_iterator = stack.popleft()
660 for t in t_iterator:
661 yield t
662 stack.append(t.get_children(**opts))
665def traverse_using(iterator, obj, visitors):
666 """Visit the given expression structure using the given iterator of
667 objects.
669 :func:`.visitors.traverse_using` is usually called internally as the result
670 of the :func:`.visitors.traverse` function.
672 :param iterator: an iterable or sequence which will yield
673 :class:`_expression.ClauseElement`
674 structures; the iterator is assumed to be the
675 product of the :func:`.visitors.iterate` function.
677 :param obj: the :class:`_expression.ClauseElement`
678 that was used as the target of the
679 :func:`.iterate` function.
681 :param visitors: dictionary of visit functions. See :func:`.traverse`
682 for details on this dictionary.
684 .. seealso::
686 :func:`.traverse`
689 """
690 for target in iterator:
691 meth = visitors.get(target.__visit_name__, None)
692 if meth:
693 meth(target)
694 return obj
697def traverse(obj, opts, visitors):
698 """Traverse and visit the given expression structure using the default
699 iterator.
701 e.g.::
703 from sqlalchemy.sql import visitors
705 stmt = select(some_table).where(some_table.c.foo == 'bar')
707 def visit_bindparam(bind_param):
708 print("found bound value: %s" % bind_param.value)
710 visitors.traverse(stmt, {}, {"bindparam": visit_bindparam})
712 The iteration of objects uses the :func:`.visitors.iterate` function,
713 which does a breadth-first traversal using a stack.
715 :param obj: :class:`_expression.ClauseElement` structure to be traversed
717 :param opts: dictionary of iteration options. This dictionary is usually
718 empty in modern usage.
720 :param visitors: dictionary of visit functions. The dictionary should
721 have strings as keys, each of which would correspond to the
722 ``__visit_name__`` of a particular kind of SQL expression object, and
723 callable functions as values, each of which represents a visitor function
724 for that kind of object.
726 """
727 return traverse_using(iterate(obj, opts), obj, visitors)
730def cloned_traverse(obj, opts, visitors):
731 """Clone the given expression structure, allowing modifications by
732 visitors.
734 Traversal usage is the same as that of :func:`.visitors.traverse`.
735 The visitor functions present in the ``visitors`` dictionary may also
736 modify the internals of the given structure as the traversal proceeds.
738 The central API feature used by the :func:`.visitors.cloned_traverse`
739 and :func:`.visitors.replacement_traverse` functions, in addition to the
740 :meth:`_expression.ClauseElement.get_children`
741 function that is used to achieve
742 the iteration, is the :meth:`_expression.ClauseElement._copy_internals`
743 method.
744 For a :class:`_expression.ClauseElement`
745 structure to support cloning and replacement
746 traversals correctly, it needs to be able to pass a cloning function into
747 its internal members in order to make copies of them.
749 .. seealso::
751 :func:`.visitors.traverse`
753 :func:`.visitors.replacement_traverse`
755 """
757 cloned = {}
758 stop_on = set(opts.get("stop_on", []))
760 def deferred_copy_internals(obj):
761 return cloned_traverse(obj, opts, visitors)
763 def clone(elem, **kw):
764 if elem in stop_on:
765 return elem
766 else:
767 if id(elem) not in cloned:
769 if "replace" in kw:
770 newelem = kw["replace"](elem)
771 if newelem is not None:
772 cloned[id(elem)] = newelem
773 return newelem
775 cloned[id(elem)] = newelem = elem._clone(clone=clone, **kw)
776 newelem._copy_internals(clone=clone, **kw)
777 meth = visitors.get(newelem.__visit_name__, None)
778 if meth:
779 meth(newelem)
780 return cloned[id(elem)]
782 if obj is not None:
783 obj = clone(
784 obj, deferred_copy_internals=deferred_copy_internals, **opts
785 )
786 clone = None # remove gc cycles
787 return obj
790def replacement_traverse(obj, opts, replace):
791 """Clone the given expression structure, allowing element
792 replacement by a given replacement function.
794 This function is very similar to the :func:`.visitors.cloned_traverse`
795 function, except instead of being passed a dictionary of visitors, all
796 elements are unconditionally passed into the given replace function.
797 The replace function then has the option to return an entirely new object
798 which will replace the one given. If it returns ``None``, then the object
799 is kept in place.
801 The difference in usage between :func:`.visitors.cloned_traverse` and
802 :func:`.visitors.replacement_traverse` is that in the former case, an
803 already-cloned object is passed to the visitor function, and the visitor
804 function can then manipulate the internal state of the object.
805 In the case of the latter, the visitor function should only return an
806 entirely different object, or do nothing.
808 The use case for :func:`.visitors.replacement_traverse` is that of
809 replacing a FROM clause inside of a SQL structure with a different one,
810 as is a common use case within the ORM.
812 """
814 cloned = {}
815 stop_on = {id(x) for x in opts.get("stop_on", [])}
817 def deferred_copy_internals(obj):
818 return replacement_traverse(obj, opts, replace)
820 def clone(elem, **kw):
821 if (
822 id(elem) in stop_on
823 or "no_replacement_traverse" in elem._annotations
824 ):
825 return elem
826 else:
827 newelem = replace(elem)
828 if newelem is not None:
829 stop_on.add(id(newelem))
830 return newelem
831 else:
832 # base "already seen" on id(), not hash, so that we don't
833 # replace an Annotated element with its non-annotated one, and
834 # vice versa
835 id_elem = id(elem)
836 if id_elem not in cloned:
837 if "replace" in kw:
838 newelem = kw["replace"](elem)
839 if newelem is not None:
840 cloned[id_elem] = newelem
841 return newelem
843 cloned[id_elem] = newelem = elem._clone(**kw)
844 newelem._copy_internals(clone=clone, **kw)
845 return cloned[id_elem]
847 if obj is not None:
848 obj = clone(
849 obj, deferred_copy_internals=deferred_copy_internals, **opts
850 )
851 clone = None # remove gc cycles
852 return obj