Refactor output and call

Each action has its own output from now on.
This commit is contained in:
jpic 2020-02-15 01:04:41 +01:00
parent b703ed379e
commit 984f09d704
15 changed files with 124 additions and 120 deletions

View File

@ -8,3 +8,7 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://yourlabs.io/oss/shlax
rev: master
hooks:
- id: shlaxfile-gitlabci

View File

@ -1,5 +1,5 @@
- id: shlaxfile-gitlabci
name: Check for added large files
name: Regenerate .gitlab-ci.yml
description: Regenerate gitlabci
entry: ./shlaxfile.py gitlabci
entry: pip install -e . && ./shlaxfile.py gitlabci
language: python

View File

@ -1,6 +1,6 @@
from .actions import *
from .image import Image
from .strategies import *
from .proc import output, Proc
from .proc import Proc
from .targets import *
from .shlaxfile import Shlaxfile

View File

@ -1,6 +1,9 @@
import inspect
import sys
from ..output import Output
from ..exceptions import WrongResult
class Action:
parent = None
@ -76,6 +79,22 @@ class Action:
return getattr(a, name)
raise AttributeError(name)
async def __call__(self, *args, **kwargs):
print(f'{self}.__call__(*args, **kwargs) not implemented')
async def call(self, *args, **kwargs):
print(f'{self}.call(*args, **kwargs) not implemented')
sys.exit(1)
def output_factory(self, *args, **kwargs):
return Output(*args, kwargs)
async def __call__(self, *args, **kwargs):
self.status = 'running'
self.output = self.output_factory(*args, **kwargs)
try:
result = await self.call(*args, **kwargs)
except WrongResult as e:
print(e)
self.status = 'fail'
else:
if self.status == 'running':
self.status = 'success'
return result

View File

