Repository: MathisFederico/LearnRL (language: python)

Issue:
Release/v1.0.2



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/python-coverage.yml b/.github/workflows/python-coverage.yml
index 45eeec8..f1f25a8 100644
--- a/.github/workflows/python-coverage.yml
+++ b/.github/workflows/python-coverage.yml
@@ -1,5 +1,5 @@
-# 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
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
 
 name: Python coverage
 
@@ -10,21 +10,51 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v2
-    - name: Set up Python 3.7
+    - name: Set up Python 3.9
       uses: actions/setup-python@v1
       with:
-        python-version: 3.7
+        python-version: 3.9
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
         pip install -r requirements.txt
-    - name: Build coverage using pytest-cov
+    - name: Build unit coverage using pytest-cov
       run: |
         pip install -r requirements-dev.txt
-        pip install pytest-cov
         pytest --cov=learnrl --cov-report=xml tests/unit
-    - name: Upload coverage-report to codacy
-      uses: codacy/codacy-coverage-reporter-action@master
+        score=$(python coverage_score.py --score)
+        color=$(python coverage_score.py --color)
+        echo "COVERAGE_UNIT_SCORE=$score"
+        echo "COVERAGE_UNIT_COLOR=$color"
+        echo "COVERAGE_UNIT_SCORE=$score" >> $GITHUB_ENV
+        echo "COVERAGE_UNIT_COLOR=$color" >> $GITHUB_ENV
+    - name: Create unit coverage badge
+      uses: schneegans/dynamic-badges-action@v1.1.0
       with:
-        project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
-        coverage-reports: coverage.xml
\ No newline at end of file
+        auth: ${{ secrets.GIST_SECRET }}
+        gistID: 00ce73155619a4544884ca6d251954b3
+        filename: learnrl_unit_coverage_badge.json
+        label: Unit coverage
+        message: ${{ env.COVERAGE_UNIT_SCORE }}
+        color: ${{ env.COVERAGE_UNIT_COLOR }}
+        style: plastic
+    - name: Build integration coverage using pytest-cov
+      run: |
+        pip install -r requirements-dev.txt
+        pytest --cov=learnrl --cov-report=xml tests/integration
+        score=$(python coverage_score.py --score)
+        color=$(python coverage_score.py --color)
+        echo "COVERAGE_INTEGRATION_SCORE=$score"
+        echo "COVERAGE_INTEGRATION_COLOR=$color"
+        echo "COVERAGE_INTEGRATION_SCORE=$score" >> $GITHUB_ENV
+        echo "COVERAGE_INTEGRATION_COLOR=$color" >> $GITHUB_ENV
+    - name: Create integration coverage badge
+      uses: schneegans/dynamic-badges-action@v1.1.0
+      with:
+        auth: ${{ secrets.GIST_SECRET }}
+        gistID: 00ce73155619a4544884ca6d251954b3
+        filename: learnrl_integration_coverage_badge.json
+        label: Integration coverage
+        message: ${{ env.COVERAGE_INTEGRATION_SCORE }}
+        color: ${{ env.COVERAGE_INTEGRATION_COLOR }}
+        style: plastic
\ No newline at end of file
diff --git a/.github/workflows/python-pylint.yml b/.github/workflows/python-pylint.yml
new file mode 100644
index 0000000..23b4d9e
--- /dev/null
+++ b/.github/workflows/python-pylint.yml
@@ -0,0 +1,39 @@
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
+
+name: Pylint
+
+on: ["push"]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python 3.9
+      uses: actions/setup-python@v1
+      with:
+        python-version: 3.9
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        pip install -r requirements.txt
+    - name: Lint with pylint
+      run: |
+        pip install -r requirements-dev.txt
+        score=$(python pylint_score.py --score)
+        color=$(python pylint_score.py --color)
+        echo "PYLINT_SCORE=$score/10.00"
+        echo "PYLINT_COLOR=$color"
+        echo "PYLINT_SCORE=$score/10.00" >> $GITHUB_ENV
+        echo "PYLINT_COLOR=$color" >> $GITHUB_ENV
+    - name: Create Pylint Badge
+      uses: schneegans/dynamic-badges-action@v1.1.0
+      with:
+        auth: ${{ secrets.GIST_SECRET }}
+        gistID: 00ce73155619a4544884ca6d251954b3
+        filename: learnrl_pylint_badge.json
+        label: Pylint
+        message: ${{ env.PYLINT_SCORE }}
+        color: ${{ env.PYLINT_COLOR }}
+        style: plastic
\ No newline at end of file
diff --git a/.github/workflows/python-pypi.yml b/.github/workflows/python-pypi.yml
index 9d76666..6eb7241 100644
--- a/.github/workflows/python-pypi.yml
+++ b/.github/workflows/python-pypi.yml
@@ -1,7 +1,7 @@
-# This workflows will upload a Python Package using Twine when a release is created
-# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
 
