Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/traitlets/utils/descriptions.py: 22%
67 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1import inspect
2import re
3import types
6def describe(article, value, name=None, verbose=False, capital=False):
7 """Return string that describes a value
9 Parameters
10 ----------
11 article : str or None
12 A definite or indefinite article. If the article is
13 indefinite (i.e. "a" or "an") the appropriate one
14 will be infered. Thus, the arguments of ``describe``
15 can themselves represent what the resulting string
16 will actually look like. If None, then no article
17 will be prepended to the result. For non-articled
18 description, values that are instances are treated
19 definitely, while classes are handled indefinitely.
20 value : any
21 The value which will be named.
22 name : str or None (default: None)
23 Only applies when ``article`` is "the" - this
24 ``name`` is a definite reference to the value.
25 By default one will be infered from the value's
26 type and repr methods.
27 verbose : bool (default: False)
28 Whether the name should be concise or verbose. When
29 possible, verbose names include the module, and/or
30 class name where an object was defined.
31 capital : bool (default: False)
32 Whether the first letter of the article should
33 be capitalized or not. By default it is not.
35 Examples
36 --------
37 Indefinite description:
39 >>> describe("a", object())
40 'an object'
41 >>> describe("a", object)
42 'an object'
43 >>> describe("a", type(object))
44 'a type'
46 Definite description:
48 >>> describe("the", object())
49 "the object at '...'"
50 >>> describe("the", object)
51 'the object object'
52 >>> describe("the", type(object))
53 'the type type'
55 Definitely named description:
57 >>> describe("the", object(), "I made")
58 'the object I made'
59 >>> describe("the", object, "I will use")
60 'the object I will use'
61 """
62 if isinstance(article, str):
63 article = article.lower()
65 if not inspect.isclass(value):
66 typename = type(value).__name__
67 else:
68 typename = value.__name__
69 if verbose:
70 typename = _prefix(value) + typename
72 if article == "the" or (article is None and not inspect.isclass(value)):
73 if name is not None:
74 result = f"{typename} {name}"
75 if article is not None:
76 return add_article(result, True, capital)
77 else:
78 return result
79 else:
80 tick_wrap = False
81 if inspect.isclass(value):
82 name = value.__name__
83 elif isinstance(value, types.FunctionType):
84 name = value.__name__
85 tick_wrap = True
86 elif isinstance(value, types.MethodType):
87 name = value.__func__.__name__
88 tick_wrap = True
89 elif type(value).__repr__ in (
90 object.__repr__,
91 type.__repr__,
92 ): # type:ignore[comparison-overlap]
93 name = "at '%s'" % hex(id(value))
94 verbose = False
95 else:
96 name = repr(value)
97 verbose = False
98 if verbose:
99 name = _prefix(value) + name
100 if tick_wrap:
101 name = name.join("''")
102 return describe(article, value, name=name, verbose=verbose, capital=capital)
103 elif article in ("a", "an") or article is None:
104 if article is None:
105 return typename
106 return add_article(typename, False, capital)
107 else:
108 raise ValueError(
109 "The 'article' argument should be 'the', 'a', 'an', or None not %r" % article
110 )
113def _prefix(value):
114 if isinstance(value, types.MethodType):
115 name = describe(None, value.__self__, verbose=True) + "."
116 else:
117 module = inspect.getmodule(value)
118 if module is not None and module.__name__ != "builtins":
119 name = module.__name__ + "."
120 else:
121 name = ""
122 return name
125def class_of(value):
126 """Returns a string of the value's type with an indefinite article.
128 For example 'an Image' or 'a PlotValue'.
129 """
130 if inspect.isclass(value):
131 return add_article(value.__name__)
132 else:
133 return class_of(type(value))
136def add_article(name, definite=False, capital=False):
137 """Returns the string with a prepended article.
139 The input does not need to begin with a charater.
141 Parameters
142 ----------
143 name : str
144 Name to which to prepend an article
145 definite : bool (default: False)
146 Whether the article is definite or not.
147 Indefinite articles being 'a' and 'an',
148 while 'the' is definite.
149 capital : bool (default: False)
150 Whether the added article should have
151 its first letter capitalized or not.
152 """
153 if definite:
154 result = "the " + name
155 else:
156 first_letters = re.compile(r"[\W_]+").sub("", name)
157 if first_letters[:1].lower() in "aeiou":
158 result = "an " + name
159 else:
160 result = "a " + name
161 if capital:
162 return result[0].upper() + result[1:]
163 else:
164 return result
167def repr_type(obj):
168 """Return a string representation of a value and its type for readable
170 error messages.
171 """
172 the_type = type(obj)
173 msg = f"{obj!r} {the_type!r}"
174 return msg