Skip to content

Commit

Permalink
Merge pull request #4 from jaspersiebring/linter
Browse files Browse the repository at this point in the history
Added automatic testing and publishing through Github Actions
  • Loading branch information
jaspersiebring committed Aug 9, 2023
2 parents ebcbf22 + 8150109 commit 9628550
Show file tree
Hide file tree
Showing 11 changed files with 436 additions and 76 deletions.
74 changes: 74 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Quality control and automated release
on:
pull_request: # Pull request events (default: open, synchronized, reopened) in any branch triggers the workflow.
push:
branches:
- main # Pushes to main (i.e. after a merged PR)
jobs:
checks_and_release:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Installing Poetry globally
run: pipx install poetry
- name: Installing Python
id: setup-python
uses: actions/setup-python@v4
with:
python-version: 3.8
- uses: actions/cache@v3
with:
path: /home/runner/.cache/pypoetry/virtualenvs
key: poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
restore-keys: |
poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
poetry-${{ steps.setup-python.outputs.python-version }}-
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y \
dpkg-dev \
build-essential \
freeglut3-dev \
libgl1-mesa-dev \
libglu1-mesa-dev \
libgstreamer-plugins-base1.0-dev \
libgtk-3-dev \
libjpeg-dev \
libnotify-dev \
libpng-dev \
libsdl2-dev \
libsm-dev \
libunwind-dev \
libtiff-dev \
libwebkit2gtk-4.0-dev \
libxtst-dev \
libgtk2.0-dev
- name: Installing Poetry environment
run: poetry install
- name: Running pytest
id: pytest
run: poetry run pytest -v
- name: Running mypy
id: mypy
run: poetry run mypy libretro_finder/ config/ tests/
- name: Running pylint
id: pylint
run: poetry run pylint libretro_finder/ config/ tests/ --fail-under=8
- name: Checking code coverage
id: coverage
run: poetry run pytest --cov=config --cov=libretro_finder --cov-fail-under=75

- name: Build source and .whl archives with Poetry
id: build
run: poetry build
if: steps.pytest.outcome == 'success' && steps.mypy.outcome == 'success' && steps.pylint.outcome == 'success' && steps.coverage.outcome == 'success'
- name: Authorize GitHub Actions to publish on PYPI
run: poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }}
if: steps.build.outcome == 'success' && github.event_name == 'push'
- name: Publish on PYPI
run: poetry publish
if: steps.build.outcome == 'success' && github.event_name == 'push'
74 changes: 74 additions & 0 deletions .github/workflows/test_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Build and release on TestPyPi
on:
workflow_dispatch: # Manual trigger (dev)
jobs:
checks_and_release:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Installing Poetry globally
run: pipx install poetry
- name: Installing Python
id: setup-python
uses: actions/setup-python@v4
with:
python-version: 3.8
- uses: actions/cache@v3
with:
path: /home/runner/.cache/pypoetry/virtualenvs
key: poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
restore-keys: |
poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
poetry-${{ steps.setup-python.outputs.python-version }}-
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y \
dpkg-dev \
build-essential \
freeglut3-dev \
libgl1-mesa-dev \
libglu1-mesa-dev \
libgstreamer-plugins-base1.0-dev \
libgtk-3-dev \
libjpeg-dev \
libnotify-dev \
libpng-dev \
libsdl2-dev \
libsm-dev \
libunwind-dev \
libtiff-dev \
libwebkit2gtk-4.0-dev \
libxtst-dev \
libgtk2.0-dev
- name: Installing Poetry environment
run: poetry install
- name: Running pytest
id: pytest
run: poetry run pytest -v
- name: Running mypy
id: mypy
run: poetry run mypy libretro_finder/ config/ tests/
- name: Running pylint
id: pylint
run: poetry run pylint libretro_finder/ config/ tests/ --fail-under=8
- name: Checking code coverage
id: coverage
run: poetry run pytest --cov=config --cov=libretro_finder --cov-fail-under=75

- name: Build source and .whl archives with Poetry
id: build
run: poetry build
if: steps.pytest.outcome == 'success' && steps.mypy.outcome == 'success' && steps.pylint.outcome == 'success' && steps.coverage.outcome == 'success'

- name: Authorize GitHub Actions to publish on PYPI
run: |
poetry config repositories.test-pypi https://test.pypi.org/legacy/
poetry config pypi-token.test-pypi ${{ secrets.TESTPYPI_API_TOKEN }}
if: steps.build.outcome == 'success'
- name: Publish on PYPI
run: poetry publish -r test-pypi
if: steps.build.outcome == 'success'
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
[![PyPI](https://img.shields.io/pypi/v/libretro-finder)](https://pypi.org/project/libretro-finder/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/libretro-finder)
![PyPI - License](https://img.shields.io/pypi/l/libretro-finder)
[![Build passing (main)](https://github.com/jaspersiebring/libretro_finder/actions/workflows/main.yml/badge.svg?branch=main&event=push)](https://github.com/jaspersiebring/libretro_finder/actions/workflows/main.yml)


Simple tool that finds and prepares your BIOS files for usage with Libretro (or its RetroArch frontend).

Expand Down Expand Up @@ -89,5 +91,5 @@ If `libretro_finder` is called without any additional arguments, LibretroFinder


### Missing features? Have some feedback? Let me know!
- [My Reddit account](https://www.reddit.com/user/qtieb/)
- [My Github account](https://github.com/jaspersiebring)
- [Open a Github issue](https://github.com/jaspersiebring)
- [Message me on Reddit ](https://www.reddit.com/user/qtieb/)
29 changes: 15 additions & 14 deletions config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@

# Parsing Libretro's system.dat and formatting as pandas dataframe
index = 0 # pylint: disable=invalid-name
SYSTEMS = []

system_series = []
with open(FILE_PATH, "r", encoding="utf-8") as file:
for line in file:
line = line.strip()
Expand All @@ -31,27 +32,27 @@
r"name (\S+)(?: size (\S+))?(?: crc (\S+))?(?: md5 (\S+))?(?: sha1 (\S+))?",
line,
)
data = {
"system": current_system,
"name": match.group(1).replace('"', "").replace("'", ""),
"size": match.group(2) if match.group(2) else None,
"crc": match.group(3) if match.group(3) else None,
"md5": match.group(4) if match.group(4) else None,
"sha1": match.group(5) if match.group(5) else None,
}
SYSTEMS.append(pd.DataFrame(data, index=[index]))
index += 1
if match:
data = {
"system": current_system,
"name": match.group(1).replace('"', "").replace("'", ""),
"size": match.group(2) if match.group(2) else None,
"crc": match.group(3) if match.group(3) else None,
"md5": match.group(4) if match.group(4) else None,
"sha1": match.group(5) if match.group(5) else None,
}
system_series.append(pd.DataFrame(data, index=[index]))
index += 1

# join dfs and drop features without checksums
SYSTEMS = pd.concat(SYSTEMS)
SYSTEMS = pd.concat(system_series)
SYSTEMS = SYSTEMS[~SYSTEMS["md5"].isnull()].reset_index(drop=True)

# path to retroarch/system (if found)
RETROARCH_PATH = find_retroarch()


# 'cli' if user passes arguments else 'start gui'
# Needs to be present before the @Gooey decorator (https://github.com/chriskiehl/Gooey/issues/449)
if len(sys.argv) >= 2:
if not "--ignore-gooey" in sys.argv:
if "--ignore-gooey" not in sys.argv:
sys.argv.append("--ignore-gooey")
8 changes: 3 additions & 5 deletions libretro_finder/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import shutil
import pathlib
from typing import List, Optional
import numpy as np
from gooey import Gooey, GooeyParser

from gooey import Gooey, GooeyParser # type: ignore
from config import SYSTEMS as system_df
from config import RETROARCH_PATH
from typing import List, Optional
from libretro_finder.utils import match_arrays, recursive_hash


Expand All @@ -17,7 +16,6 @@ def organize(search_dir: pathlib.Path, output_dir: pathlib.Path) -> None:
:param search_dir: starting location of recursive search
:param output_dir: path to output directory (will be created if it doesn't exist)
:return:
"""

# Indexing files to be checked for matching MD5 checksums
Expand Down Expand Up @@ -100,7 +98,7 @@ def main(argv: Optional[List[str]] = None) -> None:

if not search_directory.exists():
raise FileNotFoundError("Search directory does not exist..")
elif not search_directory.is_dir():
if not search_directory.is_dir():
raise NotADirectoryError("Search directory needs to be a directory..")

organize(search_dir=search_directory, output_dir=output_directory)
Expand Down
23 changes: 12 additions & 11 deletions libretro_finder/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import concurrent.futures
import hashlib
import pathlib
from typing import Tuple, Optional, List, Union
from tqdm import tqdm
import numpy as np
import vdf
from typing import Tuple, Optional, List
import platform
from string import ascii_uppercase
from tqdm import tqdm
import numpy as np
import vdf # type: ignore


# not expecting BIOS files over 15mb
MAX_BIOS_BYTES = 15728640
Expand All @@ -34,7 +35,7 @@ def recursive_hash(
:param directory: Starting directory for the glob pattern matching
:param glob: The glob pattern to match files. Defaults to "*".
:return: An array with the file_paths to selected files and an array with the corresponding MD5 hashes
:return: array with file_paths to selected files and an array with corresponding MD5 hashes
"""

file_paths = list(directory.rglob(pattern=glob))
Expand Down Expand Up @@ -65,8 +66,8 @@ def match_arrays(
:param array_a: The first array to compare.
:param array_b: The second array to compare.
:return: A tuple of three numpy arrays: unique matching values, indices of the matching values in
array_a and indices of the matching values in array_b.
:return: A tuple of three numpy arrays: unique matching values, indices of the matching values
in array_a and indices of the matching values in array_b.
"""

# expecting 1D arrays
Expand Down Expand Up @@ -123,10 +124,10 @@ def find_retroarch() -> Optional[pathlib.Path]:

env_vars = ["PROGRAMFILES(X86)", "PROGRAMFILES"]
for env_var in env_vars:
env_var = os.environ.get(env_var)
if not env_var:
env_value = os.environ.get(env_var)
if not env_value:
continue
env_path = pathlib.Path(env_var)
env_path = pathlib.Path(env_value)

if env_path.exists():
paths_to_check.append(env_path)
Expand Down Expand Up @@ -166,7 +167,7 @@ def find_retroarch() -> Optional[pathlib.Path]:

# checking for retroarch/system (one level down)
for path_to_check in paths_to_check:
# glob is needed for inconsistent parent naming (e.g. RetroArch-Win32, RetroArch-Win64, retroarch)
# glob is needed for inconsistent parent naming (e.g. RetroArch-Win32, retroarch)
for path in path_to_check.glob(system_glob):
return path
return None

0 comments on commit 9628550

Please sign in to comment.