-name: Upload Python on PyPi
+name: PyPi
 
 on:
   push:
diff --git a/README.rst b/README.rst
index 7bd7b8e..4eacb29 100644
--- a/README.rst
+++ b/README.rst
@@ -1,19 +1,30 @@
 Welcome to LearnRL's community !
 ================================
 
-.. image:: https://img.shields.io/pypi/l/learnrl
-   :alt: PyPI - License
-   :target: https://www.gnu.org/licenses/
+
+.. image:: https://github.com/MathisFederico/LearnRL/actions/workflows/python-tests.yml/badge.svg?branch=dev
+   :alt: Pytest badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-tests.yml
+
+
+.. image:: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FMathisFederico%2F00ce73155619a4544884ca6d251954b3%2Fraw%2Flearnrl_pylint_badge.json
+   :alt: Pylint badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-pylint.yml
+
+
+.. image:: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FMathisFederico%2F00ce73155619a4544884ca6d251954b3%2Fraw%2Flearnrl_unit_coverage_badge.json
+   :alt: Unit coverage badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-coverage.yml
 
 
-.. image:: https://app.codacy.com/project/badge/Grade/b4c3818135484e8b9acae67b01526957
-   :alt: Codacy - Quality
-   :target: https://www.codacy.com/gh/MathisFederico/LearnRL/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=MathisFederico/LearnRL&amp;utm_campaign=Badge_Grade
+.. image:: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FMathisFederico%2F00ce73155619a4544884ca6d251954b3%2Fraw%2Flearnrl_integration_coverage_badge.json
+   :alt: Integration coverage badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-coverage.yml
 
 
-.. image:: https://app.codacy.com/project/badge/Coverage/b4c3818135484e8b9acae67b01526957
-   :alt: Codacy - Coverage
-   :target: https://www.codacy.com/gh/MathisFederico/LearnRL/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=MathisFederico/LearnRL&amp;utm_campaign=Badge_Coverage
+.. image:: https://img.shields.io/pypi/l/learnrl
+   :alt: PyPI - License
+   :target: https://www.gnu.org/licenses/
 
 
 LearnRL is a library to use and learn reinforcement learning.
@@ -53,7 +64,7 @@ You can build and run your own Agent in a clear and sharable manner !
          """ How the Agent will remember experiences """
          ...
 
-   env = gym.make('FrozenLake-v0', is_slippery=True) # This could be any gym Environment !
+   env = gym.make('FrozenLake-v0', is_slippery=True) # This could be any gym-like Environment !
    agent = MyAgent(env.observation_space, env.action_space)
 
    pg = rl.Playground(env, agent)
@@ -93,7 +104,7 @@ The Playground will allow you to have clean logs adapted to your will with the v
    .. image:: docs\_static\images\logs-verbose-5.png
 
 
-The Playground also allows you to add Callbacks with ease, for example the WandbCallback to have a nice experiment tracking dashboard !
+The Playground also allows you to add Callbacks with ease, for example the WandbCallback to have a nice experiment tracking dashboard using `weights&biases <https://wandb.ai/site>`_!
 
 
 Installation
@@ -104,21 +115,6 @@ Install LearnRL by running::
    pip install learnrl
 
 
-Get started
------------
-
-Create:
-   - TODO: Numpy tutorials
-   - TODO: Tensorflow tutorials
-   - TODO: Pytorch tutorials
-
-
-Visualize:
-   - TODO: Tensorboard visualisation tutorial
-   - TODO: Wandb visualisation tutorial
-   - TODO: Wandb sweeps tutorial
-
-
 Documentation
 -------------
 
