Skip to content

Commit

Permalink
feat: add entry-points for tools
Browse files Browse the repository at this point in the history
  • Loading branch information
tysmith committed Oct 8, 2024
1 parent d32ca9c commit 6168b0a
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 40 deletions.
9 changes: 9 additions & 0 deletions grizzly/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,16 @@


def main(args: Namespace) -> int:
"""CLI for `grizzly`.
Arguments:
args: Result from `GrizzlyArgs.parse_args`.
Returns:
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
configure_logging(args.log_level)

LOG.info("Starting Grizzly (%d)", getpid())
LOG.debug("grizzly-framework version: %s", package_version("grizzly-framework"))

Expand Down
3 changes: 1 addition & 2 deletions grizzly/reduce/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@
"""Grizzly reducer CLI.
"""
from . import ReduceManager
from .args import ReduceArgs

raise SystemExit(ReduceManager.main(ReduceArgs().parse_args()))
raise SystemExit(ReduceManager.main())
22 changes: 17 additions & 5 deletions grizzly/reduce/bucket.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from ..replay.bucket import bucket_main
from .args import ReduceFuzzManagerIDQualityArgs
from .crash import main as crash_main

Check warning on line 6 in grizzly/reduce/bucket.py

View check run for this annotation

Codecov / codecov/patch

grizzly/reduce/bucket.py#L4-L6

Added lines #L4 - L6 were not covered by tests

if __name__ == "__main__":
from ..replay.bucket import bucket_main
from .args import ReduceFuzzManagerIDQualityArgs
from .crash import main

raise SystemExit(bucket_main(ReduceFuzzManagerIDQualityArgs().parse_args(), main))
def main() -> int:

Check warning on line 9 in grizzly/reduce/bucket.py

View check run for this annotation

Codecov / codecov/patch

grizzly/reduce/bucket.py#L9

Added line #L9 was not covered by tests
"""Wrapper for bucket_main() which is the CLI for `grizzly.reduce.bucket`.
Arguments:
None
Returns:
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
return bucket_main(ReduceFuzzManagerIDQualityArgs().parse_args(), crash_main)

Check warning on line 18 in grizzly/reduce/bucket.py

View check run for this annotation

Codecov / codecov/patch

grizzly/reduce/bucket.py#L18

Added line #L18 was not covered by tests


if __name__ == "__main__":
raise SystemExit(main())
6 changes: 4 additions & 2 deletions grizzly/reduce/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
)
from ..replay import ReplayManager, ReplayResult
from ..target import AssetManager, Target, TargetLaunchError, TargetLaunchTimeout
from .args import ReduceArgs
from .exceptions import GrizzlyReduceBaseException, NotReproducible
from .strategies import STRATEGIES

