Mercurial > hg
comparison mercurial/thirdparty/attr/converters.py @ 49643:e1c586b9a43c
attr: vendor 22.1.0
The previous version was 5 years old, and pytype 2022.06.30 started complaining
about various uses (e.g. seeing `mercurial.thirdparty.attr._make._CountingAttr`
instead of `bytearray`). Hopefully this helps. Additionally, this has official
python 3.11 support.
The `attrs` package is left out, because it is simply a bunch of *.pyi stubs and
`from attr.X import *`, and that's not how they've been used up to this point.
We'd probably need to customize those anyway to
`from mercurial.thirdparty.attr import *`.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Mon, 21 Nov 2022 15:04:42 -0500 |
parents | 765eb17a7eb8 |
children |
comparison
equal
deleted
inserted
replaced
49642:7e6f3c69c0fb | 49643:e1c586b9a43c |
---|---|
1 # SPDX-License-Identifier: MIT | |
2 | |
1 """ | 3 """ |
2 Commonly useful converters. | 4 Commonly useful converters. |
3 """ | 5 """ |
4 | 6 |
5 from __future__ import absolute_import, division, print_function | 7 |
8 import typing | |
9 | |
10 from ._compat import _AnnotationExtractor | |
11 from ._make import NOTHING, Factory, pipe | |
12 | |
13 | |
14 __all__ = [ | |
15 "default_if_none", | |
16 "optional", | |
17 "pipe", | |
18 "to_bool", | |
19 ] | |
6 | 20 |
7 | 21 |
8 def optional(converter): | 22 def optional(converter): |
9 """ | 23 """ |
10 A converter that allows an attribute to be optional. An optional attribute | 24 A converter that allows an attribute to be optional. An optional attribute |
11 is one which can be set to ``None``. | 25 is one which can be set to ``None``. |
12 | 26 |
27 Type annotations will be inferred from the wrapped converter's, if it | |
28 has any. | |
29 | |
13 :param callable converter: the converter that is used for non-``None`` | 30 :param callable converter: the converter that is used for non-``None`` |
14 values. | 31 values. |
15 | 32 |
16 .. versionadded:: 17.1.0 | 33 .. versionadded:: 17.1.0 |
17 """ | 34 """ |
18 | 35 |
19 def optional_converter(val): | 36 def optional_converter(val): |
20 if val is None: | 37 if val is None: |
21 return None | 38 return None |
22 return converter(val) | 39 return converter(val) |
23 | 40 |
41 xtr = _AnnotationExtractor(converter) | |
42 | |
43 t = xtr.get_first_param_type() | |
44 if t: | |
45 optional_converter.__annotations__["val"] = typing.Optional[t] | |
46 | |
47 rt = xtr.get_return_type() | |
48 if rt: | |
49 optional_converter.__annotations__["return"] = typing.Optional[rt] | |
50 | |
24 return optional_converter | 51 return optional_converter |
52 | |
53 | |
54 def default_if_none(default=NOTHING, factory=None): | |
55 """ | |
56 A converter that allows to replace ``None`` values by *default* or the | |
57 result of *factory*. | |
58 | |
59 :param default: Value to be used if ``None`` is passed. Passing an instance | |
60 of `attrs.Factory` is supported, however the ``takes_self`` option | |
61 is *not*. | |
62 :param callable factory: A callable that takes no parameters whose result | |
63 is used if ``None`` is passed. | |
64 | |
65 :raises TypeError: If **neither** *default* or *factory* is passed. | |
66 :raises TypeError: If **both** *default* and *factory* are passed. | |
67 :raises ValueError: If an instance of `attrs.Factory` is passed with | |
68 ``takes_self=True``. | |
69 | |
70 .. versionadded:: 18.2.0 | |
71 """ | |
72 if default is NOTHING and factory is None: | |
73 raise TypeError("Must pass either `default` or `factory`.") | |
74 | |
75 if default is not NOTHING and factory is not None: | |
76 raise TypeError( | |
77 "Must pass either `default` or `factory` but not both." | |
78 ) | |
79 | |
80 if factory is not None: | |
81 default = Factory(factory) | |
82 | |
83 if isinstance(default, Factory): | |
84 if default.takes_self: | |
85 raise ValueError( | |
86 "`takes_self` is not supported by default_if_none." | |
87 ) | |
88 | |
89 def default_if_none_converter(val): | |
90 if val is not None: | |
91 return val | |
92 | |
93 return default.factory() | |
94 | |
95 else: | |
96 | |
97 def default_if_none_converter(val): | |
98 if val is not None: | |
99 return val | |
100 | |
101 return default | |
102 | |
103 return default_if_none_converter | |
104 | |
105 | |
106 def to_bool(val): | |
107 """ | |
108 Convert "boolean" strings (e.g., from env. vars.) to real booleans. | |
109 | |
110 Values mapping to :code:`True`: | |
111 | |
112 - :code:`True` | |
113 - :code:`"true"` / :code:`"t"` | |
114 - :code:`"yes"` / :code:`"y"` | |
115 - :code:`"on"` | |
116 - :code:`"1"` | |
117 - :code:`1` | |
118 | |
119 Values mapping to :code:`False`: | |
120 | |
121 - :code:`False` | |
122 - :code:`"false"` / :code:`"f"` | |
123 - :code:`"no"` / :code:`"n"` | |
124 - :code:`"off"` | |
125 - :code:`"0"` | |
126 - :code:`0` | |
127 | |
128 :raises ValueError: for any other value. | |
129 | |
130 .. versionadded:: 21.3.0 | |
131 """ | |
132 if isinstance(val, str): | |
133 val = val.lower() | |
134 truthy = {True, "true", "t", "yes", "y", "on", "1", 1} | |
135 falsy = {False, "false", "f", "no", "n", "off", "0", 0} | |
136 try: | |
137 if val in truthy: | |
138 return True | |
139 if val in falsy: | |
140 return False | |
141 except TypeError: | |
142 # Raised when "val" is not hashable (e.g., lists) | |
143 pass | |
144 raise ValueError("Cannot convert value to bool: {}".format(val)) |