diff --git a/VERSION b/VERSION
index 7f20734..6d7de6e 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-1.0.1
\ No newline at end of file
+1.0.2
diff --git a/coverage_score.py b/coverage_score.py
new file mode 100644
index 0000000..76948f7
--- /dev/null
+++ b/coverage_score.py
@@ -0,0 +1,20 @@
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
+
+""" Module to get coverage score. """
+
+import sys
+from defusedxml.minidom import parse
+from utils import score_to_rgb_color
+
+if __name__ == '__main__':
+    file = parse('coverage.xml')
+    coverage = file.getElementsByTagName('coverage')
+    coverage = float(coverage[0].attributes['line-rate'].value)
+    coverage_min, coverage_max = 0, 1
+    if sys.argv[1] == '--score':
+        print(f"{coverage:.1%}")
+    elif sys.argv[1] == '--color':
+        print(score_to_rgb_color(coverage, coverage_min, coverage_max))
+    else:
+        raise ValueError(f"Unknowed argument: {sys.argv[1]}")
diff --git a/docs/_static/images/docs.png b/docs/_static/images/docs.png
index 3e565f4..31f0267 100644
Binary files a/docs/_static/images/docs.png and b/docs/_static/images/docs.png differ
diff --git a/docs/index.rst b/docs/index.rst
index 16569ad..9ba5e11 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,17 +1,31 @@
 Welcome to LearnRL's community !
 ================================
 
+
+.. image:: https://github.com/MathisFederico/LearnRL/actions/workflows/python-tests.yml/badge.svg?branch=dev
+   :alt: Pytest badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-tests.yml
+
+
+.. image:: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FMathisFederico%2F00ce73155619a4544884ca6d251954b3%2Fraw%2Flearnrl_pylint_badge.json
+   :alt: Pylint badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-pylint.yml
+
+
+.. image:: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FMathisFederico%2F00ce73155619a4544884ca6d251954b3%2Fraw%2Flearnrl_unit_coverage_badge.json
+   :alt: Unit coverage badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-coverage.yml
+
+
+.. image:: https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FMathisFederico%2F00ce73155619a4544884ca6d251954b3%2Fraw%2Flearnrl_integration_coverage_badge.json
+   :alt: Integration coverage badge
+   :target: https://github.com/MathisFederico/LearnRL/actions/workflows/python-coverage.yml
+
+
 .. image:: https://img.shields.io/pypi/l/learnrl
    :alt: PyPI - License
    :target: https://www.gnu.org/licenses/
 
-.. image:: https://app.codacy.com/project/badge/Grade/b4c3818135484e8b9acae67b01526957
-   :alt: Codacy - Quality
-   :target: https://www.codacy.com/gh/MathisFederico/LearnRL/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=MathisFederico/LearnRL&amp;utm_campaign=Badge_Grade
-
-.. image:: https://app.codacy.com/project/badge/Coverage/b4c3818135484e8b9acae67b01526957
-   :alt: Codacy - Coverage
-   :target: https://www.codacy.com/gh/MathisFederico/LearnRL/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=MathisFederico/LearnRL&amp;utm_campaign=Badge_Coverage
 
 LearnRL is a library to use and learn reinforcement learning.
 It's also a community off supportive enthousiasts loving to share and build RL-based AI projects !
@@ -20,10 +34,9 @@ We would love to help you make projects with LearnRL, so join us `on Discord <ht
 About LearnRL
 -------------
 
-LearnRL is a framework to use and learn reinforcement learning with a wandb integration for a good visualisation !  
-Our motto is clean, sharable and readable Agents !  
-As such, you can plug and play agents on any environment, but also look how agents are built to learn !  
-
+LearnRL is a tool to monitor and log reinforcement learning experiments.
+You build/find any compatible agent (only need an act method), you build/find a gym environment, and learnrl will make them interact together !
+LearnRL also contains both tensorboard and weights&biases integrations for a beautiful and sharable experiment tracking !  
 Also, LearnRL is cross platform compatible ! That's why no agents are built-in learnrl itself, but you can check:
    - `LearnRL for Tensorflow <https://github.com/MathisFederico/LearnRL-Tensorflow>`_
    - `LearnRL for Pytorch <https://github.com/MathisFederico/LearnRL-Pytorch>`_
@@ -51,7 +64,7 @@ You can build and run your own Agent in a clear and sharable manner !
          """ How the Agent will remember experiences """
          ...
 
-   env = gym.make('FrozenLake-v0', is_slippery=True) # This could be any gym Environment !
+   env = gym.make('FrozenLake-v0', is_slippery=True) # This could be any gym-like Environment !
    agent = MyAgent(env.observation_space, env.action_space)
 
    pg = rl.Playground(env, agent)