@ -50,7 +50,7 @@ class Commit(Action):
if not self.tags:
self.tags = ['latest']
async def __call__(self, *args, ctr=None, **kwargs):
async def call(self, *args, ctr=None, **kwargs):
self.sha = (await self.parent.parent.exec(
'buildah',
'commit',

View File

@ -104,7 +104,7 @@ class Packages(Action):
print(f'{self.container.name} | Waiting for update ...')
await asyncio.sleep(1)
async def __call__(self, *args, **kwargs):
async def call(self, *args, **kwargs):
cached = getattr(self, '_pagkages_mgr', None)
if cached:
self.mgr = cached

View File

@ -2,5 +2,5 @@ from .base import Action
class Run(Action):
async def __call__(self, *args, **kwargs):
async def call(self, *args, **kwargs):
return (await self.exec(*self.args, **self.kwargs))

View File

@ -9,7 +9,7 @@ class Service(Action):
self.names = names
super().__init__()
async def __call__(self, *args, **kwargs):
async def call(self, *args, **kwargs):
return asyncio.gather(*[
self.exec('systemctl', 'start', name, user='root')
for name in self.names

View File

@ -112,7 +112,7 @@ async def test(*args, **kwargs):
class ConsoleScript(cli2.ConsoleScript):
def __call__(self, *args, **kwargs):
def call(self, *args, **kwargs):
self.shlaxfile = None
shlaxfile = sys.argv.pop(1) if len(sys.argv) > 1 else ''
if os.path.exists(shlaxfile.split('::')[0]):

View File

@ -4,7 +4,7 @@ from shlax import *
class GitLabCIConfig(Script):
async def __call__(self, *args, write=True, **kwargs):
async def call(self, *args, write=True, **kwargs):
await super().__call__(*args, **kwargs)
self.kwargs = kwargs
for name, definition in self.context.items():
@ -17,5 +17,5 @@ class GitLabCIConfig(Script):
class Job(Action):
async def __call__(self, *args, **kwargs):
async def call(self, *args, **kwargs):
self.context[self.args[0]] = self.kwargs

76
shlax/output.py Normal file
View File

@ -0,0 +1,76 @@
class Output:
colors = (
'\x1b[1;36;45m',
'\x1b[1;36;41m',
'\x1b[1;36;40m',
'\x1b[1;37;45m',
'\x1b[1;32m',
'\x1b[1;37;44m',
)
def __init__(self, prefix=None):
self.prefix = prefix
self.prefixes = dict()
self.prefix_length = 0
def call(self, line, prefix, highlight=True, flush=True):
if prefix and prefix not in self.prefixes:
self.prefixes[prefix] = (
self.colors[len([*self.prefixes.keys()]) - 1]
)
if len(prefix) > self.prefix_length:
self.prefix_length = len(prefix)
prefix_color = self.prefixes[prefix] if prefix else ''
prefix_padding = '.' * (self.prefix_length - len(prefix) - 2) if prefix else ''
if prefix_padding:
prefix_padding = ' ' + prefix_padding + ' '
sys.stdout.buffer.write((
(
prefix_color
+ prefix_padding
+ prefix
+ ' '
+ Back.RESET
+ Style.RESET_ALL
+ Fore.LIGHTBLACK_EX
+ '| '
+ Style.RESET_ALL
if prefix
else ''
)
+ self.highlight(line, highlight)
).encode('utf8'))
if flush:
sys.stdout.flush()
def cmd(self, line, prefix):
self(
Fore.LIGHTBLACK_EX
+ '+ '
+ Style.RESET_ALL
+ self.highlight(line, 'bash'),
prefix,
highlight=False
)
def print(self, content):
self(
content,
prefix=None,
highlight=False
)
def highlight(self, line, highlight=True):
line = line.decode('utf8') if isinstance(line, bytes) else line
if not highlight or (
'\x1b[' in line
or '\033[' in line
or '\\e[' in line
):
return line
return line

View File

@ -3,99 +3,12 @@ Asynchronous process execution wrapper.
"""
import asyncio
from colorama import Fore, Back, Style
import os
import shlex
import sys
from .exceptions import WrongResult
import pygments
from pygments import lexers
from pygments.formatters import TerminalFormatter
from pygments.formatters import Terminal256Formatter
class Output:
colors = (
'\x1b[1;36;45m',
'\x1b[1;36;41m',
'\x1b[1;36;40m',
'\x1b[1;37;45m',
'\x1b[1;32m',
'\x1b[1;37;44m',
)
def __init__(self):
self.prefixes = dict()
self.prefix_length = 0
def __call__(self, line, prefix, highlight=True, flush=True):
if prefix and prefix not in self.prefixes:
self.prefixes[prefix] = (
self.colors[len([*self.prefixes.keys()]) - 1]
)
if len(prefix) > self.prefix_length:
self.prefix_length = len(prefix)
prefix_color = self.prefixes[prefix] if prefix else ''
prefix_padding = '.' * (self.prefix_length - len(prefix) - 2) if prefix else ''
if prefix_padding:
prefix_padding = ' ' + prefix_padding + ' '
sys.stdout.buffer.write((
(
prefix_color
+ prefix_padding
+ prefix
+ ' '
+ Back.RESET
+ Style.RESET_ALL
+ Fore.LIGHTBLACK_EX
+ '| '
+ Style.RESET_ALL
if prefix
else ''
)
+ self.highlight(line, highlight)
).encode('utf8'))
if flush:
sys.stdout.flush()
def cmd(self, line, prefix):
self(
Fore.LIGHTBLACK_EX
+ '+ '
+ Style.RESET_ALL
+ self.highlight(line, 'bash'),
prefix,
highlight=False
)
def print(self, content):
self(
content,
prefix=None,
highlight=False
)
def highlight(self, line, highlight=True):
line = line.decode('utf8') if isinstance(line, bytes) else line
if not highlight or (
'\x1b[' in line
or '\033[' in line
or '\\e[' in line
):
return line
elif isinstance(highlight, str):
lexer = lexers.get_lexer_by_name(highlight)
else:
lexer = lexers.get_lexer_by_name('python')
formatter = Terminal256Formatter(
style=os.getenv('PODCTL_STYLE', 'fruity'))
return pygments.highlight(line, lexer, formatter)
output = Output()
from .output import Output
class PrefixStreamProtocol(asyncio.subprocess.SubprocessStreamProtocol):
@ -104,14 +17,13 @@ class PrefixStreamProtocol(asyncio.subprocess.SubprocessStreamProtocol):
make asynchronous output readable.
"""
def __init__(self, prefix, *args, **kwargs):
self.debug = kwargs.get('debug', True)
self.prefix = prefix
def __init__(self, output, *args, **kwargs):
self.output = output
super().__init__(*args, **kwargs)
def pipe_data_received(self, fd, data):
if (self.debug is True or 'out' in str(self.debug)) and fd in (1, 2):
output(data, self.prefix, flush=False)
self.output(data, flush=False)
sys.stdout.flush()
super().pipe_data_received(fd, data)
@ -142,8 +54,9 @@ class Proc:
"""
test = False
def __init__(self, *args, prefix=None, raises=True, debug=True):
def __init__(self, *args, prefix=None, raises=True, debug=True, output=None):
self.debug = debug if not self.test else False
self.output = output or Output()
self.cmd = ' '.join(args)
self.args = args
self.prefix = prefix

View File

@ -4,7 +4,7 @@ from .script import Script
class Async(Script):
async def __call__(self, *args, **kwargs):
async def call(self, *args, **kwargs):
return asyncio.gather(*[
procs.append(action(*args, **kwargs))
for action in self.actions

View File

@ -27,17 +27,9 @@ class Script(Action):
super().__init__(**kwargs)
self.actions = Actions(self, actions)
async def __call__(self, *args, **kwargs):
async def call(self, *args, **kwargs):
for action in self.actions:
try:
await action(*args, **kwargs)
except WrongResult as e:
print(e)
action.status = 'fail'
break
else:
if action.status == 'running':
action.status = 'success'
await action(*args, **kwargs)
def shargs(self, *args, **kwargs):
user = kwargs.pop('user', None)

View File

@ -8,7 +8,7 @@ import subprocess
import sys
import textwrap
from ..proc import Proc, output
from ..proc import Proc
from ..image import Image
from .localhost import Localhost
@ -88,12 +88,12 @@ class Buildah(Localhost):
def __repr__(self):
return f'Build'
async def __call__(self, *args, debug=False, **kwargs):
async def call(self, *args, debug=False, **kwargs):
if Proc.test or os.getuid() == 0 or self.parent.parent:
self.ctr = (await self.exec('buildah', 'from', self.base, buildah=False)).out
self.mnt = Path((await self.exec('buildah', 'mount', self.ctr, buildah=False)).out)
result = await super().__call__(*args, **kwargs)
result = await super().call(*args, **kwargs)
#await self.umounts()
#await self.umount()
await self.exec('buildah', 'rm', self.ctr, raises=False, buildah=False)
@ -113,7 +113,7 @@ class Buildah(Localhost):
cli.shlaxfile.path,
cli.parser.command.name, # script name ?
]
output(' '.join(argv), 'EXECUTION', flush=True)
self.output(' '.join(argv), 'EXECUTION', flush=True)
proc = await asyncio.create_subprocess_shell(
shlex.join(argv),