mirror of
https://github.com/craigerl/aprsd.git
synced 2026-01-23 05:55:44 -05:00
Added --output-json for aprsd sample-config
This adds the ability to output the sample config as json for non-human processing.
This commit is contained in:
parent
e3fda752f6
commit
24bc86424e
@ -34,6 +34,7 @@ from oslo_config import cfg, generator
|
||||
import aprsd
|
||||
from aprsd import cli_helper, packets, threads, utils
|
||||
from aprsd.stats import collector
|
||||
from aprsd.utils import config_converter
|
||||
|
||||
# setup the global logger
|
||||
# log.basicConfig(level=log.DEBUG) # level=10
|
||||
@ -108,8 +109,14 @@ def check_version(ctx):
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option(
|
||||
'--output-json',
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help='Output the sample config in JSON format instead of INI.',
|
||||
)
|
||||
@click.pass_context
|
||||
def sample_config(ctx):
|
||||
def sample_config(ctx, output_json):
|
||||
"""Generate a sample Config file from aprsd and all installed plugins."""
|
||||
|
||||
def _get_selected_entry_points():
|
||||
@ -151,8 +158,34 @@ def sample_config(ctx):
|
||||
if not sys.argv[1:]:
|
||||
raise SystemExit from ex
|
||||
raise
|
||||
generator.generate(conf)
|
||||
return
|
||||
|
||||
if not output_json:
|
||||
generator.generate(conf)
|
||||
return
|
||||
|
||||
import io
|
||||
import json
|
||||
from contextlib import redirect_stdout
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
f = io.StringIO()
|
||||
with redirect_stdout(f):
|
||||
conf.format_ = 'json'
|
||||
generator.generate(conf)
|
||||
|
||||
s = f.getvalue()
|
||||
c = Console()
|
||||
c.print_json(data=json.loads(s))
|
||||
|
||||
|
||||
@cli.command()
|
||||
@cli_helper.add_options(cli_helper.common_options)
|
||||
@click.pass_context
|
||||
@cli_helper.process_standard_options
|
||||
def json_config(ctx):
|
||||
"""Output the current loaded configuration in JSON format."""
|
||||
click.echo(config_converter.conf_to_json(CONF))
|
||||
|
||||
|
||||
@cli.command()
|
||||
|
||||
@ -8,7 +8,6 @@ click==8.3.1 # via pip-tools
|
||||
colorama==0.4.6 # via tox
|
||||
coverage==7.13.1 # via pytest-cov
|
||||
distlib==0.4.0 # via virtualenv
|
||||
exceptiongroup==1.3.1 # via pytest
|
||||
filelock==3.20.0 # via tox, virtualenv
|
||||
identify==2.6.15 # via pre-commit
|
||||
iniconfig==2.3.0 # via pytest
|
||||
@ -32,13 +31,12 @@ pytest-cov==7.0.0 # via -r requirements-dev.in
|
||||
pyyaml==6.0.3 # via pre-commit
|
||||
ruff==0.14.13 # via -r requirements-dev.in
|
||||
setuptools==80.9.0 # via pip-tools
|
||||
tomli==2.4.0 # via build, coverage, mypy, pip-tools, pyproject-api, pytest, tox, tox-uv
|
||||
tox==4.32.0 # via tox-uv, -r requirements-dev.in
|
||||
tox-uv==1.29.0 # via -r requirements-dev.in
|
||||
types-pytz==2025.2.0.20251108 # via types-tzlocal, -r requirements-dev.in
|
||||
types-requests==2.32.4.20260107 # via -r requirements-dev.in
|
||||
types-tzlocal==5.1.0.1 # via -r requirements-dev.in
|
||||
typing-extensions==4.15.0 # via exceptiongroup, mypy, tox, virtualenv
|
||||
typing-extensions==4.15.0 # via mypy
|
||||
urllib3==2.6.2 # via types-requests
|
||||
uv==0.9.26 # via pre-commit-uv, tox-uv
|
||||
virtualenv==20.35.4 # via pre-commit, tox
|
||||
|
||||
144
tests/cmds/test_sample_config.py
Normal file
144
tests/cmds/test_sample_config.py
Normal file
@ -0,0 +1,144 @@
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
from aprsd.main import cli
|
||||
|
||||
|
||||
class TestSampleConfigCommand(unittest.TestCase):
|
||||
"""Unit tests for the sample_config command."""
|
||||
|
||||
def _create_mock_entry_point(self, name):
|
||||
"""Create a mock entry point object."""
|
||||
mock_entry = mock.Mock()
|
||||
mock_entry.name = name
|
||||
mock_entry.group = 'oslo.config.opts'
|
||||
return mock_entry
|
||||
|
||||
@mock.patch('aprsd.main.generator.generate')
|
||||
@mock.patch('aprsd.main.imp.entry_points')
|
||||
@mock.patch('aprsd.main.metadata_version')
|
||||
def test_sample_config_default_ini_output(
|
||||
self, mock_version, mock_entry_points, mock_generate
|
||||
):
|
||||
"""Test sample_config command outputs INI format by default."""
|
||||
mock_version.return_value = '1.0.0'
|
||||
# Mock entry_points to return at least one aprsd entry point
|
||||
# so that get_namespaces() returns a non-empty list
|
||||
if sys.version_info >= (3, 10):
|
||||
mock_entry_points.return_value = [
|
||||
self._create_mock_entry_point('aprsd.conf')
|
||||
]
|
||||
else:
|
||||
# For Python < 3.10, entry_points() returns a dict-like object
|
||||
mock_entry = self._create_mock_entry_point('aprsd.conf')
|
||||
mock_dict = {'oslo.config.opts': [mock_entry]}
|
||||
mock_entry_points.return_value = mock_dict
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
['sample-config'],
|
||||
catch_exceptions=False,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
# Verify generator.generate was called
|
||||
mock_generate.assert_called_once()
|
||||
# The conf object passed should not have format_ set to 'json'
|
||||
call_args = mock_generate.call_args
|
||||
conf_obj = call_args[0][0]
|
||||
# When output_json is False, format_ should not be set to 'json'
|
||||
assert not hasattr(conf_obj, 'format_') or conf_obj.format_ != 'json'
|
||||
|
||||
@mock.patch('rich.console.Console')
|
||||
@mock.patch('aprsd.main.generator.generate')
|
||||
@mock.patch('aprsd.main.imp.entry_points')
|
||||
@mock.patch('aprsd.main.metadata_version')
|
||||
def test_sample_config_json_output(
|
||||
self, mock_version, mock_entry_points, mock_generate, mock_console
|
||||
):
|
||||
"""Test sample_config command with --output-json flag outputs JSON format."""
|
||||
mock_version.return_value = '1.0.0'
|
||||
# Mock entry_points to return at least one aprsd entry point
|
||||
if sys.version_info >= (3, 10):
|
||||
mock_entry_points.return_value = [
|
||||
self._create_mock_entry_point('aprsd.conf')
|
||||
]
|
||||
else:
|
||||
# For Python < 3.10, entry_points() returns a dict-like object
|
||||
mock_entry = self._create_mock_entry_point('aprsd.conf')
|
||||
mock_dict = {'oslo.config.opts': [mock_entry]}
|
||||
mock_entry_points.return_value = mock_dict
|
||||
|
||||
# Mock generator.generate to write JSON to stdout
|
||||
# This simulates what oslo.config generator does when format_='json'
|
||||
def generate_side_effect(conf):
|
||||
import sys
|
||||
|
||||
json_output = '{"test": "config", "version": "1.0"}'
|
||||
sys.stdout.write(json_output)
|
||||
|
||||
mock_generate.side_effect = generate_side_effect
|
||||
|
||||
# Mock the Console
|
||||
mock_console_instance = mock.Mock()
|
||||
mock_console.return_value = mock_console_instance
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
['sample-config', '--output-json'],
|
||||
catch_exceptions=False,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
# Verify generator.generate was called
|
||||
mock_generate.assert_called_once()
|
||||
# Verify Console was instantiated
|
||||
mock_console.assert_called_once()
|
||||
# Verify print_json was called with parsed JSON
|
||||
mock_console_instance.print_json.assert_called_once()
|
||||
call_args = mock_console_instance.print_json.call_args
|
||||
# The data argument should be a dict (parsed JSON)
|
||||
assert isinstance(call_args[1]['data'], dict)
|
||||
assert call_args[1]['data'] == {'test': 'config', 'version': '1.0'}
|
||||
# Verify that conf.format_ was set to 'json' before generate was called
|
||||
generate_call_conf = mock_generate.call_args[0][0]
|
||||
assert generate_call_conf.format_ == 'json'
|
||||
|
||||
@mock.patch('aprsd.main.generator.generate')
|
||||
@mock.patch('aprsd.main.imp.entry_points')
|
||||
@mock.patch('aprsd.main.metadata_version')
|
||||
def test_sample_config_without_flag(
|
||||
self, mock_version, mock_entry_points, mock_generate
|
||||
):
|
||||
"""Test sample_config command without --output-json flag (explicit default)."""
|
||||
mock_version.return_value = '1.0.0'
|
||||
# Mock entry_points to return at least one aprsd entry point
|
||||
if sys.version_info >= (3, 10):
|
||||
mock_entry_points.return_value = [
|
||||
self._create_mock_entry_point('aprsd.conf')
|
||||
]
|
||||
else:
|
||||
# For Python < 3.10, entry_points() returns a dict-like object
|
||||
mock_entry = self._create_mock_entry_point('aprsd.conf')
|
||||
mock_dict = {'oslo.config.opts': [mock_entry]}
|
||||
mock_entry_points.return_value = mock_dict
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
['sample-config'],
|
||||
catch_exceptions=False,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
# Verify generator.generate was called
|
||||
mock_generate.assert_called_once()
|
||||
# Verify format_ was not set to 'json'
|
||||
call_args = mock_generate.call_args
|
||||
conf_obj = call_args[0][0]
|
||||
assert not hasattr(conf_obj, 'format_') or conf_obj.format_ != 'json'
|
||||
Loading…
x
Reference in New Issue
Block a user