Expand Down Expand Up @@ -752,16 +753,17 @@ def report(
self._status.last_reports = new_reports

@classmethod
def main(cls, args: Namespace) -> int:
def main(cls, args: Namespace | None = None) -> int:
"""CLI for `grizzly.reduce`.
Arguments:
args: Result from `ReduceArgs.parse_args`.
Returns:
0 for success. non-0 indicates a problem.
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
# pylint: disable=too-many-return-statements
args = args or ReduceArgs().parse_args()
configure_logging(args.log_level)
setlocale(LC_ALL, "")

Expand Down
14 changes: 10 additions & 4 deletions grizzly/reduce/crash.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from argparse import Namespace
from __future__ import annotations

from logging import getLogger
from typing import TYPE_CHECKING

from ..common.fuzzmanager import load_fm_data
from ..common.reporter import Quality
Expand All @@ -11,18 +13,22 @@
from .args import ReduceFuzzManagerIDArgs
from .core import ReduceManager

if TYPE_CHECKING:
from argparse import Namespace

LOG = getLogger(__name__)


def main(args: Namespace) -> int:
def main(args: Namespace | None = None) -> int:
"""CLI for `grizzly.reduce.crash`.
Arguments:
args: Result from `ReduceArgs.parse_args`.
Returns:
0 for success. non-0 indicates a problem.
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
args = args or ReduceFuzzManagerIDArgs().parse_args()
configure_logging(args.log_level)
with load_fm_data(args.input, load_bucket=not args.sig) as (crash, bucket):
LOG.info(
Expand Down Expand Up @@ -61,4 +67,4 @@ def main(args: Namespace) -> int:


if __name__ == "__main__":
raise SystemExit(main(ReduceFuzzManagerIDArgs().parse_args()))
raise SystemExit(main())
3 changes: 1 addition & 2 deletions grizzly/replay/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from .args import ReplayArgs
from .replay import ReplayManager

raise SystemExit(ReplayManager.main(ReplayArgs().parse_args()))
raise SystemExit(ReplayManager.main())
26 changes: 20 additions & 6 deletions grizzly/replay/bucket.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from argparse import Namespace
from __future__ import annotations

from logging import getLogger
from typing import Callable
from typing import TYPE_CHECKING, Callable

from ..common.fuzzmanager import Bucket
from ..common.utils import Exit, configure_logging
from .args import ReplayFuzzManagerIDQualityArgs
from .crash import main as crash_main

if TYPE_CHECKING:
from argparse import Namespace

LOG = getLogger(__name__)


Expand All @@ -21,7 +25,7 @@ def bucket_main(args: Namespace, tool_main: Callable[[Namespace], int]) -> int:
tool_main: Main function from a supported Grizzly tool.
Returns:
0 for success. non-0 indicates a problem.
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
assert callable(tool_main)
configure_logging(args.log_level)
Expand Down Expand Up @@ -49,7 +53,17 @@ def bucket_main(args: Namespace, tool_main: Callable[[Namespace], int]) -> int:
return result


def main() -> int:
"""Wrapper for bucket_main() which is the CLI for `grizzly.replay.bucket`.
Arguments:
None
Returns:
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
return bucket_main(ReplayFuzzManagerIDQualityArgs().parse_args(), crash_main)

Check warning on line 65 in grizzly/replay/bucket.py

View check run for this annotation

Codecov / codecov/patch

grizzly/replay/bucket.py#L65

Added line #L65 was not covered by tests


if __name__ == "__main__":
raise SystemExit(
bucket_main(ReplayFuzzManagerIDQualityArgs().parse_args(), crash_main)
)
raise SystemExit(main())
20 changes: 13 additions & 7 deletions grizzly/replay/bugzilla.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from argparse import Namespace
from __future__ import annotations

from logging import getLogger
from typing import TYPE_CHECKING

from ..common.bugzilla import BugzillaBug
from ..common.utils import configure_logging
from ..common.utils import Exit, configure_logging
from .args import ReplayFuzzBugzillaArgs
from .replay import ReplayManager

if TYPE_CHECKING:
from argparse import Namespace

LOG = getLogger(__name__)


def main(args: Namespace) -> int:
def main(args: Namespace | None = None) -> int:
"""CLI for `grizzly.replay.bugzilla`.
Arguments:
args: Result from `ReplayArgs.parse_args`.
Returns:
0 for success. non-0 indicates a problem.
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
args = args or ReplayFuzzBugzillaArgs().parse_args()
configure_logging(args.log_level)
bug = BugzillaBug.load(args.input)
if bug is None:
LOG.info("Failed to load Bug %d from Bugzilla", args.input)
return 1
return Exit.ERROR
LOG.info("Loaded Bug %d from Bugzilla", args.input)
with bug:
args.asset.extend(
Expand All @@ -35,10 +41,10 @@ def main(args: Namespace) -> int:
testcases = bug.testcases()
if not testcases:
LOG.error("No test case data attached to bug %d", args.input)
return 1
return Exit.ERROR
args.input = testcases
return ReplayManager.main(args)


if __name__ == "__main__":
raise SystemExit(main(ReplayFuzzBugzillaArgs().parse_args()))
raise SystemExit(main())
11 changes: 6 additions & 5 deletions grizzly/replay/crash.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@
LOG = getLogger(__name__)


def main(args: Namespace) -> int:
def main(args: Namespace | None = None) -> int:
"""CLI for `grizzly.replay.crash`.
Arguments:
args: Result from `ReplayArgs.parse_args`.
args: Result from `ReplayFuzzManagerIDArgs.parse_args`.
Returns:
0 for success. non-0 indicates a problem.
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
args = args or ReplayFuzzManagerIDArgs().parse_args()
configure_logging(args.log_level)
with load_fm_data(args.input, load_bucket=not args.sig) as (crash, bucket):
LOG.info("Loaded crash %d from FuzzManager", crash.crash_id)
Expand All @@ -38,7 +39,7 @@ def modify_args(args: Namespace, crash: CrashEntry, bucket: Bucket | None) -> Na
"""
Arguments:
args: Result from `ReplayArgs.parse_args`.
args: Result from `ReplayFuzzManagerIDArgs.parse_args`.
crash: Crash entry to process.
bucket: Bucket that contains crash.
Expand Down Expand Up @@ -77,4 +78,4 @@ def modify_args(args: Namespace, crash: CrashEntry, bucket: Bucket | None) -> Na


if __name__ == "__main__":
raise SystemExit(main(ReplayFuzzManagerIDArgs().parse_args()))
raise SystemExit(main())
13 changes: 12 additions & 1 deletion grizzly/replay/replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
TargetLaunchError,
TargetLaunchTimeout,
)
from .args import ReplayArgs

if TYPE_CHECKING:
from argparse import Namespace
Expand Down Expand Up @@ -600,8 +601,18 @@ def harness_fn(_: str) -> bytes: # pragma: no cover
result.report.cleanup()

@classmethod
def main(cls, args: Namespace) -> int:
def main(cls, args: Namespace | None = None) -> int:
"""CLI for `grizzly.reduce`.
Arguments:
args: Result from `ReplayArgs.parse_args`.
Returns:
Exit.SUCCESS (0) for success otherwise a different Exit code is returned.
"""
args = args or ReplayArgs().parse_args()
configure_logging(args.log_level)

LOG.info("Starting Grizzly Replay")
LOG.debug("grizzly-framework version: %s", package_version("grizzly-framework"))

Expand Down
6 changes: 1 addition & 5 deletions grizzly/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""test Grizzly main"""
from pathlib import Path
from platform import system

from pytest import mark, skip
Expand Down Expand Up @@ -86,7 +85,7 @@ def test_main_02(mocker, session_setup, exit_code, to_raise):
session_obj.run.side_effect = TargetLaunchError("test", mocker.Mock())
else:
session_obj.run.side_effect = to_raise()
args = mocker.MagicMock(adapter="fake", binary=Path("bin"), time_limit=1, timeout=1)
args = mocker.MagicMock(adapter="fake", time_limit=1, timeout=1)
assert main(args) == exit_code
assert target_cls.return_value.cleanup.call_count == 1

Expand All @@ -111,7 +110,6 @@ def test_main_03(mocker, session_setup, test_limit, timeout):
# no_harness=False for code coverage
args = mocker.MagicMock(
adapter="fake",
binary=Path("bin"),
no_harness=False,
time_limit=test_limit,
timeout=timeout,
Expand Down Expand Up @@ -142,7 +140,6 @@ def test_main_04(
assert sum((pernosco, rr, valgrind)) < 2, "test broken!"
args = mocker.MagicMock(
adapter="fake",
binary=Path("bin"),
pernosco=pernosco,
rr=rr,
time_limit=1,
Expand All @@ -162,7 +159,6 @@ def test_main_05(mocker, session_setup):
target_cls.return_value.https.return_value = False
args = mocker.MagicMock(
adapter="fake",
binary=Path("bin"),
use_http=False,
time_limit=1,
timeout=1,
Expand Down
10 changes: 9 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ zip_safe = False

[options.entry_points]
console_scripts =
grizzly.status = grizzly.common.status_reporter:main
grizzly = grizzly:__main__
grizzly-reduce = grizzly.reduce:__main__
grizzly-reduce-bucket = grizzly.reduce.bucket:main
grizzly-reduce-crash = grizzly.reduce.crash:main
grizzly-replay = grizzly.replay:__main__
grizzly-replay-bucket = grizzly.replay.bucket:main
grizzly-replay-bugzilla = grizzly.replay.bugzilla:main
grizzly-replay-crash = grizzly.replay.crash:main
grizzly-status = grizzly.common.status_reporter:main
grizzly_adapters =
no-op = grizzly.adapter.no_op_adapter:NoOpAdapter
grizzly_targets =
Expand Down

0 comments on commit 6168b0a

Please sign in to comment.