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

pantsbuild / pants / 20632486505

01 Jan 2026 04:21AM UTC coverage: 43.231% (-37.1%) from 80.281%
20632486505

Pull #22962

github

web-flow
Merge 08d5c63b0 into f52ab6675
Pull Request #22962: Bump the gha-deps group across 1 directory with 6 updates

26122 of 60424 relevant lines covered (43.23%)

0.86 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
2✔
5
from collections.abc import Callable
2✔
6
from typing import Any, TypeVar
2✔
7

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

11

12
class SingletonMetaclass(type):
2✔
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:
2✔
23
        # TODO: convert this into an `@memoized_classproperty`!
24
        if not hasattr(cls, "instance"):
2✔
25
            cls.instance = super().__call__(*args, **kwargs)
2✔
26
        return cls.instance
2✔
27

28

29
class _ClassPropertyDescriptor:
2✔
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:
2✔
37
        self.fget = fget
2✔
38
        self.__doc__ = doc
2✔
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:
2✔
42
        if objtype is None:
2✔
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)
2✔
46
        if getattr(self.fget.__func__, "__isabstractmethod__", False):
2✔
47
            field_name = self.fget.__func__.fget.__name__  # type: ignore[union-attr]
×
48
            raise TypeError(
×
49
                f"""\
50
The classproperty '{field_name}' in type '{objtype.__name__}' was an abstractproperty, meaning that type \
51
{objtype.__name__} must override it by setting it as a variable in the class body or defining a method \
52
with an @classproperty decorator."""
53
            )
54
        return callable_field()
2✔
55

56

57
def runtime_ignore_subscripts(cls: C) -> C:
2✔
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]
2✔
76
    def __class_getitem__(cls, item):
2✔
77
        return cls
2✔
78

79
    cls.__class_getitem__ = __class_getitem__
2✔
80

81
    return cls
2✔
82

83

84
def classproperty(func: Callable[..., T]) -> T:
2✔
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__
2✔
105

106
    if not isinstance(func, (classmethod, staticmethod)):
2✔
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]
2✔
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]
2✔
115

116

117
class _ClassDecoratorWithSentinelAttribute(ABC):
2✔
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]:
2✔
127
        return type(obj.__name__, (obj,), {"_decorated_type_checkable_type": type(self), **kwargs})
×
128

129
    def is_instance(self, obj: type[Any]) -> bool:
2✔
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

© 2026 Coveralls, Inc