Skip to content

Commit

Permalink
fix: Propagate app_name to DjanoSearch, fix naming (#119)
Browse files Browse the repository at this point in the history
* fix: Propagate app_name to DjanoSearch, fix naming

The app_name option should always filter on the whole DjangoSearch when
present, not just the report. This fixes that. Also updates some
variable and output names to be more clear about the state of the
models.

* build: Stop testing against Python 3.8

* chore: Add catalog-info

* chore: Bump version to 1.8.2
  • Loading branch information
bmtcril authored Nov 19, 2024
1 parent 0eb8375 commit f60763c
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 188 deletions.
44 changes: 22 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches: [master]
pull_request:
branches:
- '**'
- "**"

jobs:
run_tests:
Expand All @@ -14,31 +14,31 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ['3.8', '3.11', '3.12']
python-version: ["3.11", "3.12"]
toxenv: [quality, docs, django42]

steps:
- uses: actions/checkout@v2
- name: setup python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- uses: actions/checkout@v2
- name: setup python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install pip
run: pip install -r requirements/pip.txt
- name: Install pip
run: pip install -r requirements/pip.txt

- name: Install Dependencies
run: pip install -r requirements/ci.txt
- name: Install Dependencies
run: pip install -r requirements/ci.txt

- name: Run Tests
env:
TOXENV: ${{ matrix.toxenv }}
run: tox
- name: Run Tests
env:
TOXENV: ${{ matrix.toxenv }}
run: tox

- name: Run Coverage
if: matrix.python-version == '3.8' && matrix.toxenv=='django42'
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
fail_ci_if_error: true
- name: Run Coverage
if: matrix.python-version == '3.11' && matrix.toxenv=='django42'
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
fail_ci_if_error: true
12 changes: 12 additions & 0 deletions catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file records information about this repo. Its use is described in OEP-55:
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: "code-annotations"
description: "Tools for annotating code comments, linting, and Django model coverage."
spec:
owner: "bmtcril"
type: "library"
lifecycle: "production"
2 changes: 1 addition & 1 deletion code_annotations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Extensible tools for parsing annotations in codebases.
"""

__version__ = '1.8.1'
__version__ = '1.8.2'
167 changes: 108 additions & 59 deletions code_annotations/cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Command line interface for code annotation tools.
"""

import datetime
import sys
import traceback
Expand All @@ -21,53 +22,88 @@ def entry_point():
"""


@entry_point.command('django_find_annotations')
@entry_point.command("django_find_annotations")
@click.option(
"--config_file",
default=".annotations",
help="Path to the configuration file",
type=click.Path(exists=True, dir_okay=False, resolve_path=True),
)
@click.option(
"--seed_safelist/--no_safelist",
default=False,
show_default=True,
help="Generate an initial safelist file based on the current Django environment.",
)
@click.option(
'--config_file',
default='.annotations',
help='Path to the configuration file',
type=click.Path(exists=True, dir_okay=False, resolve_path=True)
"--list_local_models/--no_list_models",
default=False,
show_default=True,
help="List all locally defined models (in the current repo) that require annotations.",
)
@click.option(
"--app_name",
default=None,
help="(Optional) App name for which coverage is generated.",
)
@click.option("--report_path", default=None, help="Location to write the report")
@click.option("-v", "--verbosity", count=True, help="Verbosity level (-v through -vvv)")
@click.option(
'--seed_safelist/--no_safelist',
"--lint/--no_lint",
help="Enable or disable linting checks",
default=False,
show_default=True,
help='Generate an initial safelist file based on the current Django environment.',
)
@click.option(
'--list_local_models/--no_list_models',
"--report/--no_report",
help="Enable or disable writing the report",
default=False,
show_default=True,
)
@click.option(
"--coverage/--no_coverage",
help="Enable or disable coverage checks",
default=False,
show_default=True,
help='List all locally defined models (in the current repo) that require annotations.',
)
@click.option('--app_name', default='', help='(Optional) App name for which coverage is generated.')
@click.option('--report_path', default=None, help='Location to write the report')
@click.option('-v', '--verbosity', count=True, help='Verbosity level (-v through -vvv)')
@click.option('--lint/--no_lint', help='Enable or disable linting checks', default=False, show_default=True)
@click.option('--report/--no_report', help='Enable or disable writing the report', default=False, show_default=True)
@click.option('--coverage/--no_coverage', help='Enable or disable coverage checks', default=False, show_default=True)
def django_find_annotations(
config_file,
seed_safelist,
list_local_models,
app_name,
report_path,
verbosity,
lint,
report,
coverage
config_file,
seed_safelist,
list_local_models,
app_name,
report_path,
verbosity,
lint,
report,
coverage,
):
"""
Subcommand for dealing with annotations in Django models.
"""
try:
start_time = datetime.datetime.utcnow()

if (
not coverage
and not seed_safelist
and not list_local_models
and not lint
and not report
):
click.echo(
"No actions specified. Please specify one or more of --seed_safelist, --list_local_models, "
"--lint, --report, or --coverage"
)
sys.exit(1)

config = AnnotationConfig(config_file, report_path, verbosity)
searcher = DjangoSearch(config)
searcher = DjangoSearch(config, app_name)

# Early out if we're trying to do coverage, but a coverage target is not configured
if coverage and not config.coverage_target:
raise ConfigurationException("Please add 'coverage_target' to your configuration before running --coverage")
raise ConfigurationException(
"Please add 'coverage_target' to your configuration before running --coverage"
)

if seed_safelist:
searcher.seed_safelist()
Expand Down Expand Up @@ -107,32 +143,45 @@ def django_find_annotations(
annotation_count += len(annotated_models[filename])

elapsed = datetime.datetime.utcnow() - start_time
click.echo("Search found {} annotations in {} seconds.".format(
annotation_count, elapsed.total_seconds()
))

click.echo(
"Search found {} annotations in {} seconds.".format(
annotation_count, elapsed.total_seconds()
)
)
except Exception as exc:
click.echo(traceback.print_exc())
fail(str(exc))


@entry_point.command('static_find_annotations')
@entry_point.command("static_find_annotations")
@click.option(
'--config_file',
default='.annotations',
help='Path to the configuration file',
type=click.Path(exists=True, dir_okay=False, resolve_path=True)
"--config_file",
default=".annotations",
help="Path to the configuration file",
type=click.Path(exists=True, dir_okay=False, resolve_path=True),
)
@click.option(
'--source_path',
help='Location of the source code to search',
type=click.Path(exists=True, dir_okay=True, resolve_path=True)
"--source_path",
help="Location of the source code to search",
type=click.Path(exists=True, dir_okay=True, resolve_path=True),
)
@click.option('--report_path', default=None, help='Location to write the report')
@click.option('-v', '--verbosity', count=True, help='Verbosity level (-v through -vvv)')
@click.option('--lint/--no_lint', help='Enable or disable linting checks', default=True, show_default=True)
@click.option('--report/--no_report', help='Enable or disable writing the report file', default=True, show_default=True)
def static_find_annotations(config_file, source_path, report_path, verbosity, lint, report):
@click.option("--report_path", default=None, help="Location to write the report")
@click.option("-v", "--verbosity", count=True, help="Verbosity level (-v through -vvv)")
@click.option(
"--lint/--no_lint",
help="Enable or disable linting checks",
default=True,
show_default=True,
)
@click.option(
"--report/--no_report",
help="Enable or disable writing the report file",
default=True,
show_default=True,
)
def static_find_annotations(
config_file, source_path, report_path, verbosity, lint, report
):
"""
Subcommand to find annotations via static file analysis.
"""
Expand Down Expand Up @@ -176,18 +225,14 @@ def static_find_annotations(config_file, source_path, report_path, verbosity, li

@entry_point.command("generate_docs")
@click.option(
'--config_file',
default='.annotations',
help='Path to the configuration file',
type=click.Path(exists=True, dir_okay=False)
"--config_file",
default=".annotations",
help="Path to the configuration file",
type=click.Path(exists=True, dir_okay=False),
)
@click.option('-v', '--verbosity', count=True, help='Verbosity level (-v through -vvv)')
@click.argument("report_files", type=click.File('r'), nargs=-1)
def generate_docs(
config_file,
verbosity,
report_files
):
@click.option("-v", "--verbosity", count=True, help="Verbosity level (-v through -vvv)")
@click.argument("report_files", type=click.File("r"), nargs=-1)
def generate_docs(config_file, verbosity, report_files):
"""
Generate documentation from a code annotations report.
"""
Expand All @@ -197,15 +242,19 @@ def generate_docs(
config = AnnotationConfig(config_file, verbosity)

for key in (
'report_template_dir',
'rendered_report_dir',
'rendered_report_file_extension',
'rendered_report_source_link_prefix'
"report_template_dir",
"rendered_report_dir",
"rendered_report_file_extension",
"rendered_report_source_link_prefix",
):
if not getattr(config, key):
raise ConfigurationException(f"No {key} key in {config_file}")

config.echo("Rendering the following reports: \n{}".format("\n".join([r.name for r in report_files])))
config.echo(
"Rendering the following reports: \n{}".format(
"\n".join([r.name for r in report_files])
)
)

renderer = ReportRenderer(config, report_files)
renderer.render()
Expand Down
Loading

0 comments on commit f60763c

Please sign in to comment.