question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Enhancement] Improve Typing Support / Ensure every function has return type

See original GitHub issue

One of the goals for v1 release was to improve typing support. This issue is only concerned return types. I wanted to improve the type support so I wrote a script to parse python code and filter out function definitions and class method definitions to find out what needs typing. In the process, I figured that this would be quite useful to add as a test.

Suggestion

Add a test to ensure that every function has a return type.

This isn’t to be confused with type verification, e.g. bad return types.

Special Cases

In some cases we may want to avoid adding a return type, a decorator could be added onto the function to make it ignored by the test.

An exhaustive list of functions that are missing return types:

Missing types:
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::step_async
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::step_wait
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::seed
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::reset
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::close
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::render
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::_save_obs
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::_obs_from_buf
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::get_attr
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::set_attr
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::env_method
stable_baselines3/common/vec_env/dummy_vec_env.py::DummyVecEnv::_get_target_envs
stable_baselines3/common/logger.py::SeqWriter::write_sequence
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::__getstate__
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::__setstate__
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::set_venv
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::step_wait
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::_update_reward
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::normalize_obs
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::normalize_reward
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::unnormalize_obs
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::unnormalize_reward
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::get_original_obs
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::get_original_reward
stable_baselines3/common/vec_env/vec_normalize.py::VecNormalize::reset
stable_baselines3/common/utils.py::check_for_correct_spaces
stable_baselines3/td3/policies.py::TD3Policy::forward
stable_baselines3/common/cmd_util.py::make_vec_env
stable_baselines3/common/cmd_util.py::make_atari_env
stable_baselines3/common/buffers.py::BaseBuffer::sample
stable_baselines3/common/buffers.py::BaseBuffer::_get_samples
stable_baselines3/common/vec_env/vec_frame_stack.py::VecFrameStack::step_wait
stable_baselines3/common/vec_env/vec_frame_stack.py::VecFrameStack::reset
stable_baselines3/common/vec_env/vec_frame_stack.py::VecFrameStack::close
stable_baselines3/common/monitor.py::Monitor::close
stable_baselines3/common/atari_wrappers.py::MaxAndSkipEnv::reset
stable_baselines3/common/evaluation.py::evaluate_policy
stable_baselines3/common/policies.py::BasePolicy::forward
stable_baselines3/common/policies.py::BasePolicy::load_from_vector
stable_baselines3/common/vec_env/vec_video_recorder.py::VecVideoRecorder::reset
stable_baselines3/common/vec_env/vec_video_recorder.py::VecVideoRecorder::start_video_recorder
stable_baselines3/common/vec_env/vec_video_recorder.py::VecVideoRecorder::_video_enabled
stable_baselines3/common/vec_env/vec_video_recorder.py::VecVideoRecorder::step_wait
stable_baselines3/common/vec_env/vec_video_recorder.py::VecVideoRecorder::close_video_recorder
stable_baselines3/common/vec_env/vec_video_recorder.py::VecVideoRecorder::close
stable_baselines3/common/callbacks.py::EvalCallback::_init_callback
stable_baselines3/common/off_policy_algorithm.py::OffPolicyAlgorithm::_setup_model
stable_baselines3/common/off_policy_algorithm.py::OffPolicyAlgorithm::save_replay_buffer
stable_baselines3/common/off_policy_algorithm.py::OffPolicyAlgorithm::load_replay_buffer
stable_baselines3/common/vec_env/util.py::copy_obs_dict
stable_baselines3/common/vec_env/util.py::dict_to_obs
stable_baselines3/common/vec_env/util.py::obs_space_info
stable_baselines3/common/vec_env/vec_check_nan.py::VecCheckNan::step_async
stable_baselines3/common/vec_env/vec_check_nan.py::VecCheckNan::step_wait
stable_baselines3/common/vec_env/vec_check_nan.py::VecCheckNan::reset
stable_baselines3/common/vec_env/vec_check_nan.py::VecCheckNan::_check_val
stable_baselines3/common/vec_env/subproc_vec_env.py::_worker
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::step_async
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::step_wait
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::seed
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::reset
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::close
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::get_attr
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::set_attr
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::env_method
stable_baselines3/common/vec_env/subproc_vec_env.py::SubprocVecEnv::_get_target_remotes
stable_baselines3/common/vec_env/subproc_vec_env.py::_flatten_obs
stable_baselines3/common/noise.py::VectorizedActionNoise::base_noise
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::reset
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::step_async
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::step_wait
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::close
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::get_attr
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::set_attr
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::env_method
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::step
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::render
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::unwrapped
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::getattr_depth_check
stable_baselines3/common/vec_env/base_vec_env.py::VecEnv::_get_indices
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::step_async
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::reset
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::step_wait
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::seed
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::close
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::render
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::get_images
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::get_attr
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::set_attr
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::env_method
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::__getattr__
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::_get_all_attributes
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::getattr_recursive
stable_baselines3/common/vec_env/base_vec_env.py::VecEnvWrapper::getattr_depth_check
stable_baselines3/common/vec_env/base_vec_env.py::CloudpickleWrapper::__getstate__
stable_baselines3/common/vec_env/base_vec_env.py::CloudpickleWrapper::__setstate__
stable_baselines3/dqn/dqn.py::DQN::_on_step
stable_baselines3/common/base_class.py::BaseAlgorithm::load

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
PartiallyTypedcommented, Jul 2, 2020

It is nice to check to improve typing (mostly the vec env missing)

I am not familiar with the vec env code base, but I can deal with the others and open a PR.

It is nice to check to improve typing (mostly the vec env missing) but I would not enforce it, in some cases (abstract classes), it is easier not to specify return type

I am leaving this here as a future reference.

import ast
import pathlib


def missing_return_types():
    root = pathlib.Path("./stable_baselines3")
    files = set(root.iterdir())
    pyfiles = set()
    while files:
        f = files.pop()
        if f.is_dir():
            files.update(set(f.iterdir()))
        elif f.suffix==".py":
            pyfiles.add(f)
    invalid_definitions = []
    def recursive_iter(node, path):
        if isinstance(node, ast.FunctionDef) and node.returns is None:
            if node.name not in ("__init__", "__del__"):
                invalid_definitions.append((*path, node.name))
        if isinstance(node, ast.ClassDef):
            for newnode in ast.iter_child_nodes(node):
                recursive_iter(newnode, (*path, node.name))
        if isinstance(node, ast.Module):
            for newnode in ast.iter_child_nodes(node):
                recursive_iter(newnode, path)
    for file in pyfiles:
        recursive_iter(ast.parse(file.read_text(), filename=str(file)), (str(file),))
    invalid_definitions = list(map("::".join, invalid_definitions))
    print("Missing types:", *invalid_definitions, sep="\n")

0reactions
PartiallyTypedcommented, Jul 6, 2020

@araffin

I was playing with ‘typing.Generic’ and it is possible to define a subclass that returns a specific type without complains that the return type is different.

i.e the base policy hints TypeVar and the subclass hints the correct type. Static typers are aware of the subclass so when a policy returns an action and log prob, static typers know it returns two items.

Read more comments on GitHub >

github_iconTop Results From Across the Web

4 Tips for Improving Your Typing Accuracy and Speed - Indeed
Learn four effective tips to help you improve your typing accuracy and speed for better written communications.
Read more >
PEP 677 – Callable Type Syntax
This PEP introduces a concise and friendly syntax for callable types, supporting the same functionality as typing.Callable but with an arrow ...
Read more >
Python typing module - Use type checkers effectively
Introduced since Python 3.5, Python's typing module attempts to provide a way of hinting types to help static type checkers and linters ...
Read more >
Using Python's Type Annotations - DEV Community ‍ ‍
Using -> <type> , we can more easily show the return value types of any function or method, to avoid confusion by future...
Read more >
Writing Functions In Python - Hylke Rozema
The first function you write is count_letter() . It takes a string and a single letter and returns the number of times the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found