142 lines
4.3 KiB
Python
142 lines
4.3 KiB
Python
# This file is part of ssiv.
|
|
#
|
|
# ssiv is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# ssiv is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with ssiv. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
from io import BytesIO
|
|
from string import ascii_letters,digits
|
|
from struct import pack,unpack,calcsize
|
|
|
|
from .constants import progname
|
|
|
|
__all__=[
|
|
'str2bytes','bytes2str','packstr','unpackstr',
|
|
'prettybytes','prettypath','prettycolor','prettyrect',
|
|
'sorter_numeric',
|
|
]
|
|
|
|
_LENFMT='<Q'
|
|
_LENLEN=calcsize(_LENFMT)
|
|
|
|
_printable=tuple(ord(c) for c in f'{ascii_letters}{digits}')
|
|
_nums=f'{digits}.'
|
|
|
|
def str2bytes(s):
|
|
return s.encode('utf8') if isinstance(s,str) else s
|
|
|
|
def bytes2str(b):
|
|
return b.decode('utf8') if isinstance(b,bytes) else b
|
|
|
|
def _packbytes(data):
|
|
length=len(data)
|
|
return pack(f'{_LENFMT}{length}s',length,data)
|
|
|
|
def _unpackbytes(buf):
|
|
while head:=buf.read(_LENLEN):
|
|
try:
|
|
yield bytes2str(buf.read(unpack(_LENFMT,head)[0]))
|
|
except:
|
|
break
|
|
|
|
def packstr(*args):
|
|
return b''.join(_packbytes(str2bytes(s)) for s in args)
|
|
|
|
def unpackstr(data):
|
|
with BytesIO(data) as buf:
|
|
return tuple(_unpackbytes(buf))
|
|
|
|
def prettybytes(data):
|
|
return ''.join((chr(n) if n in _printable else f'\\x{n:02x}') for n in data)
|
|
|
|
def prettypath(container,filename):
|
|
return f'{filename}({container})' if container else f'{filename}'
|
|
|
|
def prettycolor(color):
|
|
return '#{}'.format(''.join(f'{c:02X}' for c in color))
|
|
|
|
def prettyrect(rect):
|
|
return '{2}x{3}+{0}+{1}'.format(*rect)
|
|
|
|
def sorter_numeric(s):
|
|
parts=s.split('/')
|
|
results=[]
|
|
b,_,e=parts[-1].rpartition('.')
|
|
if b and e.strip(_nums):
|
|
parts[-1:]=[b,e]
|
|
else:
|
|
parts.append('')
|
|
while parts[:-1]:
|
|
results.append([])
|
|
part=parts.pop(0)
|
|
while part.endswith('.'):
|
|
part=part[:-1]
|
|
parts[0]=f'.{parts[0]}'
|
|
while part:
|
|
try:
|
|
start=min(part.index(s) for s in digits if s in part)
|
|
except ValueError:
|
|
results[-1].append((part,0))
|
|
break
|
|
head,part=part[:start],part[start:]
|
|
if head:
|
|
results[-1].append((head,0))
|
|
tail=part.lstrip(_nums)
|
|
nstr,part=part[:len(part)-len(tail)],tail
|
|
while nstr.endswith('.'):
|
|
nstr=nstr[:-1]
|
|
part=f'.{part}'
|
|
results[-1].append(('',float(nstr)))
|
|
results[-1].append(('',0))
|
|
results.append([(parts.pop(),0)])
|
|
return results
|
|
|
|
def _logger_init():
|
|
from functools import partial
|
|
from os import environ
|
|
from . import logger
|
|
levels=dict(
|
|
# level = (bit, error, color)
|
|
fault = (1<<0, True, 'red'), # 1
|
|
error = (1<<1, True, 'orange'), # 2
|
|
warn = (1<<2, True, 'yellow'), # 4
|
|
note = (1<<3, False, 'green'), # 8
|
|
info = (1<<4, False, 'cyan'), # 16
|
|
verb = (1<<5, False, 'lightblue'), # 32
|
|
trace = (1<<6, False, 'blue'), # 64
|
|
pref = (1<<7, False, 'purple'), # 128
|
|
)
|
|
level=int(environ.get(f'{progname}_LOG_LEVEL',0))
|
|
devel=environ.get(f'{progname}_LOG_DEVEL',None) or None
|
|
for api in logger.__all__:
|
|
__all__.append(api)
|
|
globals()[api]=getattr(logger,api)
|
|
for key,(bit,error,color) in levels.items():
|
|
__all__.append(key)
|
|
globals()[key]=partial(logger.log,devel=devel is not None,
|
|
level=key,levelcolor=color,error=error) \
|
|
if (bit&level) else logger.true
|
|
if level&levels['pref'][0]:
|
|
globals()['Pref'].printer=globals()['pref']
|
|
globals()['Pref'].disabled=False
|
|
return True
|
|
|
|
assert _logger_init()
|
|
|
|
|
|
# Local Variables:
|
|
# coding: utf-8
|
|
# mode: python
|
|
# python-indent-offset: 4
|
|
# indent-tabs-mode: nil
|
|
# End:
|