Skip to content

Commit

Permalink
Add flake8 linter and Github CI (#19)
Browse files Browse the repository at this point in the history
* Cleanup code

* Add flake8 lint and github workflow

* Update build matrix

* Relax precision for python3.7
  • Loading branch information
araffin committed May 12, 2020
1 parent 299c281 commit 54f6f5b
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 45 deletions.
3 changes: 2 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ Type checking with `pytype`:
make type
```

Codestyle check with `flake8`:

```
make lint
```

Build the documentation:

```
Expand Down
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions docs/misc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:
^^^^^^^^^^^^^^
Expand Down
27 changes: 27 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 28 additions & 26 deletions setup.py
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -63,14 +61,14 @@
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',
Expand All @@ -84,28 +82,32 @@
'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',
Expand Down
2 changes: 0 additions & 2 deletions stable_baselines3/common/cmd_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

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

Expand Down
2 changes: 1 addition & 1 deletion stable_baselines3/common/identity_env.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Union, Optional
from typing import Union, Optional

import numpy as np
from gym import Env, Space
Expand Down
4 changes: 2 additions & 2 deletions stable_baselines3/common/noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def __init__(self, mean: np.ndarray,
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

Expand Down
2 changes: 1 addition & 1 deletion stable_baselines3/common/vec_env/vec_transpose.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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):
Expand Down
3 changes: 2 additions & 1 deletion tests/test_distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
1 change: 1 addition & 0 deletions tests/test_envs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, {}
Expand Down
1 change: 0 additions & 1 deletion tests/test_save_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
8 changes: 3 additions & 5 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand All @@ -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)
Expand Down
1 change: 0 additions & 1 deletion tests/test_vec_check_nan.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,4 @@ def test_check_nan():
else:
assert False


env.step(np.array([[0, 1], [0, 1]]))
7 changes: 4 additions & 3 deletions tests/test_vec_normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
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'
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 54f6f5b

Please sign in to comment.