Skip to content

Conversation

@corneliusroemer
Copy link
Member

@corneliusroemer corneliusroemer commented Jul 20, 2025

Add types to function that can be type checked and had typing code.

  • This removes the mypy notes:
    $ mypy
    augur/utils.py:444: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs  [annotation-unchecked]
    augur/utils.py:445: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs  [annotation-unchecked]
    
  • Adds stubs for Biopython's SeqFeature (generated with ChatGPT o3)
  • Adds typing for all functions in utils.py and some functions of other modules.
  • Removes no longer used ignores, and asserts on no unused ignores via setting in mypy.ini
  • Print out what flake8 complains about when it fails (previously just get "it failed")

Checklist

  • Automated checks pass
  • Check if you need to add a changelog message
  • Check if you need to add tests
  • Check if you need to update docs

@codecov
Copy link

codecov bot commented Jul 20, 2025

Codecov Report

Attention: Patch coverage is 86.00000% with 14 lines in your changes missing coverage. Please review.

Project coverage is 73.39%. Comparing base (9189a4a) to head (68e7580).

Files with missing lines Patch % Lines
augur/utils.py 85.71% 7 Missing and 2 partials ⚠️
augur/io/sequences.py 86.66% 2 Missing ⚠️
augur/filter/include_exclude_rules.py 50.00% 1 Missing ⚠️
augur/io/shell_command_runner.py 0.00% 1 Missing ⚠️
augur/parse.py 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1860      +/-   ##
==========================================
+ Coverage   73.36%   73.39%   +0.03%     
==========================================
  Files          80       80              
  Lines        8752     8762      +10     
  Branches     1784     1784              
==========================================
+ Hits         6421     6431      +10     
  Misses       2026     2026              
  Partials      305      305              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@corneliusroemer
Copy link
Member Author

Woops:

Traceback (most recent call last):
  File "/home/runner/micromamba/envs/augur/lib/python3.11/site-packages/augur/__init__.py", line 70, in run
    return args.__command__.run(args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/micromamba/envs/augur/lib/python3.11/site-packages/augur/export_v2.py", line 1222, in run
    if json_size(data_json) > MINIFY_THRESHOLD_MB * 10**6:
       ^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/micromamba/envs/augur/lib/python3.11/site-packages/augur/utils.py", line 169, in json_size
    write_json(data, counter, include_version=False)
  File "/home/runner/micromamba/envs/augur/lib/python3.11/site-packages/augur/utils.py", line 151, in write_json
    json.dump(data, handle, indent=indent, sort_keys=sort_keys, cls=AugurJSONEncoder)
  File "/home/runner/micromamba/envs/augur/lib/python3.11/json/__init__.py", line 180, in dump
    fp.write(chunk)
  File "/home/runner/micromamba/envs/augur/lib/python3.11/site-packages/augur/utils.py", line 161, in write
    n = memoryview(b).nbytes
        ^^^^^^^^^^^^^
TypeError: memoryview: a bytes-like object is required, not 'str'


An error occurred (see above) that has not been properly handled by Augur.
To report this, please open a new issue including the original command and the error above:
    <https://github.com/nextstrain/augur/issues/new/choose>

Validating schema of 'results/s/nt_muts.json'...
Validating schema of 'results/s/aa_muts.json'...
Validating config file 'defaults/auspice_config.json' against the JSON schema
Validating schema of 'defaults/auspice_config.json'...

Copy link
Contributor

@genehack genehack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few comments, no real problems?

Comment on lines -1 to +15
import Bio.SeqIO
import os

from augur.errors import AugurError
from augur.utils import augur
from importlib.metadata import version as installed_version
from packaging.version import Version
from shlex import quote as shquote
from shutil import which
from tempfile import NamedTemporaryFile
from textwrap import dedent
from typing import Iterator, Iterable, Union
from typing import Iterable, Iterator, Optional, Union

import Bio
from Bio.SeqFeature import SeqFeature, FeatureLocation
from Bio.SeqRecord import SeqRecord
from packaging.version import Version

from augur.errors import AugurError
from augur.utils import augur
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not opposed to this import re-ordering, but I don't really understand the scheme being used — in particular, why is from packaging.version import Version located where it is?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is isort, it uses 3 groups: things that ship with Python, things that are dependencies, module itself. Packaging doesn't ship, is a dependency and sorts after B.



def _read_gff(reference, feature_names):
def _read_gff(reference: str, feature_names: Optional[Union[set[str], list[str]]] = None) -> dict[str, SeqFeature]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second time seeing Optional[Union[set[str], list[str]]]; is this worth a

StringSetOrList = Optional[Union[set[str], list[str]]]

somewhere?

Comment on lines -446 to +452
for feat in gb.features:
for feature in gb.features:
feat = feature
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say if you're going to rename the loop variable, rename all the usages too, don't immediately re-assign it back to the former name.

from io import RawIOBase
from shlex import quote as shquote
from .__version__ import __version__
from Bio.SeqFeature import CompoundLocation, FeatureLocation, SeqFeature
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question as above about the ordering of this import — why not after L14 with the other Bio.* imports?

Comment on lines +10 to +12
# --------------------------------------------------------------------------- #
# Convenience aliases #
# --------------------------------------------------------------------------- #
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't really seem to be a comment syntax/style that's used in this codebase, consider aligning or converting to docstrings.

Comment on lines +53 to +55
# internal helpers (return shifted / flipped copies) --------------------- #
def _shift(self, offset: int) -> "Location": ...
def _flip(self, length: int) -> "Location": ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if they're internal-only helpers, maybe we shouldn't include types? we shouldn't be using them…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants