Skip to content

refactor: bind optional lookups once instead of calling get twice - #52

Open
blaipr wants to merge 1 commit into
ctrliq:mainfrom
blaipr:refactor/bind-optional-lookups-once
Open

refactor: bind optional lookups once instead of calling get twice#52
blaipr wants to merge 1 commit into
ctrliq:mainfrom
blaipr:refactor/bind-optional-lookups-once

Conversation

@blaipr

@blaipr blaipr commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Six places call .get() twice on the same dictionary, once to test it and once to use it:

if kwargs.get('project'):
    payload.update(project=kwargs.get('project').id, playbook=playbook)

That is correct. The guard does protect the access, and nothing mutates the dictionary in between. It reads poorly, it does the lookup twice, and a type checker cannot connect the two calls, so each one shows up as "Attribute id is not defined on None". Binding once fixes all three at no cost:

project = kwargs.get('project')
if project:
    payload.update(project=project.id, playbook=playbook)

Applied in job_templates.py, projects.py, workflow_job_templates.py twice, and page.py twice.

One in the same family is a real improvement rather than a tidy-up. logged_sleep did this:

try:
    frm = inspect.stack()[stack_depth]
    logger = logging.getLogger(inspect.getmodule(frm[0]).__name__)
except AttributeError:  # module is None (interactive shell)
    logger = log

The comment is right about why: inspect.getmodule returns None for a frame with no module, which is what an interactive shell gives. But catching AttributeError to detect that also swallows any other AttributeError raised inside the try, including one from inspect.stack() itself. The None is now tested for directly, so only the case the comment describes is handled and anything else surfaces.

Correcting something I said in #42 and #51. I described these as latent AttributeErrors waiting to happen. They are not: every one is guarded. They are a readability and double-lookup issue that a checker happens to notice, and this change is worth making on those grounds, not on a correctness scare.

Seven diagnostics retired, 131 to 124. Diffed the full list before and after: strict subset, nothing introduced.

Verified with black --check, flake8, the unit suite at 355 passing, and logged_sleep(0) exercising the rewritten path.

@ciq-it-service-account

ciq-it-service-account commented Sep 12, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Six places call `.get()` twice on the same dictionary, once to test it and once to use it:

```python
if kwargs.get('project'):
    payload.update(project=kwargs.get('project').id, playbook=playbook)
```

That is correct. The guard does protect the access, and nothing mutates the dictionary in between. It reads poorly, it does the lookup twice, and a type checker cannot connect the two calls, so each one shows up as "Attribute `id` is not defined on `None`". Binding once fixes all three at no cost:

```python
project = kwargs.get('project')
if project:
    payload.update(project=project.id, playbook=playbook)
```

Applied in `job_templates.py`, `projects.py`, `workflow_job_templates.py` twice, and `page.py` twice.

**One in the same family is a real improvement rather than a tidy-up.** `logged_sleep` did this:

```python
try:
    frm = inspect.stack()[stack_depth]
    logger = logging.getLogger(inspect.getmodule(frm[0]).__name__)
except AttributeError:  # module is None (interactive shell)
    logger = log
```

The comment is right about why: `inspect.getmodule` returns `None` for a frame with no module, which is what an interactive shell gives. But catching `AttributeError` to detect that also swallows any other `AttributeError` raised inside the `try`, including one from `inspect.stack()` itself. The `None` is now tested for directly, so only the case the comment describes is handled and anything else surfaces.

**Correcting something I said in ctrliq#42 and ctrliq#51.** I described these as latent `AttributeError`s waiting to happen. They are not: every one is guarded. They are a readability and double-lookup issue that a checker happens to notice, and this change is worth making on those grounds, not on a correctness scare.

Seven diagnostics retired, 131 to 124. Diffed the full list before and after: strict subset, nothing introduced.

Verified with `black --check`, `flake8`, the unit suite at 355 passing, and `logged_sleep(0)` exercising the rewritten path.
@blaipr
blaipr force-pushed the refactor/bind-optional-lookups-once branch from b90a563 to 95a4b0b Compare September 13, 2026 09:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants