Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.1.3 #3

Merged
merged 13 commits into from
Jul 15, 2024
29 changes: 29 additions & 0 deletions .github/workflows/actions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: mtf2json build and tests
on: [push, pull_request]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry flake8
poetry install --sync
- name: Lint with flake8
run: |
# 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 --statistics
- name: Test with pytest
run: |
poetry run pytest -v
- name: Test coverage with pytest-cov
run: |
poetry run pytest --cov=mtf2json tests/

132 changes: 104 additions & 28 deletions mtf2json/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import json
import argparse
from pathlib import Path
import os
from .mtf2json import read_mtf, write_json, ConversionError, version, mm_version
from typing import Optional


def create_parser() -> argparse.ArgumentParser:
Expand All @@ -26,9 +28,68 @@ def create_parser() -> argparse.ArgumentParser:
parser.add_argument('--version', '-V',
action='store_true',
help="Print version")
parser.add_argument('--mtf-dir', '-M',
type=str,
help="Convert all MTF files in the given directory.",
metavar="MTF_DIR")
parser.add_argument('--json-dir', '-J',
type=str,
help="Store all JSON files in the given directory.",
metavar="JSON_DIR")
parser.add_argument('--recursive', '-r',
action='store_true',
help="Recursively convert MTF files in subdirectories.")
parser.add_argument('--ignore-errors', '-i',
action='store_true',
help="Continue converting files even if an error occurs.")
return parser


def convert_dir(mtf_dir: Path,
json_dir: Optional[Path] = None,
recursive: bool = True,
ignore_errors: bool = False) -> int:
"""
Convert all MTF files in the `mtf_dir` folder to JSON (and subfolders if `recursive` is True).
The JSON files have the same name but suffix '.json' instead of '.mtf'.
If `json_dir` is given, write the JSON file to that directory.
If 'ignore_errors' is True, continue with the next file in case of a ConversionError.
"""
if not mtf_dir.is_dir():
raise ValueError(f"'{mtf_dir}' is not a directory.")

if json_dir:
if not json_dir.exists():
json_dir.mkdir(parents=True, exist_ok=True)
elif not json_dir.is_dir():
raise ValueError(f"'{json_dir}' is not a directory.")

error_occured = False
for root, _, files in os.walk(mtf_dir):
for file in files:
if file.endswith('.mtf'):
mtf_path = Path(root) / file
if json_dir:
relative_path = mtf_path.relative_to(mtf_dir)
json_path = json_dir / relative_path.with_suffix('.json')
json_path.parent.mkdir(parents=True, exist_ok=True)
else:
json_path = mtf_path.with_suffix('.json')
try:
print(f"'{mtf_path}' -> '{json_path}' ... ", end='')
data = read_mtf(mtf_path)
write_json(data, json_path)
print("SUCCESS")
except ConversionError as e:
error_occured = True
print(f"ERROR: {e}")
if not ignore_errors:
return 1
if not recursive:
break
return 1 if error_occured else 0


def main() -> None:
parser = create_parser()
args = parser.parse_args()
Expand All @@ -38,40 +99,55 @@ def main() -> None:
print(f"{version} (MM: {mm_version})")
sys.exit(0)

# check params
if not args.mtf_file or (args.json_file and len(args.mtf_file) != len(args.json_file)):
if args.json_file and len(args.mtf_file) != len(args.json_file):
print("\nError: The number of JSON files must match the number of MTF files.")
# either file conversion or directory conversion is allowed, but not both simultaneously
if (args.mtf_file and args.mtf_dir) or (args.json_file and args.json_dir):
print("\nError: Specify either --mtf-file or --mtf-dir, and either --json-file or --json-dir, but not both.")
parser.print_help()
sys.exit(1)

# set convert to True if json_file is specified
if args.json_file:
# either --mtf-file or --mtf-dir is required
if not args.mtf_file and not args.mtf_dir:
print("\nError: Either --mtf-file or --mtf-dir must be specified.")
parser.print_help()
sys.exit(1)
# nr. of arguments for --mtf-file and --json-file must match
if args.json_file and len(args.mtf_file) != len(args.json_file):
print("\nError: The number of JSON files must match the number of MTF files.")
parser.print_help()
sys.exit(1)
# set convert to True if --json-file or --json-dir are specified (or multiple MTF files)
if args.json_file or args.json_dir or (args.mtf_file and len(args.mtf_file) > 1):
args.convert = True

# read MTF
for i, mtf_file in enumerate(args.mtf_file):
path = Path(mtf_file)
if not path.exists():
print(f"File {path} does not exist!")
sys.exit(1)
try:
data = read_mtf(path)
except ConversionError as e:
print(f"Failed to convert '{path}': {e}")
sys.exit(1)

# convert to JSON and print or write to file
if args.convert:
json_path = Path(args.json_file[i]) if args.json_file else path.with_suffix('.json')
# convert given MTF file(s)
if args.mtf_file:
for i, mtf_file in enumerate(args.mtf_file):
path = Path(mtf_file)
if not path.exists():
print(f"File {path} does not exist!")
sys.exit(1)
try:
write_json(data, json_path)
print(f"Successfully saved JSON file '{json_path}'.")
except Exception as e:
print(f"Error: writing '{json_path}' failed with '{e}'")
data = read_mtf(path)
except ConversionError as e:
print(f"Failed to convert '{path}': {e}")
sys.exit(1)
else:
print(json.dumps(data))

# convert to JSON and print or write to file
if args.convert:
json_path = Path(args.json_file[i]) if args.json_file else path.with_suffix('.json')
try:
write_json(data, json_path)
print(f"Successfully saved JSON file '{json_path}'.")
except Exception as e:
print(f"Error: writing '{json_path}' failed with '{e}'")
sys.exit(1)
else:
print(json.dumps(data))

# convert all MTF files in given directory
if args.mtf_dir:
mtf_dir = Path(args.mtf_dir)
json_dir = Path(args.json_dir) if args.json_dir else None
sys.exit(convert_dir(mtf_dir, json_dir, args.recursive, args.ignore_errors))


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion mtf2json/mtf2json.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import Dict, Any, Tuple, Union, Optional, List, cast, TextIO


version = "0.1.2"
version = "0.1.3"
mm_version = "0.49.19.1"


Expand Down
8 changes: 8 additions & 0 deletions mtf2json/mtf2json.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@ from pathlib import Path
from typing import Dict, Any


version: str
mm_version: str


class ConversionError(Exception):
...


def read_mtf(path: Path) -> Dict[str, Any]: ...
def write_json(data: Dict[str, Any], path: Path) -> None: ...
87 changes: 86 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mtf2json"
version = "0.1.2"
version = "0.1.3"
description = "Convert the MegaMek MTF format to JSON."
authors = ["juk0de <[email protected]>"]
license = "MIT"
Expand All @@ -17,6 +17,7 @@ python = "^3.10"

[tool.poetry.group.test.dependencies]
pytest = "^8.2.2"
pytest-cov = "^5.0.0"

[build-system]
requires = ["poetry-core"]
Expand Down
Loading
Loading