porringer 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. porringer-0.1.0/LICENSE.md +21 -0
  2. porringer-0.1.0/PKG-INFO +16 -0
  3. porringer-0.1.0/README.md +1 -0
  4. porringer-0.1.0/porringer/__init__.py +5 -0
  5. porringer-0.1.0/porringer/api.py +21 -0
  6. porringer-0.1.0/porringer/backend/__init__.py +5 -0
  7. porringer-0.1.0/porringer/backend/builder.py +92 -0
  8. porringer-0.1.0/porringer/backend/command/__init__.py +5 -0
  9. porringer-0.1.0/porringer/backend/command/plugin.py +62 -0
  10. porringer-0.1.0/porringer/backend/command/self.py +48 -0
  11. porringer-0.1.0/porringer/backend/command/version.py +1 -0
  12. porringer-0.1.0/porringer/backend/resolver.py +50 -0
  13. porringer-0.1.0/porringer/backend/schema.py +28 -0
  14. porringer-0.1.0/porringer/console/__init__.py +5 -0
  15. porringer-0.1.0/porringer/console/command/__init__.py +1 -0
  16. porringer-0.1.0/porringer/console/command/plugin.py +66 -0
  17. porringer-0.1.0/porringer/console/command/self.py +29 -0
  18. porringer-0.1.0/porringer/console/entry.py +68 -0
  19. porringer-0.1.0/porringer/console/schema.py +38 -0
  20. porringer-0.1.0/porringer/core/__init__.py +5 -0
  21. porringer-0.1.0/porringer/core/plugin_schema/__init__.py +5 -0
  22. porringer-0.1.0/porringer/core/plugin_schema/environment.py +124 -0
  23. porringer-0.1.0/porringer/core/schema.py +85 -0
  24. porringer-0.1.0/porringer/plugin/__init__.py +4 -0
  25. porringer-0.1.0/porringer/plugin/pip/__init__.py +5 -0
  26. porringer-0.1.0/porringer/plugin/pip/plugin.py +103 -0
  27. porringer-0.1.0/porringer/plugin/pipx/__init__.py +5 -0
  28. porringer-0.1.0/porringer/plugin/pipx/plugin.py +108 -0
  29. porringer-0.1.0/porringer/plugin/winget/__init__.py +5 -0
  30. porringer-0.1.0/porringer/plugin/winget/plugin.py +129 -0
  31. porringer-0.1.0/porringer/py.typed +0 -0
  32. porringer-0.1.0/porringer/schema.py +65 -0
  33. porringer-0.1.0/porringer/test/mock/__init__.py +4 -0
  34. porringer-0.1.0/porringer/test/mock/environment.py +70 -0
  35. porringer-0.1.0/porringer/test/pytest/__init__.py +4 -0
  36. porringer-0.1.0/porringer/test/pytest/plugin.py +36 -0
  37. porringer-0.1.0/porringer/test/pytest/shared.py +90 -0
  38. porringer-0.1.0/porringer/test/pytest/tests.py +31 -0
  39. porringer-0.1.0/porringer/test/pytest/variants.py +42 -0
  40. porringer-0.1.0/porringer/utility/__init__.py +5 -0
  41. porringer-0.1.0/porringer/utility/exception.py +70 -0
  42. porringer-0.1.0/porringer/utility/plugin.py +36 -0
  43. porringer-0.1.0/porringer/utility/py.typed +0 -0
  44. porringer-0.1.0/porringer/utility/utility.py +44 -0
  45. porringer-0.1.0/pyproject.toml +131 -0
  46. porringer-0.1.0/tests/__init__.py +5 -0
  47. porringer-0.1.0/tests/integration/__init__.py +5 -0
  48. porringer-0.1.0/tests/integration/plugins/__init__.py +5 -0
  49. porringer-0.1.0/tests/integration/plugins/pip/__init__.py +5 -0
  50. porringer-0.1.0/tests/integration/plugins/pip/test_environment.py +20 -0
  51. porringer-0.1.0/tests/integration/plugins/pipx/__init__.py +5 -0
  52. porringer-0.1.0/tests/integration/plugins/pipx/test_environment.py +20 -0
  53. porringer-0.1.0/tests/integration/plugins/winget/__init__.py +5 -0
  54. porringer-0.1.0/tests/integration/plugins/winget/test_environment.py +20 -0
  55. porringer-0.1.0/tests/unit/__init__.py +5 -0
  56. porringer-0.1.0/tests/unit/plugins/__init__.py +5 -0
  57. porringer-0.1.0/tests/unit/plugins/pip/__init__.py +5 -0
  58. porringer-0.1.0/tests/unit/plugins/pip/test_environment.py +20 -0
  59. porringer-0.1.0/tests/unit/plugins/pipx/__init__.py +5 -0
  60. porringer-0.1.0/tests/unit/plugins/pipx/test_environment.py +20 -0
  61. porringer-0.1.0/tests/unit/plugins/winget/__init__.py +5 -0
  62. porringer-0.1.0/tests/unit/plugins/winget/test_environment.py +20 -0
  63. porringer-0.1.0/tests/unit/test_cli.py +19 -0
  64. porringer-0.1.0/tests/unit/test_command_plugin.py +34 -0
  65. porringer-0.1.0/tests/unit/test_command_self.py +41 -0
  66. porringer-0.1.0/tests/unit/test_plugin_schema.py +5 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Synodic Software
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.1
2
+ Name: porringer
3
+ Version: 0.1.0
4
+ Author-Email: Synodic Software <contact@synodic.software>
5
+ License: MIT
6
+ Project-URL: homepage, https://github.com/Synodic-Software/Porringer
7
+ Project-URL: repository, https://github.com/Synodic-Software/Porringer
8
+ Requires-Python: >=3.13
9
+ Requires-Dist: typer[all]>=0.15.2
10
+ Requires-Dist: pydantic>=2.11.3
11
+ Requires-Dist: platformdirs>=4.3.7
12
+ Requires-Dist: userpath>=1.9.2
13
+ Requires-Dist: packaging>=24.2
14
+ Description-Content-Type: text/markdown
15
+
16
+ # Porringer
@@ -0,0 +1 @@
1
+ # Porringer
@@ -0,0 +1,5 @@
1
+ """Porringer package.
2
+
3
+ This package provides the core functionality for the Porringer application,
4
+ including API definitions, backend processing, console commands, and utility functions.
5
+ """
@@ -0,0 +1,21 @@
1
+ """API for Porringer"""
2
+
3
+ from porringer.backend.command.plugin import PluginCommands
4
+ from porringer.backend.command.self import SelfCommands
5
+ from porringer.backend.resolver import resolve_configuration
6
+ from porringer.backend.schema import Configuration, GlobalConfiguration
7
+ from porringer.schema import (
8
+ APIParameters,
9
+ LocalConfiguration,
10
+ )
11
+
12
+
13
+ class API:
14
+ """_summary_"""
15
+
16
+ def __init__(self, local_configuration: LocalConfiguration, parameters: APIParameters) -> None:
17
+ """Initializes the API"""
18
+ self.configuration: Configuration = resolve_configuration(local_configuration, GlobalConfiguration())
19
+ self.parameters = parameters
20
+ self.plugin = PluginCommands(self.parameters.logger)
21
+ self.porringer = SelfCommands(self.parameters.logger)
@@ -0,0 +1,5 @@
1
+ """Backend package for Porringer.
2
+
3
+ This package contains modules and utilities for backend processing,
4
+ including configuration resolution, plugin management, and command execution.
5
+ """
@@ -0,0 +1,92 @@
1
+ """Builder"""
2
+
3
+ from importlib import metadata
4
+ from inspect import getmodule
5
+ from logging import Logger
6
+
7
+ from packaging.version import Version
8
+
9
+ from porringer.core.plugin_schema.environment import Environment
10
+ from porringer.core.schema import Distribution, PluginParameters
11
+ from porringer.schema import PluginInformation
12
+ from porringer.utility.exception import PluginError
13
+ from porringer.utility.utility import canonicalize_type
14
+
15
+
16
+ class Builder:
17
+ """Helper class for building Porringer projects"""
18
+
19
+ def __init__(self, logger: Logger) -> None:
20
+ """Initializes the builder"""
21
+ self.logger = logger
22
+
23
+ def find_environments(self) -> list[PluginInformation[Environment]]:
24
+ """Searches for registered environment plugins
25
+
26
+ Raises:
27
+ PluginError: Raised if there is no plugin found
28
+
29
+ Returns:
30
+ A list of loaded plugins
31
+ """
32
+ group_name = 'environment'
33
+ plugin_types: list[PluginInformation[Environment]] = []
34
+
35
+ # Filter entries by type
36
+ for entry_point in list(metadata.entry_points(group=f'porringer.{group_name}')):
37
+ loaded_type = entry_point.load()
38
+
39
+ canonicalized = canonicalize_type(loaded_type)
40
+
41
+ if entry_point.dist is None:
42
+ self.logger.error(f"Plugin '{canonicalized.name}' is not installed. Skipping")
43
+ continue
44
+
45
+ # TODO: Add metadata to plugin information, percolate to pytest_synodic API
46
+
47
+ if not issubclass(loaded_type, Environment):
48
+ self.logger.warning(
49
+ f"Found incompatible plugin. The '{canonicalized.name}' plugin must be an instance"
50
+ f" of '{group_name}'"
51
+ )
52
+ else:
53
+ self.logger.warning(f'{group_name} plugin found: {canonicalized.name} from {getmodule(loaded_type)}')
54
+ plugin_types.append(PluginInformation(loaded_type, entry_point.dist))
55
+
56
+ if not plugin_types:
57
+ raise PluginError(f'No {group_name} plugin was found')
58
+
59
+ return plugin_types
60
+
61
+ @staticmethod
62
+ def build_environment(environment_type: PluginInformation[Environment]) -> Environment:
63
+ """Constructs a single environment from input type
64
+
65
+ Args:
66
+ environment_type: The type to construct
67
+
68
+ Returns:
69
+ The instantiated environment
70
+ """
71
+ pluginVersion = Version(environment_type.distribution.version)
72
+ pluginDistribution = Distribution(version=pluginVersion)
73
+ parameters = PluginParameters(distribution=pluginDistribution)
74
+
75
+ return environment_type.type(parameters)
76
+
77
+ @staticmethod
78
+ def build_environments(environment_types: list[PluginInformation[Environment]]) -> list[Environment]:
79
+ """Constructs environments from input types
80
+
81
+ Args:
82
+ environment_types: The types to construct
83
+
84
+ Returns:
85
+ The instantiated environments
86
+ """
87
+ environments: list[Environment] = []
88
+
89
+ for environment_type in environment_types:
90
+ environments.append(Builder.build_environment(environment_type))
91
+
92
+ return environments
@@ -0,0 +1,5 @@
1
+ """Command package for Porringer backend.
2
+
3
+ This package contains command modules for backend operations,
4
+ including plugin management and self-update functionalities.
5
+ """
@@ -0,0 +1,62 @@
1
+ """The plugin command module."""
2
+
3
+ from logging import Logger
4
+
5
+ from porringer.backend.builder import Builder
6
+ from porringer.backend.resolver import resolve_list_plugins_parameters
7
+ from porringer.schema import ListPluginResults, ListPluginsParameters
8
+
9
+
10
+ class PluginCommands:
11
+ """Plugin commands"""
12
+
13
+ def __init__(self, logger: Logger) -> None:
14
+ """Initialize the SelfCommands class.
15
+
16
+ Args:
17
+ logger (Logger): Logger instance for logging actions.
18
+ """
19
+ self.logger = logger
20
+
21
+ def list(self, parameters: ListPluginsParameters) -> list[ListPluginResults]:
22
+ """Lists the plugins.
23
+
24
+ Args:
25
+ parameters: The list command parameters.
26
+
27
+ Returns:
28
+ A list of registered plugins.
29
+ """
30
+ self.logger.info('Listing plugins')
31
+
32
+ builder = Builder(self.logger)
33
+
34
+ environment_types = builder.find_environments()
35
+
36
+ environments = builder.build_environments(environment_types)
37
+
38
+ return resolve_list_plugins_parameters(environments)
39
+
40
+ def install(self, logger: Logger) -> None:
41
+ """Install a plugin"""
42
+ logger.info('Installing plugin')
43
+
44
+ builder = Builder(logger)
45
+
46
+ environment_types = builder.find_environments()
47
+
48
+ def uninstall(self, logger: Logger) -> None:
49
+ """Remove an installed plugin"""
50
+ logger.info('Uninstalling plugin')
51
+
52
+ builder = Builder(logger)
53
+
54
+ environment_types = builder.find_environments()
55
+
56
+ def update(self, logger: Logger) -> None:
57
+ """Updates the plugins.
58
+
59
+ Args:
60
+ logger: The logger.
61
+ """
62
+ logger.info('Updating plugins')
@@ -0,0 +1,48 @@
1
+ """Utilities for managing and checking the Porringer installation version."""
2
+
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ from logging import Logger
7
+
8
+
9
+ class SelfCommands:
10
+ """Commands related to the Porringer installation."""
11
+
12
+ def __init__(self, logger: Logger) -> None:
13
+ """Initialize the SelfCommands class.
14
+
15
+ Args:
16
+ logger: Logger instance for logging actions.
17
+ """
18
+ self.logger = logger
19
+
20
+ def is_pipx_installation(self) -> bool:
21
+ """Check if Porringer is installed via pipx.
22
+
23
+ Returns:
24
+ bool: True if the current Python environment is a pipx-managed venv, False otherwise.
25
+ """
26
+ return sys.prefix.split(os.sep)[-3:-1] == ['pipx', 'venvs']
27
+
28
+ def update(self) -> None:
29
+ """Upgrade the Porringer package using pipx if installed via pipx.
30
+
31
+ Raises:
32
+ NotImplementedError: If Porringer is not installed via pipx.
33
+ """
34
+ if self.is_pipx_installation():
35
+ subprocess.run(['pipx', 'upgrade', 'porringer'], check=True)
36
+ else:
37
+ raise NotImplementedError()
38
+
39
+ def check(self) -> None:
40
+ """Check for updates to the Porringer package using pipx if installed via pipx.
41
+
42
+ Raises:
43
+ NotImplementedError: If Porringer is not installed via pipx.
44
+ """
45
+ if self.is_pipx_installation():
46
+ subprocess.run(['pipx', 'upgrade', 'porringer'], check=True)
47
+ else:
48
+ raise NotImplementedError()
@@ -0,0 +1 @@
1
+ """Version utilities"""
@@ -0,0 +1,50 @@
1
+ """Resolves"""
2
+
3
+ from porringer.backend.schema import Configuration, GlobalConfiguration
4
+ from porringer.core.plugin_schema.environment import Environment
5
+ from porringer.schema import ListPluginResults, LocalConfiguration
6
+ from porringer.utility.utility import canonicalize_type
7
+
8
+
9
+ def resolve_configuration(
10
+ local_configuration: LocalConfiguration, global_configuration: GlobalConfiguration
11
+ ) -> Configuration:
12
+ """Resolves the configuration.
13
+
14
+ Args:
15
+ local_configuration: The local configuration.
16
+ global_configuration: The global configuration.
17
+
18
+ Returns:
19
+ The resolved configuration.
20
+ """
21
+ local_configuration.cache_directory.mkdir(parents=True, exist_ok=True)
22
+
23
+ global_configuration.config_directory.mkdir(parents=True, exist_ok=True)
24
+ global_configuration.data_directory.mkdir(parents=True, exist_ok=True)
25
+
26
+ return Configuration(
27
+ cache_directory=local_configuration.cache_directory,
28
+ config_directory=global_configuration.config_directory,
29
+ data_directory=global_configuration.data_directory,
30
+ )
31
+
32
+
33
+ def resolve_list_plugins_parameters(environment: list[Environment]) -> list[ListPluginResults]:
34
+ """Resolves the list plugins parameters.
35
+
36
+ Args:
37
+ environment: The environment.
38
+
39
+ Returns:
40
+ A list of plugin metadata.
41
+ """
42
+ plugin_metadata: list[ListPluginResults] = []
43
+
44
+ for plugin in environment:
45
+ canonicalized = canonicalize_type(type(plugin))
46
+
47
+ resolved_metadata = ListPluginResults(canonicalized.name, plugin.distribution.version, False)
48
+ plugin_metadata.append(resolved_metadata)
49
+
50
+ return plugin_metadata
@@ -0,0 +1,28 @@
1
+ """Backend schema"""
2
+
3
+ from pathlib import Path
4
+
5
+ from platformdirs import user_config_dir, user_data_dir
6
+ from pydantic import BaseModel, DirectoryPath, Field
7
+
8
+
9
+ class GlobalConfiguration(BaseModel):
10
+ """Global configuration that Porringer manages"""
11
+
12
+ config_directory: Path = Field(
13
+ default=Path(user_config_dir('porringer', 'synodic')),
14
+ description='The configuration directory',
15
+ )
16
+
17
+ data_directory: Path = Field(
18
+ default=Path(user_data_dir('porringer', 'synodic')),
19
+ description='The data directory',
20
+ )
21
+
22
+
23
+ class Configuration(BaseModel):
24
+ """Resolved configuration"""
25
+
26
+ cache_directory: DirectoryPath
27
+ config_directory: DirectoryPath
28
+ data_directory: DirectoryPath
@@ -0,0 +1,5 @@
1
+ """Console package for Porringer.
2
+
3
+ This package contains modules and utilities for the command-line interface,
4
+ including command definitions and configuration management.
5
+ """
@@ -0,0 +1 @@
1
+ """Commands for the Porringer console application."""
@@ -0,0 +1,66 @@
1
+ """Porringer CLI plugin command module"""
2
+
3
+ import logging
4
+ from typing import Annotated
5
+
6
+ import typer
7
+
8
+ from porringer.api import API
9
+ from porringer.console.schema import Configuration
10
+ from porringer.schema import APIParameters, ListPluginsParameters
11
+
12
+ app = typer.Typer()
13
+
14
+
15
+ @app.command('list')
16
+ def plugin_list(
17
+ context: typer.Context,
18
+ ) -> None:
19
+ """Lists available plugins
20
+
21
+ Args:
22
+ context: The click context
23
+ """
24
+ configuration = context.ensure_object(Configuration)
25
+
26
+ api_parameters = APIParameters(logging.getLogger('porringer'))
27
+ api = API(configuration.local_configuration, api_parameters)
28
+
29
+ list_parameters = ListPluginsParameters()
30
+ results = api.plugin.list(list_parameters)
31
+
32
+ for result in results:
33
+ configuration.console.print(result)
34
+
35
+
36
+ @app.command('install')
37
+ def plugin_install(
38
+ context: typer.Context, plugins: Annotated[list[str], typer.Argument(help='Plugins to install')]
39
+ ) -> None:
40
+ """Install plugins"""
41
+ for plugin in plugins:
42
+ pass
43
+
44
+
45
+ @app.command('update')
46
+ def plugin_update(
47
+ context: typer.Context, plugins: Annotated[list[str], typer.Argument(help='Plugins to update')]
48
+ ) -> None:
49
+ """Update plugins"""
50
+ for plugin in plugins:
51
+ pass
52
+
53
+
54
+ @app.command('uninstall')
55
+ def plugin_uninstall(
56
+ context: typer.Context, plugins: Annotated[list[str], typer.Argument(help='Plugins to remove')]
57
+ ) -> None:
58
+ """Remove installed plugins"""
59
+ for plugin in plugins:
60
+ pass
61
+
62
+
63
+ @app.callback(invoke_without_command=True, no_args_is_help=True)
64
+ def application() -> None:
65
+ """Plugin management and operations"""
66
+ pass
@@ -0,0 +1,29 @@
1
+ """Porringer CLI self command module."""
2
+
3
+ import typer
4
+
5
+ app = typer.Typer()
6
+
7
+
8
+ @app.command('update')
9
+ def self_update() -> None:
10
+ """Updates the Porringer application.
11
+
12
+ Raises:
13
+ NotImplementedError: This functionality is not yet implemented.
14
+ """
15
+
16
+
17
+ @app.command('check')
18
+ def self_check() -> None:
19
+ """Checks for updates to the Porringer application.
20
+
21
+ Raises:
22
+ NotImplementedError: This functionality is not yet implemented.
23
+ """
24
+
25
+
26
+ @app.callback(invoke_without_command=True, no_args_is_help=True)
27
+ def application() -> None:
28
+ """Management of the Porringer instance running the CLI application."""
29
+ pass
@@ -0,0 +1,68 @@
1
+ """Typer CLI Application"""
2
+
3
+ import logging
4
+ from typing import Annotated
5
+
6
+ import typer
7
+ from rich.console import Console
8
+
9
+ from porringer.console.command.plugin import app as plugin_app
10
+ from porringer.console.command.self import app as self_app
11
+ from porringer.console.schema import LOG_LEVELS, MAX_VERBOSITY_LEVEL, Configuration
12
+
13
+ # TODO: Hook up version to the version in pyproject.toml
14
+ __version__ = '0.1.0'
15
+
16
+ app = typer.Typer()
17
+ app.add_typer(plugin_app, name='plugin')
18
+ app.add_typer(self_app, name='self')
19
+
20
+
21
+ class TyperHandler(logging.Handler):
22
+ """A logging handler that outputs to typer"""
23
+
24
+ def __init__(self, console: Console) -> None:
25
+ """Initializes the handler"""
26
+ logging.Handler.__init__(self)
27
+
28
+ self.console = console
29
+
30
+ def emit(self, record: logging.LogRecord) -> None:
31
+ """Emits the log record to typer"""
32
+ level = next(level for level in LOG_LEVELS if level.name == record.levelname)
33
+ self.console.print(record, style=level.colour)
34
+
35
+
36
+ def version_callback(value: bool) -> None:
37
+ """Callback for the version option"""
38
+ if value:
39
+ print(f'Awesome CLI Version: {__version__}')
40
+ raise typer.Exit()
41
+
42
+
43
+ @app.callback(invoke_without_command=True, no_args_is_help=True)
44
+ def application(
45
+ context: typer.Context,
46
+ verbose: Annotated[int, typer.Option('--verbose', '-v', count=True, help='', min=0, max=MAX_VERBOSITY_LEVEL)] = 0,
47
+ debug: Annotated[bool, typer.Option('--debug', help='')] = False,
48
+ version: Annotated[
49
+ bool | None,
50
+ typer.Option('--version', callback=version_callback, is_eager=True),
51
+ ] = None,
52
+ ) -> None:
53
+ """A tool for automatic facilitation of program updates and package managers.
54
+
55
+ Args:
56
+ context: The click context object
57
+ verbose: The input verbosity level
58
+ debug: The debug flag
59
+ version: The version request
60
+ """
61
+ configuration = context.ensure_object(Configuration)
62
+
63
+ configuration.debug = debug
64
+ configuration.verbosity = verbose
65
+
66
+ logger = logging.getLogger('porringer')
67
+ handler = TyperHandler(configuration.console)
68
+ logger.addHandler(handler)
@@ -0,0 +1,38 @@
1
+ """Data schemas for console commands"""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import LiteralString
5
+
6
+ from pydantic import BaseModel, ConfigDict
7
+ from rich.console import Console
8
+
9
+ from porringer.schema import LocalConfiguration
10
+
11
+ MAX_VERBOSITY_LEVEL = 3
12
+
13
+
14
+ @dataclass
15
+ class LogLevel:
16
+ """Log level metadata"""
17
+
18
+ name: LiteralString
19
+ colour: str
20
+
21
+
22
+ LOG_LEVELS: list[LogLevel] = [
23
+ LogLevel(name='ERROR', colour='red'),
24
+ LogLevel(name='WARNING', colour='yellow'),
25
+ LogLevel(name='INFO', colour='white'),
26
+ LogLevel(name='DEBUG', colour='bright_white'),
27
+ ]
28
+
29
+
30
+ class Configuration(BaseModel):
31
+ """Configuration object for the CLI"""
32
+
33
+ model_config = ConfigDict(arbitrary_types_allowed=True)
34
+
35
+ console: Console = Console()
36
+ local_configuration: LocalConfiguration = LocalConfiguration()
37
+ debug: bool = False
38
+ verbosity: int = 0
@@ -0,0 +1,5 @@
1
+ """Core package for Porringer.
2
+
3
+ This package contains the core schemas and base classes used throughout the Porringer application,
4
+ including plugin definitions and shared data models.
5
+ """
@@ -0,0 +1,5 @@
1
+ """Plugin schema package for Porringer.
2
+
3
+ This package contains the schema definitions and base classes for plugins,
4
+ including environment plugins and their parameters.
5
+ """