@@ -59,7 +72,7 @@ You can build and run your own Agent in a clear and sharable manner !
 
 Note that 'learn' and 'remember' are optional, so this framework can also be used for baselines !
 
-Of course, you can logs any custom metrics that your Agent/Env gives you and even chose how to aggregate them through episodes or cycles:
+You can logs any custom metrics that your Agent/Env gives you and even chose how to aggregate them through different timescales.
 See the `metric codes <https://learnrl.readthedocs.io/en/latest/callbacks.html#metric-codes>`_ for more details.
 
 .. code-block:: python
@@ -76,27 +89,23 @@ See the `metric codes <https://learnrl.readthedocs.io/en/latest/callbacks.html#m
 
 The Playground will allow you to have clean logs adapted to your will with the verbose parameter:
   - Verbose 1 : episodes cycles - If your environment makes a lot of quick episodes.
-      .. image:: _static/images/logs-verbose-1.png
+   .. image:: docs\_static\images\logs-verbose-1.png
 
   - Verbose 2 : episode - To log each individual episode.
-      .. image:: _static/images/logs-verbose-2.png
+   .. image:: docs\_static\images\logs-verbose-2.png
 
   - Verbose 3 : steps cycles - If your environment makes a lot of quick steps but has long episodes.
-      .. image:: _static/images/logs-verbose-3.png
+   .. image:: docs\_static\images\logs-verbose-3.png
 
   - Verbose 4 : step - To log each individual step.
-      .. image:: _static/images/logs-verbose-4.png
+   .. image:: docs\_static\images\logs-verbose-4.png
 
   - Verbose 5 : detailled step - To debug each individual step (with observations, actions, ...).
-      .. image:: _static/images/logs-verbose-5.png
+   .. image:: docs\_static\images\logs-verbose-5.png
 
-The Playground also allows you to add Callbacks with ease, for example the WandbCallback to have a nice dashboard !
-TODO: Show wandb logging
 
-Features
---------
+The Playground also allows you to add Callbacks with ease, for example the WandbCallback to have a nice experiment tracking dashboard using `weights&biases <https://wandb.ai/site>`_!
 
-- Use this API to create your own agents and environments (even multiplayer!) with great compatibility and visualisation.
 
 Installation
 ------------
@@ -105,18 +114,6 @@ Install LearnRL by running::
 
    pip install learnrl
 
-Get started
------------
-
-Create:
-   - TODO: Numpy DQN tutorial
-   - TODO: Tensorflow tutorials
-   - TODO: Pytorch tutorials
-
-Visualize:
-   - TODO: Tensorboard visualisation tutorial
-   - TODO: Wandb visualisation tutorial
-   - TODO: Wandb sweep tutorial
 
 Table Of Content
 ----------------
diff --git a/learnrl/__init__.py b/learnrl/__init__.py
index 10545e5..7cb388c 100644
--- a/learnrl/__init__.py
+++ b/learnrl/__init__.py
@@ -3,7 +3,7 @@
 
 """LearnRL a python library to learn and log reinforcement learning"""
 
-__version__ = "1.0.1"
+__version__ = "1.0.2"
 
 from learnrl.agent import Agent
 from learnrl.envs import TurnEnv
