Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve typing: better type hints, increased type safety, mypy support #534

Merged
merged 214 commits into from
Oct 8, 2022
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
214 commits
Select commit Hold shift + click to select a range
fe6b219
Initial mypy configuration
Rocamonde Aug 23, 2022
bc06f0d
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Aug 23, 2022
43fa478
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Aug 31, 2022
ad65877
Fix types: test_envs.py
Rocamonde Aug 31, 2022
240b600
Fix types: conftest.py
Rocamonde Aug 31, 2022
45eac47
Fix types: tests/util
Rocamonde Aug 31, 2022
7e4cf7b
Fix types: tests/scripts
Rocamonde Aug 31, 2022
587be34
Fix types: tests/rewards
Rocamonde Aug 31, 2022
e793052
Fix types: tests/policies
Rocamonde Aug 31, 2022
9f367c0
Incorrect decorator in update_stats method form networks.py::BaseNorm
Rocamonde Aug 31, 2022
b8c4cb1
Fix types: tests/algorithms (adersarial and bc)
Rocamonde Aug 31, 2022
f4d62d2
Fix types: tests/algorithms (dagger and pc)
Rocamonde Aug 31, 2022
50fde43
Fix types: tests/data
Rocamonde Aug 31, 2022
97bc6aa
Linting
Rocamonde Aug 31, 2022
b992ab3
Linting
Rocamonde Sep 1, 2022
7a788cd
Fix types: algorithms/preference_comparisons.py
Rocamonde Sep 1, 2022
26c32c5
Fix types: algorithms/mce_irl.py
Rocamonde Sep 2, 2022
e6f9124
Formatting, fixed minor bug
Rocamonde Sep 2, 2022
e780672
Clarify why types are ignored
Rocamonde Sep 2, 2022
38aef21
Started fixing types on algorithms/density.py
Rocamonde Sep 3, 2022
2bdc902
Linting
Rocamonde Sep 4, 2022
ccad60b
Linting (add back type ignore after reformatting)
Rocamonde Sep 4, 2022
a5f23c0
Fixed types: imitation/data/types.py
Rocamonde Sep 4, 2022
8ae929c
Fixed types (started): imitation/data/
Rocamonde Sep 4, 2022
19f023c
Fixed types: imitation/data/buffer.py
Rocamonde Sep 5, 2022
1846945
Fixed bug in buffer.py
Rocamonde Sep 5, 2022
ca4e844
Fixed types: imitation/data/rollout.py
Rocamonde Sep 5, 2022
6204d4c
Fixed types: imitation/data/wrappers.py
Rocamonde Sep 5, 2022
44aa867
Improve makefile to support automatic cache cleaning
Rocamonde Sep 5, 2022
955c018
Fixed types: imitation/testing/
Rocamonde Sep 5, 2022
58535b8
Linting, fixed wrong return type in rewards.predict_processed_all
Rocamonde Sep 5, 2022
5ccb35f
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Sep 5, 2022
18a533f
Fixed types: imitation/policies/
Rocamonde Sep 5, 2022
c2786cf
Formatting
Rocamonde Sep 5, 2022
4c0a073
Fixed types: imitation/rewards/
Rocamonde Sep 5, 2022
44d7130
Fixed types: imitation/rewards/
Rocamonde Sep 5, 2022
af55ab2
Fixed types: imitation/scripts/
Rocamonde Sep 5, 2022
9d320bd
Fixed types: imitation/util/ and formatting
Rocamonde Sep 5, 2022
e68e32c
Linting and formatting
Rocamonde Sep 5, 2022
b062d47
Bug fixes for test errors
Rocamonde Sep 5, 2022
49cb014
Linting and typing
Rocamonde Sep 5, 2022
a332025
Improve typing in algorithms
Rocamonde Sep 5, 2022
2de6d8a
Formatting
Rocamonde Sep 5, 2022
baa6512
Bug fix
Rocamonde Sep 5, 2022
4679dfd
Formatting
Rocamonde Sep 5, 2022
73bd012
Fixes suggested by Adam.
Rocamonde Sep 6, 2022
1ecc300
Fix mypy version.
Rocamonde Sep 6, 2022
970931a
Update TabularPolicy.predict to match base class
AdamGleave Sep 6, 2022
02a4aa5
Fix not checking for dones
AdamGleave Sep 6, 2022
34dbef6
Merge remote-tracking branch 'origin/add-mypy' into add-mypy
AdamGleave Sep 6, 2022
f16f924
Change for loop to dict comprehension
AdamGleave Sep 6, 2022
ba00b40
Remove is_ensemble to clear up type checking errors
AdamGleave Sep 6, 2022
b4fd47d
Reduce code duplication and general cleanup
AdamGleave Sep 6, 2022
19227c2
Fix type annotation of step_dict
AdamGleave Sep 6, 2022
a601567
Change List to Sequence
AdamGleave Sep 7, 2022
b7d4364
Fix density.py::DensityAlgorithm._set_demo_from_batch
Rocamonde Sep 7, 2022
3ca3bf2
Fixed n_steps (OnPolicyAlgorithm)
Rocamonde Sep 7, 2022
bda08cb
Fix errors in tests
Rocamonde Sep 7, 2022
276dfaa
Include some suggestions into rollout.py and preference_comparisons.py
Rocamonde Sep 7, 2022
3171a8b
Formatting
Rocamonde Sep 7, 2022
479b2f1
Fix setter error as per https://github.com/python/mypy/issues/5936
Rocamonde Sep 7, 2022
a52c4a3
add reason for assertion.
Rocamonde Sep 7, 2022
fb72cf6
Fix style guide violation: https://google.github.io/styleguide/pyguid…
Rocamonde Sep 7, 2022
1cbf645
Update src/imitation/scripts/parallel.py
Rocamonde Sep 7, 2022
f7443cb
Move kwargs to the end.
Rocamonde Sep 7, 2022
8dd12a7
Swap order of expert_policy_type and expert_policy_path validation check
Rocamonde Sep 7, 2022
2bdc4b3
Update src/imitation/util/util.py
Rocamonde Sep 7, 2022
8e46bae
Update tests/rewards/test_reward_fn.py
Rocamonde Sep 7, 2022
163013e
Merge remote-tracking branch 'origin/add-mypy' into add-mypy
AdamGleave Sep 8, 2022
3dcfae7
Explicit random state setting and fix corresponding tests (except not…
Rocamonde Sep 8, 2022
8f5a137
Fix notebooks; add script to clean notebooks
Rocamonde Sep 8, 2022
89ba88c
Merge branch 'add-mypy' of github.com:HumanCompatibleAI/imitation int…
Rocamonde Sep 8, 2022
5f3273b
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Sep 8, 2022
6af437d
Fix all tests.
Rocamonde Sep 8, 2022
852cfb1
Formattting.
Rocamonde Sep 8, 2022
9e1622d
Additional fixes
Rocamonde Sep 8, 2022
2e8b1f0
Linting
Rocamonde Sep 8, 2022
32898c3
Remove automatically generated `_api` docs files too on `make clean`
Rocamonde Sep 8, 2022
76eb8bb
Fix docstrings.
Rocamonde Sep 9, 2022
0a1b06a
Fix issue with next(iter(iterable))
Rocamonde Sep 9, 2022
58eed54
Formatting
Rocamonde Sep 9, 2022
8c1655e
Remove whitespace
Rocamonde Sep 9, 2022
59cff9d
Add TODO message to remove type ignore later
Rocamonde Sep 9, 2022
74b90da
Remove unnecessary assertion.
Rocamonde Sep 9, 2022
54eb44c
Fixed types in density.py set_demonstrations
Rocamonde Sep 9, 2022
ced18b2
Added type ignore to pytype bug
Rocamonde Sep 9, 2022
cbc7062
Fix_get_first_iter_element and add tests
AdamGleave Sep 10, 2022
d518762
Bugfix in BC and tests -- masked as previously iterator ran out too e…
AdamGleave Sep 10, 2022
4804f69
Remove makefile for now
Rocamonde Sep 13, 2022
dcf80a8
Added link to SB3 issue for future reference.
Rocamonde Sep 13, 2022
cee0c46
Fix types of train_imitation
Rocamonde Sep 13, 2022
25aa308
Modify assert in test_bc to reflect correct type
Rocamonde Sep 13, 2022
fb7caff
Add ci/clean_notebooks.py to CI checks
Rocamonde Sep 13, 2022
b23b42d
Improve clean_notebooks.py by allowing checking only mode.
Rocamonde Sep 13, 2022
56761d6
Add ipynb notebook checks to CI
Rocamonde Sep 13, 2022
7e87d40
Add support for explicit files for notebook cleaning
Rocamonde Sep 13, 2022
e1e09fd
Clean notebooks
Rocamonde Sep 13, 2022
9bd0ff0
Small improvements in util.py
Rocamonde Sep 13, 2022
42d1e97
Replace TransitionKind with TransitionsMinimal
Rocamonde Sep 13, 2022
d0e58aa
Delete unused statement in test
Rocamonde Sep 13, 2022
4117a8f
Update src/imitation/util/util.py
Rocamonde Sep 13, 2022
908925a
Update src/imitation/util/util.py
Rocamonde Sep 13, 2022
fc1696e
Merge remote-tracking branch 'origin/add-mypy' into add-mypy
Rocamonde Sep 13, 2022
16c440e
Make type ignore specific to pytype
Rocamonde Sep 13, 2022
2c18c7e
Linting
Rocamonde Sep 13, 2022
831bfe4
Migrate from RandomState (deprecated) to Generator
Rocamonde Sep 13, 2022
3fa312b
Add backticks to error message
Rocamonde Sep 13, 2022
d00b4d6
Create "AnyNorm" alias
Rocamonde Sep 13, 2022
c1d7d12
Small fix
Rocamonde Sep 13, 2022
e456bb7
Add additional checks to shapes in _set_demo_from_batch
Rocamonde Sep 13, 2022
52b71cd
Fix RolloutStatsComputer type
Rocamonde Sep 13, 2022
a23fd29
Improved logging/messages in clean_notebooks.py
Rocamonde Sep 13, 2022
f35b222
Merge branch 'add-mypy' of git@github.com:HumanCompatibleAI/imitation…
Rocamonde Sep 13, 2022
8989c4b
Fix issues resulting from merge
Rocamonde Sep 13, 2022
2e54951
Bug fix
Rocamonde Sep 13, 2022
1d001d3
Bug fix (wasn't really fixed before)
Rocamonde Sep 13, 2022
71b29d7
Fixed docs example of BC
Rocamonde Sep 13, 2022
89197d0
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Sep 14, 2022
d1d12d5
Fix bugs resulting from merge
Rocamonde Sep 14, 2022
d8d355f
Fix docs (dagger.rst) caught by sphinx CI
Rocamonde Sep 14, 2022
7ba6dc6
Add mypy to CI
Rocamonde Sep 14, 2022
024ca75
Continue fixing miscellaneous type errors
Rocamonde Sep 14, 2022
fca8624
Linting
Rocamonde Sep 14, 2022
4923f59
Fix issue with normalize_input_layer type
Rocamonde Sep 23, 2022
44bb66c
Add support for checking presence of generic type ignores
Rocamonde Sep 23, 2022
7f6f36b
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Sep 23, 2022
849d70a
Allow subdirectories in notebook clean
Rocamonde Sep 23, 2022
2639fd1
Add full typing support for TransitionsMinimal as a sequence
Rocamonde Sep 23, 2022
cca71d0
Fix types for density.py
Rocamonde Sep 23, 2022
b888f13
Misc fixes
Rocamonde Sep 26, 2022
e56c0e3
Add support for prefix context manager in logger (from #529)
Rocamonde Sep 26, 2022
939c52f
Added back accidentally removed code
Rocamonde Sep 27, 2022
da5c038
Replaced preference comparisons prefix with ctx manager
Rocamonde Sep 27, 2022
9652189
Fixed errors
Rocamonde Sep 27, 2022
e0f59df
Merge branch 'prefix-logger' of github.com:HumanCompatibleAI/imitatio…
Rocamonde Sep 27, 2022
e53dbcc
Bug fixes
Rocamonde Sep 27, 2022
b7e44cb
Docstring fixes
Rocamonde Sep 27, 2022
3c58cb0
Fix bug in serialize.py
Rocamonde Sep 27, 2022
1e3f10b
Merge branch 'prefix-logger' of github.com:HumanCompatibleAI/imitatio…
Rocamonde Sep 27, 2022
7541784
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Sep 27, 2022
765aa3f
Fixed codecheck by pointing notebook checks to docs
Rocamonde Sep 27, 2022
568446b
Add rng to mce_irl.rst (doctest)
Rocamonde Sep 27, 2022
1aacc95
Add rng to density.rst (doctest)
Rocamonde Sep 27, 2022
630f2e1
Fix remaining rst files
Rocamonde Sep 27, 2022
4f3fea5
Increase sample size to reduce flakiness
Rocamonde Sep 27, 2022
a2a459b
Ignore files not passing mypy for now
Rocamonde Sep 27, 2022
e5bad0b
Comment in wrong line
Rocamonde Sep 27, 2022
1352bf7
Comment in wrong line
Rocamonde Sep 27, 2022
7abd9f5
Merge branch 'add-mypy' of github.com:HumanCompatibleAI/imitation int…
Rocamonde Sep 27, 2022
94e9705
Move excluded files to argument
Rocamonde Sep 27, 2022
617444e
Add quotes to mypy arg call
Rocamonde Sep 27, 2022
d1eebbb
Fix CI mypy call
Rocamonde Sep 27, 2022
5dd02aa
Fix CI yaml
Rocamonde Sep 27, 2022
db7dc22
Break ignored files up into one line each
Rocamonde Sep 27, 2022
e69bd78
Address PR comments
Rocamonde Sep 28, 2022
f4f14f0
Point SB3 to master to include bug fix
Rocamonde Sep 28, 2022
6364dc3
Merge branch 'prefix-logger' of github.com:HumanCompatibleAI/imitatio…
Rocamonde Sep 28, 2022
9025b5d
Do not follow imports for ignored files
Rocamonde Sep 29, 2022
146979b
Format / fix tests for context manager
Rocamonde Sep 29, 2022
5a19b8e
Merge remote-tracking branch 'origin/prefix-logger' into add-mypy
Rocamonde Sep 29, 2022
ebc3138
Switch to sb3 1.6.1
Rocamonde Sep 29, 2022
9e2e3c4
Merge remote-tracking branch 'origin/prefix-logger' into add-mypy
Rocamonde Sep 29, 2022
28991da
Formatting
Rocamonde Sep 29, 2022
9b67ae3
Merge remote-tracking branch 'origin/prefix-logger' into add-mypy
Rocamonde Sep 29, 2022
d650712
Merge branch 'master' of github.com:HumanCompatibleAI/imitation into …
Rocamonde Oct 3, 2022
9f50e3b
Remove unused import
Rocamonde Oct 3, 2022
2a4d541
Remove unused fixture
Rocamonde Oct 3, 2022
4526e33
Add coveragerc file
Rocamonde Oct 3, 2022
d0920ce
Add utils test
Rocamonde Oct 3, 2022
8b63ed9
Add tests and asserts
Rocamonde Oct 3, 2022
cc2d752
Add test to synthetic gatherer
Rocamonde Oct 3, 2022
77f672d
Add trajectory unwrap tests
Rocamonde Oct 3, 2022
0edb9b6
Formatting
Rocamonde Oct 3, 2022
92972f2
Remove bracket typo
Rocamonde Oct 3, 2022
09eb309
Fix .coveragerc instruction
Rocamonde Oct 3, 2022
8780d08
Improve density algo coverage and bug fixes
Rocamonde Oct 5, 2022
9a66f0f
Fix bug in test
Rocamonde Oct 5, 2022
3d0db4b
Add pragma no cover updates
Rocamonde Oct 5, 2022
6f9ff97
Minor coverage tweaks
Rocamonde Oct 5, 2022
f8d6dbd
Fix iterator test
Rocamonde Oct 6, 2022
589b0b7
Update ci/check_typeignore.py
Rocamonde Oct 7, 2022
c3668fc
DRY clean_notebooks.py
Rocamonde Oct 7, 2022
0fccd63
Minor tweak in check_typeignore.py
Rocamonde Oct 7, 2022
487bcc7
Added all checks to CI
Rocamonde Oct 7, 2022
c758243
Move imports to top-level
Rocamonde Oct 7, 2022
6921336
Move main to main() function in script
Rocamonde Oct 7, 2022
bc41787
Minor fixes
Rocamonde Oct 7, 2022
609c4d0
Remove tweak after new SB3 release
Rocamonde Oct 7, 2022
445f57d
Split main() into helper functions.
Rocamonde Oct 7, 2022
707ba66
Fix edge case of n=0 in seed generator
Rocamonde Oct 7, 2022
b4f3cd6
Update src/imitation/scripts/common/rl.py
Rocamonde Oct 7, 2022
f839021
Fix general type ignore in src
Rocamonde Oct 7, 2022
b75478f
Merge remote-tracking branch 'origin/add-mypy' into add-mypy
Rocamonde Oct 7, 2022
cc2d587
Fix type ignore errors
Rocamonde Oct 7, 2022
4232b45
Formatting
Rocamonde Oct 7, 2022
872f6b8
Update src/imitation/util/util.py
Rocamonde Oct 7, 2022
de3c397
Update src/imitation/scripts/common/rl.py
Rocamonde Oct 7, 2022
e87d2c5
Update src/imitation/util/util.py
Rocamonde Oct 7, 2022
57b5904
Replace todo with todo+issue link
Rocamonde Oct 7, 2022
a60afee
Add explicit type ignore arg
Rocamonde Oct 7, 2022
bf298f1
Merge remote-tracking branch 'origin/add-mypy' into add-mypy
Rocamonde Oct 7, 2022
ffb82cc
Add excluded files to code_checks.sh
Rocamonde Oct 7, 2022
eb26516
Unbreak line
Rocamonde Oct 7, 2022
86a5534
Misc fixes
Rocamonde Oct 7, 2022
71886db
Add training to the density algorithm
Rocamonde Oct 7, 2022
7bc0935
Fix no attribute error
Rocamonde Oct 7, 2022
586046f
Type ignore to `with raises` test
Rocamonde Oct 7, 2022
4620ef6
Remove unused import
Rocamonde Oct 7, 2022
a184971
Check typeignore for all SRC files
Rocamonde Oct 8, 2022
07067f0
Clean notebooks
Rocamonde Oct 8, 2022
b7bfdb4
Remove unused import
Rocamonde Oct 8, 2022
6e0dbb1
Ignore the file itself from typeignore check
Rocamonde Oct 8, 2022
71557f6
Add exception to docstring
Rocamonde Oct 8, 2022
f935873
Fix bad naming for clean_notebooks
Rocamonde Oct 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ executors:
resource_class: xlarge
environment:
# If you change these, also change ci/code_checks.sh
SRC_FILES: src/ tests/ experiments/ examples/ docs/conf.py setup.py ci/clean_notebooks.py
SRC_FILES: src/ tests/ experiments/ examples/ docs/conf.py setup.py ci/
NUM_CPUS: 8
static-analysis-medium:
<<: *defaults
resource_class: medium
environment:
# If you change these, also change ci/code_checks.sh
SRC_FILES: src/ tests/ experiments/ examples/ docs/conf.py setup.py ci/clean_notebooks.py
SRC_FILES: src/ tests/ experiments/ examples/ docs/conf.py setup.py ci/
NUM_CPUS: 2
EXCLUDE_MYPY: |
(?x)(
Expand Down Expand Up @@ -246,6 +246,10 @@ jobs:
name: ipynb-check
command: ./ci/clean_notebooks.py --check ./docs/tutorials

- run:
name: typeignore-check
command: ./ci/check_typeignore.py ./src/ ./tests/

- run:
name: flake8
command: flake8 --version && flake8 -j "${NUM_CPUS}" ${SRC_FILES}
Expand Down
5 changes: 3 additions & 2 deletions ci/Xdummy-entrypoint.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/python3

# This script starts an X server and sets DISPLAY, then runs wrapped command.
"""This script starts an X server and sets DISPLAY, then runs wrapped command."""

# Usage: ./Xdummy-entrypoint.py [command]
#
# Adapted from https://github.com/openai/mujoco-py/blob/master/vendor/Xdummy-entrypoint
Expand Down Expand Up @@ -31,7 +32,7 @@
"-config",
"/etc/dummy_xorg.conf",
":0",
]
],
)
os.environ["DISPLAY"] = ":0"

Expand Down
68 changes: 45 additions & 23 deletions ci/check_typeignore.py
Original file line number Diff line number Diff line change
@@ -1,67 +1,89 @@
#!/usr/bin/env python

"""This script checks that no files in our source code have a "#type: ignore" comment without explicitly indicating the
reason for the ignore. This is to ensure that we don't accidentally ignore errors that we should be fixing."""

"""Check for invalid "# type: ignore" comments.

This script checks that no files in our source code have a "#type: ignore" comment
without explicitly indicating the reason for the ignore. This is to ensure that we
don't accidentally ignore errors that we should be fixing.
"""
import argparse
import os
import re
import pathlib
import re
import sys
from typing import List

import click

# Regex to match a "# type: ignore" comment not followed by a reason.
TYPE_IGNORE_COMMENT = re.compile(r"#\s*type:\s*ignore\s*(?![^\[]*\[)")

# Regex to match a "# type: ignore[<reason>]" comment.
TYPE_IGNORE_REASON_COMMENT = re.compile(r"#\s*type:\s*ignore\[(?P<reason>.*)\]")


class InvalidTypeIgnore(ValueError):
"""Raised when a file has an invalid "# type: ignore" comment."""


def check_file(file: pathlib.Path):
"""Checks that the given file has no "# type: ignore" comments without a reason."""
with open(file, "r") as f:
for i, line in enumerate(f):
if TYPE_IGNORE_COMMENT.search(line):
raise ValueError(f"{file}:{i+1}: Found a '# type: ignore' comment without a reason.")
raise InvalidTypeIgnore(
f"{file}:{i+1}: Found a '# type: ignore' comment without a reason.",
)

if search := TYPE_IGNORE_REASON_COMMENT.search(line):
reason = search.group("reason")
if reason == "":
raise ValueError(f"{file}:{i+1}: Found a '# type: ignore[]' comment without a reason.")
raise InvalidTypeIgnore(
f"{file}:{i+1}: Found a '# type: ignore[]' "
"comment without a reason.",
)


def check_files(files: List[pathlib.Path]):
"""Checks that the given files have no "# type: ignore" comments without a reason."""
"""Checks that the given files have no type: ignore comments without a reason."""
for file in files:
check_file(file)


def get_files_to_check(root_dir: pathlib.Path) -> List[pathlib.Path]:
def get_files_to_check(root_dirs: List[pathlib.Path]) -> List[pathlib.Path]:
"""Returns a list of files that should be checked for "# type: ignore" comments."""
# Get the list of files that should be checked.
files = []
for root, _, filenames in os.walk(root_dir):
for filename in filenames:
if filename.endswith(".py"):
files.append(pathlib.Path(root) / filename)
for root_dir in root_dirs:
for root, _, filenames in os.walk(root_dir):
for filename in filenames:
if filename.endswith(".py"):
files.append(pathlib.Path(root) / filename)

return files


@click.command()
@click.option("--root-dir", type=click.Path(exists=True, file_okay=False, dir_okay=True), default="src")
def main(root_dir: str):
"""Checks that no files in our source code have a "#type: ignore" comment without explicitly indicating the
reason for the ignore. This is to ensure that we don't accidentally ignore errors that we should be fixing."""
files = get_files_to_check(pathlib.Path(root_dir))
def parse_args():
"""Parse command-line arguments."""
parser = argparse.ArgumentParser()
parser.add_argument(
"files",
nargs="+",
type=pathlib.Path,
help="List of files or paths to check for invalid '# type: ignore' comments.",
)
args = parser.parse_args()
return parser, args


def main():
"""Check for invalid "# type: ignore" comments."""
parser, args = parse_args()
file_list = get_files_to_check(args.files)
try:
check_files(files)
except ValueError as e:
check_files(file_list)
except InvalidTypeIgnore as e:
print(e)
sys.exit(1)


if __name__ == "__main__":
main()
main()
76 changes: 49 additions & 27 deletions ci/clean_notebooks.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#!/usr/bin/env python
"""Clean all notebooks in the repository."""
import argparse
import pathlib
import sys
import traceback
from typing import Any, List, Tuple

import nbformat

Expand Down Expand Up @@ -38,27 +42,28 @@ def clean_notebook(file: pathlib.Path, check_only=False) -> None:
# Remove the output and metadata from each cell
# also reset the execution count
# if the cell has no code, remove it
fields_defaults: List[Tuple[str, Any]] = [
("execution_count", None),
("outputs", []),
("metadata", {}),
]
for cell in nb.cells:
if "outputs" in cell and cell["outputs"]:
if check_only:
raise UncleanNotebookError(f"Notebook {file} has outputs")
cell["outputs"] = []
was_dirty = True
if "metadata" in cell and cell["metadata"]:
if check_only:
raise UncleanNotebookError(f"Notebook {file} has metadata")
cell["metadata"] = {}
was_dirty = True
if "execution_count" in cell and cell["execution_count"]:
if check_only:
raise UncleanNotebookError(f"Notebook {file} has execution count")
cell["execution_count"] = None
was_dirty = True
if cell["cell_type"] == "code" and not cell["source"]:
if check_only:
raise UncleanNotebookError(f"Notebook {file} has empty code cell")
nb.cells.remove(cell)
was_dirty = True
for field, default in fields_defaults:
if cell.get(field) != default:
Copy link
Member

Choose a reason for hiding this comment

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

There's a slight semantic change here which I think wasn't intended. Previously you were OK with "field" not in cell" -- but now for outputs/metadata you add the default. This has caused the notebooks to have "outputs": [] even for text entries that don't usually produce any output.

Probably want to change this to something like if field in cell and cell.get(field) != default? Or have a list of permissible values as well as defaults, like:

for field, default, allowed in fields_defaults:
    if cell.get(field) not in allowed:
        # ....

where you could include None in allowed for "outputs" even while keeping [] as the default.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the "correct" way to format is to have an empty list for code cells, no entry for any other cell. Not sure if the best way to do this is by allowing different defaults by different cell types. What you're suggesting achieves the same result when using a notebook executor because md cells never add the "outputs" key, but it would not roll it back automatically from e.g. the state it is now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Came up with a solution for this, it is somewhat different to what we've discussed, let me know if you want to take a look before I merge.

was_dirty = True
if check_only:
raise UncleanNotebookError(
f"Notebook {file} is not clean: cell has "
f"field {field!r} with value {cell[field]!r} (expected "
f"{default!r}). Cell:\n{cell['source']!r}",
)
else:
cell[field] = default

if not check_only and was_dirty:
# Write the notebook
Expand All @@ -67,12 +72,10 @@ def clean_notebook(file: pathlib.Path, check_only=False) -> None:
print(f"Cleaned {file}")


if __name__ == "__main__":
def parse_args():
"""Parse command-line arguments."""
# if the argument --check has been passed, check if the notebooks are clean
# otherwise, clean them in-place
import argparse
import traceback

parser = argparse.ArgumentParser()
# capture files and paths to clean
parser.add_argument(
Expand All @@ -83,13 +86,13 @@ def clean_notebook(file: pathlib.Path, check_only=False) -> None:
)
parser.add_argument("--check", action="store_true")
args = parser.parse_args()
check_only = args.check
# build list of files to scan from list of paths and files
return parser, args


def get_files(input_paths: List):
"""Build list of files to scan from list of paths and files."""
files = []
if len(args.files) == 0:
parser.print_help()
exit(1)
for file in args.files:
for file in input_paths:
if file.is_dir():
files.extend(file.glob("**/*.ipynb"))
else:
Expand All @@ -99,10 +102,29 @@ def clean_notebook(file: pathlib.Path, check_only=False) -> None:
print(f"Skipping {file} (not a notebook)")
if not files:
print("No notebooks found")
exit(1)
sys.exit(1)
return files


def main():
"""Clean all notebooks in the repository, or check that they are clean."""
parser, args = parse_args()
check_only = args.check
input_paths = args.files

if len(input_paths) == 0:
parser.print_help()
sys.exit(1)

files = get_files(input_paths)

for file in files:
try:
clean_notebook(file, check_only=check_only)
except UncleanNotebookError:
traceback.print_exc()
exit(1)
sys.exit(1)


if __name__ == "__main__":
main()
16 changes: 14 additions & 2 deletions ci/code_checks.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
#!/usr/bin/env bash

# If you change these, also change .circleci/config.yml.
SRC_FILES=(src/ tests/ experiments/ examples/ docs/conf.py setup.py ci/clean_notebooks.py)
SRC_FILES=(src/ tests/ experiments/ examples/ docs/conf.py setup.py ci/)
EXCLUDE_MYPY="(?x)(
src/imitation/algorithms/preference_comparisons.py$
| src/imitation/rewards/reward_nets.py$
| src/imitation/util/sacred.py$
| src/imitation/algorithms/base.py$
| src/imitation/scripts/train_preference_comparisons.py$
| src/imitation/rewards/serialize.py$
| src/imitation/scripts/common/train.py$
| src/imitation/algorithms/mce_irl.py$
| src/imitation/algorithms/density.py$
| tests/algorithms/test_bc.py$
)"

