• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 19015773527

02 Nov 2025 05:33PM UTC coverage: 17.872% (-62.4%) from 80.3%
19015773527

Pull #22816

github

web-flow
Merge a12d75757 into 6c024e162
Pull Request #22816: Update Pants internal Python to 3.14

4 of 5 new or added lines in 3 files covered. (80.0%)

28452 existing lines in 683 files now uncovered.

9831 of 55007 relevant lines covered (17.87%)

0.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.84
/src/python/pants/util/meta.py
1
# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from abc import ABC, abstractmethod
1✔
5
from collections.abc import Callable
1✔
6
from typing import Any, TypeVar
1✔
7

8
T = TypeVar("T")
1✔
9
C = TypeVar("C", bound=type[Any])
1✔
10

11

12
class SingletonMetaclass(type):
1✔
13
    """When using this metaclass in your class definition, your class becomes a singleton. That is,
14
    every construction returns the same instance.
15

16
    Example class definition:
17

18
      class Unicorn(metaclass=SingletonMetaclass):
19
        pass
20
    """
21

22
    def __call__(cls, *args: Any, **kwargs: Any) -> Any:
1✔
23
        # TODO: convert this into an `@memoized_classproperty`!
24
        if not hasattr(cls, "instance"):
1✔
25
            cls.instance = super().__call__(*args, **kwargs)
1✔
26
        return cls.instance
1✔
27

28

29
class _ClassPropertyDescriptor:
1✔
30
    """Define a readable attribute on a class, given a function."""
31

32
    # The current solution is preferred as it doesn't require any modifications to the class
33
    # definition beyond declaring a @classproperty.  It seems overriding __set__ and __delete__ would
34
    # require defining a metaclass or overriding __setattr__/__delattr__ (see
35
    # https://stackoverflow.com/questions/5189699/how-to-make-a-class-property).
36
    def __init__(self, fget: classmethod | staticmethod, doc: str | None) -> None:
1✔
37
        self.fget = fget
1✔
38
        self.__doc__ = doc
1✔
39

40
    # See https://docs.python.org/3/howto/descriptor.html for more details.
41
    def __get__(self, obj: T, objtype: type[T] | None = None) -> Any:
1✔
42
        if objtype is None:
1✔
43
            objtype = type(obj)
×
44
            # Get the callable field for this object, which may be a property.
45
        callable_field = self.fget.__get__(obj, objtype)
1✔
46
        if getattr(self.fget.__func__, "__isabstractmethod__", False):
1✔
UNCOV
47
            field_name = self.fget.__func__.fget.__name__  # type: ignore[union-attr]
×
UNCOV
48
            raise TypeError(
×
49
                """\
50
The classproperty '{func_name}' in type '{type_name}' was an abstractproperty, meaning that type \
51
{type_name} must override it by setting it as a variable in the class body or defining a method \
52
with an @classproperty decorator.""".format(func_name=field_name, type_name=objtype.__name__)
53
            )
54
        return callable_field()
1✔
55

56

57
def runtime_ignore_subscripts(cls: C) -> C:
1✔
58
    """Use as a decorator on a class to make it subscriptable at runtime, returning the class.
59

60
    Generally, this is used inside the `else` of a `TYPE_CHECKING` check.
61

62
    Usage:
63
    >>> if TYPE_CHECKING:
64
    ...     class MyClass(Generic[...]):
65
    ...         ...
66
    ... else:
67
    ...     @runtime_ignore_subscripts
68
    ...     class MyClass:
69
    ...         ...
70
    ...
71
    >>> MyClass[int] is MyClass
72
    True
73
    """
74

75
    @classmethod  # type: ignore[misc]
1✔
76
    def __class_getitem__(cls, item):
1✔
77
        return cls
1✔
78

79
    cls.__class_getitem__ = __class_getitem__
1✔
80

81
    return cls
1✔
82

83

84
def classproperty(func: Callable[..., T]) -> T:
1✔
85
    """Use as a decorator on a method definition to make it a class-level attribute.
86

87
    This decorator can be applied to a method, a classmethod, or a staticmethod. This decorator will
88
    bind the first argument to the class object.
89

90
    Usage:
91
    >>> class Foo:
92
    ...   @classproperty
93
    ...   def name(cls):
94
    ...     return cls.__name__
95
    ...
96
    >>> Foo.name
97
    'Foo'
98

99
    Setting or deleting the attribute of this name will overwrite this property.
100

101
    The docstring of the classproperty `x` for a class `C` can be obtained by
102
    `C.__dict__['x'].__doc__`.
103
    """
104
    doc = func.__doc__
1✔
105

106
    if not isinstance(func, (classmethod, staticmethod)):
1✔
107
        # MyPy complains about converting a Callable -> classmethod. We use a Callable in the first
108
        # place because there is no typing.classmethod, i.e. a type that takes generic arguments, and
109
        # we need to use TypeVars for the call sites of this decorator to work properly.
110
        func = classmethod(func)  # type: ignore[assignment]
1✔
111

112
    # If we properly annotated this function as returning a _ClassPropertyDescriptor, then MyPy would
113
    # no longer work correctly at call sites for this decorator.
114
    return _ClassPropertyDescriptor(func, doc)  # type: ignore[arg-type, return-value]
1✔
115

116

117
class _ClassDecoratorWithSentinelAttribute(ABC):
1✔
118
    """Base class to wrap a class decorator which sets a "sentinel attribute".
119

120
    This functionality is exposed via the `@decorated_type_checkable` decorator.
121
    """
122

123
    @abstractmethod
124
    def __call__(self, cls: type[Any]) -> type[Any]: ...
125

126
    def define_instance_of(self, obj: type[Any], **kwargs) -> type[Any]:
1✔
127
        return type(obj.__name__, (obj,), {"_decorated_type_checkable_type": type(self), **kwargs})
×
128

129
    def is_instance(self, obj: type[Any]) -> bool:
1✔
130
        return getattr(obj, "_decorated_type_checkable_type", None) is type(self)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc