From 83f8b2e8ec746232891e314eb33dd8f6ceb9c1af Mon Sep 17 00:00:00 2001 From: Numerlor Date: Tue, 14 Jun 2022 23:02:10 +0200 Subject: Check assignments nested in ifs when searching for symbol definition --- docs/utils.py | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'docs/utils.py') diff --git a/docs/utils.py b/docs/utils.py index bb8074ba..5be5292b 100644 --- a/docs/utils.py +++ b/docs/utils.py @@ -71,21 +71,11 @@ def linkcode_resolve(repo_link: str, domain: str, info: dict[str, str]) -> typin while isinstance(source.body[0], ast.ClassDef): source = source.body[0] - for ast_obj in source.body: - if isinstance(ast_obj, ast.Assign): - names = [] - for target in ast_obj.targets: - if isinstance(target, ast.Tuple): - names.extend([name.id for name in target.elts]) - else: - names.append(target.id) - - if symbol_name in names: - start, end = ast_obj.lineno, ast_obj.end_lineno - break - else: + pos = _global_assign_pos(source, symbol_name) + if pos is None: raise Exception(f"Could not find symbol `{symbol_name}` in {module.__name__}.") - + else: + start, end = pos _, offset = inspect.getsourcelines(symbol[-2]) if offset != 0: offset -= 1 @@ -107,6 +97,35 @@ def linkcode_resolve(repo_link: str, domain: str, info: dict[str, str]) -> typin return url +class NodeWithBody(typing.Protocol): + """An AST node with the body attribute.""" + body: list[ast.AST] + + +def _global_assign_pos(ast_: NodeWithBody, name: str) -> typing.Union[tuple[int, int], None]: + """ + Find the first instance where the `name` global is defined in `ast_`. + + Top level assignments, and assignments nested in top level ifs are checked. + """ + for ast_obj in ast_.body: + if isinstance(ast_obj, ast.Assign): + names = [] + for target in ast_obj.targets: + if isinstance(target, ast.Tuple): + names.extend([name.id for name in target.elts]) + else: + names.append(target.id) + + if name in names: + return ast_obj.lineno, ast_obj.end_lineno + + elif isinstance(ast_obj, ast.If): + pos_in_if = _global_assign_pos(ast_obj, name) + if pos_in_if is not None: + return pos_in_if + + def cleanup() -> None: """Remove unneeded autogenerated doc files, and clean up others.""" included = __get_included() -- cgit v1.2.3 From c51a2d7e39cdc881efe65cceb5a82649db08d92d Mon Sep 17 00:00:00 2001 From: Numerlor Date: Tue, 14 Jun 2022 23:02:42 +0200 Subject: Only append ids from Name nodes --- docs/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'docs/utils.py') diff --git a/docs/utils.py b/docs/utils.py index 5be5292b..a4662ba4 100644 --- a/docs/utils.py +++ b/docs/utils.py @@ -99,6 +99,7 @@ def linkcode_resolve(repo_link: str, domain: str, info: dict[str, str]) -> typin class NodeWithBody(typing.Protocol): """An AST node with the body attribute.""" + body: list[ast.AST] @@ -113,9 +114,10 @@ def _global_assign_pos(ast_: NodeWithBody, name: str) -> typing.Union[tuple[int, names = [] for target in ast_obj.targets: if isinstance(target, ast.Tuple): - names.extend([name.id for name in target.elts]) + names.extend([name.id for name in target.elts if isinstance(name, ast.Name)]) else: - names.append(target.id) + if isinstance(target, ast.Name): + names.append(target.id) if name in names: return ast_obj.lineno, ast_obj.end_lineno -- cgit v1.2.3 From c8b23bbbd25372a55d6e3640b68cd96828922af0 Mon Sep 17 00:00:00 2001 From: Numerlor Date: Tue, 21 Jun 2022 15:09:57 +0200 Subject: reword docstrings Co-authored-by: MarkKoz --- botcore/utils/cooldown.py | 14 +++++++------- botcore/utils/function.py | 9 +++------ docs/utils.py | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) (limited to 'docs/utils.py') diff --git a/botcore/utils/cooldown.py b/botcore/utils/cooldown.py index a06dce46..9e79e48a 100644 --- a/botcore/utils/cooldown.py +++ b/botcore/utils/cooldown.py @@ -70,9 +70,9 @@ class _CommandCooldownManager: """ Manage invocation cooldowns for a command through the arguments the command is called with. - A cooldown is set through `set_cooldown` for a channel with the given `call_arguments`, - if `is_on_cooldown` is checked within `cooldown_duration` seconds - of the call to `set_cooldown` with the same arguments, True is returned. + Use `set_cooldown` to set a cooldown, + and `is_on_cooldown` to check for a cooldown for a channel with the given arguments. + A cooldown lasts for `cooldown_duration` seconds. """ def __init__(self, *, cooldown_duration: float): @@ -99,7 +99,7 @@ class _CommandCooldownManager: cooldowns_list.append(_CooldownItem(call_arguments, timeout_timestamp)) def is_on_cooldown(self, channel: Hashable, call_arguments: _ArgsTuple) -> bool: - """Check whether ``call_arguments`` is on cooldown in ``channel``.""" + """Check whether `call_arguments` is on cooldown in `channel`.""" current_time = time.monotonic() try: return self._cooldowns.get((channel, call_arguments), -math.inf) > current_time @@ -115,9 +115,9 @@ class _CommandCooldownManager: async def _periodical_cleanup(self, initial_delay: float) -> None: """ - Wait for `initial_delay`, after that delete stale items every hour. + Delete stale items every hour after waiting for `initial_delay`. - The `initial_delay` ensures we're not running cleanups for every command at the same time. + The `initial_delay` ensures cleanups are not running for every command at the same time. """ await asyncio.sleep(initial_delay) while True: @@ -151,7 +151,7 @@ def block_duplicate_invocations( Args: cooldown_duration: Length of the cooldown in seconds. - send_notice: If True, the user is notified of the cooldown with a reply. + send_notice: If :obj:`True`, notify the user about the cooldown with a reply. Returns: A decorator that adds a wrapper which applies the cooldowns. diff --git a/botcore/utils/function.py b/botcore/utils/function.py index 1cde5cd9..e8d24e90 100644 --- a/botcore/utils/function.py +++ b/botcore/utils/function.py @@ -28,17 +28,14 @@ def update_wrapper_globals( ignored_conflict_names: Set[str] = frozenset(), ) -> Callable[_P, _R]: r""" - Update globals of the ``wrapper`` function with the globals from the ``wrapped`` function. + Create a copy of ``wrapper``\, the copy's globals are updated with ``wrapped``\'s globals. For forwardrefs in command annotations, discord.py uses the ``__global__`` attribute of the function - to resolve their values, with decorators that replace the function this breaks because they have + to resolve their values. This breaks for decorators that replace the function because they have their own globals. - This function creates a new function functionally identical to ``wrapper``\, which has the globals replaced with - a merge of ``wrapped``\s globals and the ``wrapper``\s globals. - .. warning:: - This function captures the state of ``wrapped``\'s module's globals when it's called, + This function captures the state of ``wrapped``\'s module's globals when it's called; changes won't be reflected in the new function's globals. Args: diff --git a/docs/utils.py b/docs/utils.py index a4662ba4..9d299ebf 100644 --- a/docs/utils.py +++ b/docs/utils.py @@ -107,7 +107,7 @@ def _global_assign_pos(ast_: NodeWithBody, name: str) -> typing.Union[tuple[int, """ Find the first instance where the `name` global is defined in `ast_`. - Top level assignments, and assignments nested in top level ifs are checked. + Check top-level assignments and assignments nested in top-level if blocks. """ for ast_obj in ast_.body: if isinstance(ast_obj, ast.Assign): -- cgit v1.2.3