Skip to content

Commit b78111e

Browse files
committed
Improve documentation, typing compliance, and removed deprecated code
1 parent 7ea9791 commit b78111e

File tree

2 files changed

+23
-62
lines changed

2 files changed

+23
-62
lines changed

src/tap/tap.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
TupleTypeEnforcer,
2727
define_python_object_encoder,
2828
as_python_object,
29-
fix_py36_copy,
3029
enforce_reproducibility,
3130
PathLike,
3231
)
@@ -227,7 +226,7 @@ def _add_argument(self, *name_or_flags, **kwargs) -> None:
227226
# Handle Tuple type (with type args) by extracting types of Tuple elements and enforcing them
228227
elif get_origin(var_type) in (Tuple, tuple) and len(get_args(var_type)) > 0:
229228
loop = False
230-
types = get_args(var_type)
229+
types = list(get_args(var_type))
231230

232231
# Handle Tuple[type, ...]
233232
if len(types) == 2 and types[1] == Ellipsis:
@@ -331,7 +330,7 @@ def add_subparser(self, flag: str, subparser_type: type, **kwargs) -> None:
331330
self._subparser_buffer.append((flag, subparser_type, kwargs))
332331

333332
def _add_subparsers(self) -> None:
334-
"""Add each of the subparsers to the Tap object. """
333+
"""Add each of the subparsers to the Tap object."""
335334
# Initialize the _subparsers object if not already created
336335
if self._subparsers is None and len(self._subparser_buffer) > 0:
337336
self._subparsers = super(Tap, self).add_subparsers()
@@ -345,7 +344,7 @@ def add_subparsers(self, **kwargs) -> None:
345344
self._subparsers = super().add_subparsers(**kwargs)
346345

347346
def _configure(self) -> None:
348-
"""Executes the user-defined configuration. """
347+
"""Executes the user-defined configuration."""
349348
# Call the user-defined configuration
350349
self.configure()
351350

@@ -526,11 +525,7 @@ def _get_class_dict(self) -> Dict[str, Any]:
526525
class_dict = {
527526
var: val
528527
for var, val in class_dict.items()
529-
if not (
530-
var.startswith("_")
531-
or callable(val)
532-
or isinstance(val, (staticmethod, classmethod, property))
533-
)
528+
if not (var.startswith("_") or callable(val) or isinstance(val, (staticmethod, classmethod, property)))
534529
}
535530

