Skip to content

Commit

Permalink
Merge pull request #20 from dalager/lint-test-action-improvement
Browse files Browse the repository at this point in the history
Updating lint/test CI pipeline
  • Loading branch information
dalager authored Oct 10, 2024
2 parents a51a97f + 80c7fa9 commit 50105c9
Show file tree
Hide file tree
Showing 10 changed files with 556 additions and 174 deletions.
67 changes: 61 additions & 6 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,77 @@ jobs:
python-version: ["3.10", "3.11", "3.12"]

steps:
# 1. Check out the repository
- uses: actions/checkout@v4

# 2. Set up Python environment
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies

# 3. Cache pip dependencies based on pyproject.toml and setup.cfg (if any)
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml', '**/setup.cfg') }}
restore-keys: |
${{ runner.os }}-pip-
# 4. Install build requirements
- name: Install build requirements
run: |
python -m pip install --upgrade pip setuptools wheel
# 5. Install project dependencies
- name: Install dependencies
run: |
pip install .
# 6. Cache test dependencies
- name: Cache test dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-test-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-test-
# 7. Install test and lint dependencies
- name: Install test and lint dependencies
run: |
pip install .[test]
pip install flake8
- name: Lint with flake8
# 8. Lint with flake8 - Errors
- name: Lint with flake8 (Errors)
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
continue-on-error: false

# 9. Lint with flake8 - Warnings
- name: Lint with flake8 (Warnings)
run: |
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
continue-on-error: true

# 10. Run tests with pytest
- name: Test with pytest
run: |
pip install .[test]
pytest
pytest --junitxml=reports/junit.xml --cov=graphedexcel --cov-report=xml
# 11. Upload test coverage to Codecov (Optional)
- name: Upload results to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false

# 12. Upload Test Reports (Optional)
- name: Upload Test Report
if: always()
uses: actions/upload-artifact@v3
with:
name: junit-test-report
path: reports/junit.xml
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ python -m graphedexcel <path_to_excel_file>
### Parameters from `--help`

```
usage: graphedexcel [-h] [--remove-unconnected] [--as-directed-graph] [--no-visualize]
[--layout {spring,circular,kamada_kawai,shell,spectral}] [--config CONFIG]
[--output-path OUTPUT_PATH] [--open-image]
usage: graphedexcel [-h] [--as-directed-graph] [--no-visualize]
[--layout {spring,circular,kamada_kawai,shell,spectral}]
[--config CONFIG] [--output-path OUTPUT_PATH]
[--open-image]
path_to_excel
Process an Excel file to build and visualize dependency graphs.
Expand All @@ -76,17 +77,18 @@ positional arguments:
options:
-h, --help show this help message and exit
--remove-unconnected, -r
Remove unconnected nodes from the dependency graph.
--as-directed-graph, -d
Treat the dependency graph as directed.
--no-visualize, -n Skip the visualization of the dependency graph.
--layout,-l {spring,circular,kamada_kawai,shell,spectral}
Layout algorithm for graph visualization (default: spring).
--config CONFIG, -c CONFIG
Path to the configuration file for visualization. See README for details.
--output-path OUTPUT_PATH, -o OUTPUT_PATH
Specify the output path for the generated graph image.
--no-visualize, -n Skip the visualization of the dependency
graph.
--layout, -l {spring,circular,kamada_kawai,shell,spectral}
Layout algorithm for graph visualization
(default: spring).
--config, -c CONFIG Path to the configuration file for
visualization. See README for details.
--output-path, -o OUTPUT_PATH
Specify the output path for the generated
graph image.
--open-image Open the generated image after visualization.
```

Expand Down
11 changes: 8 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ dependencies = [
]

[project.optional-dependencies]
test = ["black==21.9b0", "pytest==8.3"]

test = [
"black==21.9b0",
"pytest==8.3",
"pytest-cov>=3.0.0", # Added for coverage reporting
"flake8>=6.0.0", # Ensure flake8 is included here for consistency
"codecov>=2.1.11", # (Optional) If you intend to use Codecov's Python package]
]
[project.urls]
Homepage = "https://github.com/dalager/graphedexcel"
Issues = "https://github.com/dalager/graphedexcel/issues"
Expand All @@ -33,5 +38,5 @@ build-backend = "setuptools.build_meta"