set -x # echo commands
set -e # quit immediately on error
Expand All @@ -23,7 +35,7 @@ fi
if [ "${skipexpensive:-}" != "true" ]; then
echo "Type checking"
pytype -j auto "${SRC_FILES[@]}"
mypy --show-error-codes "${SRC_FILES[@]}"
mypy "${SRC_FILES[@]}" --exclude "${EXCLUDE_MYPY}" --follow-imports=silent --show-error-codes

echo "Building docs (validates docstrings)"
pushd docs/
Expand Down
10 changes: 9 additions & 1 deletion docs/tutorials/1_train_bc.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"[download this notebook here](https://github.com/HumanCompatibleAI/imitation/blob/master/docs/tutorials/1_train_bc.ipynb)\n",
"# Train an Agent using Behavior Cloning\n",
Expand All @@ -16,6 +17,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"First we need some kind of expert in CartPole-v1 so we can sample some expert trajectories.\n",
"For convenience we just train one using the stable-baselines3 library."
Expand Down Expand Up @@ -48,6 +50,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"Let's quickly check if the expert is any good.\n",
"We usually should be able to reach a reward of 500, which is the maximum achievable value."
Expand All @@ -68,6 +71,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"Now we can use the expert to sample some trajectories.\n",
"We flatten them right away since we are only interested in the individual transitions for behavior cloning.\n",
Expand Down Expand Up @@ -99,6 +103,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"Let's have a quick look at what we just generated using those library functions:"
]
Expand All @@ -120,6 +125,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"After we collected our transitions, it's time to set up our behavior cloning algorithm."
]
Expand All @@ -143,6 +149,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"As you can see the untrained policy only gets poor rewards:"
]
Expand All @@ -160,6 +167,7 @@
{
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"After training, we can match the rewards of the expert (500):"
]
Expand Down Expand Up @@ -200,4 +208,4 @@
},
"nbformat": 4,
"nbformat_minor": 2
}
}
Loading