536531
return class_dict
@@ -712,7 +707,6 @@ def __str__(self) -> str:
712707
"""
713708
return pformat(self.as_dict())
714709

715-
@fix_py36_copy
716710
def __deepcopy__(self, memo: Dict[int, Any] = None) -> TapType:
717711
"""Deepcopy the Tap object."""
718712
copied = type(self).__new__(type(self))
@@ -722,7 +716,7 @@ def __deepcopy__(self, memo: Dict[int, Any] = None) -> TapType:
722716

723717
memo[id(self)] = copied
724718

725-
for (k, v) in self.__dict__.items():
719+
for k, v in self.__dict__.items():
726720
copied.__dict__[k] = deepcopy(v, memo)
727721

728722
return copied

src/tap/utils.py

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def get_argument_name(*name_or_flags) -> str:
146146
return "help"
147147

148148
if len(name_or_flags) > 1:
149-
name_or_flags = [n_or_f for n_or_f in name_or_flags if n_or_f.startswith("--")]
149+
name_or_flags = tuple(n_or_f for n_or_f in name_or_flags if n_or_f.startswith("--"))
150150

151151
if len(name_or_flags) != 1:
152152
raise ValueError(f"There should only be a single canonical name for argument {name_or_flags}!")
@@ -204,39 +204,33 @@ def get_class_column(tokens: Iterable[tokenize.TokenInfo]) -> int:
204204

205205

206206
def source_line_to_tokens(tokens: Iterable[tokenize.TokenInfo]) -> Dict[int, List[Dict[str, Union[str, int]]]]:
207-
"""
208-
Gets a dictionary mapping from line number to a dictionary of tokens on that line for an object's source code,
209-
given the tokens of the object's source code.
210-
"""
207+
"""Extract a map from each line number to list of mappings providing information about each token."""
211208
line_to_tokens = {}
212209
for token_type, token, (start_line, start_column), (end_line, end_column), line in tokens:
213-
line_to_tokens.setdefault(start_line, []).append({
214-
'token_type': token_type,
215-
'token': token,
216-
'start_line': start_line,
217-
'start_column': start_column,
218-
'end_line': end_line,
219-
'end_column': end_column,
220-
'line': line
221-
})
210+
line_to_tokens.setdefault(start_line, []).append(
211+
{
212+
"token_type": token_type,
213+
"token": token,
214+
"start_line": start_line,
215+
"start_column": start_column,
216+
"end_line": end_line,
217+
"end_column": end_column,
218+
"line": line,
219+
}
220+
)
222221

223222
return line_to_tokens
224223

225224

226225
def get_subsequent_assign_lines(source_cls: str) -> Set[int]:
227-
"""
228-
For all multiline assign statements, get the line numbers after the first line of the assignment,
229-
given the source code of the object.
230-
"""
231-
226+
"""For all multiline assign statements, get the line numbers after the first line in the assignment."""
232227
# Parse source code using ast (with an if statement to avoid indentation errors)
233228
source = f"if True:\n{textwrap.indent(source_cls, ' ')}"
234229
body = ast.parse(source).body[0]
235230

236231
# Set up warning message
237232
parse_warning = (
238-
"Could not parse class source code to extract comments. "
239-
"Comments in the help string may be incorrect."
233+
"Could not parse class source code to extract comments. Comments in the help string may be incorrect."
240234
)
241235

242236
# Check for correct parsing
@@ -322,7 +316,7 @@ def get_class_variables(cls: type) -> Dict[str, Dict[str, str]]:
322316
token["token"] = token["token"][num_quote_chars:-num_quote_chars]
323317

324318
# Remove the unicode escape sequences (e.g. "\"")
325-
token["token"] = bytes(token["token"], encoding='ascii').decode('unicode-escape')
319+
token["token"] = bytes(token["token"], encoding="ascii").decode("unicode-escape")
326320

327321
# Add the token to the comment, stripping whitespace
328322
variable_to_comment[class_variable]["comment"] += sep + token["token"].strip()
@@ -351,7 +345,7 @@ def get_class_variables(cls: type) -> Dict[str, Dict[str, str]]:
351345
return variable_to_comment
352346

353347

354-
def get_literals(literal: Literal, variable: str) -> Tuple[Callable[[str], Any], List[str]]:
348+
def get_literals(literal: Literal, variable: str) -> Tuple[Callable[[str], Any], List[type]]:
355349
"""Extracts the values from a Literal type and ensures that the values are all primitive types."""
356350
literals = list(get_args(literal))
357351

@@ -476,7 +470,7 @@ def default(self, obj: Any) -> Any:
476470

477471

478472
class UnpicklableObject:
479-
"""A class that serves as a placeholder for an object that could not be pickled. """
473+
"""A class that serves as a placeholder for an object that could not be pickled."""
480474

481475
def __eq__(self, other):
482476
return isinstance(other, UnpicklableObject)
@@ -508,33 +502,6 @@ def as_python_object(dct: Any) -> Any:
508502
return dct
509503

510504

511-
def fix_py36_copy(func: Callable) -> Callable:
512-
"""Decorator that fixes functions using Python 3.6 deepcopy of ArgumentParsers.
513-
514-
Based on https://stackoverflow.com/questions/6279305/typeerror-cannot-deepcopy-this-pattern-object
515-
"""
516-
if sys.version_info[:2] > (3, 6):
517-
return func
518-
519-
@wraps(func)
520-
def wrapper(*args, **kwargs):
521-
re_type = type(re.compile(""))
522-
has_prev_val = re_type in copy._deepcopy_dispatch
523-
prev_val = copy._deepcopy_dispatch.get(re_type, None)
524-
copy._deepcopy_dispatch[type(re.compile(""))] = lambda r, _: r
525-
526-
result = func(*args, **kwargs)
527-
528-
if has_prev_val:
529-
copy._deepcopy_dispatch[re_type] = prev_val
530-
else:
531-
del copy._deepcopy_dispatch[re_type]
532-
533-
return result
534-
535-
return wrapper
536-
537-
538505
def enforce_reproducibility(
539506
saved_reproducibility_data: Optional[Dict[str, str]], current_reproducibility_data: Dict[str, str], path: PathLike
540507
) -> None:

0 commit comments

Comments
 (0)