mirror of
https://github.com/saymrwulf/stable-baselines3.git
synced 2026-09-16 22:20:26 +00:00
Add flake8 linter and Github CI (#19)
* Cleanup code * Add flake8 lint and github workflow * Update build matrix * Relax precision for python3.7
This commit is contained in:
parent
299c28140e
commit
54f6f5b6fb
17 changed files with 130 additions and 45 deletions
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -24,6 +24,7 @@
|
|||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the tests accordingly (*required for a bug fix or a new feature*).
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have ensured `pytest` and `pytype` both pass.
|
||||
- [ ] I have checked the codestyle using `make lint`
|
||||
- [ ] I have ensured `make pytest` and `make type` both pass.
|
||||
|
||||
<!--- This Template is an edited version of the one from https://github.com/evilsocket/pwnagotchi/ -->
|
||||
|
|
|
|||
43
.github/workflows/ci.yml
vendored
Normal file
43
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Skip CI if [ci skip] in the commit message
|
||||
if: "! contains(toJSON(github.event.commits.*.message), '[ci skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.6, 3.7] # 3.8 not supported yet by pytype
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
# cpu version of pytorch
|
||||
pip install torch==1.4.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
|
||||
pip install .[extra,tests,docs]
|
||||
# Use headless version
|
||||
pip install opencv-python-headless
|
||||
- name: Type check
|
||||
run: |
|
||||
make type
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
make lint
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
make pytest
|
||||
|
|
@ -99,6 +99,12 @@ Type checking with `pytype`:
|
|||
make type
|
||||
```
|
||||
|
||||
Codestyle check with `flake8`:
|
||||
|
||||
```
|
||||
make lint
|
||||
```
|
||||
|
||||
Build the documentation:
|
||||
|
||||
```
|
||||
|
|
|
|||
9
Makefile
9
Makefile
|
|
@ -6,6 +6,13 @@ pytest:
|
|||
type:
|
||||
pytype
|
||||
|
||||
lint:
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
# see https://lintlyci.github.io/Flake8Rules/
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings.
|
||||
flake8 . --count --exit-zero --statistics
|
||||
|
||||
doc:
|
||||
cd docs && make html
|
||||
|
||||
|
|
@ -15,7 +22,7 @@ spelling:
|
|||
clean:
|
||||
cd docs && make clean
|
||||
|
||||
.PHONY: clean spelling doc
|
||||
.PHONY: clean spelling doc lint
|
||||
|
||||
# Build docker images
|
||||
# If you do export RELEASE=True, it will also push them
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ Others:
|
|||
- Sync ``VecEnvs`` with Stable-Baselines
|
||||
- Update requirement: ``gym>=0.17``
|
||||
- Added ``.readthedoc.yml`` file
|
||||
- Added ``flake8`` and ``make lint`` command
|
||||
- Added Github workflow
|
||||
|
||||
Documentation:
|
||||
^^^^^^^^^^^^^^
|
||||
|
|
|
|||
27
setup.cfg
27
setup.cfg
|
|
@ -19,3 +19,30 @@ filterwarnings =
|
|||
|
||||
[pytype]
|
||||
inputs = stable_baselines3
|
||||
|
||||
[flake8]
|
||||
ignore = W503,W504 # line breaks before and after binary operators
|
||||
# Ignore import not used when aliases are defined
|
||||
per-file-ignores =
|
||||
./stable_baselines3/__init__.py:F401
|
||||
./stable_baselines3/common/__init__.py:F401
|
||||
./stable_baselines3/a2c/__init__.py:F401
|
||||
./stable_baselines3/ppo/__init__.py:F401
|
||||
./stable_baselines3/sac/__init__.py:F401
|
||||
./stable_baselines3/td3/__init__.py:F401
|
||||
./stable_baselines3/common/vec_env/__init__.py:F401
|
||||
exclude =
|
||||
# No need to traverse our git directory
|
||||
.git,
|
||||
# There's no value in checking cache directories
|
||||
__pycache__,
|
||||
# Don't check the doc
|
||||
docs/
|
||||
# This contains our built documentation
|
||||
build,
|
||||
# This contains builds of flake8 that we don't want to check
|
||||
dist
|
||||
*.egg-info
|
||||
max-complexity = 15
|
||||
# The GitHub editor is 127 chars wide
|
||||
max-line-length = 127
|
||||
|
|
|
|||
54
setup.py
54
setup.py
|
|
@ -1,6 +1,4 @@
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
with open(os.path.join('stable_baselines3', 'version.txt'), 'r') as file_handler:
|
||||
|
|
@ -63,14 +61,14 @@ from stable_baselines3 import PPO
|
|||
model = PPO('MlpPolicy', 'CartPole-v1').learn(10000)
|
||||
```
|
||||
|
||||
"""
|
||||
""" # noqa:E501
|
||||
|
||||
|
||||
setup(name='stable_baselines3',
|
||||
packages=[package for package in find_packages()
|
||||
if package.startswith('stable_baselines3')],
|
||||
package_data={
|
||||
'stable_baselines3': ['py.typed', 'version.txt']
|
||||
'stable_baselines3': ['py.typed', 'version.txt']
|
||||
},
|
||||
install_requires=[
|
||||
'gym>=0.17',
|
||||
|
|
@ -84,28 +82,32 @@ setup(name='stable_baselines3',
|
|||
'matplotlib'
|
||||
],
|
||||
extras_require={
|
||||
'tests': [
|
||||
'pytest',
|
||||
'pytest-cov',
|
||||
'pytest-env',
|
||||
'pytest-xdist',
|
||||
'pytype',
|
||||
],
|
||||
'docs': [
|
||||
'sphinx',
|
||||
'sphinx-autobuild',
|
||||
'sphinx-rtd-theme',
|
||||
# For spelling
|
||||
'sphinxcontrib.spelling',
|
||||
# Type hints support
|
||||
# 'sphinx-autodoc-typehints'
|
||||
],
|
||||
'extra': [
|
||||
# For render
|
||||
'opencv-python',
|
||||
# For atari games,
|
||||
'atari_py~=0.2.0', 'pillow'
|
||||
]
|
||||
'tests': [
|
||||
# Run tests and coverage
|
||||
'pytest',
|
||||
'pytest-cov',
|
||||
'pytest-env',
|
||||
'pytest-xdist',
|
||||
# Type check
|
||||
'pytype',
|
||||
# Lint code
|
||||
'flake8>=3.8'
|
||||
],
|
||||
'docs': [
|
||||
'sphinx',
|
||||
'sphinx-autobuild',
|
||||
'sphinx-rtd-theme',
|
||||
# For spelling
|
||||
'sphinxcontrib.spelling',
|
||||
# Type hints support
|
||||
# 'sphinx-autodoc-typehints'
|
||||
],
|
||||
'extra': [
|
||||
# For render
|
||||
'opencv-python',
|
||||
# For atari games,
|
||||
'atari_py~=0.2.0', 'pillow'
|
||||
]
|
||||
},
|
||||
description='Pytorch version of Stable Baselines, implementations of reinforcement learning algorithms.',
|
||||
author='Antonin Raffin',
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ from typing import Dict, Any, Optional, Callable, Type, Union
|
|||
|
||||
import gym
|
||||
|
||||
from stable_baselines3.common import logger
|
||||
from stable_baselines3.common.monitor import Monitor
|
||||
from stable_baselines3.common.utils import set_random_seed
|
||||
from stable_baselines3.common.atari_wrappers import AtariWrapper
|
||||
from stable_baselines3.common.vec_env import DummyVecEnv, SubprocVecEnv
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Union, Optional
|
||||
from typing import Union, Optional
|
||||
|
||||
import numpy as np
|
||||
from gym import Env, Space
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ class OrnsteinUhlenbeckActionNoise(ActionNoise):
|
|||
super(OrnsteinUhlenbeckActionNoise, self).__init__()
|
||||
|
||||
def __call__(self) -> np.ndarray:
|
||||
noise = self.noise_prev + self._theta * (self._mu - self.noise_prev) * self._dt + \
|
||||
self._sigma * np.sqrt(self._dt) * np.random.normal(size=self._mu.shape)
|
||||
noise = (self.noise_prev + self._theta * (self._mu - self.noise_prev) * self._dt
|
||||
+ self._sigma * np.sqrt(self._dt) * np.random.normal(size=self._mu.shape))
|
||||
self.noise_prev = noise
|
||||
return noise
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from stable_baselines3.common.vec_env.base_vec_env import VecEnv, VecEnvWrapper
|
|||
from stable_baselines3.common.preprocessing import is_image_space
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from stable_baselines3.common.type_aliases import GymStepReturn
|
||||
from stable_baselines3.common.type_aliases import GymStepReturn # noqa: F401
|
||||
|
||||
|
||||
class VecTransposeImage(VecEnvWrapper):
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ def test_squashed_gaussian(model_class):
|
|||
actions = dist.get_actions()
|
||||
assert th.max(th.abs(actions)) <= 1.0
|
||||
|
||||
|
||||
def test_sde_distribution():
|
||||
n_actions = 1
|
||||
deterministic_actions = th.ones(N_SAMPLES, n_actions) * 0.1
|
||||
|
|
@ -95,4 +96,4 @@ def test_categorical():
|
|||
actions = dist.get_actions()
|
||||
entropy = dist.entropy()
|
||||
log_prob = dist.log_prob(actions)
|
||||
assert th.allclose(entropy.mean(), -log_prob.mean(), rtol=1e-4)
|
||||
assert th.allclose(entropy.mean(), -log_prob.mean(), rtol=2e-4)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ def test_high_dimension_action_space():
|
|||
env = FakeImageEnv()
|
||||
# Patch the action space
|
||||
env.action_space = spaces.Box(low=-1, high=1, shape=(20,), dtype=np.float32)
|
||||
|
||||
# Patch to avoid error
|
||||
def patched_step(_action):
|
||||
return env.observation_space.sample(), 0.0, False, {}
|
||||
|
|
|
|||
|
|
@ -230,7 +230,6 @@ def test_save_load_policy(model_class, policy_str):
|
|||
|
||||
del policy, actor
|
||||
|
||||
|
||||
policy = policy_class.load("./logs/policy.pkl")
|
||||
if actor_class is not None:
|
||||
actor = actor_class.load("./logs/actor.pkl")
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ def test_make_vec_env(env_id, n_envs, vec_env_cls, wrapper_class):
|
|||
@pytest.mark.parametrize("env_id", ['BreakoutNoFrameskip-v4'])
|
||||
@pytest.mark.parametrize("n_envs", [1, 2])
|
||||
@pytest.mark.parametrize("wrapper_kwargs", [None, dict(clip_reward=False, screen_size=60)])
|
||||
def test_make_vec_env(env_id, n_envs, wrapper_kwargs):
|
||||
def test_make_atari_env(env_id, n_envs, wrapper_kwargs):
|
||||
env_id = 'BreakoutNoFrameskip-v4'
|
||||
env = make_atari_env(env_id, n_envs,
|
||||
wrapper_kwargs=wrapper_kwargs, monitor_dir=None, seed=0)
|
||||
|
|
@ -55,15 +55,14 @@ def test_make_vec_env(env_id, n_envs, wrapper_kwargs):
|
|||
if wrapper_kwargs is not None:
|
||||
assert obs.shape == (n_envs, 60, 60, 1)
|
||||
assert wrapped_atari_env.observation_space.shape == (60, 60, 1)
|
||||
assert wrapped_atari_env.clip_reward == False
|
||||
assert wrapped_atari_env.clip_reward is False
|
||||
else:
|
||||
assert obs.shape == (n_envs, 84, 84, 1)
|
||||
assert wrapped_atari_env.observation_space.shape == (84, 84, 1)
|
||||
assert wrapped_atari_env.clip_reward == True
|
||||
assert wrapped_atari_env.clip_reward is True
|
||||
assert np.max(np.abs(reward)) < 1.0
|
||||
|
||||
|
||||
|
||||
def test_custom_vec_env(tmp_path):
|
||||
"""
|
||||
Stand alone test for a special case (passing a custom VecEnv class) to avoid doubling the number of tests.
|
||||
|
|
@ -73,7 +72,6 @@ def test_custom_vec_env(tmp_path):
|
|||
monitor_dir=monitor_dir, seed=0,
|
||||
vec_env_cls=SubprocVecEnv, vec_env_kwargs={'start_method': None})
|
||||
|
||||
|
||||
assert env.num_envs == 1
|
||||
assert isinstance(env, SubprocVecEnv)
|
||||
assert os.path.isdir(monitor_dir)
|
||||
|
|
|
|||
|
|
@ -68,5 +68,4 @@ def test_check_nan():
|
|||
else:
|
||||
assert False
|
||||
|
||||
|
||||
env.step(np.array([[0, 1], [0, 1]]))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import pytest
|
|||
import numpy as np
|
||||
|
||||
from stable_baselines3.common.running_mean_std import RunningMeanStd
|
||||
from stable_baselines3.common.vec_env import DummyVecEnv, VecNormalize, VecFrameStack, sync_envs_normalization, unwrap_vec_normalize
|
||||
from stable_baselines3.common.vec_env import (DummyVecEnv, VecNormalize, VecFrameStack, sync_envs_normalization,
|
||||
unwrap_vec_normalize)
|
||||
from stable_baselines3 import SAC, TD3
|
||||
|
||||
ENV_ID = 'Pendulum-v0'
|
||||
|
|
@ -53,8 +54,8 @@ def _make_warmstart_cartpole():
|
|||
def test_runningmeanstd():
|
||||
"""Test RunningMeanStd object"""
|
||||
for (x_1, x_2, x_3) in [
|
||||
(np.random.randn(3), np.random.randn(4), np.random.randn(5)),
|
||||
(np.random.randn(3, 2), np.random.randn(4, 2), np.random.randn(5, 2))]:
|
||||
(np.random.randn(3), np.random.randn(4), np.random.randn(5)),
|
||||
(np.random.randn(3, 2), np.random.randn(4, 2), np.random.randn(5, 2))]:
|
||||
rms = RunningMeanStd(epsilon=0.0, shape=x_1.shape[1:])
|
||||
|
||||
x_cat = np.concatenate([x_1, x_2, x_3], axis=0)
|
||||
|
|
|
|||
Loading…
Reference in a new issue