emcd-projects 1.14__py3-none-any.whl

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.
emcdproj/__/imports.py ADDED
@@ -0,0 +1,60 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Common imports and type aliases used throughout the package. '''
22
+
23
+ # pylint: disable=unused-import
24
+ # ruff: noqa: F401
25
+
26
+
27
+ from __future__ import annotations
28
+
29
+ import abc
30
+ import collections.abc as cabc
31
+ import contextlib as ctxl
32
+ import json
33
+ import math
34
+ import os
35
+ import shutil
36
+ import types
37
+
38
+ from pathlib import Path
39
+
40
+ import typing_extensions as typx
41
+ # --- BEGIN: Injected by Copier ---
42
+ import tyro
43
+ # --- END: Injected by Copier ---
44
+
45
+ from absence import Absential, absent, is_absent
46
+ from frigid.qaliases import (
47
+ ImmutableClass,
48
+ ImmutableDataclass,
49
+ ImmutableProtocolDataclass,
50
+ immutable,
51
+ )
52
+ from platformdirs import PlatformDirs
53
+
54
+
55
+ ComparisonResult: typx.TypeAlias = bool | types.NotImplementedType
56
+
57
+
58
+ package_name = __name__.split( '.', maxsplit = 1 )[ 0 ]
59
+ simple_tyro_class = tyro.conf.configure( )
60
+ standard_tyro_class = tyro.conf.configure( tyro.conf.OmitArgPrefixes )
@@ -0,0 +1,83 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Preparation of the library core. '''
22
+
23
+
24
+ from . import imports as __
25
+ from . import application as _application
26
+ # from . import configuration as _configuration
27
+ # from . import dictedits as _dictedits
28
+ from . import distribution as _distribution
29
+ # from . import environment as _environment
30
+ from . import state as _state
31
+
32
+
33
+ async def prepare( # pylint: disable=too-many-arguments,too-many-locals
34
+ exits: __.ctxl.AsyncExitStack,
35
+ application: _application.Information = _application.Information( ),
36
+ # configedits: _dictedits.Edits = ( ),
37
+ # configfile: __.Absential[ __.Path ] = __.absent,
38
+ # environment: bool = False,
39
+ ) -> _state.Globals:
40
+ ''' Prepares globals DTO for use with library functions.
41
+
42
+ Also:
43
+ * Configures logging for library package (not application).
44
+ * Optionally, loads process environment from files.
45
+
46
+ Note that asynchronous preparation allows for applications to
47
+ concurrently initialize other entities outside of the library, even
48
+ though the library initialization, itself, is inherently sequential.
49
+ '''
50
+ directories = application.produce_platform_directories( )
51
+ distribution = (
52
+ await _distribution.Information.prepare(
53
+ package = __.package_name, exits = exits ) )
54
+ # configuration = (
55
+ # await _configuration.acquire(
56
+ # application_name = application.name,
57
+ # directories = directories,
58
+ # distribution = distribution,
59
+ # edits = configedits,
60
+ # file = configfile ) )
61
+ auxdata = _state.Globals(
62
+ application = application,
63
+ # configuration = configuration,
64
+ directories = directories,
65
+ distribution = distribution,
66
+ exits = exits )
67
+ # if environment: await _environment.update( auxdata )
68
+ # _inscribe_preparation_report( auxdata )
69
+ return auxdata
70
+
71
+
72
+ # def _inscribe_preparation_report( auxdata: _state.Globals ):
73
+ # scribe = __.produce_scribe( __.package_name )
74
+ # scribe.debug( f"Application Name: {auxdata.application.name}" )
75
+ # # scribe.debug( f"Execution ID: {auxdata.application.execution_id}" )
76
+ # scribe.debug( "Application Cache Location: {}".format(
77
+ # auxdata.provide_cache_location( ) ) )
78
+ # scribe.debug( "Application Data Location: {}".format(
79
+ # auxdata.provide_data_location( ) ) )
80
+ # scribe.debug( "Application State Location: {}".format(
81
+ # auxdata.provide_state_location( ) ) )
82
+ # scribe.debug( "Package Data Location: {}".format(
83
+ # auxdata.distribution.provide_data_location( ) ) )
emcdproj/__/state.py ADDED
@@ -0,0 +1,80 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Immutable global state. '''
22
+
23
+
24
+ from . import imports as __
25
+ from . import application as _application
26
+ from . import distribution as _distribution
27
+
28
+
29
+ # class DirectorySpecies( __.enum.Enum ): # TODO: Python 3.11: StrEnum
30
+ # ''' Possible species for locations. '''
31
+ #
32
+ # Cache = 'cache'
33
+ # Data = 'data'
34
+ # State = 'state'
35
+
36
+
37
+ class Globals( metaclass = __.ImmutableDataclass ):
38
+ ''' Immutable global data. Required by some library functions. '''
39
+
40
+ application: _application.Information
41
+ # configuration: __.AccretiveDictionary[ str, __.typx.Any ]
42
+ directories: __.PlatformDirs
43
+ distribution: _distribution.Information
44
+ exits: __.ctxl.AsyncExitStack
45
+
46
+ def as_dictionary( self ) -> __.cabc.Mapping[ str, __.typx.Any ]:
47
+ ''' Returns shallow copy of state. '''
48
+ from dataclasses import fields
49
+ return {
50
+ field.name: getattr( self, field.name )
51
+ for field in fields( self ) }
52
+
53
+ # def provide_cache_location( self, *appendages: str ) -> __.Path:
54
+ # ''' Provides cache location from configuration. '''
55
+ # return self.provide_location( DirectorySpecies.Cache, *appendages )
56
+
57
+ # def provide_data_location( self, *appendages: str ) -> __.Path:
58
+ # ''' Provides data location from configuration. '''
59
+ # return self.provide_location( DirectorySpecies.Data, *appendages )
60
+
61
+ # def provide_state_location( self, *appendages: str ) -> __.Path:
62
+ # ''' Provides state location from configuration. '''
63
+ # return self.provide_location( DirectorySpecies.State, *appendages )
64
+
65
+ # def provide_location(
66
+ # self, species: DirectorySpecies, *appendages: str
67
+ # ) -> __.Path:
68
+ # ''' Provides particular species of location from configuration. '''
69
+ # species_name = species.value
70
+ # base = getattr( self.directories, f"user_{species_name}_path" )
71
+ # spec = self.configuration.get( 'locations', { } ).get( species_name )
72
+ # if spec:
73
+ # args: dict[ str, str | __.Path ] = {
74
+ # f"user_{species_name}": base,
75
+ # 'user_home': __.Path.home( ),
76
+ # 'application_name': self.application.name,
77
+ # }
78
+ # base = __.Path( spec.format( **args ) )
79
+ # if appendages: return base.joinpath( *appendages )
80
+ # return base
emcdproj/__init__.py ADDED
@@ -0,0 +1,39 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Project management utilities. '''
22
+
23
+
24
+ from . import __
25
+ # --- BEGIN: Injected by Copier ---
26
+ from . import exceptions
27
+ # --- END: Injected by Copier ---
28
+
29
+
30
+ __version__ = '1.14'
31
+
32
+
33
+ def main( ):
34
+ ''' Entrypoint. '''
35
+ from .cli import execute
36
+ execute( )
37
+
38
+
39
+ # TODO: Reclassify package modules as immutable and concealed.
emcdproj/__main__.py ADDED
@@ -0,0 +1,28 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Entrypoint. '''
22
+
23
+
24
+ # Note: Use absolute import for PyInstaller happiness.
25
+ from emcdproj.cli import execute
26
+
27
+
28
+ if '__main__' == __name__: execute( )
@@ -0,0 +1,7 @@
1
+ ''' Stubs for additional "builtin" types. '''
2
+
3
+ # https://github.com/microsoft/pyright/blob/main/docs/builtins.md
4
+
5
+ from ictruck import Truck
6
+
7
+ ictr: Truck
emcdproj/cli.py ADDED
@@ -0,0 +1,115 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Command-line interface. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+ from . import interfaces as _interfaces
28
+ from . import website as _website
29
+
30
+
31
+ class VersionCommand(
32
+ _interfaces.CliCommand,
33
+ decorators = ( __.standard_tyro_class, ),
34
+ ):
35
+ ''' Prints version information. '''
36
+
37
+ async def __call__( self, auxdata: __.Globals ) -> None:
38
+ from . import __version__ # pylint: disable=cyclic-import
39
+ print( f"{__package__} {__version__}" )
40
+ raise SystemExit( 0 )
41
+
42
+
43
+ class Cli(
44
+ metaclass = __.ImmutableDataclass,
45
+ decorators = ( __.simple_tyro_class, ),
46
+ ):
47
+ ''' Various utilities for projects by Github user '@emcd'. '''
48
+
49
+ application: __.ApplicationInformation
50
+ # configfile: __.typx.Optional[ str ] = None
51
+ # display: ConsoleDisplay
52
+ command: __.typx.Union[
53
+ __.typx.Annotated[
54
+ _website.CommandDispatcher,
55
+ __.tyro.conf.subcommand( 'website', prefix_name = False ),
56
+ ],
57
+ __.typx.Annotated[
58
+ VersionCommand,
59
+ __.tyro.conf.subcommand( 'version', prefix_name = False ),
60
+ ],
61
+ ]
62
+
63
+ async def __call__( self ):
64
+ ''' Invokes command after library preparation. '''
65
+ nomargs = self.prepare_invocation_args( )
66
+ async with __.ctxl.AsyncExitStack( ) as exits:
67
+ auxdata = await _prepare( exits = exits, **nomargs )
68
+ ictr( 0 )( self.command )
69
+ await self.command( auxdata = auxdata )
70
+ # await self.command( auxdata = auxdata, display = self.display )
71
+
72
+ def prepare_invocation_args(
73
+ self,
74
+ ) -> __.cabc.Mapping[ str, __.typx.Any ]:
75
+ ''' Prepares arguments for initial configuration. '''
76
+ # configedits: __.DictionaryEdits = (
77
+ # self.command.provide_configuration_edits( ) )
78
+ args: dict[ str, __.typx.Any ] = dict(
79
+ application = self.application,
80
+ # configedits = configedits,
81
+ # environment = True,
82
+ )
83
+ # if self.configfile: args[ 'configfile' ] = self.configfile
84
+ return args
85
+
86
+
87
+ def execute( ) -> None:
88
+ ''' Entrypoint for CLI execution. '''
89
+ from asyncio import run
90
+ config = (
91
+ __.tyro.conf.HelptextFromCommentsOff,
92
+ )
93
+ try: run( __.tyro.cli( Cli, config = config )( ) )
94
+ except SystemExit: raise
95
+ except BaseException:
96
+ # TODO: Log exception.
97
+ raise SystemExit( 1 ) from None
98
+
99
+
100
+ async def _prepare(
101
+ application: __.ApplicationInformation,
102
+ # configedits: __.DictionaryEdits,
103
+ # environment: bool,
104
+ exits: __.ctxl.AsyncExitStack,
105
+ ) -> __.Globals:
106
+ ''' Configures logging based on verbosity. '''
107
+ import ictruck
108
+ # TODO: Finetune Icecream truck installation from CLI arguments.
109
+ ictruck.install( trace_levels = 9 )
110
+ auxdata = await __.prepare(
111
+ application = application,
112
+ # configedits = configedits,
113
+ # environment = environment,
114
+ exits = exits )
115
+ return auxdata
File without changes
@@ -0,0 +1,35 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg"
2
+ width="{{ total_width }}" height="20"
3
+ role="img" aria-label="{{ label_text }}: {{ value_text }}"
4
+ >
5
+ <title>{{ label_text }}: {{ value_text }}</title>
6
+ <linearGradient id="s" x2="0" y2="100%">
7
+ <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
8
+ <stop offset="1" stop-opacity=".1"/>
9
+ </linearGradient>
10
+ <clipPath id="r">
11
+ <rect width="{{ total_width }}" height="20" rx="3" fill="#fff"/>
12
+ </clipPath>
13
+ <g clip-path="url(#r)">
14
+ <rect width="{{ label_width }}" height="20" fill="#555"/>
15
+ <rect x="{{ label_width }}" width="{{ value_width }}" height="20" fill="{{ color }}"/>
16
+ <rect width="{{ total_width }}" height="20" fill="url(#s)"/>
17
+ </g>
18
+ <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
19
+ <text aria-hidden="true"
20
+ x="{{ label_width / 2 * 10 }}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)"
21
+ >
22
+ {{ label_text }}
23
+ </text>
24
+ <text x="{{ label_width / 2 * 10 }}" y="140" transform="scale(.1)" fill="#fff">{{ label_text }}</text>
25
+ <text aria-hidden="true"
26
+ x="{{ label_width * 10 + value_width / 2 * 10 }}" y="150"
27
+ fill="#010101" fill-opacity=".3" transform="scale(.1)"
28
+ >
29
+ {{ value_text }}
30
+ </text>
31
+ <text x="{{ label_width * 10 + value_width / 2 * 10 }}" y="140" transform="scale(.1)" fill="#fff">
32
+ {{ value_text }}
33
+ </text>
34
+ </g>
35
+ </svg>
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Available Releases</title>
7
+ <style>
8
+ table {
9
+ width: 100%;
10
+ border-collapse: collapse;
11
+ }
12
+ th, td {
13
+ padding: 8px;
14
+ text-align: left;
15
+ border-bottom: 1px solid #ddd;
16
+ }
17
+ th {
18
+ background-color: #f2f2f2;
19
+ }
20
+ tr:hover {
21
+ background-color: #f5f5f5;
22
+ }
23
+ </style>
24
+ </head>
25
+ <body>
26
+ <h1>Available Releases</h1>
27
+ <table>
28
+ <thead>
29
+ <tr>
30
+ <th>Version</th>
31
+ <th>Documentation</th>
32
+ <th>Coverage</th>
33
+ </tr>
34
+ </thead>
35
+ <tbody>
36
+ {% for version, attributes in versions.items() %}
37
+ <tr>
38
+ <td>{{ version }}</td>
39
+ <td>
40
+ {% if 'sphinx-html' in attributes %}
41
+ <a href="{{ version }}/sphinx-html/index.html">Docs</a>
42
+ {% else %}
43
+ N/A
44
+ {% endif %}
45
+ </td>
46
+ <td>
47
+ {% if 'coverage-pytest' in attributes %}
48
+ <a href="{{ version }}/coverage-pytest/index.html">Coverage</a>
49
+ {% else %}
50
+ N/A
51
+ {% endif %}
52
+ </td>
53
+ </tr>
54
+ {% endfor %}
55
+ </tbody>
56
+ </table>
57
+ </body>
58
+ </html>
emcdproj/exceptions.py ADDED
@@ -0,0 +1,69 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Family of exceptions for package API. '''
22
+
23
+
24
+ from . import __
25
+
26
+
27
+ class Omniexception(
28
+ BaseException,
29
+ metaclass = __.ImmutableClass,
30
+ decorators = ( __.immutable, ),
31
+ ):
32
+ ''' Base for all exceptions raised by package API. '''
33
+ # TODO: Class and instance attribute concealment.
34
+
35
+ _attribute_visibility_includes_: __.cabc.Collection[ str ] = (
36
+ frozenset( ( '__cause__', '__context__', ) ) )
37
+
38
+
39
+ class Omnierror( Omniexception, Exception ):
40
+ ''' Base for error exceptions raised by package API. '''
41
+
42
+
43
+ class DataAwol( Omnierror, AssertionError ):
44
+ ''' Unexpected data absence. '''
45
+
46
+ def __init__( self, source: str, label: str ):
47
+ super( ).__init__(
48
+ f"Necessary data with label '{label}' is missing from {source}." )
49
+
50
+
51
+ class FileDataAwol( DataAwol ):
52
+ ''' Unexpected data absence from file. '''
53
+
54
+ def __init__( self, file: str | __.Path, label: str ):
55
+ super( ).__init__( source = f"file '{file}'", label = label )
56
+
57
+
58
+ class FileAwol( Omnierror, AssertionError ):
59
+ ''' Unexpected file absence. '''
60
+
61
+ def __init__( self, file: str | __.Path ):
62
+ super( ).__init__( f"Necessary file is missing at '{file}'." )
63
+
64
+
65
+ class FileEmpty( Omnierror, AssertionError ):
66
+ ''' Unexpectedly empty file. '''
67
+
68
+ def __init__( self, file: str| __.Path ):
69
+ super( ).__init__( f"Unexpectedly empty file at '{file}'." )
emcdproj/filesystem.py ADDED
@@ -0,0 +1,39 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Filesystem operations and utilities. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+
28
+
29
+ @__.ctxl.contextmanager
30
+ def chdir( directory: __.Path ) -> __.cabc.Iterator[ __.Path ]:
31
+ ''' Temporarily changes working directory.
32
+
33
+ Not thread-safe or async-safe.
34
+ '''
35
+ # TODO: Python 3.11: contextlib.chdir
36
+ original = __.os.getcwd( )
37
+ __.os.chdir( directory )
38
+ try: yield directory
39
+ finally: __.os.chdir( original )
emcdproj/interfaces.py ADDED
@@ -0,0 +1,41 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Abstract bases and interfaces. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+
28
+
29
+ class CliCommand( # pylint: disable=invalid-metaclass
30
+ __.typx.Protocol,
31
+ metaclass = __.ImmutableProtocolDataclass,
32
+ decorators = ( __.typx.runtime_checkable, ),
33
+ ):
34
+ ''' CLI command. '''
35
+
36
+ @__.abc.abstractmethod
37
+ async def __call__( self, auxdata: __.Globals ) -> None:
38
+ ''' Executes command with global state. '''
39
+ raise NotImplementedError
40
+
41
+ # TODO: provide_configuration_edits
emcdproj/py.typed ADDED
File without changes