Conditions | 16 |
Total Lines | 62 |
Lines | 0 |
Ratio | 0 % |
Changes | 3 | ||
Bugs | 1 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like fmt_table() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | """Helper functions and classes""" |
||
17 | if TYPE_CHECKING: |
||
18 | from .wm import WindowManager # NOQA |
||
19 | |||
20 | # pylint: disable=C0103 |
||
21 | PercentRect = Tuple[float, float, float, float] |
||
22 | Strut = Tuple[int, int, int, int, int, int, int, int, int, int, int, int] |
||
23 | |||
24 | # FIXME: Replace */** with a dict so I can be strict here |
||
25 | CommandCB = Callable[..., Any] |
||
26 | except: # pylint: disable=bare-except |
||
27 | pass |
||
|
|||
28 | |||
29 | def clamp_idx(idx, stop, wrap=True): |
||
30 | # type: (int, int, bool) -> int |
||
31 | """Ensure a 0-based index is within a given range [0, stop). |
||
32 | |||
33 | Uses the same half-open range convention as Python slices. |
||
34 | |||
35 | @param wrap: If C{True}, wrap around rather than saturating. |
||
36 | """ |
||
37 | if wrap: |
||
38 | return idx % stop |
||
39 | else: |
||
40 | return max(min(idx, stop - 1), 0) |
||
41 | |||
42 | def powerset(iterable): # type: (Iterable[Any]) -> Iterator[Sequence[Any]] |
||
43 | """C{powerset([1,2,3])} --> C{() (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)} |
||
44 | |||
45 | @rtype: iterable |
||
46 | """ |
||
47 | i = list(iterable) |
||
48 | return chain.from_iterable(combinations(i, j) for j in range(len(i) + 1)) |
||
49 | |||
50 | def fmt_table(rows, # type: Any |
||
51 | headers, # type: Sequence |
||
52 | group_by=None # type: Optional[int] |
||
53 | ): # type: (...) -> str |
||
54 | """Format a collection as a textual table. |
||
55 | |||
56 | @param headers: Header labels for the columns |
||
57 | @param group_by: Index of the column to group results by. |
||
58 | @type rows: C{dict} or iterable of iterables |
||
59 | @type headers: C{list(str)} |
||
60 | @type group_by: C{int} |
||
61 | |||
62 | @attention: This uses C{zip()} to combine things. The number of columns |
||
63 | displayed will be defined by the narrowest of all rows. |
||
64 | |||
65 | @rtype: C{str} |
||
66 | """ |
||
67 | output = [] # type: List[str] |
||
68 | |||
69 | if isinstance(rows, dict): |
||
70 | rows = list(sorted(rows.items())) |
||
71 | |||
72 | groups = {} # type: Dict[str, List[str]] |
||
73 | if group_by is not None: |
||
74 | headers = list(headers) |
||
75 | headers.pop(group_by) |
||
76 | rows = [list(row) for row in rows] |
||
77 | for row in rows: |
||
78 | group = row.pop(group_by) |
||
79 | groups.setdefault(group, []).append(row) |
||
182 |
Except handlers which only contain
pass
and do not have anelse
clause can usually simply be removed: