diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 9e63a1fe..1ec9d49a 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -14,14 +14,6 @@ RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requ -r /tmp/pip-tmp/boptest_requirements.txt \ && rm -rf /tmp/pip-tmp -# Install beobench problem set libraries -ENV MAIN_PYTHONPATH = "${PYTHONPATH}" -ENV PYTHONPATH "${PYTHONPATH}:/tmp" -COPY beobench/installer.py beobench/constants.py /tmp/beobench/ -RUN python /tmp/beobench/installer.py \ - && rm -rf /tmp/beobench -ENV PYTHONPATH = "${MAIN_PYTHONPATH}" - # Install nvidia container runtime RUN wget -O tmp/nvidia-container-toolkit.deb https://nvidia.github.io/libnvidia-container/stable/debian10/amd64/nvidia-container-toolkit_1.7.0-1_amd64.deb \ && wget -O tmp/nvidia-container-tools.deb https://nvidia.github.io/libnvidia-container/stable/debian10/amd64/libnvidia-container-tools_1.7.0-1_amd64.deb \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 863f2b93..bb2b0b73 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -17,12 +17,13 @@ "workspaceFolder": "/workspace", // "workspaceMount": "source=remote-workspace,target=/workspace,type=volume", // ADAPT: the mount must be adapted to cloned repo location - "workspaceMount": "source=/home/rdnfn-docker/main/repos/github/beobench/,target=/workspace,type=bind,consistency=cached", + "workspaceMount": "source=/home/rdnfn-docker/main/repos/github/beobench/,target=/workspace/beobench/,type=bind,consistency=cached", // ADAPT: the mount must be adapted to the gitconfig location on the remote machine "mounts": [ - "source=/home/rdnfn-docker/.gitconfig,target=/.gitconfig,type=bind,consistency=cached" + "source=/home/rdnfn-docker/.gitconfig,target=/root/.gitconfig,type=bind,consistency=cached", + "source=/home/rdnfn-docker/main/repos/github/beobench_contrib,target=/workspace/beobench_contrib/,type=bind,consistency=cached" ], - "postCreateCommand": "pwd && pip install -e .", + "postCreateCommand": "cd ./beobench && pip install -e .", // Set *default* container specific settings.json values on container create. "settings": { "python.defaultInterpreterPath": "/usr/local/bin/python", diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 452a076d..74d680a0 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -117,12 +117,26 @@ To run a subset of tests:: Deploying --------- -A reminder for the maintainers on how to deploy. -Make sure all your changes are committed (including an entry in HISTORY.rst). -Then run:: +A reminder for the maintainers on how to deploy. Follow this checklist (inspired by `this checklist `_ and `this packaging tutorial `_): -$ bump2version patch # possible: major / minor / patch -$ git push -$ git push --tags +1. Update ``HISTORY.rst`` and commit with message like "aux: add changelog for upcoming release 0.1.0" +2. Run -Travis will then deploy to PyPI if tests pass. + .. code-block:: console + + bump2version patch # possible: major / minor / patch + +3. Push commits +4. Build the package + + .. code-block:: console + + python3 -m build + +5. Upload the package (this will ask for password/token from pypi.org) + + .. code-block:: console + + twine upload dist/* + +6. Add release tag on github diff --git a/HISTORY.rst b/HISTORY.rst index a79e5b2b..db8d2cd9 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,13 @@ History ======= +0.2.1 (2022-02-03) +------------------ + +* Add integration with sinergym +* Move gym integrations to separate beobench_contrib repo +* Make usage of GPUs in containers optional + 0.2.0 (2022-01-18) ------------------ diff --git a/PYPI_README.rst b/PYPI_README.rst index b95cbce4..14dd34bc 100644 --- a/PYPI_README.rst +++ b/PYPI_README.rst @@ -23,12 +23,12 @@ Features *Some of the features are work in progress* -**Main features** +Main features - *RL algorithm collection:* what's the best RL method for your BEO problem? Building on `Ray RLlib `_, beobench provides a large collection of pre-configured RL algorithm experiments that can be easily applied to your new BEO problem. - *Problem collection:* beobench provides ready-to-use docker containers for popular BEO gym-type problem libraries. By enforcing a strict OpenAI ``gym.Env`` it makes testing your method on different libraries easy. -**Additional features** +Additional features - *Experiment logging:* log experiment results in a reproducible and shareable manner via `Weights and Biases`_. - *Hyperparameter tuning:* easily tune hyperparameters using the extensive `Ray Tune Search API `_. diff --git a/README.rst b/README.rst index 1ce4d651..c1013e90 100644 --- a/README.rst +++ b/README.rst @@ -31,12 +31,12 @@ Features *Some of the features are work in progress* -**Main features** +Main features - *RL algorithm collection:* what's the best RL method for your BEO problem? Building on `Ray RLlib `_, beobench provides a large collection of pre-configured RL algorithm experiments that can be easily applied to your new BEO problem. - *Problem collection:* beobench provides ready-to-use docker containers for popular BEO gym-type problem libraries. By enforcing a strict OpenAI ``gym.Env`` it makes testing your method on different libraries easy. -**Additional features** +Additional features - *Experiment logging:* log experiment results in a reproducible and shareable manner via `Weights and Biases`_. - *Hyperparameter tuning:* easily tune hyperparameters using the extensive `Ray Tune Search API `_. @@ -61,7 +61,7 @@ Run your first beobench experiment in three steps: .. code-block:: console pip install beobench - + 3. Finally, start your first experiment using: .. code-block:: console diff --git a/beobench/__init__.py b/beobench/__init__.py index 40d66695..0d7427e6 100644 --- a/beobench/__init__.py +++ b/beobench/__init__.py @@ -2,6 +2,6 @@ __author__ = """rdnfn""" __email__ = "-" -__version__ = "0.2.0" +__version__ = "0.2.1" from beobench.utils import restart diff --git a/beobench/experiment/containers.py b/beobench/experiment/containers.py index f46eb9d7..37c68b92 100644 --- a/beobench/experiment/containers.py +++ b/beobench/experiment/containers.py @@ -21,14 +21,14 @@ def build_experiment_container( if use_no_cache: flags.append("--no-cache") - AVAILABLE_INTEGRATIONS = ["boptest"] # pylint: disable=invalid-name + AVAILABLE_INTEGRATIONS = ["boptest","sinergym"] # pylint: disable=invalid-name if build_context in AVAILABLE_INTEGRATIONS: docker_tag = f"beobench_{build_context}:latest" integration_name = build_context build_context = ( f"https://github.com/rdnfn/" - f"beobench.git#master:beobench/integrations/{build_context}" + f"beobench_contrib.git#main:gyms/{build_context}" ) print( ( diff --git a/beobench/experiment/definitions/default.py b/beobench/experiment/definitions/default.py index a53bd162..30575885 100644 --- a/beobench/experiment/definitions/default.py +++ b/beobench/experiment/definitions/default.py @@ -56,7 +56,6 @@ "framework": "torch", "log_level": "WARNING", "num_workers": 8, # 1 for silent mode, can at least be 6 - "num_gpus": 1, "seed": ray.tune.randint(0, 10000000), }, "log_to_file": True, diff --git a/beobench/experiment/definitions/experiment_003_sinergym.py b/beobench/experiment/definitions/experiment_003_sinergym.py new file mode 100644 index 00000000..468148fd --- /dev/null +++ b/beobench/experiment/definitions/experiment_003_sinergym.py @@ -0,0 +1,42 @@ +"""An experiment to test sinergym integration.""" + +import ray.tune +from beobench.experiment.definitions.default import problem, method, rllib_setup + + +problem = { + "name": "sinergym_test_problem", + "description": ("Control problem corresponding to " "created by sinergym env ''."), + "problem_library": "sinergym", + "rllib_experiment_config": { + "config": { + "env": "sinergym-Eplus-5Zone-hot-continuous-v1", + "env_config": { + "name": "Eplus-5Zone-hot-continuous-v1", + "normalize": True, + }, + "gamma": 0.999, + "output": "/root/ray_results/debug/", + "output_compress_columns": [], + "soft_horizon": False, + "no_done_at_end": False, + "horizon": 10000, + }, + "stop": {"timesteps_total": 400000}, + }, +} + +rllib_setup = { + "rllib_experiment_config": { + "config": { + # Utilities settings + "framework": "torch", + "log_level": "WARNING", + "num_workers": 8, # 1 for silent mode, can at least be 6 + "num_gpus": 1, + "seed": ray.tune.randint(0, 10000000), + }, + "log_to_file": True, + "checkpoint_freq": 10000, + }, +} diff --git a/beobench/experiment/scheduler.py b/beobench/experiment/scheduler.py index b70ae765..5bf060a5 100644 --- a/beobench/experiment/scheduler.py +++ b/beobench/experiment/scheduler.py @@ -21,6 +21,8 @@ def run( wandb_project: str = "", wandb_entity: str = "", wandb_api_key: str = "", + use_gpu: bool = False, + docker_shm_size: str = "2gb", no_additional_container: bool = False, use_no_cache: bool = False, ) -> None: @@ -39,6 +41,10 @@ def run( "initial_experiments". wandb_entity (str, optional): Name of wandb entity. Defaults to "beobench". wandb_api_key (str, optional): wandb API key. Defaults to None. + use_gpu (bool, optional): whether to use GPU from the host system. Defaults to + False. + docker_shm_size(str, optional): size of the shared memory available to the + container. Defaults to '2gb'." no_additional_container (bool, optional): wether not to start another container to run experiments in. Defaults to False, which means that another container is started to run experiments in. @@ -59,6 +65,16 @@ def run( experiment_def = importlib.util.module_from_spec(spec) spec.loader.exec_module(experiment_def) + # check if all attributes present and replace with default if not + if not hasattr(experiment_def, "problem"): + experiment_def.problem = beobench.experiment.definitions.default.problem + if not hasattr(experiment_def, "method"): + experiment_def.method = beobench.experiment.definitions.default.method + if not hasattr(experiment_def, "rllib_setup"): + experiment_def.rllib_setup = ( + beobench.experiment.definitions.default.rllib_setup + ) + if no_additional_container: # Add wandb callback if sufficient information @@ -71,11 +87,17 @@ def run( ) else: callbacks = [] + + # change RLlib setup if GPU used + rllib_setup = experiment_def.rllib_setup + if use_gpu: + rllib_setup["rllib_experiment_config"]["config"]["num_gpus"] = 1 + # run experiment in ray tune run_in_tune( problem_def=experiment_def.problem, method_def=experiment_def.method, - rllib_setup=experiment_def.rllib_setup, + rllib_setup=rllib_setup, rllib_callbacks=callbacks, ) else: @@ -91,7 +113,6 @@ def run( build_context=experiment_def.problem["problem_library"], use_no_cache=use_no_cache, ) - beobench.experiment.containers.create_docker_network("beobench-net") # define docker arguments/options/flags unique_id = uuid.uuid4().hex[:6] @@ -106,6 +127,28 @@ def run( f"{exp_file_abs}:{exp_file_on_docker}:ro", ] + # enable docker-from-docker access only for built-in boptest integration. + if experiment_def.problem["problem_library"] == "boptest": + + # Create docker network (only useful if starting other containers) + beobench.experiment.containers.create_docker_network("beobench-net") + + docker_flags += [ + # enable access to docker-from-docker + "-v", + "/var/run/docker.sock:/var/run/docker.sock", + # network allows access to BOPTEST API in other containers + "--network", + "beobench-net", + ] + + # enabling GPU access in docker container + if use_gpu: + docker_flags += [ + # add all available GPUs + "--gpus=all", + ] + # define flags for beobench scheduler call inside experiment container beobench_flags = [] if experiment_file: @@ -114,6 +157,8 @@ def run( beobench_flags.append(f"--wandb-project={wandb_project}") if wandb_entity: beobench_flags.append(f"--wandb-entity={wandb_entity}") + if use_gpu: + beobench_flags.append("--use-gpu") beobench_flag_str = " ".join(beobench_flags) # if no wandb API key is given try to get it from env @@ -124,21 +169,13 @@ def run( args = [ "docker", "run", - # the mounted socket allows access to docker - "-v", - "/var/run/docker.sock:/var/run/docker.sock", # mount experiment data dir "-v", f"{local_dir_abs}:/root/ray_results", # automatically remove container when stopped/exited "--rm", - # network allows access to BOPTEST API in other containers - "--network", - "beobench-net", # add more memory - "--shm-size=20.48gb", - # add available GPUs, - "--gpus=all", + f"--shm-size={docker_shm_size}", "--name", container_name, *docker_flags, @@ -183,6 +220,16 @@ def run( default="", help="Weights and biases API key.", ) +@click.option( + "--use-gpu", + is_flag=True, + help="Whether to use GPUs from the host system in experiment container.", +) +@click.option( + "--docker-shm-size", + default="2gb", + help="Size of shared memory available to experiment container.", +) @click.option( "--no-additional-container", is_flag=True, @@ -199,6 +246,8 @@ def run_command( wandb_project: str, wandb_entity: str, wandb_api_key: str, + use_gpu: bool, + docker_shm_size: str, no_additional_container: bool, use_no_cache: bool, ) -> None: @@ -216,6 +265,8 @@ def run_command( wandb_project=wandb_project, wandb_entity=wandb_entity, wandb_api_key=wandb_api_key, + use_gpu=use_gpu, + docker_shm_size=docker_shm_size, no_additional_container=no_additional_container, use_no_cache=use_no_cache, ) diff --git a/beobench/integrations/__init__.py b/beobench/integrations/__init__.py deleted file mode 100644 index 40209a36..00000000 --- a/beobench/integrations/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Subpackage for integrations with other tools""" diff --git a/beobench/integrations/boptest/Dockerfile b/beobench/integrations/boptest/Dockerfile deleted file mode 100644 index 5041d99b..00000000 --- a/beobench/integrations/boptest/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# Beobench main docker file for experiments -# To build this use -# > DOCKER_BUILDKIT=0 docker build --no-cache -t beobench:latest -f Dockerfile.boptest https://github.com/rdnfn/beobench.git#:docker - -FROM python:3.7 - -# install docker CLI -RUN wget -O tmp/docker-ce-cli.deb https://download.docker.com/linux/debian/dists/bullseye/pool/stable/amd64/docker-ce-cli_20.10.11~3-0~debian-bullseye_amd64.deb \ - && dpkg -i tmp/docker-ce-cli.deb \ - && rm tmp/docker-ce-cli.deb - - -# install beobench -RUN pip3 --disable-pip-version-check --no-cache-dir install git+https://github.com/rdnfn/beobench - -# add env creator -COPY env_creator.py /opt/beobench/experiment_setup/ -# add env creator to python path -ENV PYTHONPATH "${PYTHONPATH}:/opt/beobench/experiment_setup/" - -# use installer script to install BOPTEST -COPY installer.py tmp/ -RUN python tmp/installer.py \ - && rm tmp/installer.py diff --git a/beobench/integrations/boptest/env_creator.py b/beobench/integrations/boptest/env_creator.py deleted file mode 100644 index 3149f575..00000000 --- a/beobench/integrations/boptest/env_creator.py +++ /dev/null @@ -1,181 +0,0 @@ -"""Module for creating boptest testcases and managing their docker containers""" - -import pathlib -import subprocess -import time -import uuid -import docker - -try: - import boptest_gym -except ImportError as error: - raise ImportError( - ( - "boptest_gym package is not installed. " - "You may want to use `installer.py` in the boptest integration" - "to install BOPTEST including the boptest_gym package." - ) - ) from error - -from beobench.constants import DEFAULT_INSTALL_PATH - - -def build_testcase( - testcase: str = "testcase1", - install_path: pathlib.Path = DEFAULT_INSTALL_PATH, -) -> None: - """Build a docker image for a BOPTEST testcase. - - A built image is required before running a testcase. - - Args: - testcase (str, optional): testcase name. Defaults to "testcase1". - install_path (pathlib.Path, optional): path of beobench installation. - Defaults to DEFAULT_INSTALL_PATH. - """ - - subprocess.check_call( - ["make", "build", f"TESTCASE={testcase}"], - cwd=_get_boptest_path(install_path), - ) - - -def run_testcase( - testcase: str = "testcase1", - install_path: pathlib.Path = DEFAULT_INSTALL_PATH, - add_wait_time: bool = True, -) -> str: - """Run BOPTEST testcase docker image. - - Args: - testcase (str, optional): testcase to run. Defaults to "testcase1". - install_path (pathlib.Path, optional): path of beobench installation. - Defaults to DEFAULT_INSTALL_PATH. - add_wait_time (bool, optional): wether to add some wait time for - API in container to get ready. This is useful when after this - command the API is immidiately accessed. Defaults to True. - - Returns: - str: name of container - str: url of testcase API - """ - - img_name = f"boptest_{testcase}" - unique_id = uuid.uuid4().hex[:6] - container_name = f"auto_{img_name}_{unique_id}" - # ip_plus_port = f"127.0.0.1:{local_port}" - - # In order to be able to change the port - # this command is executed directly - # without the using the make file. - print(f"Creating BOPTEST testcase in container named '{container_name}'...") - args = [ - "docker", - "run", - "--name", - container_name, - "--rm", - # "-it", - # "-p", - # f"{ip_plus_port}:5000", - "--network=beobench-net", - "--detach=true", - img_name, - "/bin/bash", - "-c", - "python restapi.py && bash", - ] - - subprocess.check_call( - args, - cwd=_get_boptest_path(install_path), - ) - - if add_wait_time: - # Allow for the docker image to launch - time.sleep(5) - - # Getting the API port on the host machine. - # This is necessary because, if local_port is set to 0, - # a random free port is allocated. - # client = docker.from_env() - # container = client.containers.get(container_name) - # host_ip = container.ports["5000/tcp"][0]["HostIp"] - # host_port = container.ports["5000/tcp"][0]["HostPort"] - # url = f"http://{host_ip}:{host_port}" - url = f"http://{container_name}:5000" - - print(f"Container created. The BOPTEST API is exposed at '{url}'.") - - return container_name, url - - -def stop_container(container_name: str) -> None: - """Stop docker container. - - Args: - container_name (str): name of docker container to stop. - """ - client = docker.from_env() - container = client.containers.get(container_name) - container.stop(timeout=0) - - -def _get_boptest_path(install_path: pathlib.Path) -> pathlib.Path: - """Get BOPTEST path from beobench install path. - - Args: - install_path (str): path of beobench installation. - - Returns: - pathlib.Path: path to BOPTEST installation. - """ - return install_path / "boptest" - - -def create_env(env_config: dict = None) -> boptest_gym.BoptestGymEnv: - """Create BOPTEST gym environment. - - Args: - env_config (dict, optional): configuration kwargs of BOPTEST gym. - Defaults to None. - - Returns: - boptest_gym.BoptestGymEnv: a gym environment. - """ - - if not env_config: - env_config = { - "boptest_testcase": "bestest_hydronic_heat_pump", - "gym_kwargs": { - "actions": ["oveHeaPumY_u"], - "observations": {"reaTZon_y": (280.0, 310.0)}, - "random_start_time": True, - "max_episode_length": 86400, - "warmup_period": 10, - "step_period": 900, - }, - "normalize": True, - } - - container_name, url = run_testcase(env_config["boptest_testcase"]) - print("cname", container_name) - env = boptest_gym.BoptestGymEnv(url=url, **env_config["gym_kwargs"]) - - # ensure that the container is stopped once env closed - def custom_stop_container(): - stop_container(container_name) - - env.close = custom_stop_container - - if "normalize" in env_config and env_config["normalize"] is True: - env = boptest_gym.NormalizedActionWrapper(env) - env = boptest_gym.NormalizedObservationWrapper(env) - - if "discretize" in env_config and env_config["discretize"]: - env = boptest_gym.core.DiscretizedActionWrapper( - env, - n_bins_act=env_config["discretize"], - ) - - return env diff --git a/beobench/integrations/boptest/installer.py b/beobench/integrations/boptest/installer.py deleted file mode 100644 index 18df1855..00000000 --- a/beobench/integrations/boptest/installer.py +++ /dev/null @@ -1,145 +0,0 @@ -"""Module to install different boptest libraries""" - -# For python 3.7 -from __future__ import annotations - -import os -import pathlib -import sys -import click -import subprocess -import warnings - -# Constants -DEFAULT_INSTALL_PATH = pathlib.Path("/opt/beobench") - - -# Repo URLs and dependencies -BOPTEST_REPO_URL = "https://github.com/ibpsa/project1-boptest.git" -BOPTEST_REPO_NAME = "project1-boptest" -BOPTEST_COMMIT = "703daf26a9e9e18de7141c021cbfe36aa3578ea8" -BOPTEST_PIP_DEP = [ - "flask-restful==0.3.9", - "pandas==1.3.4", - "flask_cors==3.0.10", - # BOPTEST gym cannot be added as a direct or extra - # dependency in setup.py because pypi does not accept - # such direct dependencies. Therefore it is installed - # here. - ( - "boptest_gym@git+" - "https://github.com/rdnfn/project1-boptest-gym.git@rdnfn/feature-packaging" - ), -] - - -@click.command() -@click.option( - "--install_path", default=DEFAULT_INSTALL_PATH, help="installation path to use" -) -@click.option( - "--pip_install_dep", - default=True, - help="whether to install python dependencies via pip. Defaults to True.", -) -def install( - install_path: str = DEFAULT_INSTALL_PATH, - pip_install_dep: bool = True, -): - """Install the BOPTEST libraries into the `install_path` directory. - - Args: - install_path (str, optional): Path of installation. - Defaults to DEFAULT_INSTALL_PATH. - pip_install_dep (bool, optional): whether to install python dependencies - via pip. Defaults to True. - """ - install_path = pathlib.Path(install_path) - - print("Installing BOPTEST...") - - _clone_repo( - BOPTEST_REPO_URL, - BOPTEST_REPO_NAME, - install_path, - BOPTEST_COMMIT, - alt_name="boptest", - ) - - if pip_install_dep: - _install_pip_dependencies(BOPTEST_PIP_DEP) - - # Warning about BOPTEST PYTHONPATH requirement - boptest_path = install_path / "boptest" - warnings.warn( - ( - "In order to use the examples, BOPTEST requires" - " you to add its repo directory" - " to the PYTHONPATH variable. This can be done by using the command" - f" `export PYTHONPATH=$PYTHONPATH:{boptest_path}` before executing" - " their script." - ), - ) - - print(f"BOPTEST has been successfully installed at '{boptest_path}'.") - - -def _clone_repo( - repo_https_url: str, - repo_name: str, - local_path: str = None, - commit: str = None, - alt_name: str = None, -) -> None: - """Clone git repo from https URL, and set it to specific commit. - - Args: - repo_https_url (str): https URL of repo to clone. - repo_name (str): default name of repo folder. - local_path (str, optional): path to clone repo to. - Defaults to None (current working dir). - commit (str, optional): commit hash of commit the - repo should be reset to. Defaults to None (latest commit). - alt_name (str, optional): name that the local repo - folder is renamed to. Defaults to None (stay the same). - """ - - local_path = pathlib.Path(local_path) - os.makedirs(local_path, exist_ok=True) - - try: - # Clone repo - with subprocess.Popen(["git", "clone", repo_https_url], cwd=local_path): - pass - - # Set repo to fixed commit - with subprocess.Popen( - ["git", "reset", "--hard", commit], cwd=local_path / repo_name - ): - pass - - # Rename repo - if alt_name is not None: - print(f"Renaming repo from '{repo_name}' to '{alt_name}'...") - os.rename(local_path / repo_name, local_path / alt_name) - except OSError: - print( - f"{repo_name} appears to be already installed in '{local_path}'.", - "Skipping installation.", - ) - except Exception as e: - raise e - - -def _install_pip_dependencies(pip_requirements: list[str]): - """Install pip dependencies from requirements list. - - Args: - pip_requirements (list[str]): list of pip requirements. - """ - print("Installing pip dependencies...") - subprocess.check_call([sys.executable, "-m", "pip", "install", *pip_requirements]) - - -if __name__ == "__main__": - install() diff --git a/setup.cfg b/setup.cfg index a2566cf7..872b1dde 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.0 +current_version = 0.2.1 commit = True tag = True diff --git a/setup.py b/setup.py index 06e012c7..7f76b474 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ with open("HISTORY.rst", encoding="UTF-8") as history_file: history = history_file.read() -version = "0.2.0" +version = "0.2.1" requirements = [ "wandb",