[tool.pytest.ini_options]
minversion = "8.0"
addopts = "-ra"
addopts = "-ra --cov=graphedexcel --cov-report=xml --cov-report=term"
testpaths = ["tests"]
145 changes: 2 additions & 143 deletions src/graphedexcel/__main__.py
Original file line number Diff line number Diff line change
@@ -1,146 +1,5 @@
import os
import sys
import argparse
import logging
from .graphbuilder import build_graph_and_stats
from .graph_summarizer import print_summary
from .graph_visualizer import visualize_dependency_graph
from graphedexcel.cli import main
from graphedexcel import logger_config # noqa: F401

logger = logging.getLogger("graphedexcel.main")


def parse_arguments():
parser = argparse.ArgumentParser(
prog="graphedexcel",
description="Process an Excel file to build and visualize dependency graphs.",
)

# Positional argument for the path to the Excel file
parser.add_argument(
"path_to_excel", type=str, help="Path to the Excel file to process."
)

# Optional flags with shorthand aliases
parser.add_argument(
"--remove-unconnected",
"-r",
action="store_true",
help="Remove unconnected nodes from the dependency graph.",
)

parser.add_argument(
"--as-directed-graph",
"-d",
action="store_true",
help="Treat the dependency graph as directed.",
)

parser.add_argument(
"--no-visualize",
"-n",
action="store_true",
help="Skip the visualization of the dependency graph.",
)

parser.add_argument(
"--layout",
"-l",
type=str,
default="spring",
choices=["spring", "circular", "kamada_kawai", "shell", "spectral"],
help="Layout algorithm for graph visualization (default: spring).",
)

parser.add_argument(
"--config",
"-c",
type=str,
help="Path to the configuration file for visualization. See README for details.",
)

parser.add_argument(
"--output-path",
"-o",
type=str,
default=None,
help="Specify the output path for the generated graph image.",
)

parser.add_argument(
"--open-image",
action="store_true",
help="Open the generated image after visualization.",
)

return parser.parse_args()


def main():
args = parse_arguments()

path_to_excel = args.path_to_excel

# Check if the file exists
if not os.path.exists(path_to_excel):
logger.error(f"File not found: {path_to_excel}")
sys.exit(1)

# Build the dependency graph and gather statistics
dependency_graph, function_stats = build_graph_and_stats(
path_to_excel,
remove_unconnected=args.remove_unconnected,
as_directed=args.as_directed_graph,
)

# Print summary of the dependency graph
print_summary(dependency_graph, function_stats)

if args.no_visualize:
logger.info("Skipping visualization as per the '--no-visualize' flag.")
sys.exit(0)

logger.info("Visualizing the graph of dependencies. (This might take a while...)")

# Determine layout
layout = args.layout

# Configuration path
config_path = args.config

# Determine output filename
if args.output_path:
filename = args.output_path
else:
# Create a default filename based on the Excel file name
base_name = os.path.splitext(os.path.basename(path_to_excel))[0]
filename = f"{base_name}_dependency_graph.png"

# Visualize the dependency graph
visualize_dependency_graph(dependency_graph, filename, config_path, layout)

logger.info(f"Dependency graph image saved to {filename}.")

# Open the image file if requested
if args.open_image:
try:
os.startfile(filename) # Note: os.startfile is Windows-specific
except AttributeError:
# For macOS and Linux, use 'open' and 'xdg-open' respectively
import subprocess
import platform

if platform.system() == "Darwin": # macOS
subprocess.call(["open", filename])
elif platform.system() == "Linux":
subprocess.call(["xdg-open", filename])
else:
logger.warning("Unable to open the image automatically on this OS.")


if __name__ == "__main__":
try:
main()
except Exception as e:
logger.exception("An unexpected error occurred:", e)
sys.exit(1)
main()
Loading

0 comments on commit 50105c9

Please sign in to comment.