FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

# SOME DESCRIPTIVE TITLE. # Copyright (C) 2001 Python Software Foundation # This file is distributed under the same license as the Python package. # FIRST AUTHOR , YEAR. # # Translators: # Swen Bachmann, 2026 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Python 3.14\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-09-28 03:11+0000\n" "PO-Revision-Date: 2026-05-08 17:17+0000\n" "Last-Translator: Swen Bachmann, 2026\n" "Language-Team: German (https://app.transifex.com/python-doc/teams/5390/de/)\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../../library/annotationlib.rst:2 msgid ":mod:`!annotationlib` --- Functionality for introspecting annotations" msgstr "" #: ../../library/annotationlib.rst:9 msgid "**Source code:** :source:`Lib/annotationlib.py`" msgstr "" #: ../../library/annotationlib.rst:18 msgid "" "The :mod:`!annotationlib` module provides tools for introspecting :term:" "`annotations ` on modules, classes, and functions." msgstr "" #: ../../library/annotationlib.rst:21 msgid "" "Annotations are :ref:`lazily evaluated ` and often contain " "forward references to objects that are not yet defined when the annotation " "is created. This module provides a set of low-level tools that can be used " "to retrieve annotations in a reliable way, even in the presence of forward " "references and other edge cases." msgstr "" #: ../../library/annotationlib.rst:26 msgid "" "This module supports retrieving annotations in three main formats (see :" "class:`Format`), each of which works best for different use cases:" msgstr "" #: ../../library/annotationlib.rst:29 msgid "" ":attr:`~Format.VALUE` evaluates the annotations and returns their value. " "This is most straightforward to work with, but it may raise errors, for " "example if the annotations contain references to undefined names." msgstr "" #: ../../library/annotationlib.rst:32 msgid "" ":attr:`~Format.FORWARDREF` returns :class:`ForwardRef` objects for " "annotations that cannot be resolved, allowing you to inspect the annotations " "without evaluating them. This is useful when you need to work with " "annotations that may contain unresolved forward references." msgstr "" #: ../../library/annotationlib.rst:36 msgid "" ":attr:`~Format.STRING` returns the annotations as a string, similar to how " "it would appear in the source file. This is useful for documentation " "generators that want to display annotations in a readable way." msgstr "" #: ../../library/annotationlib.rst:40 msgid "" "The :func:`get_annotations` function is the main entry point for retrieving " "annotations. Given a function, class, or module, it returns an annotations " "dictionary in the requested format. This module also provides functionality " "for working directly with the :term:`annotate function` that is used to " "evaluate annotations, such as :func:`get_annotate_from_class_namespace` and :" "func:`call_annotate_function`, as well as the :func:`call_evaluate_function` " "function for working with :term:`evaluate functions `." msgstr "" #: ../../library/annotationlib.rst:51 msgid "" "Most functionality in this module can execute arbitrary code; see :ref:`the " "security section ` for more information." msgstr "" #: ../../library/annotationlib.rst:56 msgid "" ":pep:`649` proposed the current model for how annotations work in Python." msgstr "" #: ../../library/annotationlib.rst:58 msgid "" ":pep:`749` expanded on various aspects of :pep:`649` and introduced the :mod:" "`!annotationlib` module." msgstr "" #: ../../library/annotationlib.rst:61 msgid "" ":ref:`annotations-howto` provides best practices for working with " "annotations." msgstr "" #: ../../library/annotationlib.rst:64 msgid "" ":pypi:`typing-extensions` provides a backport of :func:`get_annotations` " "that works on earlier versions of Python." msgstr "" #: ../../library/annotationlib.rst:68 msgid "Annotation semantics" msgstr "" #: ../../library/annotationlib.rst:70 msgid "" "The way annotations are evaluated has changed over the history of Python 3, " "and currently still depends on a :ref:`future import `. There have " "been execution models for annotations:" msgstr "" #: ../../library/annotationlib.rst:74 msgid "" "*Stock semantics* (default in Python 3.0 through 3.13; see :pep:`3107` and :" "pep:`526`): Annotations are evaluated eagerly, as they are encountered in " "the source code." msgstr "" #: ../../library/annotationlib.rst:77 msgid "" "*Stringified annotations* (used with ``from __future__ import annotations`` " "in Python 3.7 and newer; see :pep:`563`): Annotations are stored as strings " "only." msgstr "" #: ../../library/annotationlib.rst:80 msgid "" "*Deferred evaluation* (default in Python 3.14 and newer; see :pep:`649` and :" "pep:`749`): Annotations are evaluated lazily, only when they are accessed." msgstr "" #: ../../library/annotationlib.rst:83 msgid "As an example, consider the following program::" msgstr "" #: ../../library/annotationlib.rst:85 msgid "" "def func(a: Cls) -> None:\n" " print(a)\n" "\n" "class Cls: pass\n" "\n" "print(func.__annotations__)" msgstr "" #: ../../library/annotationlib.rst:92 msgid "This will behave as follows:" msgstr "" #: ../../library/annotationlib.rst:94 msgid "" "Under stock semantics (Python 3.13 and earlier), it will throw a :exc:" "`NameError` at the line where ``func`` is defined, because ``Cls`` is an " "undefined name at that point." msgstr "" #: ../../library/annotationlib.rst:97 msgid "" "Under stringified annotations (if ``from __future__ import annotations`` is " "used), it will print ``{'a': 'Cls', 'return': 'None'}``." msgstr "" #: ../../library/annotationlib.rst:99 msgid "" "Under deferred evaluation (Python 3.14 and later), it will print ``{'a': " ", 'return': None}``." msgstr "" #: ../../library/annotationlib.rst:102 msgid "" "Stock semantics were used when function annotations were first introduced in " "Python 3.0 (by :pep:`3107`) because this was the simplest, most obvious way " "to implement annotations. The same execution model was used when variable " "annotations were introduced in Python 3.6 (by :pep:`526`). However, stock " "semantics caused problems when using annotations as type hints, such as a " "need to refer to names that are not yet defined when the annotation is " "encountered. In addition, there were performance problems with executing " "annotations at module import time. Therefore, in Python 3.7, :pep:`563` " "introduced the ability to store annotations as strings using the ``from " "__future__ import annotations`` syntax. The plan at the time was to " "eventually make this behavior the default, but a problem appeared: " "stringified annotations are more difficult to process for those who " "introspect annotations at runtime. An alternative proposal, :pep:`649`, " "introduced the third execution model, deferred evaluation, and was " "implemented in Python 3.14. Stringified annotations are still used if ``from " "__future__ import annotations`` is present, but this behavior will " "eventually be removed." msgstr "" #: ../../library/annotationlib.rst:121 msgid "Classes" msgstr "Klassen" #: ../../library/annotationlib.rst:125 msgid "" "An :class:`~enum.IntEnum` describing the formats in which annotations can be " "returned. Members of the enum, or their equivalent integer values, can be " "passed to :func:`get_annotations` and other functions in this module, as " "well as to :attr:`~object.__annotate__` functions." msgstr "" #: ../../library/annotationlib.rst:133 msgid "Values are the result of evaluating the annotation expressions." msgstr "" #: ../../library/annotationlib.rst:138 msgid "" "Special value used to signal that an annotate function is being evaluated in " "a special environment with fake globals. When passed this value, annotate " "functions should either return the same value as for the :attr:`Format." "VALUE` format, or raise :exc:`NotImplementedError` to signal that they do " "not support execution in this environment. This format is only used " "internally and should not be passed to the functions in this module." msgstr "" #: ../../library/annotationlib.rst:149 msgid "" "Values are real annotation values (as per :attr:`Format.VALUE` format) for " "defined values, and :class:`ForwardRef` proxies for undefined values. Real " "objects may contain references to :class:`ForwardRef` proxy objects." msgstr "" #: ../../library/annotationlib.rst:157 msgid "" "Values are the text string of the annotation as it appears in the source " "code, up to modifications including, but not restricted to, whitespace " "normalizations and constant values optimizations." msgstr "" #: ../../library/annotationlib.rst:161 msgid "" "The exact values of these strings may change in future versions of Python." msgstr "" #: ../../library/annotationlib.rst:167 msgid "A proxy object for forward references in annotations." msgstr "" #: ../../library/annotationlib.rst:169 msgid "" "Instances of this class are returned when the :attr:`~Format.FORWARDREF` " "format is used and annotations contain a name that cannot be resolved. This " "can happen when a forward reference is used in an annotation, such as when a " "class is referenced before it is defined." msgstr "" #: ../../library/annotationlib.rst:176 msgid "" "A string containing the code that was evaluated to produce the :class:" "`~ForwardRef`. The string may not be exactly equivalent to the original " "source." msgstr "" #: ../../library/annotationlib.rst:182 msgid "Evaluate the forward reference, returning its value." msgstr "" #: ../../library/annotationlib.rst:184 msgid "" "If the *format* argument is :attr:`~Format.VALUE` (the default), this method " "may throw an exception, such as :exc:`NameError`, if the forward reference " "refers to a name that cannot be resolved. The arguments to this method can " "be used to provide bindings for names that would otherwise be undefined. If " "the *format* argument is :attr:`~Format.FORWARDREF`, the method will never " "throw an exception, but may return a :class:`~ForwardRef` instance. For " "example, if the forward reference object contains the code " "``list[undefined]``, where ``undefined`` is a name that is not defined, " "evaluating it with the :attr:`~Format.FORWARDREF` format will return " "``list[ForwardRef('undefined')]``. If the *format* argument is :attr:" "`~Format.STRING`, the method will return :attr:`~ForwardRef.__forward_arg__`." msgstr "" #: ../../library/annotationlib.rst:196 msgid "" "The *owner* parameter provides the preferred mechanism for passing scope " "information to this method. The owner of a :class:`~ForwardRef` is the " "object that contains the annotation from which the :class:`~ForwardRef` " "derives, such as a module object, type object, or function object." msgstr "" #: ../../library/annotationlib.rst:201 msgid "" "The *globals*, *locals*, and *type_params* parameters provide a more precise " "mechanism for influencing the names that are available when the :class:" "`~ForwardRef` is evaluated. *globals* and *locals* are passed to :func:" "`eval`, representing the global and local namespaces in which the name is " "evaluated. The *type_params* parameter is relevant for objects created using " "the native syntax for :ref:`generic classes ` and :ref:" "`functions `. It is a tuple of :ref:`type parameters " "` that are in scope while the forward reference is being " "evaluated. For example, if evaluating a :class:`~ForwardRef` retrieved from " "an annotation found in the class namespace of a generic class ``C``, " "*type_params* should be set to ``C.__type_params__``." msgstr "" #: ../../library/annotationlib.rst:212 msgid "" ":class:`~ForwardRef` instances returned by :func:`get_annotations` retain " "references to information about the scope they originated from, so calling " "this method with no further arguments may be sufficient to evaluate such " "objects. :class:`~ForwardRef` instances created by other means may not have " "any information about their scope, so passing arguments to this method may " "be necessary to evaluate them successfully." msgstr "" #: ../../library/annotationlib.rst:219 msgid "" "If no *owner*, *globals*, *locals*, or *type_params* are provided and the :" "class:`~ForwardRef` does not contain information about its origin, empty " "globals and locals dictionaries are used." msgstr "" #: ../../library/annotationlib.rst:227 msgid "Functions" msgstr "Funktionen" #: ../../library/annotationlib.rst:231 msgid "" "Convert an annotations dict containing runtime values to a dict containing " "only strings. If the values are not already strings, they are converted " "using :func:`type_repr`. This is meant as a helper for user-provided " "annotate functions that support the :attr:`~Format.STRING` format but do not " "have access to the code creating the annotations." msgstr "" #: ../../library/annotationlib.rst:238 msgid "" "For example, this is used to implement the :attr:`~Format.STRING` format " "for :class:`typing.TypedDict` classes created through the functional syntax:" msgstr "" #: ../../library/annotationlib.rst:241 msgid "" ">>> from typing import TypedDict\n" ">>> Movie = TypedDict(\"movie\", {\"name\": str, \"year\": int})\n" ">>> get_annotations(Movie, format=Format.STRING)\n" "{'name': 'str', 'year': 'int'}" msgstr "" #: ../../library/annotationlib.rst:252 msgid "" "Call the :term:`annotate function` *annotate* with the given *format*, a " "member of the :class:`Format` enum, and return the annotations dictionary " "produced by the function." msgstr "" #: ../../library/annotationlib.rst:256 msgid "" "This helper function is required because annotate functions generated by the " "compiler for functions, classes, and modules only support the :attr:`~Format." "VALUE` format when called directly. To support other formats, this function " "calls the annotate function in a special environment that allows it to " "produce annotations in the other formats. This is a useful building block " "when implementing functionality that needs to partially evaluate annotations " "while a class is being constructed." msgstr "" #: ../../library/annotationlib.rst:265 msgid "" "*owner* is the object that owns the annotation function, usually a function, " "class, or module. If provided, it is used in the :attr:`~Format.FORWARDREF` " "format to produce a :class:`ForwardRef` object that carries more information." msgstr "" #: ../../library/annotationlib.rst:272 msgid "" ":PEP:`PEP 649 ` " "contains an explanation of the implementation technique used by this " "function." msgstr "" #: ../../library/annotationlib.rst:280 msgid "" "Call the :term:`evaluate function` *evaluate* with the given *format*, a " "member of the :class:`Format` enum, and return the value produced by the " "function. This is similar to :func:`call_annotate_function`, but the latter " "always returns a dictionary mapping strings to annotations, while this " "function returns a single value." msgstr "" #: ../../library/annotationlib.rst:286 msgid "" "This is intended for use with the evaluate functions generated for lazily " "evaluated elements related to type aliases and type parameters:" msgstr "" #: ../../library/annotationlib.rst:289 msgid ":meth:`typing.TypeAliasType.evaluate_value`, the value of type aliases" msgstr "" #: ../../library/annotationlib.rst:290 msgid ":meth:`typing.TypeVar.evaluate_bound`, the bound of type variables" msgstr "" #: ../../library/annotationlib.rst:291 msgid "" ":meth:`typing.TypeVar.evaluate_constraints`, the constraints of type " "variables" msgstr "" #: ../../library/annotationlib.rst:293 msgid "" ":meth:`typing.TypeVar.evaluate_default`, the default value of type variables" msgstr "" #: ../../library/annotationlib.rst:295 msgid "" ":meth:`typing.ParamSpec.evaluate_default`, the default value of parameter " "specifications" msgstr "" #: ../../library/annotationlib.rst:297 msgid "" ":meth:`typing.TypeVarTuple.evaluate_default`, the default value of type " "variable tuples" msgstr "" #: ../../library/annotationlib.rst:300 msgid "" "*owner* is the object that owns the evaluate function, such as the type " "alias or type variable object." msgstr "" #: ../../library/annotationlib.rst:303 msgid "" "*format* can be used to control the format in which the value is returned:" msgstr "" #: ../../library/annotationlib.rst:305 msgid "" ">>> type Alias = undefined\n" ">>> call_evaluate_function(Alias.evaluate_value, Format.VALUE)\n" "Traceback (most recent call last):\n" "...\n" "NameError: name 'undefined' is not defined\n" ">>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)\n" "ForwardRef('undefined')\n" ">>> call_evaluate_function(Alias.evaluate_value, Format.STRING)\n" "'undefined'" msgstr "" #: ../../library/annotationlib.rst:321 msgid "" "Retrieve the :term:`annotate function` from a class namespace dictionary " "*namespace*. Return :const:`!None` if the namespace does not contain an " "annotate function. This is primarily useful before the class has been fully " "created (e.g., in a metaclass); after the class exists, the annotate " "function can be retrieved with ``cls.__annotate__``. See :ref:`below " "` for an example using this function in a metaclass." msgstr "" #: ../../library/annotationlib.rst:331 msgid "Compute the annotations dict for an object." msgstr "" #: ../../library/annotationlib.rst:333 msgid "" "*obj* may be a callable, class, module, or other object with :attr:`~object." "__annotate__` or :attr:`~object.__annotations__` attributes. Passing any " "other object raises :exc:`TypeError`." msgstr "" #: ../../library/annotationlib.rst:337 msgid "" "The *format* parameter controls the format in which annotations are " "returned, and must be a member of the :class:`Format` enum or its integer " "equivalent. The different formats work as follows:" msgstr "" #: ../../library/annotationlib.rst:341 msgid "" "VALUE: :attr:`!object.__annotations__` is tried first; if that does not " "exist, the :attr:`!object.__annotate__` function is called if it exists." msgstr "" #: ../../library/annotationlib.rst:344 msgid "" "FORWARDREF: If :attr:`!object.__annotations__` exists and can be evaluated " "successfully, it is used; otherwise, the :attr:`!object.__annotate__` " "function is called. If it does not exist either, :attr:`!object." "__annotations__` is tried again and any error from accessing it is re-raised." msgstr "" #: ../../library/annotationlib.rst:349 msgid "" "When calling :attr:`!object.__annotate__` it is first called with :attr:" "`~Format.FORWARDREF`. If this is not implemented, it will then check if :" "attr:`~Format.VALUE_WITH_FAKE_GLOBALS` is supported and use that in the fake " "globals environment. If neither of these formats are supported, it will fall " "back to using :attr:`~Format.VALUE`. If :attr:`~Format.VALUE` fails, the " "error from this call will be raised." msgstr "" #: ../../library/annotationlib.rst:355 msgid "" "STRING: If :attr:`!object.__annotate__` exists, it is called first; " "otherwise, :attr:`!object.__annotations__` is used and stringified using :" "func:`annotations_to_string`." msgstr "" #: ../../library/annotationlib.rst:359 msgid "" "When calling :attr:`!object.__annotate__` it is first called with :attr:" "`~Format.STRING`. If this is not implemented, it will then check if :attr:" "`~Format.VALUE_WITH_FAKE_GLOBALS` is supported and use that in the fake " "globals environment. If neither of these formats are supported, it will fall " "back to using :attr:`~Format.VALUE` with the result converted using :func:" "`annotations_to_string`. If :attr:`~Format.VALUE` fails, the error from this " "call will be raised." msgstr "" #: ../../library/annotationlib.rst:366 msgid "" "Returns a dict. :func:`!get_annotations` returns a new dict every time it's " "called; calling it twice on the same object will return two different but " "equivalent dicts." msgstr "" #: ../../library/annotationlib.rst:370 msgid "This function handles several details for you:" msgstr "" #: ../../library/annotationlib.rst:372 msgid "" "If *eval_str* is true, values of type :class:`!str` will be un-stringized " "using :func:`eval`. This is intended for use with stringized annotations " "(``from __future__ import annotations``). It is an error to set *eval_str* " "to true with formats other than :attr:`Format.VALUE`." msgstr "" #: ../../library/annotationlib.rst:377 msgid "" "If *obj* doesn't have an annotations dict, returns an empty dict. (Functions " "and methods always have an annotations dict; classes, modules, and other " "types of callables may not.)" msgstr "" #: ../../library/annotationlib.rst:381 msgid "" "Ignores inherited annotations on classes, as well as annotations on " "metaclasses. If a class doesn't have its own annotations dict, returns an " "empty dict." msgstr "" #: ../../library/annotationlib.rst:384 msgid "" "All accesses to object members and dict values are done using ``getattr()`` " "and ``dict.get()`` for safety." msgstr "" #: ../../library/annotationlib.rst:387 msgid "" "*eval_str* controls whether or not values of type :class:`!str` are replaced " "with the result of calling :func:`eval` on those values:" msgstr "" #: ../../library/annotationlib.rst:390 msgid "" "If eval_str is true, :func:`eval` is called on values of type :class:`!str`. " "(Note that :func:`!get_annotations` doesn't catch exceptions; if :func:" "`eval` raises an exception, it will unwind the stack past the :func:`!" "get_annotations` call.)" msgstr "" #: ../../library/annotationlib.rst:394 msgid "" "If *eval_str* is false (the default), values of type :class:`!str` are " "unchanged." msgstr "" #: ../../library/annotationlib.rst:397 msgid "" "*globals* and *locals* are passed in to :func:`eval`; see the documentation " "for :func:`eval` for more information. If *globals* or *locals* is :const:`!" "None`, this function may replace that value with a context-specific default, " "contingent on ``type(obj)``:" msgstr "" #: ../../library/annotationlib.rst:402 msgid "If *obj* is a module, *globals* defaults to ``obj.__dict__``." msgstr "" #: ../../library/annotationlib.rst:403 msgid "" "If *obj* is a class, *globals* defaults to ``sys.modules[obj.__module__]." "__dict__`` and *locals* defaults to the *obj* class namespace." msgstr "" #: ../../library/annotationlib.rst:406 msgid "" "If *obj* is a callable, *globals* defaults to :attr:`obj.__globals__ " "`, although if *obj* is a wrapped function (using :" "func:`functools.update_wrapper`) or a :class:`functools.partial` object, it " "is unwrapped until a non-wrapped function is found." msgstr "" #: ../../library/annotationlib.rst:412 msgid "" "Calling :func:`!get_annotations` is best practice for accessing the " "annotations dict of any object. See :ref:`annotations-howto` for more " "information on annotations best practices." msgstr "" #: ../../library/annotationlib.rst:416 msgid "" ">>> def f(a: int, b: str) -> float:\n" "... pass\n" ">>> get_annotations(f)\n" "{'a': , 'b': , 'return': }" msgstr "" #: ../../library/annotationlib.rst:427 msgid "" "Convert an arbitrary Python value to a format suitable for use by the :attr:" "`~Format.STRING` format. This calls :func:`repr` for most objects, but has " "special handling for some objects, such as type objects." msgstr "" #: ../../library/annotationlib.rst:431 msgid "" "This is meant as a helper for user-provided annotate functions that support " "the :attr:`~Format.STRING` format but do not have access to the code " "creating the annotations. It can also be used to provide a user-friendly " "string representation for other objects that contain values that are " "commonly encountered in annotations." msgstr "" #: ../../library/annotationlib.rst:441 msgid "Recipes" msgstr "" #: ../../library/annotationlib.rst:446 msgid "Using annotations in a metaclass" msgstr "" #: ../../library/annotationlib.rst:448 msgid "" "A :ref:`metaclass ` may want to inspect or even modify the " "annotations in a class body during class creation. Doing so requires " "retrieving annotations from the class namespace dictionary. For classes " "created with ``from __future__ import annotations``, the annotations will be " "in the ``__annotations__`` key of the dictionary. For other classes with " "annotations, :func:`get_annotate_from_class_namespace` can be used to get " "the annotate function, and :func:`call_annotate_function` can be used to " "call it and retrieve the annotations. Using the :attr:`~Format.FORWARDREF` " "format will usually be best, because this allows the annotations to refer to " "names that cannot yet be resolved when the class is created." msgstr "" #: ../../library/annotationlib.rst:459 msgid "" "To modify the annotations, it is best to create a wrapper annotate function " "that calls the original annotate function, makes any necessary adjustments, " "and returns the result." msgstr "" #: ../../library/annotationlib.rst:463 msgid "" "Below is an example of a metaclass that filters out all :class:`typing." "ClassVar` annotations from the class and puts them in a separate attribute:" msgstr "" #: ../../library/annotationlib.rst:466 msgid "" "import annotationlib\n" "import typing\n" "\n" "class ClassVarSeparator(type):\n" " def __new__(mcls, name, bases, ns):\n" " if \"__annotations__\" in ns: # from __future__ import annotations\n" " annotations = ns[\"__annotations__\"]\n" " classvar_keys = {\n" " key for key, value in annotations.items()\n" " # Use string comparison for simplicity; a more robust solution\n" " # could use annotationlib.ForwardRef.evaluate\n" " if value.startswith(\"ClassVar\")\n" " }\n" " classvars = {key: annotations[key] for key in classvar_keys}\n" " ns[\"__annotations__\"] = {\n" " key: value for key, value in annotations.items()\n" " if key not in classvar_keys\n" " }\n" " wrapped_annotate = None\n" " elif annotate := annotationlib.get_annotate_from_class_namespace(ns):\n" " annotations = annotationlib.call_annotate_function(\n" " annotate, format=annotationlib.Format.FORWARDREF\n" " )\n" " classvar_keys = {\n" " key for key, value in annotations.items()\n" " if typing.get_origin(value) is typing.ClassVar\n" " }\n" " classvars = {key: annotations[key] for key in classvar_keys}\n" "\n" " def wrapped_annotate(format):\n" " annos = annotationlib.call_annotate_function(annotate, format, " "owner=typ)\n" " return {key: value for key, value in annos.items() if key not in " "classvar_keys}\n" "\n" " else: # no annotations\n" " classvars = {}\n" " wrapped_annotate = None\n" " typ = super().__new__(mcls, name, bases, ns)\n" "\n" " if wrapped_annotate is not None:\n" " # Wrap the original __annotate__ with a wrapper that removes " "ClassVars\n" " typ.__annotate__ = wrapped_annotate\n" " typ.classvars = classvars # Store the ClassVars in a separate " "attribute\n" " return typ" msgstr "" #: ../../library/annotationlib.rst:514 msgid "Creating a custom callable annotate function" msgstr "" #: ../../library/annotationlib.rst:516 msgid "" "Custom :term:`annotate functions ` may be literal " "functions like those automatically generated for functions, classes, and " "modules. Or, they may wish to utilise the encapsulation provided by classes, " "in which case any :term:`callable` can be used as an :term:`annotate " "function`." msgstr "" #: ../../library/annotationlib.rst:521 msgid "" "To provide the :attr:`~Format.VALUE`, :attr:`~Format.STRING`, or :attr:" "`~Format.FORWARDREF` formats directly, an :term:`annotate function` must " "provide the following attribute:" msgstr "" #: ../../library/annotationlib.rst:525 msgid "" "A callable ``__call__`` with signature ``__call__(format, /) -> dict``, that " "does not raise a :exc:`NotImplementedError` when called with a supported " "format." msgstr "" #: ../../library/annotationlib.rst:528 msgid "" "To provide the :attr:`~Format.VALUE_WITH_FAKE_GLOBALS` format, which is used " "to automatically generate :attr:`~Format.STRING` or :attr:`~Format." "FORWARDREF` if they are not supported directly, :term:`annotate functions " "` must provide the following attributes:" msgstr "" #: ../../library/annotationlib.rst:533 msgid "" "A callable ``__call__`` with signature ``__call__(format, /) -> dict``, that " "does not raise a :exc:`NotImplementedError` when called with :attr:`~Format." "VALUE_WITH_FAKE_GLOBALS`." msgstr "" #: ../../library/annotationlib.rst:536 msgid "" "A :ref:`code object ` ``__code__`` containing the compiled " "code for the annotate function." msgstr "" #: ../../library/annotationlib.rst:538 msgid "" "Optional: A tuple of the function's positional defaults ``__kwdefaults__``, " "if the function represented by ``__code__`` uses any positional defaults." msgstr "" #: ../../library/annotationlib.rst:540 msgid "" "Optional: A dict of the function's keyword defaults ``__defaults__``, if the " "function represented by ``__code__`` uses any keyword defaults." msgstr "" #: ../../library/annotationlib.rst:542 msgid "Optional: All other :ref:`function attributes `." msgstr "" #: ../../library/annotationlib.rst:544 msgid "" "class Annotate:\n" " called_formats = []\n" "\n" " def __call__(self, format=None, /, *, _self=None):\n" " # When called with fake globals, `_self` will be the\n" " # actual self value, and `self` will be the format.\n" " if _self is not None:\n" " self, format = _self, self\n" "\n" " self.called_formats.append(format)\n" " if format >> from annotationlib import call_annotate_function, Format\n" ">>> call_annotate_function(Annotate(), format=Format.STRING)\n" "{'x': 'MyType'}" msgstr "" #: ../../library/annotationlib.rst:576 msgid "Or used as the annotate function for an object:" msgstr "" #: ../../library/annotationlib.rst:578 msgid "" ">>> from annotationlib import get_annotations, Format\n" ">>> class C:\n" "... pass\n" ">>> C.__annotate__ = Annotate()\n" ">>> get_annotations(Annotate(), format=Format.STRING)\n" "{'x': 'MyType'}" msgstr "" #: ../../library/annotationlib.rst:589 msgid "Limitations of the ``STRING`` format" msgstr "" #: ../../library/annotationlib.rst:591 msgid "" "The :attr:`~Format.STRING` format is meant to approximate the source code of " "the annotation, but the implementation strategy used means that it is not " "always possible to recover the exact source code." msgstr "" #: ../../library/annotationlib.rst:595 msgid "" "First, the stringifier of course cannot recover any information that is not " "present in the compiled code, including comments, whitespace, " "parenthesization, and operations that get simplified by the compiler." msgstr "" #: ../../library/annotationlib.rst:599 msgid "" "Second, the stringifier can intercept almost all operations that involve " "names looked up in some scope, but it cannot intercept operations that " "operate fully on constants. As a corollary, this also means it is not safe " "to request the ``STRING`` format on untrusted code: Python is powerful " "enough that it is possible to achieve arbitrary code execution even with no " "access to any globals or builtins. For example:" msgstr "" #: ../../library/annotationlib.rst:605 msgid "" ">>> def f(x: (1).__class__.__base__.__subclasses__()[-1].__init__." "__builtins__[\"print\"](\"Hello world\")): pass\n" "...\n" ">>> annotationlib.get_annotations(f, format=annotationlib.Format.STRING)\n" "Hello world\n" "{'x': 'None'}" msgstr "" #: ../../library/annotationlib.rst:614 msgid "" "This particular example works as of the time of writing, but it relies on " "implementation details and is not guaranteed to work in the future." msgstr "" #: ../../library/annotationlib.rst:617 msgid "" "Among the different kinds of expressions that exist in Python, as " "represented by the :mod:`ast` module, some expressions are supported, " "meaning that the ``STRING`` format can generally recover the original source " "code; others are unsupported, meaning that they may result in incorrect " "output or an error." msgstr "" #: ../../library/annotationlib.rst:622 msgid "The following are supported (sometimes with caveats):" msgstr "" #: ../../library/annotationlib.rst:624 msgid ":class:`ast.BinOp`" msgstr "" #: ../../library/annotationlib.rst:625 msgid ":class:`ast.UnaryOp`" msgstr "" #: ../../library/annotationlib.rst:627 msgid "" ":class:`ast.Invert` (``~``), :class:`ast.UAdd` (``+``), and :class:`ast." "USub` (``-``) are supported" msgstr "" #: ../../library/annotationlib.rst:628 msgid ":class:`ast.Not` (``not``) is not supported" msgstr "" #: ../../library/annotationlib.rst:630 msgid ":class:`ast.Dict` (except when using ``**`` unpacking)" msgstr "" #: ../../library/annotationlib.rst:631 msgid ":class:`ast.Set`" msgstr "" #: ../../library/annotationlib.rst:632 msgid ":class:`ast.Compare`" msgstr "" #: ../../library/annotationlib.rst:634 msgid ":class:`ast.Eq` and :class:`ast.NotEq` are supported" msgstr "" #: ../../library/annotationlib.rst:635 msgid "" ":class:`ast.Lt`, :class:`ast.LtE`, :class:`ast.Gt`, and :class:`ast.GtE` are " "supported, but the operand may be flipped" msgstr "" #: ../../library/annotationlib.rst:636 msgid "" ":class:`ast.Is`, :class:`ast.IsNot`, :class:`ast.In`, and :class:`ast.NotIn` " "are not supported" msgstr "" #: ../../library/annotationlib.rst:638 msgid ":class:`ast.Call` (except when using ``**`` unpacking)" msgstr "" #: ../../library/annotationlib.rst:639 msgid "" ":class:`ast.Constant` (though not the exact representation of the constant; " "for example, escape sequences in strings are lost; hexadecimal numbers are " "converted to decimal)" msgstr "" #: ../../library/annotationlib.rst:641 msgid ":class:`ast.Attribute` (assuming the value is not a constant)" msgstr "" #: ../../library/annotationlib.rst:642 msgid ":class:`ast.Subscript` (assuming the value is not a constant)" msgstr "" #: ../../library/annotationlib.rst:643 msgid ":class:`ast.Starred` (``*`` unpacking)" msgstr "" #: ../../library/annotationlib.rst:644 msgid ":class:`ast.Name`" msgstr "" #: ../../library/annotationlib.rst:645 msgid ":class:`ast.List`" msgstr "" #: ../../library/annotationlib.rst:646 msgid ":class:`ast.Tuple`" msgstr "" #: ../../library/annotationlib.rst:647 msgid ":class:`ast.Slice`" msgstr "" #: ../../library/annotationlib.rst:649 msgid "" "The following are unsupported, but throw an informative error when " "encountered by the stringifier:" msgstr "" #: ../../library/annotationlib.rst:652 msgid "" ":class:`ast.FormattedValue` (f-strings; error is not detected if conversion " "specifiers like ``!r`` are used)" msgstr "" #: ../../library/annotationlib.rst:654 msgid ":class:`ast.JoinedStr` (f-strings)" msgstr "" #: ../../library/annotationlib.rst:656 msgid "The following are unsupported and result in incorrect output:" msgstr "" #: ../../library/annotationlib.rst:658 msgid ":class:`ast.BoolOp` (``and`` and ``or``)" msgstr "" #: ../../library/annotationlib.rst:659 msgid ":class:`ast.IfExp`" msgstr "" #: ../../library/annotationlib.rst:660 msgid ":class:`ast.Lambda`" msgstr "" #: ../../library/annotationlib.rst:661 msgid ":class:`ast.ListComp`" msgstr "" #: ../../library/annotationlib.rst:662 msgid ":class:`ast.SetComp`" msgstr "" #: ../../library/annotationlib.rst:663 msgid ":class:`ast.DictComp`" msgstr "" #: ../../library/annotationlib.rst:664 msgid ":class:`ast.GeneratorExp`" msgstr "" #: ../../library/annotationlib.rst:666 msgid "" "The following are disallowed in annotation scopes and therefore not relevant:" msgstr "" #: ../../library/annotationlib.rst:668 msgid ":class:`ast.NamedExpr` (``:=``)" msgstr "" #: ../../library/annotationlib.rst:669 msgid ":class:`ast.Await`" msgstr "" #: ../../library/annotationlib.rst:670 msgid ":class:`ast.Yield`" msgstr "" #: ../../library/annotationlib.rst:671 msgid ":class:`ast.YieldFrom`" msgstr "" #: ../../library/annotationlib.rst:675 msgid "Limitations of the ``FORWARDREF`` format" msgstr "" #: ../../library/annotationlib.rst:677 msgid "" "The :attr:`~Format.FORWARDREF` format aims to produce real values as much as " "possible, with anything that cannot be resolved replaced with :class:" "`ForwardRef` objects. It is affected by broadly the same Limitations as the :" "attr:`~Format.STRING` format: annotations that perform operations on " "literals or that use unsupported expression types may raise exceptions when " "evaluated using the :attr:`~Format.FORWARDREF` format." msgstr "" #: ../../library/annotationlib.rst:684 msgid "Below are a few examples of the behavior with unsupported expressions:" msgstr "" #: ../../library/annotationlib.rst:686 msgid "" ">>> from annotationlib import get_annotations, Format\n" ">>> def zerodiv(x: 1 / 0): ...\n" ">>> get_annotations(zerodiv, format=Format.STRING)\n" "Traceback (most recent call last):\n" " ...\n" "ZeroDivisionError: division by zero\n" ">>> get_annotations(zerodiv, format=Format.FORWARDREF)\n" "Traceback (most recent call last):\n" " ...\n" "ZeroDivisionError: division by zero\n" ">>> def ifexp(x: 1 if y else 0): ...\n" ">>> get_annotations(ifexp, format=Format.STRING)\n" "{'x': '1'}" msgstr "" #: ../../library/annotationlib.rst:705 msgid "Security implications of introspecting annotations" msgstr "" #: ../../library/annotationlib.rst:707 msgid "" "Much of the functionality in this module involves executing code related to " "annotations, which can then do arbitrary things. For example, :func:" "`get_annotations` may call an arbitrary :term:`annotate function`, and :meth:" "`ForwardRef.evaluate` may call :func:`eval` on an arbitrary string. Code " "contained in an annotation might make arbitrary system calls, enter an " "infinite loop, or perform any other operation. This is also true for any " "access of the :attr:`~object.__annotations__` attribute, and for various " "functions in the :mod:`typing` module that work with annotations, such as :" "func:`typing.get_type_hints`." msgstr "" #: ../../library/annotationlib.rst:716 msgid "" "Any security issue arising from this also applies immediately after " "importing code that may contain untrusted annotations: importing code can " "always cause arbitrary operations to be performed. However, it is unsafe to " "accept strings or other input from an untrusted source and pass them to any " "of the APIs for introspecting annotations, for example by editing an " "``__annotations__`` dictionary or directly creating a :class:`ForwardRef` " "object." msgstr ""

Back | FazBrowse Home | New Git URL