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: end-of-file-fixer
- id: check-yaml - id: check-yaml
- id: check-added-large-files - 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 - id: shlaxfile-gitlabci
name: Check for added large files name: Regenerate .gitlab-ci.yml
description: Regenerate gitlabci description: Regenerate gitlabci
entry: ./shlaxfile.py gitlabci entry: pip install -e . && ./shlaxfile.py gitlabci
language: python language: python

View File

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

View File

@ -1,6 +1,9 @@
import inspect import inspect
import sys import sys
from ..output import Output
from ..exceptions import WrongResult
class Action: class Action:
parent = None parent = None
@ -76,6 +79,22 @@ class Action:
return getattr(a, name) return getattr(a, name)
raise AttributeError(name) raise AttributeError(name)
async def __call__(self, *args, **kwargs): async def call(self, *args, **kwargs):
print(f'{self}.__call__(*args, **kwargs) not implemented') print(f'{self}.call(*args, **kwargs) not implemented')
sys.exit(1) 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: if not self.tags:
self.tags = ['latest'] 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( self.sha = (await self.parent.parent.exec(
'buildah', 'buildah',
'commit', 'commit',

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@ from shlax import *
class GitLabCIConfig(Script): class GitLabCIConfig(Script):
async def __call__(self, *args, write=True, **kwargs): async def call(self, *args, write=True, **kwargs):
await super().__call__(*args, **kwargs) await super().__call__(*args, **kwargs)
self.kwargs = kwargs self.kwargs = kwargs
for name, definition in self.context.items(): for name, definition in self.context.items():
@ -17,5 +17,5 @@ class GitLabCIConfig(Script):
class Job(Action): class Job(Action):
async def __call__(self, *args, **kwargs): async def call(self, *args, **kwargs):
self.context[self.args[0]] = self.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 import asyncio
from colorama import Fore, Back, Style
import os import os
import shlex import shlex
import sys import sys
from .exceptions import WrongResult from .exceptions import WrongResult
import pygments from .output import Output
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()
class PrefixStreamProtocol(asyncio.subprocess.SubprocessStreamProtocol): class PrefixStreamProtocol(asyncio.subprocess.SubprocessStreamProtocol):
@ -104,14 +17,13 @@ class PrefixStreamProtocol(asyncio.subprocess.SubprocessStreamProtocol):
make asynchronous output readable. make asynchronous output readable.
""" """
def __init__(self, prefix, *args, **kwargs): def __init__(self, output, *args, **kwargs):
self.debug = kwargs.get('debug', True) self.output = output
self.prefix = prefix
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def pipe_data_received(self, fd, data): def pipe_data_received(self, fd, data):
if (self.debug is True or 'out' in str(self.debug)) and fd in (1, 2): 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() sys.stdout.flush()
super().pipe_data_received(fd, data) super().pipe_data_received(fd, data)
@ -142,8 +54,9 @@ class Proc:
""" """
test = False 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.debug = debug if not self.test else False
self.output = output or Output()
self.cmd = ' '.join(args) self.cmd = ' '.join(args)
self.args = args self.args = args
self.prefix = prefix self.prefix = prefix

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import subprocess
import sys import sys
import textwrap import textwrap
from ..proc import Proc, output from ..proc import Proc
from ..image import Image from ..image import Image
from .localhost import Localhost from .localhost import Localhost
@ -88,12 +88,12 @@ class Buildah(Localhost):
def __repr__(self): def __repr__(self):
return f'Build' 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: if Proc.test or os.getuid() == 0 or self.parent.parent:
self.ctr = (await self.exec('buildah', 'from', self.base, buildah=False)).out 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) 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.umounts()
#await self.umount() #await self.umount()
await self.exec('buildah', 'rm', self.ctr, raises=False, buildah=False) await self.exec('buildah', 'rm', self.ctr, raises=False, buildah=False)
@ -113,7 +113,7 @@ class Buildah(Localhost):
cli.shlaxfile.path, cli.shlaxfile.path,
cli.parser.command.name, # script name ? 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( proc = await asyncio.create_subprocess_shell(
shlex.join(argv), shlex.join(argv),