diff --git a/pylint_score.py b/pylint_score.py
new file mode 100644
index 0000000..2b7cb0d
--- /dev/null
+++ b/pylint_score.py
@@ -0,0 +1,70 @@
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
+
+""" Module to get pylint score. """
+
+import sys
+import html
+from pylint.interfaces import IReporter
+from pylint.reporters import *
+from pylint.lint import Run
+from utils import score_to_rgb_color
+
+class MyReporterClass(BaseReporter):
+    """Report messages and layouts."""
+
+    __implements__ = IReporter
+    name = "myreporter"
+    extension = "myreporter"
+
+    def __init__(self, output=sys.stdout):
+        BaseReporter.__init__(self, output)
+        self.messages = []
+
+    def handle_message(self, msg):
+        """Manage message of different type and in the context of path."""
+        self.messages.append(
+            {
+                "type": msg.category,
+                "module": msg.module,
+                "obj": msg.obj,
+                "line": msg.line,
+                "column": msg.column,
+                "path": msg.path,
+                "symbol": msg.symbol,
+                "message": html.escape(msg.msg or "", quote=False),
+                "message-id": msg.msg_id,
+            }
+        )
+
+    def display_messages(self, layout):
+        """Do nothing."""
+
+    def display_reports(self, layout):
+        """Do nothing."""
+
+    def _display(self, layout):
+        """Do nothing."""
+
+
+def register(linter):
+    """Register the reporter classes with the linter."""
+    linter.register_reporter(MyReporterClass)
+
+if __name__ == '__main__':
+    options = [
+        'learnrl',
+        "--output-format=pylint_score.MyReporterClass"
+    ]
+    results = Run(options, exit=False)
+    score = results.linter.stats['global_note']
+    score_min = 8.0
+    score_max = 10
+    if sys.argv[1] == '--score':
+        print(f"{score:.2f}")
+        if score < score_min or score > score_max:
+            raise Exception(f'Insufficient score with pylint: {score:.2f}<{score_min:.2f}')
+    elif sys.argv[1] == '--color':
+        print(score_to_rgb_color(score, score_min=score_min, score_max=score_max))
+    else:
+        raise ValueError(f"Unknowed argument: {sys.argv[1]}")
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 2fa0ff0..7e9903a 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,8 +1,10 @@
 pytest
+pytest-cov
 pytest-mock
 pytest-check
 pytest-pspec
 pylint
 pylint-pytest
+defusedxml == 0.7.1
 wandb >= 0.10.0
 tensorflow >= 2.3.0
diff --git a/requirements.txt b/requirements.txt
index fa96cf7..21110e5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
 numpy
-gym
\ No newline at end of file
+gym==0.17.3
\ No newline at end of file
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..26e35ab
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,16 @@
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
+
+""" Module for badges colors """
+
+from colorsys import hsv_to_rgb
+
+def interpolate(weight, x, y):
+    return x * weight + (1-weight) * y
+
+def score_to_rgb_color(score, score_min, score_max):
+    normalized_score = max(0, (score - score_min) / (score_max - score_min))
+    hsv_color = (interpolate(normalized_score, 0.33, 0), 1, 1)
+    rgb_color = hsv_to_rgb(*hsv_color)
+    rgb_color = tuple(int(255*value) for value in rgb_color)
+    return f"rgb{rgb_color}"


Test patch:
diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml
index db3c6a0..1f58164 100644
--- a/.github/workflows/python-tests.yml
+++ b/.github/workflows/python-tests.yml
@@ -1,23 +1,17 @@
-# 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
+# LearnRL a python library to learn and use reinforcement learning
+# Copyright (C) 2020 Mathïs FEDERICO <https://www.gnu.org/licenses/>
 
-name: Python tests
+name: Pytest
 
-on:
-  push:
-    branches:
-      - master
-      - release/*
-  pull_request:
-    branches: [ master, dev, release/* ]
+on: ["push"]
 
 jobs:
   build:
 
-    runs-on: ubuntu-latest
+    runs-on: windows-latest
     strategy:
       matrix:
-        python-version: [3.6, 3.7, 3.8]
+        python-version: [3.7, 3.8, 3.9]
 
     steps:
     - uses: actions/checkout@v2
@@ -28,13 +22,15 @@ jobs:
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install tensorflow
         pip install -r requirements.txt
-        pip install -r requirements-dev.txt
-    - name: Lint with pylint
+    - name: Lint with flake8
       run: |
-        pylint learnrl/
-        pylint --exit-zero tests/
+        pip install flake8
+        # stop the build if there are Python syntax errors or undefined names
+        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
     - name: Test with pytest
       run: |
-        pytest
+        pip install -r requirements-dev.txt
+        pytest tests
diff --git a/tests/integrations/__init__.py b/tests/integration/__init__.py
similarity index 100%
rename from tests/integrations/__init__.py
rename to tests/integration/__init__.py
diff --git a/tests/integrations/callbacks/__init__.py b/tests/integration/callbacks/__init__.py
similarity index 100%
rename from tests/integrations/callbacks/__init__.py
rename to tests/integration/callbacks/__init__.py
diff --git a/tests/integrations/callbacks/test_logging.py b/tests/integration/callbacks/test_logging.py
similarity index 100%
rename from tests/integrations/callbacks/test_logging.py
rename to tests/integration/callbacks/test_logging.py