Make installable by pip in editable mode

This commit is contained in:
Sebastian Lenzlinger 2024-06-27 17:50:21 +02:00
parent f024d6dec6
commit a29ffe92a6
4 changed files with 63 additions and 30 deletions

View File

@ -1,9 +1,6 @@
import json import json
import subprocess
import click import click
from pathlib import PurePath, Path from pathlib import Path
import configparser
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
import sys import sys
@ -60,48 +57,57 @@ def setup_logging(verbosity, debug):
def create_default_config(cfg_file): def create_default_config(cfg_file):
"""Create default iottb config file.""" """Create default iottb config file."""
assert logger is not None, 'Logger must be initialized'
logger.info(f'Creating default config file at {cfg_file}') logger.info(f'Creating default config file at {cfg_file}')
# By default, create iottb.db in user home
defaults = { defaults = {
'DefaultDatabase': DB_NAME, 'DefaultDatabase': DB_NAME,
'DatabaseLocations': { 'DatabaseLocations': {
DB_NAME: str(Path.home() / DB_NAME) DB_NAME: str(Path.home() / DB_NAME)
} }
} }
with open(cfg_file, 'w') as config_file: try:
json.dump(defaults, config_file) with open(cfg_file, 'w') as config_file:
json.dump(defaults, config_file)
except IOError as e:
logger.error(f"Failed to create default configuration file at {cfg_file}: {e}")
raise RuntimeError(f"Failed to create configuration file: {e}") from e
return defaults return defaults
def load_config(ctx, param, value): def load_config(cfg_file):
""" Try to load iottb config file. """Loads or creates default configuration from given file path."""
If the file does not exist, it will be created with default values.`
Try to load the iottb config file from the given path.
If the file does not exist, it will be created with default values.
The only value set is the path to the iottb.db file.
"""
logger.info(f'Loading config from {value}')
cfg_file = value
if not cfg_file.is_file(): if not cfg_file.is_file():
defaults = create_default_config(cfg_file) return create_default_config(cfg_file)
else: with open(cfg_file, 'r') as config_file:
defaults = json.load(cfg_file) return json.load(config_file)
ctx.obj['path']['cfg'] = cfg_file
ctx.obj['path']['db'] = defaults['DatabaseLocations'][defaults['DefaultDatabase']]
@click.group() @click.group()
@click.option('-v', '--verbosity', type=click.IntRange(0, MAX_VERBOSITY), default=0, @click.option('-v', '--verbosity', count=True, type=click.IntRange(0, 3), default=0,
help='Set verbosity') help='Set verbosity')
@click.option('-d', '--debug', is_flag=True, default=False, help='Enable debug mode') @click.option('-d', '--debug', is_flag=True, default=False,
@click.option('--cfg-file', type=click.Path(), default=Path(click.get_app_dir(APP_NAME)).joinpath('iottb.cfg'), help='Enable debug mode')
envvar='IOTTB_CONF_HOME', is_eager=True, callback=load_config, help='Path to iottb config file') @click.option('--cfg-file', type=click.Path(exists=True),
default=Path(click.get_app_dir(APP_NAME)).joinpath('iottb.cfg'),
envvar='IOTTB_CONF_HOME', help='Path to iottb config file')
@click.pass_context @click.pass_context
def main(verbosity, debug): def cli(ctx, verbosity, debug, cfg_file):
setup_logging(verbosity, debug) ctx.ensure_object(dict) # Make sure context is ready for use
ctx.obj['CONFIG'] = load_config(cfg_file) # Load configuration directly
setup_logging(verbosity, debug) # Setup logging based on the loaded configuration and other options
@click.command()
@click.option('-d', '--dest', default=Path.home(), type=str, help='Location to put (new) iottb database')
@click.option('--name', default=DB_NAME, type=str, help='Name of new database.')
@click.option('--update-default/ --no-update-default', default=True,
help='If new db should be set as the new default')
@click.pass_context
def init_db(ctx, dest, name, update_default):
logger.debug('TOP init_db')
cli.add_command(init_db)
if __name__ == '__main__': if __name__ == '__main__':
main(auto_envvar_prefix='IOTTB') cli(auto_envvar_prefix='IOTTB')

7
poetry.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
package = []
[metadata]
lock-version = "2.0"
python-versions = "^3.12"
content-hash = "34e39677d8527182346093002688d17a5d2fc204b9eb3e094b2e6ac519028228"

View File

@ -8,6 +8,8 @@ readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.12" python = "^3.12"
[tool.poetry.scripts]
iottb = "iottb.main:cli"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]

View File

@ -0,0 +1,18 @@
# test_main.py
import pytest
from click.testing import CliRunner
from iottb.main import cli # Adjust this import according to your project's structure
@pytest.fixture
def runner():
"""Fixture to return a Click CliRunner instance."""
return CliRunner()
def test_debug_option(runner):
"""Test if the debug mode sets the appropriate flag in the context."""
result = runner.invoke(cli, ['--debug'])
assert result.exit_code == 0
# If debug mode affects logging or other behavior, validate those:
assert 'DEBUG mode on' in result.output