From 4e5d2845a023706e701085b430d8692d1a0a9735 Mon Sep 17 00:00:00 2001 From: Bamboofungus Date: Fri, 25 Aug 2023 01:48:48 +0900 Subject: [PATCH 01/26] Fix syntax/imports and add TODOs/notests in docs --- docs/api/parallel.md | 2 +- docs/api/wrappers/pz_wrappers.md | 6 ++++-- docs/api/wrappers/shimmy_wrappers.md | 9 ++++++--- docs/api/wrappers/supersuit_wrappers.md | 2 +- docs/content/basic_usage.md | 14 +++++++++++--- docs/content/environment_creation.md | 4 ++-- docs/content/environment_tests.md | 15 +++++++++------ docs/environments/atari.md | 2 +- docs/environments/butterfly.md | 2 +- 9 files changed, 36 insertions(+), 20 deletions(-) diff --git a/docs/api/parallel.md b/docs/api/parallel.md index a5f7abfce..d32e0b7b4 100644 --- a/docs/api/parallel.md +++ b/docs/api/parallel.md @@ -26,7 +26,7 @@ from pettingzoo.butterfly import pistonball_v6 parallel_env = pistonball_v6.parallel_env(render_mode="human") observations, infos = parallel_env.reset(seed=42) -while env.agents: +while parallel_env.agents: # this is where you would insert your policy actions = {agent: parallel_env.action_space(agent).sample() for agent in parallel_env.agents} diff --git a/docs/api/wrappers/pz_wrappers.md b/docs/api/wrappers/pz_wrappers.md index 51b40bc44..4a2412ded 100644 --- a/docs/api/wrappers/pz_wrappers.md +++ b/docs/api/wrappers/pz_wrappers.md @@ -63,12 +63,13 @@ We wanted our pettingzoo environments to be both easy to use and easy to impleme You can apply these wrappers to your environment in a similar manner to the below examples: To wrap a Parallel environment. -```python +```python notest from pettingzoo.utils import CaptureStdoutWrapper from pettingzoo.butterfly import pistonball_v6 parallel_env = pistonball_v6.env() parallel_env = CaptureStdoutWrapper(parallel_env) +#TODO parallel_env.reset() returns None here observations, infos = parallel_env.reset() while parallel_env.agents: @@ -77,7 +78,7 @@ while parallel_env.agents: ``` To wrap an AEC environment: -```python +```python notest from pettingzoo.utils import TerminateIllegalWrapper from pettingzoo.classic import rps_v2 env = rps_v2.env() @@ -90,6 +91,7 @@ for agent in env.agent_iter(): action = None else: action = env.action_space(agent).sample() # this is where you would insert your policy + #TODO RPS observe() returns an np.array instead of dict, triggering an assert statement in TerminateIllegalWrapper env.step(action) env.close() ``` diff --git a/docs/api/wrappers/shimmy_wrappers.md b/docs/api/wrappers/shimmy_wrappers.md index bfe9515f8..877d2a4ff 100644 --- a/docs/api/wrappers/shimmy_wrappers.md +++ b/docs/api/wrappers/shimmy_wrappers.md @@ -25,8 +25,9 @@ The [Shimmy](https://shimmy.farama.org/) package (`pip install shimmy`) allows c To load a DeepMind Control [multi-agent soccer game](https://github.com/deepmind/dm_control/blob/main/dm_control/locomotion/soccer/README.md): -```python +```python notest from shimmy import DmControlMultiAgentCompatibilityV0 +#TODO ModuleNotFoundError: No module named 'dm_control' from dm_control.locomotion import soccer as dm_soccer env = dm_soccer.load(team_size=2) @@ -40,7 +41,8 @@ while env.agents: To load an OpenSpiel game of [backgammon](https://github.com/deepmind/open_spiel/blob/master/docs/games.md#backgammon): -```python +```python notest +#TODO ImportError: cannot import name 'OpenspielCompatibilityV0' from 'shimmy' from shimmy import OpenspielCompatibilityV0 import pyspiel @@ -61,7 +63,8 @@ for agent in env.agent_iter(): To load a Melting Pot [prisoner's dilemma in the matrix](https://github.com/deepmind/meltingpot/blob/main/docs/substrate_scenario_details.md#prisoners-dilemma-in-the-matrix) substrate: -```python +```python notest +#TODO ImportError: Melting Pot or PettingZoo is not installed, run `pip install 'shimmy[melting-pot]' and install Melting Pot via https://github.com/deepmind/meltingpot#installation` from shimmy import MeltingPotCompatibilityV0 env = MeltingPotCompatibilityV0(substrate_name="prisoners_dilemma_in_the_matrix__arena", render_mode="human") observations, infos = env.reset() diff --git a/docs/api/wrappers/supersuit_wrappers.md b/docs/api/wrappers/supersuit_wrappers.md index deb6579a3..5b46ba7a9 100644 --- a/docs/api/wrappers/supersuit_wrappers.md +++ b/docs/api/wrappers/supersuit_wrappers.md @@ -8,7 +8,7 @@ The [SuperSuit](https://github.com/Farama-Foundation/SuperSuit) companion packag To convert [space invaders](/environments/atari/space_invaders/) to a greyscale observation space and stack the last 4 frames: -``` python +``` python notest from pettingzoo.atari import space_invaders_v2 from supersuit import color_reduction_v0, frame_stack_v1 diff --git a/docs/content/basic_usage.md b/docs/content/basic_usage.md index 2f3cd8836..382ca5a24 100644 --- a/docs/content/basic_usage.md +++ b/docs/content/basic_usage.md @@ -25,19 +25,25 @@ env = pistonball_v6.env() Environments are generally highly configurable via arguments at creation, i.e.: ``` python -cooperative_pong.env(ball_speed=18, left_paddle_speed=25, -right_paddle_speed=25, is_cake_paddle=True, max_cycles=900, bounce_randomness=False) +from pettingzoo.butterfly import cooperative_pong_v5 + +cooperative_pong_v5.env(ball_speed=18, left_paddle_speed=25, +right_paddle_speed=25, cake_paddle=True, max_cycles=900, bounce_randomness=False) ``` ## Interacting With Environments Environments can be interacted with using a similar interface to Gymnasium: -``` python +``` python notest +from pettingzoo.butterfly import cooperative_pong_v5 + +env = cooperative_pong_v5.env() env.reset() for agent in env.agent_iter(): observation, reward, termination, truncation, info = env.last() action = env.action_space(agent).sample() # this is where you would insert your policy + #TODO ValueError: when an agent is dead, the only valid action is None env.step(action) ``` @@ -116,6 +122,8 @@ When an agent is terminated or truncated, it's removed from `agents`, so when th If you have a wrapped environment, and you want to get the unwrapped environment underneath all the layers of wrappers (so that you can manually call a function or change some underlying aspect of the environment), you can use the `.unwrapped` attribute. If the environment is already a base environment, the `.unwrapped` attribute will just return itself. ``` python +from pettingzoo.butterfly import knights_archers_zombies_v10 + base_env = knights_archers_zombies_v10.env().unwrapped ``` diff --git a/docs/content/environment_creation.md b/docs/content/environment_creation.md index f0cb89023..9bc1c98df 100644 --- a/docs/content/environment_creation.md +++ b/docs/content/environment_creation.md @@ -68,8 +68,8 @@ from pettingzoo.utils.deprecated_module import DeprecatedModule knights_archers_zombies_v0 = DeprecatedModule("knights_archers_zombies", "v0", "v10") ``` This declaration tells the user that `knights_archers_zombies_v0` is deprecated and `knights_archers_zombies_v10` should be used instead. In particular, it gives the following error: -``` python +``` python notest from pettingzoo.butterfly import knights_archers_zombies_v0 knights_archers_zombies_v0.env() -# pettingzoo.utils.deprecated_module.DeprecatedEnv: knights_archers_zombies_v0 is now deprecated, use knights_archers_zombies_v10 instead + ``` diff --git a/docs/content/environment_tests.md b/docs/content/environment_tests.md index b4577bb0b..48de97999 100644 --- a/docs/content/environment_tests.md +++ b/docs/content/environment_tests.md @@ -37,15 +37,15 @@ To have a properly reproducible environment that utilizes randomness, you need t The seed test takes in a function that creates a pettingzoo environment. For example -``` python +``` python notest from pettingzoo.test import seed_test, parallel_seed_test from pettingzoo.butterfly import pistonball_v6 env_fn = pistonball_v6.env -seed_test(env_fn, num_cycles=10, test_kept_state=True) +seed_test(env_fn, num_cycles=10) # or for parallel environments parallel_env_fn = pistonball_v6.parallel_env -parallel_seed_test(parallel_env_fn, num_cycles=10, test_kept_state=True) +parallel_seed_test(parallel_env_fn) ``` Internally, there are two separate tests. @@ -61,10 +61,11 @@ The second optional argument, `test_kept_state` allows the user to disable the s The max cycles test tests that the `max_cycles` environment argument exists and the resulting environment actually runs for the correct number of cycles. If your environment does not take a `max_cycles` argument, you should not run this test. The reason this test exists is that many off-by-one errors are possible when implementing `max_cycles`. An example test usage looks like: -``` python +``` python notest from pettingzoo.test import max_cycles_test from pettingzoo.butterfly import pistonball_v6 env = pistonball_v6.env() +#TODO AttributeError: 'OrderEnforcingWrapper' object has no attribute 'parallel_env' max_cycles_test(env) ``` @@ -72,10 +73,11 @@ max_cycles_test(env) The render test checks that rendering 1) does not crash and 2) produces output of the correct type when given a mode (only supports `'human'`, `'ansi'`, and `'rgb_array'` modes). -``` python +``` python notest from pettingzoo.test import render_test from pettingzoo.butterfly import pistonball_v6 env = pistonball_v6.env() +#TODO TypeError: 'OrderEnforcingWrapper' object is not callable render_test(env) ``` @@ -103,9 +105,10 @@ performance_benchmark(env) The save observation test is to visually inspect the observations of games with graphical observations to make sure they are what is intended. We have found that observations are a huge source of bugs in environments, so it is good to manually check them when possible. This test just tries to save the observations of all the agents. If it fails, then it just prints a warning. The output needs to be visually inspected for correctness. -``` python +``` python notest from pettingzoo.test import test_save_obs from pettingzoo.butterfly import pistonball_v6 env = pistonball_v6.env() +#TODO running test_save_obs creates multiple files each time doctests are run here test_save_obs(env) ``` diff --git a/docs/environments/atari.md b/docs/environments/atari.md index 4839f94ac..c68921d72 100644 --- a/docs/environments/atari.md +++ b/docs/environments/atari.md @@ -92,7 +92,7 @@ pip install supersuit Here is some example usage for the Atari preprocessing: -``` python +``` python notest import supersuit from pettingzoo.atari import space_invaders_v1 diff --git a/docs/environments/butterfly.md b/docs/environments/butterfly.md index aa008be1b..2bde3760c 100644 --- a/docs/environments/butterfly.md +++ b/docs/environments/butterfly.md @@ -50,7 +50,7 @@ env.close() ``` To launch a [Knights Archers Zombies](/environments/butterfly/knights_archers_zombies/) environment with interactive user input (see [manual_policy.py](https://github.com/Farama-Foundation/PettingZoo/blob/master/pettingzoo/butterfly/knights_archers_zombies/manual_policy.py)): -```python +```python notest import pygame from pettingzoo.butterfly import knights_archers_zombies_v10 From c66a73033f23d168e24d5d1622b9c152db3463d2 Mon Sep 17 00:00:00 2001 From: Bamboofungus Date: Fri, 1 Sep 2023 17:07:39 +0900 Subject: [PATCH 02/26] Fix some errors and add typing to render_test --- docs/api/wrappers/pz_wrappers.md | 7 ++++--- docs/api/wrappers/shimmy_wrappers.md | 7 +++---- docs/content/basic_usage.md | 17 ++++++++++++----- docs/content/environment_tests.md | 12 +++++------- docs/environments/butterfly.md | 4 ++-- pettingzoo/test/render_test.py | 5 ++++- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/docs/api/wrappers/pz_wrappers.md b/docs/api/wrappers/pz_wrappers.md index 4a2412ded..e99511ba4 100644 --- a/docs/api/wrappers/pz_wrappers.md +++ b/docs/api/wrappers/pz_wrappers.md @@ -66,10 +66,11 @@ To wrap a Parallel environment. ```python notest from pettingzoo.utils import CaptureStdoutWrapper from pettingzoo.butterfly import pistonball_v6 -parallel_env = pistonball_v6.env() + +parallel_env = pistonball_v6.parallel_env(render_mode="human") +# TODO: parallel_env render_mode doesn't exist here parallel_env = CaptureStdoutWrapper(parallel_env) -#TODO parallel_env.reset() returns None here observations, infos = parallel_env.reset() while parallel_env.agents: @@ -78,7 +79,7 @@ while parallel_env.agents: ``` To wrap an AEC environment: -```python notest +```python from pettingzoo.utils import TerminateIllegalWrapper from pettingzoo.classic import rps_v2 env = rps_v2.env() diff --git a/docs/api/wrappers/shimmy_wrappers.md b/docs/api/wrappers/shimmy_wrappers.md index 877d2a4ff..843b16758 100644 --- a/docs/api/wrappers/shimmy_wrappers.md +++ b/docs/api/wrappers/shimmy_wrappers.md @@ -41,13 +41,12 @@ while env.agents: To load an OpenSpiel game of [backgammon](https://github.com/deepmind/open_spiel/blob/master/docs/games.md#backgammon): -```python notest -#TODO ImportError: cannot import name 'OpenspielCompatibilityV0' from 'shimmy' -from shimmy import OpenspielCompatibilityV0 +```python +from shimmy import OpenSpielCompatibilityV0 import pyspiel env = pyspiel.load_game("backgammon") -env = OpenspielCompatibilityV0(game=env, render_mode=None) +env = OpenSpielCompatibilityV0(env=env, render_mode=None) env.reset() for agent in env.agent_iter(): diff --git a/docs/content/basic_usage.md b/docs/content/basic_usage.md index 382ca5a24..54e02b8c9 100644 --- a/docs/content/basic_usage.md +++ b/docs/content/basic_usage.md @@ -35,16 +35,23 @@ right_paddle_speed=25, cake_paddle=True, max_cycles=900, bounce_randomness=False Environments can be interacted with using a similar interface to Gymnasium: -``` python notest +``` python from pettingzoo.butterfly import cooperative_pong_v5 -env = cooperative_pong_v5.env() -env.reset() +env = cooperative_pong_v5.env(render_mode="human") +env.reset(seed=42) + for agent in env.agent_iter(): observation, reward, termination, truncation, info = env.last() - action = env.action_space(agent).sample() # this is where you would insert your policy - #TODO ValueError: when an agent is dead, the only valid action is None + + if termination or truncation: + action = None + else: + # this is where you would insert your policy + action = env.action_space(agent).sample() + env.step(action) +env.close() ``` The commonly used methods are: diff --git a/docs/content/environment_tests.md b/docs/content/environment_tests.md index 48de97999..0c1659d62 100644 --- a/docs/content/environment_tests.md +++ b/docs/content/environment_tests.md @@ -37,7 +37,7 @@ To have a properly reproducible environment that utilizes randomness, you need t The seed test takes in a function that creates a pettingzoo environment. For example -``` python notest +``` python from pettingzoo.test import seed_test, parallel_seed_test from pettingzoo.butterfly import pistonball_v6 env_fn = pistonball_v6.env @@ -72,13 +72,12 @@ max_cycles_test(env) ## Render Test The render test checks that rendering 1) does not crash and 2) produces output of the correct type when given a mode (only supports `'human'`, `'ansi'`, and `'rgb_array'` modes). - -``` python notest +``` python from pettingzoo.test import render_test from pettingzoo.butterfly import pistonball_v6 -env = pistonball_v6.env() +env_func = pistonball_v6.env #TODO TypeError: 'OrderEnforcingWrapper' object is not callable -render_test(env) +render_test(env_func) ``` The render test method takes in an optional argument `custom_tests` that allows for additional tests in non-standard modes. @@ -105,10 +104,9 @@ performance_benchmark(env) The save observation test is to visually inspect the observations of games with graphical observations to make sure they are what is intended. We have found that observations are a huge source of bugs in environments, so it is good to manually check them when possible. This test just tries to save the observations of all the agents. If it fails, then it just prints a warning. The output needs to be visually inspected for correctness. -``` python notest +``` python from pettingzoo.test import test_save_obs from pettingzoo.butterfly import pistonball_v6 env = pistonball_v6.env() -#TODO running test_save_obs creates multiple files each time doctests are run here test_save_obs(env) ``` diff --git a/docs/environments/butterfly.md b/docs/environments/butterfly.md index 10dd467a6..49a08cc00 100644 --- a/docs/environments/butterfly.md +++ b/docs/environments/butterfly.md @@ -50,7 +50,7 @@ env.close() ``` To launch a [Knights Archers Zombies](/environments/butterfly/knights_archers_zombies/) environment with interactive user input (see [manual_policy.py](https://github.com/Farama-Foundation/PettingZoo/blob/master/pettingzoo/butterfly/knights_archers_zombies/manual_policy.py)): -```python notest +```python import pygame from pettingzoo.butterfly import knights_archers_zombies_v10 @@ -63,7 +63,7 @@ for agent in env.agent_iter(): observation, reward, termination, truncation, info = env.last() if termination or truncation: - action = None + action = None elif agent == manual_policy.agent: # get user input (controls are WASD and space) action = manual_policy(observation, agent) diff --git a/pettingzoo/test/render_test.py b/pettingzoo/test/render_test.py index a4f4959f5..13091b81b 100644 --- a/pettingzoo/test/render_test.py +++ b/pettingzoo/test/render_test.py @@ -1,6 +1,9 @@ from __future__ import annotations +from typing import Callable + import numpy as np +from gymnasium.core import Env def collect_render_results(env): @@ -24,7 +27,7 @@ def collect_render_results(env): return results -def render_test(env_fn, custom_tests={}): +def render_test(env_fn: Callable[[], Env], custom_tests={}): env = env_fn(render_mode="human") render_modes = env.metadata.get("render_modes")[:] assert ( From b357bb31cd9db287b2955475b0b6a9ee250d73f0 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 17:28:05 -0400 Subject: [PATCH 03/26] Clean up wrappers code, TerminateIllegal support info action masks, update docs slightly --- .github/workflows/linux-test.yml | 2 +- .github/workflows/macos-test.yml | 4 +- CONTRIBUTING.md | 1 + conftest.py | 9 +++ docs/api/wrappers/pz_wrappers.md | 57 ++++++++++++------- docs/api/wrappers/shimmy_wrappers.md | 9 ++- pettingzoo/test/api_test.py | 3 +- pettingzoo/utils/conversions.py | 18 ++++++ .../utils/wrappers/assert_out_of_bounds.py | 1 + pettingzoo/utils/wrappers/capture_stdout.py | 1 + .../utils/wrappers/clip_out_of_bounds.py | 1 + pettingzoo/utils/wrappers/order_enforcing.py | 1 + .../utils/wrappers/terminate_illegal.py | 22 +++++-- pyproject.toml | 3 +- tutorials/SB3/test/test_sb3_action_mask.py | 12 ++-- 15 files changed, 102 insertions(+), 42 deletions(-) create mode 100644 conftest.py diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 30cdbe6b8..7cec3e0a6 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -38,4 +38,4 @@ jobs: pip install dist/*.tar.gz - name: Release Test run: | - xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term + xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term -n auto diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml index ad780d207..d33f687c8 100644 --- a/.github/workflows/macos-test.yml +++ b/.github/workflows/macos-test.yml @@ -26,5 +26,5 @@ jobs: AutoROM -v - name: Full Python tests run: | - pytest ./test/pytest_runner_test.py - pytest ./test/all_parameter_combs_test.py + pytest -v --cov=pettingzoo --cov-report term -n auto + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a316fc683..0dc38f536 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,7 @@ Contributing code is done through standard github methods: ### Considerations - Make sure existing tests pass (`pip install -e .[all]` and then run `pytest -v` -- may also need to `apt-get`/`brew` `install swig` and `AutoROM -v`) +- Note: `pytest -v -n auto` - Make sure your new code is properly tested and fully-covered - Any fixes to environments should include fixes to the appropriate documentation - Changes to environment functionality should be avoided when reasonable, and when they occur the environment version must be bumped. diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..b8e687813 --- /dev/null +++ b/conftest.py @@ -0,0 +1,9 @@ +def pytest_markdown_docs_globals(): + import pettingzoo + import gymnasium + import shimmy + return {"math": pettingzoo, "gymnasium": gymnasium, "shimmy": shimmy} + +# pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ + +# pytest ../docs --markdown-docs -m markdown-docs --ignore=../docs/_scripts --ignore=../docs/conf.py \ No newline at end of file diff --git a/docs/api/wrappers/pz_wrappers.md b/docs/api/wrappers/pz_wrappers.md index e99511ba4..3bfbf8286 100644 --- a/docs/api/wrappers/pz_wrappers.md +++ b/docs/api/wrappers/pz_wrappers.md @@ -62,27 +62,11 @@ We wanted our pettingzoo environments to be both easy to use and easy to impleme You can apply these wrappers to your environment in a similar manner to the below examples: -To wrap a Parallel environment. -```python notest -from pettingzoo.utils import CaptureStdoutWrapper -from pettingzoo.butterfly import pistonball_v6 - -parallel_env = pistonball_v6.parallel_env(render_mode="human") -# TODO: parallel_env render_mode doesn't exist here -parallel_env = CaptureStdoutWrapper(parallel_env) - -observations, infos = parallel_env.reset() - -while parallel_env.agents: - actions = {agent: parallel_env.action_space(agent).sample() for agent in parallel_env.agents} # this is where you would insert your policy - observations, rewards, terminations, truncations, infos = parallel_env.step(actions) -``` - To wrap an AEC environment: ```python from pettingzoo.utils import TerminateIllegalWrapper -from pettingzoo.classic import rps_v2 -env = rps_v2.env() +from pettingzoo.classic import tictactoe_v3 +env = tictactoe_v3.env() env = TerminateIllegalWrapper(env, illegal_reward=-1) env.reset() @@ -92,12 +76,47 @@ for agent in env.agent_iter(): action = None else: action = env.action_space(agent).sample() # this is where you would insert your policy - #TODO RPS observe() returns an np.array instead of dict, triggering an assert statement in TerminateIllegalWrapper env.step(action) env.close() ``` Note: Most AEC environments include TerminateIllegalWrapper in their initialization, so this code does not change the environment's behavior. +To wrap a Parallel environment. +```python +from pettingzoo.utils import BaseParallelWrapper +from pettingzoo.butterfly import pistonball_v6 + +parallel_env = pistonball_v6.parallel_env(render_mode="human") +parallel_env = BaseParallelWrapper(parallel_env) + +observations, infos = parallel_env.reset() + +while parallel_env.agents: + actions = {agent: parallel_env.action_space(agent).sample() for agent in parallel_env.agents} # this is where you would insert your policy + observations, rewards, terminations, truncations, infos = parallel_env.step(actions) +``` + +```{eval-rst} +.. warning:: + + Included PettingZoo wrappers currently do not support parallel environments, to use them you must convert your environment to AEC, apply the wrapper, and convert back to parallel. +``` +```python +from pettingzoo.utils import ClipOutOfBoundsWrapper +from pettingzoo.sisl import multiwalker_v9 +from pettingzoo.utils import aec_to_parallel + +parallel_env = multiwalker_v9.env(render_mode="human") +parallel_env = ClipOutOfBoundsWrapper(parallel_env) +parallel_env = aec_to_parallel(parallel_env) + +observations, infos = parallel_env.reset() + +while parallel_env.agents: + actions = {agent: parallel_env.action_space(agent).sample() for agent in parallel_env.agents} # this is where you would insert your policy + observations, rewards, terminations, truncations, infos = parallel_env.step(actions) +``` + ```{eval-rst} .. currentmodule:: pettingzoo.utils.wrappers diff --git a/docs/api/wrappers/shimmy_wrappers.md b/docs/api/wrappers/shimmy_wrappers.md index 843b16758..58f4e572f 100644 --- a/docs/api/wrappers/shimmy_wrappers.md +++ b/docs/api/wrappers/shimmy_wrappers.md @@ -40,13 +40,13 @@ while env.agents: ``` -To load an OpenSpiel game of [backgammon](https://github.com/deepmind/open_spiel/blob/master/docs/games.md#backgammon): +To load an OpenSpiel game of [backgammon](https://github.com/deepmind/open_spiel/blob/master/docs/games.md#backgammon), wrapped with [TerminateIllegalWrapper](https://pettingzoo.farama.org/api/wrappers/pz_wrappers/#pettingzoo.utils.wrappers.TerminateIllegalWrapper): ```python from shimmy import OpenSpielCompatibilityV0 -import pyspiel +from pettingzoo.utils import TerminateIllegalWrapper -env = pyspiel.load_game("backgammon") -env = OpenSpielCompatibilityV0(env=env, render_mode=None) +env = OpenSpielCompatibilityV0(game_name="chess", render_mode=None) +env = TerminateIllegalWrapper(env, illegal_reward=-1) env.reset() for agent in env.agent_iter(): @@ -63,7 +63,6 @@ for agent in env.agent_iter(): To load a Melting Pot [prisoner's dilemma in the matrix](https://github.com/deepmind/meltingpot/blob/main/docs/substrate_scenario_details.md#prisoners-dilemma-in-the-matrix) substrate: ```python notest -#TODO ImportError: Melting Pot or PettingZoo is not installed, run `pip install 'shimmy[melting-pot]' and install Melting Pot via https://github.com/deepmind/meltingpot#installation` from shimmy import MeltingPotCompatibilityV0 env = MeltingPotCompatibilityV0(substrate_name="prisoners_dilemma_in_the_matrix__arena", render_mode="human") observations, infos = env.reset() diff --git a/pettingzoo/test/api_test.py b/pettingzoo/test/api_test.py index 868832777..f8718579c 100644 --- a/pettingzoo/test/api_test.py +++ b/pettingzoo/test/api_test.py @@ -71,7 +71,6 @@ def action_mask(): "texas_holdem_no_limit_v6", "texas_holdem_v4", "go_v5", - "hanabi_v4", "chess_v6", "connect_four_v3", "tictactoe_v3", @@ -93,7 +92,7 @@ def action_mask(): "texas_holdem_no_limit_v6", "texas_holdem_v4", "go_v5", - "hanabi_v4", + "hanabi_v5", "knights_archers_zombies_v10", "chess_v6", "connect_four_v3", diff --git a/pettingzoo/utils/conversions.py b/pettingzoo/utils/conversions.py index 48cf1fadb..b564cd7d9 100644 --- a/pettingzoo/utils/conversions.py +++ b/pettingzoo/utils/conversions.py @@ -123,6 +123,15 @@ def __init__(self, aec_env): self.metadata = aec_env.metadata + try: + self.render_mode = ( + self.aec_env.render_mode # pyright: ignore[reportGeneralTypeIssues] + ) + except AttributeError: + warnings.warn( + f"The base environment `{aec_env}` does not have a `render_mode` defined." + ) + # Not every environment has the .state_space attribute implemented try: self.state_space = self.aec_env.state_space @@ -406,6 +415,15 @@ def __init__(self, aec_env: AECEnv[AgentID, ObsType, Optional[ActionType]]): except AttributeError: pass + try: + self.render_mode = ( + self.aec_env.render_mode # pyright: ignore[reportGeneralTypeIssues] + ) + except AttributeError: + warnings.warn( + f"The base environment `{aec_env}` does not have a `render_mode` defined." + ) + @property def unwrapped(self): return self.aec_env.unwrapped diff --git a/pettingzoo/utils/wrappers/assert_out_of_bounds.py b/pettingzoo/utils/wrappers/assert_out_of_bounds.py index 7cf73ba30..c99845118 100644 --- a/pettingzoo/utils/wrappers/assert_out_of_bounds.py +++ b/pettingzoo/utils/wrappers/assert_out_of_bounds.py @@ -8,6 +8,7 @@ class AssertOutOfBoundsWrapper(BaseWrapper[AgentID, ObsType, ActionType]): """Asserts if the action given to step is outside of the action space.""" def __init__(self, env: AECEnv[AgentID, ObsType, ActionType]): + assert isinstance(env, AECEnv), "AssertOutOfBoundsWrapper is only compatible with AEC environments" super().__init__(env) def step(self, action: ActionType) -> None: diff --git a/pettingzoo/utils/wrappers/capture_stdout.py b/pettingzoo/utils/wrappers/capture_stdout.py index 06f55d2e5..b98804089 100644 --- a/pettingzoo/utils/wrappers/capture_stdout.py +++ b/pettingzoo/utils/wrappers/capture_stdout.py @@ -7,6 +7,7 @@ class CaptureStdoutWrapper(BaseWrapper): """Takes an environment which prints to terminal, and gives it an `ansi` render mode where it captures the terminal output and returns it as a string instead.""" def __init__(self, env: AECEnv): + assert isinstance(env, AECEnv), "CaptureStdoutWrapper is only compatible with AEC environments" assert hasattr(env, "render_mode"), f"Environment {env} has no render_mode." assert ( env.render_mode == "human" # pyright: ignore[reportGeneralTypeIssues] diff --git a/pettingzoo/utils/wrappers/clip_out_of_bounds.py b/pettingzoo/utils/wrappers/clip_out_of_bounds.py index 7eb84665d..920713c53 100644 --- a/pettingzoo/utils/wrappers/clip_out_of_bounds.py +++ b/pettingzoo/utils/wrappers/clip_out_of_bounds.py @@ -16,6 +16,7 @@ class ClipOutOfBoundsWrapper(BaseWrapper): def __init__(self, env: AECEnv): super().__init__(env) + assert isinstance(env, AECEnv), "ClipOutOfBoundsWrapper is only compatible with AEC environments." assert all( isinstance(self.action_space(agent), Box) for agent in getattr(self, "possible_agents", []) diff --git a/pettingzoo/utils/wrappers/order_enforcing.py b/pettingzoo/utils/wrappers/order_enforcing.py index bc14954da..58fe0370c 100644 --- a/pettingzoo/utils/wrappers/order_enforcing.py +++ b/pettingzoo/utils/wrappers/order_enforcing.py @@ -27,6 +27,7 @@ class OrderEnforcingWrapper(BaseWrapper[AgentID, ObsType, ActionType]): """ def __init__(self, env: AECEnv[AgentID, ObsType, ActionType]): + assert isinstance(env, AECEnv), "OrderEnforcingWrapper is only compatible with AEC environments" self._has_reset = False self._has_rendered = False self._has_updated = False diff --git a/pettingzoo/utils/wrappers/terminate_illegal.py b/pettingzoo/utils/wrappers/terminate_illegal.py index b4c242d57..289e10275 100644 --- a/pettingzoo/utils/wrappers/terminate_illegal.py +++ b/pettingzoo/utils/wrappers/terminate_illegal.py @@ -18,29 +18,38 @@ def __init__( super().__init__(env) self._illegal_value = illegal_reward self._prev_obs = None + self._prev_info = None def reset(self, seed: int | None = None, options: dict | None = None) -> None: self._terminated = False self._prev_obs = None + self._prev_info = None super().reset(seed=seed, options=options) def observe(self, agent: AgentID) -> ObsType | None: obs = super().observe(agent) if agent == self.agent_selection: self._prev_obs = obs + self._prev_info = self.infos[self.agent_selection] return obs + + def step(self, action: ActionType) -> None: current_agent = self.agent_selection if self._prev_obs is None: self.observe(self.agent_selection) - assert self._prev_obs - assert isinstance(self._prev_obs, dict) - assert ( - "action_mask" in self._prev_obs - ), "action_mask must always be part of environment observation as an element in a dictionary observation to use the TerminateIllegalWrapper" - _prev_action_mask = self._prev_obs["action_mask"] + if isinstance(self._prev_obs, dict): + assert ( + "action_mask" in self._prev_obs + ), f"`action_mask` not found in dictionary observation: {self._prev_obs}. Action mask must either be in `observation['action_mask']` or `info['action_mask']` to use TerminateIllegalWrapper." + _prev_action_mask = self._prev_obs["action_mask"] + + else: + assert ("action_mask" in self._prev_info), f"`action_mask` not found in info for non-dictionary observation: {self._prev_info}. Action mask must either be in observation['action_mask'] or info['action_mask'] to use TerminateIllegalWrapper." + _prev_action_mask = self._prev_info["action_mask"] self._prev_obs = None + self._prev_info = None if self._terminated and ( self.terminations[self.agent_selection] or self.truncations[self.agent_selection] @@ -56,6 +65,7 @@ def step(self, action: ActionType) -> None: self.terminations = {d: True for d in self.agents} self.truncations = {d: True for d in self.agents} self._prev_obs = None + self._prev_info = None self.rewards = {d: 0 for d in self.truncations} self.rewards[current_agent] = float(self._illegal_value) self._accumulate_rewards() diff --git a/pyproject.toml b/pyproject.toml index fc29e42fd..14df73031 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ testing = [ "AutoROM", "pytest", "pytest-cov", + "pytest-xdist", "pre-commit", ] all = [ @@ -104,4 +105,4 @@ typeCheckingMode = "basic" reportMissingImports = false [tool.pytest.ini_options] -addopts = [ "--ignore-glob=*/__init__.py" ] +addopts = [ "--ignore-glob=*/__init__.py", "--ignore=tutorials" ] diff --git a/tutorials/SB3/test/test_sb3_action_mask.py b/tutorials/SB3/test/test_sb3_action_mask.py index f8f803766..7908747b9 100644 --- a/tutorials/SB3/test/test_sb3_action_mask.py +++ b/tutorials/SB3/test/test_sb3_action_mask.py @@ -6,7 +6,7 @@ chess_v6, gin_rummy_v4, go_v5, - hanabi_v4, + hanabi_v5, leduc_holdem_v4, texas_holdem_no_limit_v6, texas_holdem_v4, @@ -29,15 +29,15 @@ # More difficult environments which will likely take more training time MEDIUM_ENVS = [ leduc_holdem_v4, # with 10x as many steps it gets higher total rewards (9 vs -9), 0.52 winrate, and 0.92 vs 0.83 total scores - hanabi_v4, # even with 10x as many steps, total score seems to always be tied between the two agents + hanabi_v5, # even with 10x as many steps, total score seems to always be tied between the two agents tictactoe_v3, # even with 10x as many steps, agent still loses every time (most likely an error somewhere) + chess_v6, # difficult to train because games take so long, performance varies heavily ] # Most difficult environments to train agents for (and longest games # TODO: test board_size to see if smaller go board is more easily solvable HARD_ENVS = [ - chess_v6, # difficult to train because games take so long, 0.28 winrate even after 10x - go_v5, # difficult to train because games take so long + go_v5, # difficult to train because games take so long, may be another issue causing poor performance ] @@ -119,8 +119,8 @@ def test_action_mask_hard(env_fn): ) assert ( - winrate < 0.5 - ), "Policy should not perform better than 50% winrate" # 28% for chess, 0% for go + winrate > 0 + ), "Policy should not perform better than 50% winrate" # 0% for go # Watch two games (disabled by default) # eval_action_mask(env_fn, num_games=2, render_mode="human", **env_kwargs) From e816cc3d0034a7c806454fb1e385398f31a372e0 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 17:36:07 -0400 Subject: [PATCH 04/26] Pre-commit, add ignore for tutorials on pytest by default, add ci test for checking md docs --- .github/workflows/docs-test.yml | 36 +++++++++++++++++++ .github/workflows/macos-test.yml | 1 - CONTRIBUTING.md | 2 +- conftest.py | 7 ++-- docs/README.md | 4 +++ docs/api/wrappers/pz_wrappers.md | 2 +- docs/api/wrappers/shimmy_wrappers.md | 2 +- pettingzoo/utils/conversions.py | 1 + .../utils/wrappers/assert_out_of_bounds.py | 4 ++- pettingzoo/utils/wrappers/capture_stdout.py | 4 ++- .../utils/wrappers/clip_out_of_bounds.py | 4 ++- pettingzoo/utils/wrappers/order_enforcing.py | 4 ++- .../utils/wrappers/terminate_illegal.py | 9 +++-- tutorials/SB3/test/test_sb3_action_mask.py | 4 +-- 14 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/docs-test.yml diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml new file mode 100644 index 000000000..b3cd0ff4e --- /dev/null +++ b/.github/workflows/docs-test.yml @@ -0,0 +1,36 @@ +# 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: Documentation tests + +on: + push: + branches: [master] + pull_request: + branches: [master] + +permissions: + contents: read + +jobs: + linux-test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11'] + steps: + - uses: actions/checkout@v3 + # - uses: openrndr/setup-opengl@v1.1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + sudo apt-get install python3-opengl xvfb + pip install -e .[all] + pip install -e .[testing] + AutoROM -v + - name: Documentation test + run: | + pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ -n auto diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml index d33f687c8..5a6e1b9ab 100644 --- a/.github/workflows/macos-test.yml +++ b/.github/workflows/macos-test.yml @@ -27,4 +27,3 @@ jobs: - name: Full Python tests run: | pytest -v --cov=pettingzoo --cov-report term -n auto - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0dc38f536..4eec58ecb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ Contributing code is done through standard github methods: ### Considerations - Make sure existing tests pass (`pip install -e .[all]` and then run `pytest -v` -- may also need to `apt-get`/`brew` `install swig` and `AutoROM -v`) -- Note: `pytest -v -n auto` +- Note: `pytest -v -n auto` - Make sure your new code is properly tested and fully-covered - Any fixes to environments should include fixes to the appropriate documentation - Changes to environment functionality should be avoided when reasonable, and when they occur the environment version must be bumped. diff --git a/conftest.py b/conftest.py index b8e687813..45734d0a0 100644 --- a/conftest.py +++ b/conftest.py @@ -1,9 +1,12 @@ def pytest_markdown_docs_globals(): - import pettingzoo import gymnasium import shimmy + + import pettingzoo + return {"math": pettingzoo, "gymnasium": gymnasium, "shimmy": shimmy} + # pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ -# pytest ../docs --markdown-docs -m markdown-docs --ignore=../docs/_scripts --ignore=../docs/conf.py \ No newline at end of file +# pytest ../docs --markdown-docs -m markdown-docs --ignore=../docs/_scripts --ignore=../docs/conf.py diff --git a/docs/README.md b/docs/README.md index 88d091ebd..4a800c3db 100644 --- a/docs/README.md +++ b/docs/README.md @@ -37,3 +37,7 @@ To rebuild the documentation automatically every time a change is made: cd docs sphinx-autobuild -b dirhtml . _build ``` + +## Test the documentation +The plugin [pytest-markdown-docs](https://github.com/modal-labs/pytest-markdown-docs) allows us to test our documentation to ensure that example code runs successfully. To test, run the following command: +pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ -n auto diff --git a/docs/api/wrappers/pz_wrappers.md b/docs/api/wrappers/pz_wrappers.md index 3bfbf8286..d3eb21c38 100644 --- a/docs/api/wrappers/pz_wrappers.md +++ b/docs/api/wrappers/pz_wrappers.md @@ -101,7 +101,7 @@ while parallel_env.agents: Included PettingZoo wrappers currently do not support parallel environments, to use them you must convert your environment to AEC, apply the wrapper, and convert back to parallel. ``` -```python +```python from pettingzoo.utils import ClipOutOfBoundsWrapper from pettingzoo.sisl import multiwalker_v9 from pettingzoo.utils import aec_to_parallel diff --git a/docs/api/wrappers/shimmy_wrappers.md b/docs/api/wrappers/shimmy_wrappers.md index 58f4e572f..de5599a8b 100644 --- a/docs/api/wrappers/shimmy_wrappers.md +++ b/docs/api/wrappers/shimmy_wrappers.md @@ -41,7 +41,7 @@ while env.agents: To load an OpenSpiel game of [backgammon](https://github.com/deepmind/open_spiel/blob/master/docs/games.md#backgammon), wrapped with [TerminateIllegalWrapper](https://pettingzoo.farama.org/api/wrappers/pz_wrappers/#pettingzoo.utils.wrappers.TerminateIllegalWrapper): -```python +```python notest from shimmy import OpenSpielCompatibilityV0 from pettingzoo.utils import TerminateIllegalWrapper diff --git a/pettingzoo/utils/conversions.py b/pettingzoo/utils/conversions.py index b564cd7d9..099c11a1a 100644 --- a/pettingzoo/utils/conversions.py +++ b/pettingzoo/utils/conversions.py @@ -1,3 +1,4 @@ +# pyright: reportGeneralTypeIssues=false import copy import warnings from collections import defaultdict diff --git a/pettingzoo/utils/wrappers/assert_out_of_bounds.py b/pettingzoo/utils/wrappers/assert_out_of_bounds.py index c99845118..84e713476 100644 --- a/pettingzoo/utils/wrappers/assert_out_of_bounds.py +++ b/pettingzoo/utils/wrappers/assert_out_of_bounds.py @@ -8,7 +8,9 @@ class AssertOutOfBoundsWrapper(BaseWrapper[AgentID, ObsType, ActionType]): """Asserts if the action given to step is outside of the action space.""" def __init__(self, env: AECEnv[AgentID, ObsType, ActionType]): - assert isinstance(env, AECEnv), "AssertOutOfBoundsWrapper is only compatible with AEC environments" + assert isinstance( + env, AECEnv + ), "AssertOutOfBoundsWrapper is only compatible with AEC environments" super().__init__(env) def step(self, action: ActionType) -> None: diff --git a/pettingzoo/utils/wrappers/capture_stdout.py b/pettingzoo/utils/wrappers/capture_stdout.py index b98804089..d74fa1e58 100644 --- a/pettingzoo/utils/wrappers/capture_stdout.py +++ b/pettingzoo/utils/wrappers/capture_stdout.py @@ -7,7 +7,9 @@ class CaptureStdoutWrapper(BaseWrapper): """Takes an environment which prints to terminal, and gives it an `ansi` render mode where it captures the terminal output and returns it as a string instead.""" def __init__(self, env: AECEnv): - assert isinstance(env, AECEnv), "CaptureStdoutWrapper is only compatible with AEC environments" + assert isinstance( + env, AECEnv + ), "CaptureStdoutWrapper is only compatible with AEC environments" assert hasattr(env, "render_mode"), f"Environment {env} has no render_mode." assert ( env.render_mode == "human" # pyright: ignore[reportGeneralTypeIssues] diff --git a/pettingzoo/utils/wrappers/clip_out_of_bounds.py b/pettingzoo/utils/wrappers/clip_out_of_bounds.py index 920713c53..fb7a4bdf5 100644 --- a/pettingzoo/utils/wrappers/clip_out_of_bounds.py +++ b/pettingzoo/utils/wrappers/clip_out_of_bounds.py @@ -16,7 +16,9 @@ class ClipOutOfBoundsWrapper(BaseWrapper): def __init__(self, env: AECEnv): super().__init__(env) - assert isinstance(env, AECEnv), "ClipOutOfBoundsWrapper is only compatible with AEC environments." + assert isinstance( + env, AECEnv + ), "ClipOutOfBoundsWrapper is only compatible with AEC environments." assert all( isinstance(self.action_space(agent), Box) for agent in getattr(self, "possible_agents", []) diff --git a/pettingzoo/utils/wrappers/order_enforcing.py b/pettingzoo/utils/wrappers/order_enforcing.py index 58fe0370c..6b78c9d7d 100644 --- a/pettingzoo/utils/wrappers/order_enforcing.py +++ b/pettingzoo/utils/wrappers/order_enforcing.py @@ -27,7 +27,9 @@ class OrderEnforcingWrapper(BaseWrapper[AgentID, ObsType, ActionType]): """ def __init__(self, env: AECEnv[AgentID, ObsType, ActionType]): - assert isinstance(env, AECEnv), "OrderEnforcingWrapper is only compatible with AEC environments" + assert isinstance( + env, AECEnv + ), "OrderEnforcingWrapper is only compatible with AEC environments" self._has_reset = False self._has_rendered = False self._has_updated = False diff --git a/pettingzoo/utils/wrappers/terminate_illegal.py b/pettingzoo/utils/wrappers/terminate_illegal.py index 289e10275..2a0e521bf 100644 --- a/pettingzoo/utils/wrappers/terminate_illegal.py +++ b/pettingzoo/utils/wrappers/terminate_illegal.py @@ -1,3 +1,4 @@ +# pyright reportGeneralTypeIssues=false from __future__ import annotations from pettingzoo.utils.env import ActionType, AECEnv, AgentID, ObsType @@ -33,20 +34,22 @@ def observe(self, agent: AgentID) -> ObsType | None: self._prev_info = self.infos[self.agent_selection] return obs - - def step(self, action: ActionType) -> None: current_agent = self.agent_selection if self._prev_obs is None: self.observe(self.agent_selection) if isinstance(self._prev_obs, dict): + assert self._prev_obs is not None assert ( "action_mask" in self._prev_obs ), f"`action_mask` not found in dictionary observation: {self._prev_obs}. Action mask must either be in `observation['action_mask']` or `info['action_mask']` to use TerminateIllegalWrapper." _prev_action_mask = self._prev_obs["action_mask"] else: - assert ("action_mask" in self._prev_info), f"`action_mask` not found in info for non-dictionary observation: {self._prev_info}. Action mask must either be in observation['action_mask'] or info['action_mask'] to use TerminateIllegalWrapper." + assert self._prev_info is not None + assert ( + "action_mask" in self._prev_info + ), f"`action_mask` not found in info for non-dictionary observation: {self._prev_info}. Action mask must either be in observation['action_mask'] or info['action_mask'] to use TerminateIllegalWrapper." _prev_action_mask = self._prev_info["action_mask"] self._prev_obs = None self._prev_info = None diff --git a/tutorials/SB3/test/test_sb3_action_mask.py b/tutorials/SB3/test/test_sb3_action_mask.py index 7908747b9..3835af393 100644 --- a/tutorials/SB3/test/test_sb3_action_mask.py +++ b/tutorials/SB3/test/test_sb3_action_mask.py @@ -118,9 +118,7 @@ def test_action_mask_hard(env_fn): env_fn, num_games=100, render_mode=None, **env_kwargs ) - assert ( - winrate > 0 - ), "Policy should not perform better than 50% winrate" # 0% for go + assert winrate > 0, "Policy should not perform better than 50% winrate" # 0% for go # Watch two games (disabled by default) # eval_action_mask(env_fn, num_games=2, render_mode="human", **env_kwargs) From 32bc7273b7ce942b13aad4a730539560437b04ec Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 17:40:16 -0400 Subject: [PATCH 05/26] Add pytest markdown docs requirement --- .github/workflows/docs-test.yml | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index b3cd0ff4e..67c86bf12 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.11'] steps: - uses: actions/checkout@v3 # - uses: openrndr/setup-opengl@v1.1 diff --git a/pyproject.toml b/pyproject.toml index 14df73031..972dac2eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ testing = [ "pytest-cov", "pytest-xdist", "pre-commit", + "pytest-markdown-docs" ] all = [ "multi_agent_ale_py==0.1.11", From cf0b35d1c378cf372ee2cb26c59da4f212473833 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 17:57:55 -0400 Subject: [PATCH 06/26] Add pytest xdist by default to pytest (speeds tests up immensely), ignores dirs --- .github/workflows/docs-test.yml | 2 +- .github/workflows/linux-test.yml | 2 +- .github/workflows/macos-test.yml | 2 +- CONTRIBUTING.md | 1 - docs/README.md | 2 +- docs/api/wrappers/supersuit_wrappers.md | 2 +- pyproject.toml | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index 67c86bf12..e34b6b37e 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -33,4 +33,4 @@ jobs: AutoROM -v - name: Documentation test run: | - pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ -n auto + pytest docs --markdown-docs -m markdown-docs diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 7cec3e0a6..30cdbe6b8 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -38,4 +38,4 @@ jobs: pip install dist/*.tar.gz - name: Release Test run: | - xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term -n auto + xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml index 5a6e1b9ab..0a6f4d762 100644 --- a/.github/workflows/macos-test.yml +++ b/.github/workflows/macos-test.yml @@ -26,4 +26,4 @@ jobs: AutoROM -v - name: Full Python tests run: | - pytest -v --cov=pettingzoo --cov-report term -n auto + pytest -v --cov=pettingzoo --cov-report term diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4eec58ecb..a316fc683 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,6 @@ Contributing code is done through standard github methods: ### Considerations - Make sure existing tests pass (`pip install -e .[all]` and then run `pytest -v` -- may also need to `apt-get`/`brew` `install swig` and `AutoROM -v`) -- Note: `pytest -v -n auto` - Make sure your new code is properly tested and fully-covered - Any fixes to environments should include fixes to the appropriate documentation - Changes to environment functionality should be avoided when reasonable, and when they occur the environment version must be bumped. diff --git a/docs/README.md b/docs/README.md index 4a800c3db..ca40d0417 100644 --- a/docs/README.md +++ b/docs/README.md @@ -40,4 +40,4 @@ sphinx-autobuild -b dirhtml . _build ## Test the documentation The plugin [pytest-markdown-docs](https://github.com/modal-labs/pytest-markdown-docs) allows us to test our documentation to ensure that example code runs successfully. To test, run the following command: -pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ -n auto +pytest docs --markdown-docs -m markdown-docs diff --git a/docs/api/wrappers/supersuit_wrappers.md b/docs/api/wrappers/supersuit_wrappers.md index 5b46ba7a9..deb6579a3 100644 --- a/docs/api/wrappers/supersuit_wrappers.md +++ b/docs/api/wrappers/supersuit_wrappers.md @@ -8,7 +8,7 @@ The [SuperSuit](https://github.com/Farama-Foundation/SuperSuit) companion packag To convert [space invaders](/environments/atari/space_invaders/) to a greyscale observation space and stack the last 4 frames: -``` python notest +``` python from pettingzoo.atari import space_invaders_v2 from supersuit import color_reduction_v0, frame_stack_v1 diff --git a/pyproject.toml b/pyproject.toml index 972dac2eb..f832d9013 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -106,4 +106,4 @@ typeCheckingMode = "basic" reportMissingImports = false [tool.pytest.ini_options] -addopts = [ "--ignore-glob=*/__init__.py", "--ignore=tutorials" ] +addopts = [ "--ignore-glob=*/__init__.py", "-n=auto", "--ignore=tutorials", "--ignore=docs/_scripts", "--ignore=conf.py", "--ignore=docs/environments/"] From 2129aadfd1846e99884780895fae87dbc3a2a1a9 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 17:59:47 -0400 Subject: [PATCH 07/26] pre-commit, clean up conftest --- conftest.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/conftest.py b/conftest.py index 45734d0a0..f6f8d6563 100644 --- a/conftest.py +++ b/conftest.py @@ -1,12 +1,13 @@ def pytest_markdown_docs_globals(): import gymnasium import shimmy + import supersuit import pettingzoo - return {"math": pettingzoo, "gymnasium": gymnasium, "shimmy": shimmy} - - -# pytest docs --markdown-docs -m markdown-docs --ignore=docs/_scripts --ignore=conf.py --ignore=docs/environments/ - -# pytest ../docs --markdown-docs -m markdown-docs --ignore=../docs/_scripts --ignore=../docs/conf.py + return { + "math": pettingzoo, + "gymnasium": gymnasium, + "shimmy": shimmy, + "supersuit": supersuit, + } From fe3123cce723ecd2e7c67579df6a3884910db185 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 18:09:20 -0400 Subject: [PATCH 08/26] Fix various minor bugs and remove some notest parts --- docs/api/wrappers/shimmy_wrappers.md | 1 - docs/content/environment_creation.md | 2 +- docs/content/environment_tests.md | 7 ++----- docs/environments/atari.md | 6 +++--- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/docs/api/wrappers/shimmy_wrappers.md b/docs/api/wrappers/shimmy_wrappers.md index de5599a8b..d39b1756f 100644 --- a/docs/api/wrappers/shimmy_wrappers.md +++ b/docs/api/wrappers/shimmy_wrappers.md @@ -27,7 +27,6 @@ To load a DeepMind Control [multi-agent soccer game](https://github.com/deepmind ```python notest from shimmy import DmControlMultiAgentCompatibilityV0 -#TODO ModuleNotFoundError: No module named 'dm_control' from dm_control.locomotion import soccer as dm_soccer env = dm_soccer.load(team_size=2) diff --git a/docs/content/environment_creation.md b/docs/content/environment_creation.md index 9bc1c98df..401603daf 100644 --- a/docs/content/environment_creation.md +++ b/docs/content/environment_creation.md @@ -71,5 +71,5 @@ This declaration tells the user that `knights_archers_zombies_v0` is deprecated ``` python notest from pettingzoo.butterfly import knights_archers_zombies_v0 knights_archers_zombies_v0.env() - +# pettingzoo.utils.deprecated_module.DeprecatedEnv: knights_archers_zombies_v0 is now deprecated, use knights_archers_zombies_v10 instead ``` diff --git a/docs/content/environment_tests.md b/docs/content/environment_tests.md index 0c1659d62..369ffe98f 100644 --- a/docs/content/environment_tests.md +++ b/docs/content/environment_tests.md @@ -61,12 +61,10 @@ The second optional argument, `test_kept_state` allows the user to disable the s The max cycles test tests that the `max_cycles` environment argument exists and the resulting environment actually runs for the correct number of cycles. If your environment does not take a `max_cycles` argument, you should not run this test. The reason this test exists is that many off-by-one errors are possible when implementing `max_cycles`. An example test usage looks like: -``` python notest +``` python from pettingzoo.test import max_cycles_test from pettingzoo.butterfly import pistonball_v6 -env = pistonball_v6.env() -#TODO AttributeError: 'OrderEnforcingWrapper' object has no attribute 'parallel_env' -max_cycles_test(env) +max_cycles_test(pistonball_v6) ``` ## Render Test @@ -76,7 +74,6 @@ The render test checks that rendering 1) does not crash and 2) produces output o from pettingzoo.test import render_test from pettingzoo.butterfly import pistonball_v6 env_func = pistonball_v6.env -#TODO TypeError: 'OrderEnforcingWrapper' object is not callable render_test(env_func) ``` diff --git a/docs/environments/atari.md b/docs/environments/atari.md index c68921d72..a42e03f38 100644 --- a/docs/environments/atari.md +++ b/docs/environments/atari.md @@ -92,11 +92,11 @@ pip install supersuit Here is some example usage for the Atari preprocessing: -``` python notest +``` python import supersuit -from pettingzoo.atari import space_invaders_v1 +from pettingzoo.atari import space_invaders_v2 -env = space_invaders_v1.env() +env = space_invaders_v2.env() # as per openai baseline's MaxAndSKip wrapper, maxes over the last 2 frames # to deal with frame flickering From 287f3b6a984b5e1f73ed53578ecbf4f71f09125b Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 18:14:14 -0400 Subject: [PATCH 09/26] Add xvfb to allow doctest to work with human rendering --- .github/workflows/docs-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index e34b6b37e..cf7f45e70 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -33,4 +33,4 @@ jobs: AutoROM -v - name: Documentation test run: | - pytest docs --markdown-docs -m markdown-docs + xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs From 2125133cc639e80e025b1bb47d03695d72b8f2bb Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 18:23:36 -0400 Subject: [PATCH 10/26] test running the linux tutorials in parallel for a given directory/test type --- .github/workflows/linux-tutorials-test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-tutorials-test.yml b/.github/workflows/linux-tutorials-test.yml index 20ba3000c..0b2ed9694 100644 --- a/.github/workflows/linux-tutorials-test.yml +++ b/.github/workflows/linux-tutorials-test.yml @@ -28,11 +28,13 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies and run tutorials run: | - sudo apt-get install python3-opengl xvfb + sudo apt-get install python3-opengl xvfb parallel + export PATH=/path/to/parallel:$PATH export root_dir=$(pwd) cd tutorials/${{ matrix.tutorial }} pip install -r requirements.txt pip uninstall -y pettingzoo pip install -e $root_dir[testing] AutoROM -v - for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done +# for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done + ls *.py | parallel xvfb-run -a -s "-screen 0 1024x768x24" python \ No newline at end of file From dade74e6125d5f71a71ea35675b02c855b88f608 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 18:33:53 -0400 Subject: [PATCH 11/26] Add supersuit and shimmy to docs test ci --- .github/workflows/docs-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index cf7f45e70..52a76e4e6 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -30,6 +30,7 @@ jobs: sudo apt-get install python3-opengl xvfb pip install -e .[all] pip install -e .[testing] + pip install supersuit shimmy AutoROM -v - name: Documentation test run: | From a3b953ef43a457847eed123534ca31c2aa86e80e Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 18:42:20 -0400 Subject: [PATCH 12/26] Pre-commit cleanup CI --- .github/workflows/linux-tutorials-test.yml | 2 +- tutorials/EnvironmentCreation/4-TestingTheEnvironment.txt | 0 tutorials/EnvironmentCreation/5-UsingWithAPI.txt | 0 tutorials/EnvironmentCreation/6-UsingWithRL.txt | 0 4 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 tutorials/EnvironmentCreation/4-TestingTheEnvironment.txt delete mode 100644 tutorials/EnvironmentCreation/5-UsingWithAPI.txt delete mode 100644 tutorials/EnvironmentCreation/6-UsingWithRL.txt diff --git a/.github/workflows/linux-tutorials-test.yml b/.github/workflows/linux-tutorials-test.yml index 0b2ed9694..2b8203a0c 100644 --- a/.github/workflows/linux-tutorials-test.yml +++ b/.github/workflows/linux-tutorials-test.yml @@ -37,4 +37,4 @@ jobs: pip install -e $root_dir[testing] AutoROM -v # for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done - ls *.py | parallel xvfb-run -a -s "-screen 0 1024x768x24" python \ No newline at end of file + ls *.py | parallel xvfb-run -a -s "-screen 0 1024x768x24" python diff --git a/tutorials/EnvironmentCreation/4-TestingTheEnvironment.txt b/tutorials/EnvironmentCreation/4-TestingTheEnvironment.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tutorials/EnvironmentCreation/5-UsingWithAPI.txt b/tutorials/EnvironmentCreation/5-UsingWithAPI.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tutorials/EnvironmentCreation/6-UsingWithRL.txt b/tutorials/EnvironmentCreation/6-UsingWithRL.txt deleted file mode 100644 index e69de29bb..000000000 From 6d39d5ae10b1ba0f7c8f41884fc72d5958536ce4 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 18:48:17 -0400 Subject: [PATCH 13/26] Test coverage in CI (probably will remove) --- .github/workflows/linux-test.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 30cdbe6b8..cbf520237 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -39,3 +39,27 @@ jobs: - name: Release Test run: | xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term + - name: Run coverage + run: | + coverage report -m + - name: Coverage Badge + uses: tj-actions/coverage-badge-py@v2 + - name: Verify Changed files + uses: tj-actions/verify-changed-files@v16 + id: verify-changed-files + with: + files: coverage.svg + - name: Commit files + if: steps.verify-changed-files.outputs.files_changed == 'true' + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git add coverage.svg + git commit -m "Updated coverage.svg" + + - name: Push changes + if: steps.verify-changed-files.outputs.files_changed == 'true' + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.github_token }} + branch: ${{ github.ref }} From 60e6e39435cedd7fee6f538f9759691941168428 Mon Sep 17 00:00:00 2001 From: elliottower Date: Fri, 1 Sep 2023 19:28:30 -0400 Subject: [PATCH 14/26] Clean up --- .github/workflows/linux-test.yml | 24 ---------------------- .github/workflows/linux-tutorials-test.yml | 3 +-- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index cbf520237..30cdbe6b8 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -39,27 +39,3 @@ jobs: - name: Release Test run: | xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term - - name: Run coverage - run: | - coverage report -m - - name: Coverage Badge - uses: tj-actions/coverage-badge-py@v2 - - name: Verify Changed files - uses: tj-actions/verify-changed-files@v16 - id: verify-changed-files - with: - files: coverage.svg - - name: Commit files - if: steps.verify-changed-files.outputs.files_changed == 'true' - run: | - git config --local user.email "github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - git add coverage.svg - git commit -m "Updated coverage.svg" - - - name: Push changes - if: steps.verify-changed-files.outputs.files_changed == 'true' - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.github_token }} - branch: ${{ github.ref }} diff --git a/.github/workflows/linux-tutorials-test.yml b/.github/workflows/linux-tutorials-test.yml index f6aa52660..6f46375af 100644 --- a/.github/workflows/linux-tutorials-test.yml +++ b/.github/workflows/linux-tutorials-test.yml @@ -36,5 +36,4 @@ jobs: pip uninstall -y pettingzoo pip install -e $root_dir[testing] AutoROM -v -# for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done - ls *.py | parallel xvfb-run -a -s "-screen 0 1024x768x24" python + for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done From c323726dc94a1b5a42b929426801c17ace3b89d1 Mon Sep 17 00:00:00 2001 From: elliottower Date: Sat, 2 Sep 2023 13:22:54 -0400 Subject: [PATCH 15/26] Add doctests for all env mds as well --- .github/workflows/docs-test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index 52a76e4e6..b29f28169 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -32,6 +32,10 @@ jobs: pip install -e .[testing] pip install supersuit shimmy AutoROM -v + - name: Install documentation dependencies + run: pip install -r docs/requirements.txt + - name: Generate environment docs + run: python docs/_scripts/gen_envs_mds.py - name: Documentation test run: | xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs From f109783fa212bdcb9d4d4fd993ebf57dea589548 Mon Sep 17 00:00:00 2001 From: elliottower Date: Sat, 2 Sep 2023 13:45:17 -0400 Subject: [PATCH 16/26] Add imports for all modules, allow testing of in-line argument examples from env docs (don't include import) --- conftest.py | 9 ++++++++- pyproject.toml | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/conftest.py b/conftest.py index f6f8d6563..7e823fa60 100644 --- a/conftest.py +++ b/conftest.py @@ -4,10 +4,17 @@ def pytest_markdown_docs_globals(): import supersuit import pettingzoo + from pettingzoo.utils.all_modules import all_environments - return { + libs = { "math": pettingzoo, "gymnasium": gymnasium, "shimmy": shimmy, "supersuit": supersuit, } + # Format: {"go_v5": , ...} + envs = { + name.split("/")[1]: module for name, module in all_environments.items() + } + libs.update(envs) + return libs.update(envs) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f832d9013..5c59c9654 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -106,4 +106,4 @@ typeCheckingMode = "basic" reportMissingImports = false [tool.pytest.ini_options] -addopts = [ "--ignore-glob=*/__init__.py", "-n=auto", "--ignore=tutorials", "--ignore=docs/_scripts", "--ignore=conf.py", "--ignore=docs/environments/"] +addopts = [ "--ignore-glob=*/__init__.py", "-n=auto", "--ignore=tutorials", "--ignore=docs/_scripts", "--ignore=conf.py"] From 7eaf9ca58ce9e0b1a79b3b8b30dbb4a941d62a07 Mon Sep 17 00:00:00 2001 From: elliottower Date: Sat, 2 Sep 2023 13:53:23 -0400 Subject: [PATCH 17/26] pre-commit --- conftest.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/conftest.py b/conftest.py index 7e823fa60..3843bb891 100644 --- a/conftest.py +++ b/conftest.py @@ -13,8 +13,6 @@ def pytest_markdown_docs_globals(): "supersuit": supersuit, } # Format: {"go_v5": , ...} - envs = { - name.split("/")[1]: module for name, module in all_environments.items() - } + envs = {name.split("/")[1]: module for name, module in all_environments.items()} libs.update(envs) - return libs.update(envs) \ No newline at end of file + return libs.update(envs) From 9e347a25fee4501f27ce8e586c7bec701e7eb7eb Mon Sep 17 00:00:00 2001 From: elliottower Date: Sat, 2 Sep 2023 14:06:50 -0400 Subject: [PATCH 18/26] Test using pytest split with docs test to speed up (28 tests was 10 mins, now 155 test roughly 6x) --- .github/workflows/docs-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index b29f28169..f381a31ce 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -18,6 +18,7 @@ jobs: strategy: matrix: python-version: ['3.11'] + group: [ 1, 2, 3, 4, 5 ] steps: - uses: actions/checkout@v3 # - uses: openrndr/setup-opengl@v1.1 @@ -38,4 +39,4 @@ jobs: run: python docs/_scripts/gen_envs_mds.py - name: Documentation test run: | - xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs + xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 5 --group ${{ matrix.group }} From f52aa9a3603aa2fbdf81ac6799ef9521881f1039 Mon Sep 17 00:00:00 2001 From: elliottower Date: Sat, 2 Sep 2023 14:06:56 -0400 Subject: [PATCH 19/26] Test using pytest split with docs test to speed up (28 tests was 10 mins, now 155 test roughly 6x) --- .github/workflows/docs-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index f381a31ce..12d9f6635 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: python-version: ['3.11'] - group: [ 1, 2, 3, 4, 5 ] + group: [ 1, 2, 3, 4, 5, 6 ] steps: - uses: actions/checkout@v3 # - uses: openrndr/setup-opengl@v1.1 @@ -39,4 +39,4 @@ jobs: run: python docs/_scripts/gen_envs_mds.py - name: Documentation test run: | - xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 5 --group ${{ matrix.group }} + xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 6 --group ${{ matrix.group }} From 618e3229c5d91970e3392896d0121eb6ce388f05 Mon Sep 17 00:00:00 2001 From: elliottower Date: Sat, 2 Sep 2023 14:26:58 -0400 Subject: [PATCH 20/26] Add pytest-split install --- .github/workflows/docs-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index 12d9f6635..980a99dd3 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -31,7 +31,7 @@ jobs: sudo apt-get install python3-opengl xvfb pip install -e .[all] pip install -e .[testing] - pip install supersuit shimmy + pip install supersuit shimmy pytest-split AutoROM -v - name: Install documentation dependencies run: pip install -r docs/requirements.txt From 017952689731f695edf2935fd59436cabd5f62c2 Mon Sep 17 00:00:00 2001 From: elliottower Date: Sun, 3 Sep 2023 00:09:20 -0400 Subject: [PATCH 21/26] Fix some of the documentation bugs --- conftest.py | 4 ++-- pettingzoo/classic/hanabi/hanabi.py | 6 +++--- pettingzoo/mpe/simple_world_comm/simple_world_comm.py | 2 +- pettingzoo/sisl/multiwalker/multiwalker.py | 2 +- pettingzoo/sisl/waterworld/waterworld.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conftest.py b/conftest.py index 3843bb891..9bf11262e 100644 --- a/conftest.py +++ b/conftest.py @@ -7,7 +7,7 @@ def pytest_markdown_docs_globals(): from pettingzoo.utils.all_modules import all_environments libs = { - "math": pettingzoo, + "pettingzoo": pettingzoo, "gymnasium": gymnasium, "shimmy": shimmy, "supersuit": supersuit, @@ -15,4 +15,4 @@ def pytest_markdown_docs_globals(): # Format: {"go_v5": , ...} envs = {name.split("/")[1]: module for name, module in all_environments.items()} libs.update(envs) - return libs.update(envs) + return libs diff --git a/pettingzoo/classic/hanabi/hanabi.py b/pettingzoo/classic/hanabi/hanabi.py index 626ae430a..1f108b310 100644 --- a/pettingzoo/classic/hanabi/hanabi.py +++ b/pettingzoo/classic/hanabi/hanabi.py @@ -32,13 +32,13 @@ Hanabi takes in a number of arguments defining the size and complexity of the game. Default is a full 2 player hanabi game. ``` python -hanabi_v5.env(colors=5, rank=5, players=2, hand_size=5, max_information_tokens=8, -max_life_tokens=3, observation_type="minimal") +hanabi_v5.env(colors=5, ranks=5, players=2, hand_size=5, max_information_tokens=8, +max_life_tokens=3, observation_type='minimal') ``` `colors`: Number of colors the cards can take (affects size of deck) -`rank`: Number of ranks the cards can take (affects size of deck) +`ranks`: Number of ranks the cards can take (affects size of deck) `hand_size`: Size of player's hands. Standard game is (4 if players >= 4 else 5) diff --git a/pettingzoo/mpe/simple_world_comm/simple_world_comm.py b/pettingzoo/mpe/simple_world_comm/simple_world_comm.py index d0642ea55..598c0d23e 100644 --- a/pettingzoo/mpe/simple_world_comm/simple_world_comm.py +++ b/pettingzoo/mpe/simple_world_comm/simple_world_comm.py @@ -51,7 +51,7 @@ ### Arguments ``` python -simple_world_comm.env(num_good=2, num_adversaries=4, num_obstacles=1, +simple_world_comm_v3.env(num_good=2, num_adversaries=4, num_obstacles=1, num_food=2, max_cycles=25, num_forests=2, continuous_actions=False) ``` diff --git a/pettingzoo/sisl/multiwalker/multiwalker.py b/pettingzoo/sisl/multiwalker/multiwalker.py index 567f9fc49..b398268e9 100644 --- a/pettingzoo/sisl/multiwalker/multiwalker.py +++ b/pettingzoo/sisl/multiwalker/multiwalker.py @@ -78,7 +78,7 @@ ``` python multiwalker_v9.env(n_walkers=3, position_noise=1e-3, angle_noise=1e-3, forward_reward=1.0, terminate_reward=-100.0, fall_reward=-10.0, shared_reward=True, -terminate_on_fall=True, remove_on_fall=True, terrain_legth=200, max_cycles=500) +terminate_on_fall=True, remove_on_fall=True, terrain_length=200, max_cycles=500) ``` diff --git a/pettingzoo/sisl/waterworld/waterworld.py b/pettingzoo/sisl/waterworld/waterworld.py index 3973856c2..d2de2eb21 100644 --- a/pettingzoo/sisl/waterworld/waterworld.py +++ b/pettingzoo/sisl/waterworld/waterworld.py @@ -82,7 +82,7 @@ ``` python waterworld_v4.env(n_pursuers=5, n_evaders=5, n_poisons=10, n_coop=2, n_sensors=20, -sensor_range=0.2,radius=0.015, obstacle_radius=0.2, +sensor_range=0.2,radius=0.015, obstacle_radius=0.2, n_obstacles=1, obstacle_coord=[(0.5, 0.5)], pursuer_max_accel=0.01, evader_speed=0.01, poison_speed=0.01, poison_reward=-1.0, food_reward=10.0, encounter_reward=0.01, thrust_penalty=-0.5, local_ratio=1.0, speed_features=True, max_cycles=500) From 0c3c9edc3a00ea9b287916f6bc182e6475e88faa Mon Sep 17 00:00:00 2001 From: elliottower Date: Sun, 3 Sep 2023 00:50:52 -0400 Subject: [PATCH 22/26] Add temp testing code to download artifacts and combine durations, fix last issues --- .github/workflows/docs-test.yml | 26 +++++++++++++++++-- pettingzoo/atari/maze_craze/maze_craze.py | 2 +- .../cooperative_pong/cooperative_pong.py | 4 +-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index 980a99dd3..2be4cfae8 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -13,7 +13,7 @@ permissions: contents: read jobs: - linux-test: + docs-test: runs-on: ubuntu-latest strategy: matrix: @@ -37,6 +37,28 @@ jobs: run: pip install -r docs/requirements.txt - name: Generate environment docs run: python docs/_scripts/gen_envs_mds.py + - name: Download durations from most recent GitHub workflow run + id: download-artifact + uses: dawidd6/action-download-artifact@v2 - name: Documentation test run: | - xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 6 --group ${{ matrix.group }} + xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 6 --group ${{ matrix.group }} --store-durations --clean-durations + - name: Upload partial durations + uses: actions/upload-artifact@v3 + with: + name: split-${{ matrix.group }} + path: .test_durations + upload-timings: + needs: docs-test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Download artifacts + uses: actions/download-artifact@v3 + - name: Combine test-durations + run: jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations + - name: Upload final durations + uses: actions/upload-artifact@v3 + with: + name: split-${{ matrix.group }} + path: .test_durations diff --git a/pettingzoo/atari/maze_craze/maze_craze.py b/pettingzoo/atari/maze_craze/maze_craze.py index e30a87996..5c3b77a87 100644 --- a/pettingzoo/atari/maze_craze/maze_craze.py +++ b/pettingzoo/atari/maze_craze/maze_craze.py @@ -42,7 +42,7 @@ Parameters specific to Maze Craze are ``` python -maze_craze.env(game_version="robbers", visibilty_level=0) +maze_craze_v3.env(game_version="robbers", visibilty_level=0) ``` `game_version`: Possibilities are "robbers", "race", "capture", corresponding to the 3 game versions described above diff --git a/pettingzoo/butterfly/cooperative_pong/cooperative_pong.py b/pettingzoo/butterfly/cooperative_pong/cooperative_pong.py index 44b1492a8..0751a12e7 100644 --- a/pettingzoo/butterfly/cooperative_pong/cooperative_pong.py +++ b/pettingzoo/butterfly/cooperative_pong/cooperative_pong.py @@ -9,7 +9,7 @@ This environment is part of the butterfly environments. Please read that page first for general information. -| Import | `from pettingzoo.butterfly import cooperative_pong_v4` | +| Import | `from pettingzoo.butterfly import cooperative_pong_v5` | |----------------------|--------------------------------------------------------| | Actions | Discrete | | Parallel API | Yes | @@ -37,7 +37,7 @@ ### Arguments ``` python -cooperative_pong_v4.env(ball_speed=9, left_paddle_speed=12, +cooperative_pong_v5.env(ball_speed=9, left_paddle_speed=12, right_paddle_speed=12, cake_paddle=True, max_cycles=900, bounce_randomness=False, max_reward=100, off_screen_penalty=-10) ``` From 150db6aaa2f2323dacf6dd6afcb82efaec99fabe Mon Sep 17 00:00:00 2001 From: elliottower Date: Sun, 3 Sep 2023 00:59:33 -0400 Subject: [PATCH 23/26] Add yml formatter to fix weird formatting inconsistencies, fix bug of artifact failing if not found --- .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE/bug.yml | 87 +++++----- .github/ISSUE_TEMPLATE/proposal.yml | 83 +++++----- .github/ISSUE_TEMPLATE/question.yml | 37 ++--- .github/workflows/build-docs.yml | 71 +++++---- .github/workflows/build-publish.yml | 101 ++++++------ .github/workflows/docs-manual-versioning.yml | 115 +++++++------- .github/workflows/docs-test.yml | 110 +++++++------ .github/workflows/docs-versioning.yml | 97 +++++------ .github/workflows/linux-test.yml | 63 ++++---- .github/workflows/linux-tutorials-test.yml | 60 ++++--- .github/workflows/macos-test.yml | 40 +++-- .github/workflows/pre-commit.yml | 28 ++-- .pre-commit-config.yaml | 159 ++++++++++--------- 14 files changed, 527 insertions(+), 525 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index c5d88ac82..82385e14b 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ +--- github: Farama-Foundation diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 223b02dce..03d4b311a 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,51 +1,52 @@ +--- name: Bug Report description: Submit a bug report -title: "[Bug Report] Bug title" -labels: ["bug"] +title: '[Bug Report] Bug title' +labels: [bug] body: - - type: textarea - id: description - attributes: - label: Describe the bug - description: A clear and concise description of what the bug is. - validations: - required: true + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true - - type: textarea - id: code-example - attributes: - label: Code example - description: | - Bug reports without minimal code examples take 5-10x longer to solve. - We'll give you a cookie if you add the stack trace too! - Save time, add code. - This will be automatically formatted into code, so no need for backticks. - render: shell + - type: textarea + id: code-example + attributes: + label: Code example + description: | + Bug reports without minimal code examples take 5-10x longer to solve. + We'll give you a cookie if you add the stack trace too! + Save time, add code. + This will be automatically formatted into code, so no need for backticks. + render: shell - - type: textarea - id: system-info - attributes: - label: System info - description: | - Describe the characteristic of your environment: - * Describe how PettingZoo was installed (pip, source, ...) - * Version of `pettingzoo` (by `pettingzoo.__version__`) - * What OS/version you're using. Note that while we will accept PRs to improve Window's support, we do not officially support it. - * Python version + - type: textarea + id: system-info + attributes: + label: System info + description: | + Describe the characteristic of your environment: + * Describe how PettingZoo was installed (pip, source, ...) + * Version of `pettingzoo` (by `pettingzoo.__version__`) + * What OS/version you're using. Note that while we will accept PRs to improve Window's support, we do not officially support it. + * Python version - - type: textarea - id: additional-context - attributes: - label: Additional context - description: Add any other context about the problem here. + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context about the problem here. - - type: checkboxes - id: checklist - attributes: - label: Checklist - options: - - label: > - I have checked that there is no similar [issue](https://github.com/Farama-Foundation/PettingZoo/issues) in - the repo - required: true + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: > + I have checked that there is no similar [issue](https://github.com/Farama-Foundation/PettingZoo/issues) in + the repo + required: true diff --git a/.github/ISSUE_TEMPLATE/proposal.yml b/.github/ISSUE_TEMPLATE/proposal.yml index f485b628c..848877c36 100644 --- a/.github/ISSUE_TEMPLATE/proposal.yml +++ b/.github/ISSUE_TEMPLATE/proposal.yml @@ -1,49 +1,50 @@ +--- name: Proposal description: Propose changes that are not fixing bugs -title: "[Proposal] Proposal title" -labels: ["enhancement"] +title: '[Proposal] Proposal title' +labels: [enhancement] body: - - type: textarea - id: proposal - attributes: - label: Proposal - description: A clear and concise description of the proposal. - validations: - required: true + - type: textarea + id: proposal + attributes: + label: Proposal + description: A clear and concise description of the proposal. + validations: + required: true - - type: textarea - id: motivation - attributes: - label: Motivation - description: | - Please outline the motivation for the proposal. - Is your feature request related to a problem? e.g.,"I'm always frustrated when [...]". - If this is related to another GitHub issue, please link here too. + - type: textarea + id: motivation + attributes: + label: Motivation + description: | + Please outline the motivation for the proposal. + Is your feature request related to a problem? e.g.,"I'm always frustrated when [...]". + If this is related to another GitHub issue, please link here too. - - type: textarea - id: pitch - attributes: - label: Pitch - description: A clear and concise description of what you want to happen. + - type: textarea + id: pitch + attributes: + label: Pitch + description: A clear and concise description of what you want to happen. - - type: textarea - id: alternatives - attributes: - label: Alternatives - description: A clear and concise description of any alternative solutions or features you've considered, if any. + - type: textarea + id: alternatives + attributes: + label: Alternatives + description: A clear and concise description of any alternative solutions or features you've considered, if any. - - type: textarea - id: additional-context - attributes: - label: Additional context - description: Add any other context or screenshots about the feature request here. + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request here. - - type: checkboxes - id: checklist - attributes: - label: Checklist - options: - - label: > - I have checked that there is no similar [issue](https://github.com/Farama-Foundation/PettingZoo/issues) in - the repo - required: true + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: > + I have checked that there is no similar [issue](https://github.com/Farama-Foundation/PettingZoo/issues) in + the repo + required: true diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index 94c7feeee..8af14d3de 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -1,22 +1,23 @@ +--- name: Question description: Ask a question -title: "[Question] Question title" -labels: ["question"] +title: '[Question] Question title' +labels: [question] body: - - type: markdown - attributes: - value: > - If you have basic questions about reinforcement learning algorithms, please ask on - [r/reinforcementlearning](https://www.reddit.com/r/reinforcementlearning/) or in the - [RL Discord](https://discord.com/invite/xhfNqQv) (if you're new please use the beginners channel). - Basic questions that are not bugs or feature requests will be closed without reply, because GitHub - issues are not an appropriate venue for these. Advanced/nontrivial questions, especially in areas where - documentation is lacking, are very much welcome. + - type: markdown + attributes: + value: > + If you have basic questions about reinforcement learning algorithms, please ask on + [r/reinforcementlearning](https://www.reddit.com/r/reinforcementlearning/) or in the + [RL Discord](https://discord.com/invite/xhfNqQv) (if you're new please use the beginners channel). + Basic questions that are not bugs or feature requests will be closed without reply, because GitHub + issues are not an appropriate venue for these. Advanced/nontrivial questions, especially in areas where + documentation is lacking, are very much welcome. - - type: textarea - id: question - attributes: - label: Question - description: Your question - validations: - required: true + - type: textarea + id: question + attributes: + label: Question + description: Your question + validations: + required: true diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index af0d78329..bc8367dcd 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,49 +1,50 @@ +--- name: Build Documentation website on: - push: - branches: [master] + push: + branches: [master] permissions: - contents: write + contents: write jobs: - docs: - name: Generate Website - runs-on: ubuntu-latest - env: - SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v3 + docs: + name: Generate Website + runs-on: ubuntu-latest + env: + SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.9' + - uses: actions/setup-python@v4 + with: + python-version: '3.9' - - name: Install dependencies - run: pip install -r docs/requirements.txt + - name: Install dependencies + run: pip install -r docs/requirements.txt - - name: Install PettingZoo - run: pip install .[all] + - name: Install PettingZoo + run: pip install .[all] - - name: Generate environment docs - run: python docs/_scripts/gen_envs_mds.py + - name: Generate environment docs + run: python docs/_scripts/gen_envs_mds.py - - name: Generate environments display - run: python docs/_scripts/gen_envs_display.py + - name: Generate environments display + run: python docs/_scripts/gen_envs_display.py - - name: Build - run: sphinx-build -b dirhtml -v docs _build + - name: Build + run: sphinx-build -b dirhtml -v docs _build - - name: Move 404 - run: mv _build/404/index.html _build/404.html + - name: Move 404 + run: mv _build/404/index.html _build/404.html - - name: Update 404 links - run: python docs/_scripts/move_404.py _build/404.html + - name: Update 404 links + run: python docs/_scripts/move_404.py _build/404.html - - name: Remove .doctrees - run: rm -r _build/.doctrees + - name: Remove .doctrees + run: rm -r _build/.doctrees - - name: Upload to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: _build - target-folder: main - clean: false + - name: Upload to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: _build + target-folder: main + clean: false diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 799fda065..d52c6a3ef 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -1,3 +1,4 @@ +--- # This workflow will build and (if release) publish Python distributions to PyPI # For more information see: # - https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions @@ -7,57 +8,57 @@ name: build-publish on: - release: - types: [published] + release: + types: [published] jobs: - build-wheels: - runs-on: ${{ matrix.os }} - permissions: - contents: read - strategy: - matrix: - include: - - os: ubuntu-latest - python: 38 - platform: manylinux_x86_64 - - os: ubuntu-latest - python: 39 - platform: manylinux_x86_64 - - os: ubuntu-latest - python: 310 - platform: manylinux_x86_64 - - os: ubuntu-latest - python: 311 - platform: manylinux_x86_64 + build-wheels: + runs-on: ${{ matrix.os }} + permissions: + contents: read + strategy: + matrix: + include: + - os: ubuntu-latest + python: 38 + platform: manylinux_x86_64 + - os: ubuntu-latest + python: 39 + platform: manylinux_x86_64 + - os: ubuntu-latest + python: 310 + platform: manylinux_x86_64 + - os: ubuntu-latest + python: 311 + platform: manylinux_x86_64 - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dependencies - run: python -m pip install --upgrade setuptools wheel build - - name: Build wheels - run: python -m build --sdist --wheel - - name: Store wheels - uses: actions/upload-artifact@v2 - with: - path: dist + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.x + - name: Install dependencies + run: python -m pip install --upgrade setuptools wheel build + - name: Build wheels + run: python -m build --sdist --wheel + - name: Store wheels + uses: actions/upload-artifact@v2 + with: + path: dist - publish: - runs-on: ubuntu-latest - needs: - - build-wheels - if: github.event_name == 'release' && github.event.action == 'published' - steps: - - name: Download dists - uses: actions/download-artifact@v2 - with: - name: artifact - path: dist - - name: Publish - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.PYPI_API_TOKEN }} + publish: + runs-on: ubuntu-latest + needs: + - build-wheels + if: github.event_name == 'release' && github.event.action == 'published' + steps: + - name: Download dists + uses: actions/download-artifact@v2 + with: + name: artifact + path: dist + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/docs-manual-versioning.yml b/.github/workflows/docs-manual-versioning.yml index 4c2688419..bde319b3f 100644 --- a/.github/workflows/docs-manual-versioning.yml +++ b/.github/workflows/docs-manual-versioning.yml @@ -1,74 +1,75 @@ +--- name: Manual Docs Versioning on: - workflow_dispatch: - inputs: - version: - description: 'Documentation version to create' - required: true - commit: - description: 'Commit used to build the Documentation version' - required: false - latest: - description: 'Latest version' - type: boolean + workflow_dispatch: + inputs: + version: + description: Documentation version to create + required: true + commit: + description: Commit used to build the Documentation version + required: false + latest: + description: Latest version + type: boolean permissions: - contents: write + contents: write jobs: - docs: - name: Generate Website for new version - runs-on: ubuntu-latest - env: - SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v3 - if: inputs.commit == '' + docs: + name: Generate Website for new version + runs-on: ubuntu-latest + env: + SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v3 + if: inputs.commit == '' - - uses: actions/checkout@v3 - if: inputs.commit != '' - with: - ref: ${{ inputs.commit }} + - uses: actions/checkout@v3 + if: inputs.commit != '' + with: + ref: ${{ inputs.commit }} - - uses: actions/setup-python@v4 - with: - python-version: '3.9' + - uses: actions/setup-python@v4 + with: + python-version: '3.9' - - name: Install dependencies - run: pip install -r docs/requirements.txt + - name: Install dependencies + run: pip install -r docs/requirements.txt - - name: Install PettingZoo - run: pip install .[all] + - name: Install PettingZoo + run: pip install .[all] - - name: Generate environment docs - run: python docs/_scripts/gen_envs_mds.py + - name: Generate environment docs + run: python docs/_scripts/gen_envs_mds.py - - name: Generate environments display - run: python docs/_scripts/gen_envs_display.py + - name: Generate environments display + run: python docs/_scripts/gen_envs_display.py - - name: Build - run: sphinx-build -b dirhtml -v docs _build + - name: Build + run: sphinx-build -b dirhtml -v docs _build - - name: Move 404 - run: mv _build/404/index.html _build/404.html + - name: Move 404 + run: mv _build/404/index.html _build/404.html - - name: Update 404 links - run: python docs/_scripts/move_404.py _build/404.html + - name: Update 404 links + run: python docs/_scripts/move_404.py _build/404.html - - name: Remove .doctrees - run: rm -r _build/.doctrees + - name: Remove .doctrees + run: rm -r _build/.doctrees - - name: Upload to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: _build - target-folder: ${{ inputs.version }} - clean: false + - name: Upload to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: _build + target-folder: ${{ inputs.version }} + clean: false - - name: Upload to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 - if: inputs.latest - with: - folder: _build - clean-exclude: | - *.*.*/ - main + - name: Upload to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + if: inputs.latest + with: + folder: _build + clean-exclude: | + *.*.*/ + main diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index 2be4cfae8..e065d8c70 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -1,64 +1,62 @@ -# 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: Documentation tests on: - push: - branches: [master] - pull_request: - branches: [master] + push: + branches: [master] + pull_request: + branches: [master] permissions: - contents: read + contents: read jobs: - docs-test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.11'] - group: [ 1, 2, 3, 4, 5, 6 ] - steps: - - uses: actions/checkout@v3 - # - uses: openrndr/setup-opengl@v1.1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get install python3-opengl xvfb - pip install -e .[all] - pip install -e .[testing] - pip install supersuit shimmy pytest-split - AutoROM -v - - name: Install documentation dependencies - run: pip install -r docs/requirements.txt - - name: Generate environment docs - run: python docs/_scripts/gen_envs_mds.py - - name: Download durations from most recent GitHub workflow run - id: download-artifact - uses: dawidd6/action-download-artifact@v2 - - name: Documentation test - run: | - xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 6 --group ${{ matrix.group }} --store-durations --clean-durations - - name: Upload partial durations - uses: actions/upload-artifact@v3 - with: - name: split-${{ matrix.group }} - path: .test_durations - upload-timings: - needs: docs-test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Download artifacts - uses: actions/download-artifact@v3 - - name: Combine test-durations - run: jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations - - name: Upload final durations - uses: actions/upload-artifact@v3 - with: - name: split-${{ matrix.group }} - path: .test_durations + docs-test: + runs-on: ubuntu-latest + strategy: + matrix: + group: [1, 2, 3, 4, 5, 6] + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.11 + uses: actions/setup-python@v3 + with: + python-version: '3.11' + - name: Install dependencies + run: | + sudo apt-get install python3-opengl xvfb + pip install -e .[all] + pip install -e .[testing] + pip install supersuit shimmy pytest-split + AutoROM -v + - name: Install documentation dependencies + run: pip install -r docs/requirements.txt + - name: Generate environment docs + run: python docs/_scripts/gen_envs_mds.py + - name: Download durations from most recent GitHub workflow run + id: download-artifact + uses: dawidd6/action-download-artifact@v2 + with: + if_no_artifact_found: warn + - name: Documentation test + run: | + xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 6 --group ${{ matrix.group }} --store-durations --clean-durations + - name: Upload partial durations + uses: actions/upload-artifact@v3 + with: + name: split-${{ matrix.group }} + path: .test_durations + upload-timings: + needs: docs-test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Download artifacts + uses: actions/download-artifact@v3 + - name: Combine test-durations + run: jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations + - name: Upload final durations + uses: actions/upload-artifact@v3 + with: + name: split-${{ matrix.group }} + path: .test_durations diff --git a/.github/workflows/docs-versioning.yml b/.github/workflows/docs-versioning.yml index e892a1d91..eb6905c4c 100644 --- a/.github/workflows/docs-versioning.yml +++ b/.github/workflows/docs-versioning.yml @@ -1,64 +1,65 @@ +--- name: Docs Versioning on: - push: - tags: - - 'v?*.*.*' + push: + tags: + - v?*.*.* permissions: - contents: write + contents: write jobs: - docs: - name: Generate Website for new version - runs-on: ubuntu-latest - env: - SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v3 + docs: + name: Generate Website for new version + runs-on: ubuntu-latest + env: + SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.9' + - uses: actions/setup-python@v4 + with: + python-version: '3.9' - - name: Get tag - id: tag - uses: dawidd6/action-get-tag@v1 - with: - strip_v: true + - name: Get tag + id: tag + uses: dawidd6/action-get-tag@v1 + with: + strip_v: true - - name: Install dependencies - run: pip install -r docs/requirements.txt + - name: Install dependencies + run: pip install -r docs/requirements.txt - - name: Install PettingZoo - run: pip install .[all] + - name: Install PettingZoo + run: pip install .[all] - - name: Generate environment docs - run: python docs/_scripts/gen_envs_mds.py + - name: Generate environment docs + run: python docs/_scripts/gen_envs_mds.py - - name: Generate environments display - run: python docs/_scripts/gen_envs_display.py + - name: Generate environments display + run: python docs/_scripts/gen_envs_display.py - - name: Build - run: sphinx-build -b dirhtml -v docs _build + - name: Build + run: sphinx-build -b dirhtml -v docs _build - - name: Move 404 - run: mv _build/404/index.html _build/404.html + - name: Move 404 + run: mv _build/404/index.html _build/404.html - - name: Update 404 links - run: python docs/_scripts/move_404.py _build/404.html + - name: Update 404 links + run: python docs/_scripts/move_404.py _build/404.html - - name: Remove .doctrees - run: rm -r _build/.doctrees + - name: Remove .doctrees + run: rm -r _build/.doctrees - - name: Upload to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: _build - target-folder: ${{steps.tag.outputs.tag}} - clean: false + - name: Upload to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: _build + target-folder: ${{steps.tag.outputs.tag}} + clean: false - - name: Upload to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: _build - clean-exclude: | - *.*.*/ - main + - name: Upload to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: _build + clean-exclude: | + *.*.*/ + main diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 30cdbe6b8..2d25a5dde 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -1,41 +1,38 @@ -# 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: Python tests on: - push: - branches: [master] - pull_request: - branches: [master] + push: + branches: [master] + pull_request: + branches: [master] permissions: - contents: read + contents: read jobs: - linux-test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] - steps: - - uses: actions/checkout@v3 - # - uses: openrndr/setup-opengl@v1.1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get install python3-opengl xvfb - pip install -e .[all] - pip install -e .[testing] - AutoROM -v - - name: Source distribution test - run: | - python -m pip install --upgrade build - python -m build --sdist - pip install dist/*.tar.gz - - name: Release Test - run: | - xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term + linux-test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11'] + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + sudo apt-get install python3-opengl xvfb + pip install -e .[all] + pip install -e .[testing] + AutoROM -v + - name: Source distribution test + run: | + python -m pip install --upgrade build + python -m build --sdist + pip install dist/*.tar.gz + - name: Release Test + run: | + xvfb-run -s "-screen 0 1024x768x24" pytest -v --cov=pettingzoo --cov-report term diff --git a/.github/workflows/linux-tutorials-test.yml b/.github/workflows/linux-tutorials-test.yml index 6f46375af..a304f97bb 100644 --- a/.github/workflows/linux-tutorials-test.yml +++ b/.github/workflows/linux-tutorials-test.yml @@ -1,39 +1,37 @@ -# 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: Tutorial tests on: - push: - branches: [master] - pull_request: - branches: [master] + push: + branches: [master] + pull_request: + branches: [master] permissions: - contents: read + contents: read jobs: - tutorial-test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] - tutorial: ['Tianshou', 'CustomEnvironment', 'CleanRL', 'SB3/kaz', 'SB3/waterworld', 'SB3/connect_four', 'SB3/test'] # TODO: add back Ray once next release after 2.6.2 - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies and run tutorials - run: | - sudo apt-get install python3-opengl xvfb parallel - export PATH=/path/to/parallel:$PATH - export root_dir=$(pwd) - cd tutorials/${{ matrix.tutorial }} - pip install -r requirements.txt - pip uninstall -y pettingzoo - pip install -e $root_dir[testing] - AutoROM -v - for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done + tutorial-test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11'] + tutorial: [Tianshou, CustomEnvironment, CleanRL, SB3/kaz, SB3/waterworld, SB3/connect_four, SB3/test] # TODO: add back Ray once next release after 2.6.2 + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies and run tutorials + run: | + sudo apt-get install python3-opengl xvfb parallel + export PATH=/path/to/parallel:$PATH + export root_dir=$(pwd) + cd tutorials/${{ matrix.tutorial }} + pip install -r requirements.txt + pip uninstall -y pettingzoo + pip install -e $root_dir[testing] + AutoROM -v + for f in *.py; do xvfb-run -a -s "-screen 0 1024x768x24" python "$f"; done diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml index 0a6f4d762..ba848fd8d 100644 --- a/.github/workflows/macos-test.yml +++ b/.github/workflows/macos-test.yml @@ -1,29 +1,27 @@ -# 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: MacOS tests on: - push: - branches: [master] + push: + branches: [master] permissions: - contents: read + contents: read jobs: - macos-test: - runs-on: macos-11 - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.8 - uses: actions/setup-python@v3 - with: - python-version: 3.8 - - name: Install dependencies - run: | - pip install -e .[all] - pip install -e .[testing] - AutoROM -v - - name: Full Python tests - run: | - pytest -v --cov=pettingzoo --cov-report term + macos-test: + runs-on: macos-11 + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.8 + uses: actions/setup-python@v3 + with: + python-version: 3.8 + - name: Install dependencies + run: | + pip install -e .[all] + pip install -e .[testing] + AutoROM -v + - name: Full Python tests + run: | + pytest -v --cov=pettingzoo --cov-report term diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 26515d79f..c8cb6feb7 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,22 +1,20 @@ -# https://pre-commit.com -# This GitHub Action assumes that the repo contains a valid .pre-commit-config.yaml file. --- name: pre-commit on: - pull_request: - push: - branches: [master] + pull_request: + push: + branches: [master] permissions: - contents: read + contents: read jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - run: pip install pre-commit - - run: pre-commit --version - - run: pre-commit install - - run: pre-commit run --all-files + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - run: pip install pre-commit + - run: pre-commit --version + - run: pre-commit install + - run: pre-commit run --all-files diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 08174efa7..7205ba055 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,81 +1,86 @@ +--- # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: check-symlinks - - id: destroyed-symlinks - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - id: check-toml - - id: check-ast - - id: check-added-large-files - - id: check-merge-conflict - - id: check-executables-have-shebangs - - id: check-shebang-scripts-are-executable - - id: detect-private-key - - id: debug-statements - - id: mixed-line-ending - args: [ "--fix=lf" ] - - repo: https://github.com/python/black - rev: 23.3.0 - hooks: - - id: black - - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 - hooks: - - id: codespell - args: - - --skip=*.css,*.js,*.map,*.scss,*.svg - - --ignore-words-list=magent - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 - hooks: - - id: flake8 - args: - - '--per-file-ignores=*/__init__.py:F401 test/all_parameter_combs_test.py:F405 pettingzoo/classic/go/go.py:W605' - - --extend-ignore=E203 - - --max-complexity=205 - - --max-line-length=300 - - --show-source - - --statistics - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - args: ["--profile", "black"] - - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 - hooks: - - id: pyupgrade - args: ["--py38-plus"] - - repo: https://github.com/pycqa/pydocstyle - rev: 6.3.0 - hooks: - - id: pydocstyle - args: - - --source - - --explain - - --convention=google - - --count + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-symlinks + - id: destroyed-symlinks + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-toml + - id: check-ast + - id: check-added-large-files + - id: check-merge-conflict + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable + - id: detect-private-key + - id: debug-statements + - id: mixed-line-ending + args: [--fix=lf] + - repo: https://github.com/python/black + rev: 23.3.0 + hooks: + - id: black + - repo: https://github.com/codespell-project/codespell + rev: v2.2.4 + hooks: + - id: codespell + args: + - --skip=*.css,*.js,*.map,*.scss,*.svg + - --ignore-words-list=magent + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + args: + - --per-file-ignores=*/__init__.py:F401 test/all_parameter_combs_test.py:F405 pettingzoo/classic/go/go.py:W605 + - --extend-ignore=E203 + - --max-complexity=205 + - --max-line-length=300 + - --show-source + - --statistics + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + args: [--profile, black] + - repo: https://github.com/asottile/pyupgrade + rev: v3.3.2 + hooks: + - id: pyupgrade + args: [--py38-plus] + - repo: https://github.com/pycqa/pydocstyle + rev: 6.3.0 + hooks: + - id: pydocstyle + args: + - --source + - --explain + - --convention=google + - --count # TODO: Remove ignoring rules D101, D102, D103, D105 (add docstrings to all public methods) - - --add-ignore=D100,D107,D101,D102,D103,D105 - exclude: "__init__.py$|^pettingzoo.test|^docs" - additional_dependencies: ["tomli"] - - repo: local - hooks: - - id: pyright - name: pyright - entry: pyright - language: node - pass_filenames: false - types: [python] - additional_dependencies: ["pyright"] - args: - - --project=pyproject.toml - - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.26.3 - hooks: - - id: check-github-workflows + - --add-ignore=D100,D107,D101,D102,D103,D105 + exclude: __init__.py$|^pettingzoo.test|^docs + additional_dependencies: [tomli] + - repo: local + hooks: + - id: pyright + name: pyright + entry: pyright + language: node + pass_filenames: false + types: [python] + additional_dependencies: [pyright] + args: + - --project=pyproject.toml + - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt + rev: 0.2.3 + hooks: + - id: yamlfmt + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.26.3 + hooks: + - id: check-github-workflows From 097aab868586f2fb17605fc000abf6ffe684e69f Mon Sep 17 00:00:00 2001 From: elliottower Date: Mon, 4 Sep 2023 00:16:04 -0400 Subject: [PATCH 24/26] Add move test durations from subfolder to root directory so script works --- .github/workflows/docs-test.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index e065d8c70..bd412ac43 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - group: [1, 2, 3, 4, 5, 6] + group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] steps: - uses: actions/checkout@v3 - name: Set up Python 3.11 @@ -40,7 +40,7 @@ jobs: if_no_artifact_found: warn - name: Documentation test run: | - xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 6 --group ${{ matrix.group }} --store-durations --clean-durations + xvfb-run -s "-screen 0 1024x768x24" pytest docs --markdown-docs -m markdown-docs --splits 10 --group ${{ matrix.group }} --store-durations --clean-durations - name: Upload partial durations uses: actions/upload-artifact@v3 with: @@ -54,7 +54,9 @@ jobs: - name: Download artifacts uses: actions/download-artifact@v3 - name: Combine test-durations - run: jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations + run: | + mv */.test_durations . + jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations - name: Upload final durations uses: actions/upload-artifact@v3 with: From a06745ae527cec9e7e932daec28b68fbfd8ad879 Mon Sep 17 00:00:00 2001 From: elliottower Date: Mon, 4 Sep 2023 01:12:01 -0400 Subject: [PATCH 25/26] Fix yml typo --- .github/workflows/docs-test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index bd412ac43..a51c95023 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -55,7 +55,9 @@ jobs: uses: actions/download-artifact@v3 - name: Combine test-durations run: | - mv */.test_durations . + # Move all test durations to same folder and append numbers + find . -type f -name '.test_durations' -exec bash -c 'i=1; while [ -e "./test_durations_$i" ]; do i=$((i+1)); done; mv "$1" "./test_durations_$i";' _ {} \; + # Combine all test durations files jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations - name: Upload final durations uses: actions/upload-artifact@v3 From 5da18160001536d5c4bcd859ba020d9b2a1f7a7a Mon Sep 17 00:00:00 2001 From: elliottower Date: Mon, 4 Sep 2023 01:14:47 -0400 Subject: [PATCH 26/26] Ensure github workflow passes even if the uplaod timings fails --- .github/workflows/docs-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docs-test.yml b/.github/workflows/docs-test.yml index a51c95023..d916fa8b0 100644 --- a/.github/workflows/docs-test.yml +++ b/.github/workflows/docs-test.yml @@ -59,6 +59,7 @@ jobs: find . -type f -name '.test_durations' -exec bash -c 'i=1; while [ -e "./test_durations_$i" ]; do i=$((i+1)); done; mv "$1" "./test_durations_$i";' _ {} \; # Combine all test durations files jq -s 'reduce inputs as $item ({}; . + $item)' .test_durations.* > .test_durations + continue-on-error: true - name: Upload final durations uses: actions/upload-artifact@v3 with: