amend displaying step and task + compat project imprastorage
This commit is contained in:
parent
23741be148
commit
14b5e9fab4
|
@ -126,19 +126,10 @@ class Cli(AbstractCli):
|
|||
Sys.g.LOG_QUEUE.put(Sys.g.SIGNAL_STOP)
|
||||
|
||||
else :
|
||||
self.parser.error_cmd((('unknow command ',(a[0],Sys.Clz.fgb3)),))
|
||||
self.parser.error_cmd((('unknow command ',(a[0],Sys.Clz.fgb3)),), True)
|
||||
|
||||
if not o.quiet : Sys.dprint()
|
||||
|
||||
#~
|
||||
#~ @staticmethod
|
||||
#~ def error_cmd(data):
|
||||
#~ """"""
|
||||
#~ Cli.print_usage('')
|
||||
#~ Sys.dprint()
|
||||
#~ Sys.pwarn(data, True)
|
||||
#~ Cli.exit(1)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def print_usage(data, withoutHeader=False):
|
||||
|
|
|
@ -87,9 +87,7 @@ class CliApp:
|
|||
if self.o.outputfile is None :
|
||||
self.o.outputfile = Sys.basename(self.a[1])
|
||||
if self.o.outputfile[-len(Kirmah.EXT):] != Kirmah.EXT :
|
||||
print(self.o.outputfile[-len(Kirmah.EXT):])
|
||||
self.o.outputfile += Kirmah.EXT
|
||||
print(self.o.outputfile)
|
||||
|
||||
d = self.getDefaultOption((self.o.compress,self.o.fullcompress,self.o.nocompress))
|
||||
compress = (KirmahHeader.COMP_END if d == 0 or (d is None and Io.is_binary(self.a[1])) else (KirmahHeader.COMP_ALL if d==1 or d is None else KirmahHeader.COMP_NONE))
|
||||
|
|
|
@ -48,7 +48,7 @@ PRG_LICENSE = 'GNU GPL v3'
|
|||
PRG_RESOURCES_PATH = '/usr/share/'+PRG_PACKAGE+sep
|
||||
if not isdir(PRG_RESOURCES_PATH):
|
||||
PRG_RESOURCES_PATH = dirname(dirname(realpath(__file__)))+sep+'resources'+sep+PRG_PACKAGE+sep
|
||||
print(PRG_RESOURCES_PATH)
|
||||
#~ print(PRG_RESOURCES_PATH)
|
||||
PRG_GLADE_PATH = PRG_RESOURCES_PATH+'glade'+sep+PRG_PACKAGE+'.glade'
|
||||
PRG_LICENSE_PATH = PRG_RESOURCES_PATH+'/LICENSE'
|
||||
PRG_LOGO_PATH = join(PRG_RESOURCES_PATH,'..'+sep,'pixmaps'+sep,PRG_PACKAGE+sep,PRG_PACKAGE+'.png')
|
||||
|
|
|
@ -63,7 +63,7 @@ def hash_sha256_file(path):
|
|||
return sha256(open(path, mode='rb').read()).hexdigest()
|
||||
|
||||
|
||||
@Log()
|
||||
@Log(Const.LOG_ALL)
|
||||
def hash_md5_file(path):
|
||||
"""Get a md5 hash of file from path
|
||||
:Returns: `str`
|
||||
|
@ -104,7 +104,7 @@ class KeyGen :
|
|||
""""""
|
||||
|
||||
@Log(Const.LOG_BUILD)
|
||||
def __init__(self, length, salt=None):
|
||||
def __init__(self, length=1024, salt=None):
|
||||
""""""
|
||||
self.new(length, salt)
|
||||
|
||||
|
@ -613,8 +613,7 @@ class Kirmah:
|
|||
@Log()
|
||||
def split(self, fromPath, hlst):
|
||||
""""""
|
||||
if not Sys.is_cli_cancel():
|
||||
self.DIR_OUTBOX = ''
|
||||
if not Sys.is_cli_cancel():
|
||||
f = open(fromPath, 'rb+')
|
||||
m, p, rsz = mmap(f.fileno(), 0), 0, 0
|
||||
fsize = Sys.getsize(fromPath)
|
||||
|
@ -766,11 +765,11 @@ class Kirmah:
|
|||
d = Sys.datetime.now()
|
||||
if compstart :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Compressing data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Compressing data')
|
||||
self.compress_start(fp, tp, compstart, emit=emit)
|
||||
if compstart :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Compression mode', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
|
||||
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
|
||||
if emit : Sys.cli_emit_progress(5)
|
||||
return fp, tp, decHeader['rmode'], decHeader['mmode'], compend
|
||||
|
@ -783,14 +782,14 @@ class Kirmah:
|
|||
if rmode :
|
||||
#~ self.mpRandomFileContent(fp, tp, 4)
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Randomizing data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Randomizing data')
|
||||
self.randomFileContent(fp, tp, emit=emit)
|
||||
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
|
||||
if emit : Sys.cli_emit_progress(75)
|
||||
|
||||
if mmode :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Mixing data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Mixing data')
|
||||
self.mixdata(fp, tp, True, emit=emit)
|
||||
|
||||
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
|
||||
|
@ -799,17 +798,17 @@ class Kirmah:
|
|||
if compend :
|
||||
d = Sys.datetime.now()
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Compressing data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Compressing data')
|
||||
self.compress_end(fp, toPath, compend, emit=emit)
|
||||
if emit : Sys.cli_emit_progress(95)
|
||||
|
||||
if compend :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Compression mode', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
|
||||
|
||||
# clean tmp files
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Cleaning')
|
||||
if not Sys.g.QUIET : Sys.ptask('Cleaning')
|
||||
|
||||
try :
|
||||
Sys.removeFile(self.tmpPath1)
|
||||
|
@ -850,21 +849,21 @@ class Kirmah:
|
|||
def encrypt_mproc(self, fp, tp, nproc=1, emit=True):
|
||||
""""""
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Encrypting data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Encrypting data')
|
||||
d = Sys.datetime.now()
|
||||
c = not Sys.is_cli_cancel()
|
||||
if c:
|
||||
if nproc == 1 :
|
||||
self.encryptToFile(fp, tp)
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Encrypt data', d, c)
|
||||
if not Sys.g.QUIET : Sys.pstep('Encrypt data', d, c)
|
||||
else :
|
||||
hlstPaths = self.prepare_mproc_encode(fp, nproc)
|
||||
mg = Manager(self.mproc_encode_part, nproc, None, Sys.g.MPEVENT)
|
||||
mg.run()
|
||||
self.mpMergeFiles(hlstPaths, tp, emit=emit)
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Encrypt data (multiproc)', d, c)
|
||||
if not Sys.g.QUIET : Sys.pstep('Encrypt data (multiproc)', d, c)
|
||||
if emit : Sys.cli_emit_progress(70)
|
||||
|
||||
|
||||
|
@ -901,9 +900,9 @@ class Kirmah:
|
|||
if len(decHeader) > 0 :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
if decHeader['smode'] == self.mark[fsize%len(self.mark)] :
|
||||
Sys.pstep('Reading Header', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Reading Header', d, True)
|
||||
else :
|
||||
Sys.pstep('Reading Header', d, False, False, False)
|
||||
if not Sys.g.QUIET : Sys.pstep('Reading Header', d, False, False, False)
|
||||
raise BadKeyException('wrong key')
|
||||
|
||||
compend, compstart = not decHeader['cmode']== KirmahHeader.COMP_NONE, decHeader['cmode']== KirmahHeader.COMP_ALL
|
||||
|
@ -913,26 +912,26 @@ class Kirmah:
|
|||
if compend :
|
||||
d = Sys.datetime.now()
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Uncompressing data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Uncompressing data')
|
||||
self.uncompress_end(fp, tp, compend, emit=emit)
|
||||
if emit : Sys.cli_emit_progress(10)
|
||||
if compend :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Compression mode', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
|
||||
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
|
||||
|
||||
|
||||
if decHeader['mmode'] :
|
||||
d = Sys.datetime.now()
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Sorting data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Sorting data')
|
||||
self.unmixdata(fp, tp, emit=emit)
|
||||
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
|
||||
if emit : Sys.cli_emit_progress(20)
|
||||
if decHeader['rmode'] :
|
||||
d = Sys.datetime.now()
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Reordering data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Reordering data')
|
||||
self.unRandomFileContent(fp, tp, emit=emit)
|
||||
fp, tp = tp, self.tmpPath2 if tp == self.tmpPath1 else self.tmpPath1
|
||||
if emit : Sys.cli_emit_progress(25)
|
||||
|
@ -947,15 +946,15 @@ class Kirmah:
|
|||
if emit : Sys.cli_emit_progress(80)
|
||||
if compstart :
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Uncompressing data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Uncompressing data')
|
||||
self.uncompress_start(fromPath, toPath, compstart, emit=emit)
|
||||
if emit : Sys.cli_emit_progress(90)
|
||||
if compstart:
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Compression mode', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Compression mode', d, True)
|
||||
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Cleaning')
|
||||
if not Sys.g.QUIET : Sys.ptask('Cleaning')
|
||||
if emit : Sys.cli_emit_progress(95)
|
||||
try :
|
||||
Sys.removeFile(self.tmpPath1)
|
||||
|
@ -969,7 +968,7 @@ class Kirmah:
|
|||
def decrypt_mproc(self, fromPath, toPath, nproc=1, emit=True):
|
||||
""""""
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.ptask('Decrypting data')
|
||||
if not Sys.g.QUIET : Sys.ptask('Decrypting data')
|
||||
d = Sys.datetime.now()
|
||||
c = not Sys.is_cli_cancel()
|
||||
if c:
|
||||
|
@ -977,14 +976,14 @@ class Kirmah:
|
|||
if nproc == 1 :
|
||||
self.decryptToFile(fromPath, toPath)
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Decrypt data', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Decrypt data', d, True)
|
||||
else :
|
||||
hlstPaths = self.prepare_mproc_decode(fromPath, nproc)
|
||||
mg = Manager(self.mproc_decode_part, nproc, None, Sys.g.MPEVENT, emit=True)
|
||||
mg.run()
|
||||
self.mpMergeFiles(hlstPaths, toPath, emit=emit)
|
||||
if Sys.g.DEBUG : Sys.wlog(Sys.dprint())
|
||||
Sys.pstep('Decrypt data (multiproc)', d, True)
|
||||
if not Sys.g.QUIET : Sys.pstep('Decrypt data (multiproc)', d, True)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ class AbstractCli():
|
|||
""""""
|
||||
if not Sys.isUnix : Const.LINE_SEP_CHAR = '-'
|
||||
AbstractCli.conf = prgconf
|
||||
self.CHQ = "'"
|
||||
self.parser = TinyParser()
|
||||
self.parser.print_help = self.print_help
|
||||
self.parser.print_usage = self.print_usage
|
||||
|
@ -98,7 +99,7 @@ class AbstractCli():
|
|||
self.parser.add_option('-q', '--quiet' , action='store_true', default=False)
|
||||
|
||||
self.parser.add_option('--no-color' , action='store_true' , default=False)
|
||||
|
||||
|
||||
|
||||
def error_cmd(self, data, pusage=False):
|
||||
""""""
|
||||
|
@ -127,7 +128,7 @@ class AbstractCli():
|
|||
Sys.wlog(a)
|
||||
Sys.wlog(b + c + d + e + f )
|
||||
Sys.wlog(a)
|
||||
Sys.wlog(Sys.dprint())
|
||||
#~ Sys.wlog(Sys.dprint())
|
||||
|
||||
|
||||
@staticmethod
|
||||
|
|
488
psr/imap.py
Normal file
488
psr/imap.py
Normal file
|
@ -0,0 +1,488 @@
|
|||
from imaplib import Commands, IMAP4_SSL, Time2Internaldate
|
||||
from binascii import b2a_base64, a2b_base64
|
||||
from codecs import register, StreamReader, StreamWriter
|
||||
from email import message_from_bytes
|
||||
from email.header import decode_header
|
||||
from email.message import Message
|
||||
from re import search as research, split as resplit
|
||||
|
||||
from psr.sys import Io, Sys, Const
|
||||
from psr.log import Log
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ ImapUtf7 decoding/encoding ~~
|
||||
|
||||
def _seq_encode(seq,l):
|
||||
""""""
|
||||
if len(seq) > 0 :
|
||||
l.append('&%s-' % str(b2a_base64(bytes(''.join(seq),'utf-16be')),'utf-8').rstrip('\n=').replace('/', ','))
|
||||
elif l:
|
||||
l.append('-')
|
||||
|
||||
|
||||
def _seq_decode(seq,l):
|
||||
""""""
|
||||
d = ''.join(seq[1:])
|
||||
pad = 4-(len(d)%4)
|
||||
l.append(str(a2b_base64(bytes(d.replace(',', '/')+pad*'=','utf-16be')),'utf-16be'))
|
||||
|
||||
|
||||
def encode(s):
|
||||
""""""
|
||||
l, e, = [], []
|
||||
for c in s :
|
||||
if ord(c) in range(0x20,0x7e):
|
||||
if e : _seq_encode(e,l)
|
||||
e = []
|
||||
l.append(c)
|
||||
if c == '&' : l.append('-')
|
||||
else :
|
||||
e.append(c)
|
||||
if e : _seq_encode(e,l)
|
||||
return ''.join(l)
|
||||
|
||||
|
||||
def decode(s):
|
||||
""""""
|
||||
l, d = [], []
|
||||
for c in s:
|
||||
if c == '&' and not d : d.append('&')
|
||||
elif c == '-' and d:
|
||||
if len(d) == 1: l.append('&')
|
||||
else : _seq_decode(d,l)
|
||||
d = []
|
||||
elif d: d.append(c)
|
||||
else: l.append(c)
|
||||
if d: _seq_decode(d,l)
|
||||
return ''.join(l)
|
||||
|
||||
|
||||
def _encoder(s):
|
||||
""""""
|
||||
e = bytes(encode(s),'utf-8')
|
||||
return e, len(e)
|
||||
|
||||
|
||||
def _decoder(s):
|
||||
""""""
|
||||
d = decode(str(s,'utf-8'))
|
||||
return d, len(d)
|
||||
|
||||
|
||||
def _codec_imap4utf7(name):
|
||||
""""""
|
||||
if name == 'imap4-utf-7':
|
||||
return (_encoder, _decoder, Imap4Utf7StreamReader, Imap4Utf7StreamWriter)
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ StreamReader & StreamWriter ~~
|
||||
|
||||
class Imap4Utf7StreamReader(StreamReader):
|
||||
def decode(self, s, errors='strict'): return _decoder(s)
|
||||
|
||||
class Imap4Utf7StreamWriter(StreamWriter):
|
||||
def decode(self, s, errors='strict'): return _encoder(s)
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ registering codec ~~
|
||||
|
||||
register(_codec_imap4utf7)
|
||||
|
||||
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ Imap utilities ~~
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ class ImapConfig ~~
|
||||
|
||||
class ImapConfig:
|
||||
""""""
|
||||
|
||||
def __init__(self, host, user, pwd, port=993):
|
||||
""""""
|
||||
self.host = host
|
||||
self.user = user
|
||||
self.pwd = pwd
|
||||
self.port = port
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ class ImapClient ~~
|
||||
|
||||
class ImapClient(IMAP4_SSL):
|
||||
""""""
|
||||
|
||||
Commands['XLIST'] = ('AUTH', 'SELECTED')
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def xlist(self, directory='""', pattern='*'):
|
||||
"""(X)List mailbox names in directory matching pattern. Using Google's XLIST extension
|
||||
|
||||
(status, [data]) = <instance>.xlist(directory='""', pattern='*')
|
||||
|
||||
'data' is list of XLIST responses.
|
||||
|
||||
thks to barduck : http://stackoverflow.com/users/602242/barduck
|
||||
"""
|
||||
try :
|
||||
name = 'XLIST'
|
||||
status, data = self._simple_command(name, directory, pattern)
|
||||
return self._untagged_response(status, data, name)
|
||||
except :
|
||||
return 'NO', ''
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ class ImapHelper ~~
|
||||
|
||||
class ImapHelper:
|
||||
""""""
|
||||
|
||||
K_HEAD, K_DATA = 0, 1
|
||||
""""""
|
||||
OK = 'OK'
|
||||
""""""
|
||||
KO = 'NO'
|
||||
""""""
|
||||
ENCODING = 'utf-8'
|
||||
""""""
|
||||
REG_SATUS = r'^"?(.*)"? \(([^\(]*)\)'
|
||||
""""""
|
||||
NO_SELECT = '\\Noselect'
|
||||
""""""
|
||||
CHILDREN = '\\HasChildren'
|
||||
""""""
|
||||
NO_CHILDREN = '\\HasNoChildren'
|
||||
""""""
|
||||
INBOX = '\\Inbox'
|
||||
""""""
|
||||
DRAFTS = '\\Drafts'
|
||||
""""""
|
||||
TRASH = '\\Trash'
|
||||
""""""
|
||||
SENT = '\\Sent'
|
||||
""""""
|
||||
DELETED = '\\Deleted'
|
||||
""""""
|
||||
FLAGS = '+FLAGS'
|
||||
""""""
|
||||
|
||||
@Log(Const.LOG_BUILD)
|
||||
def __init__(self, conf, box='INBOX'):
|
||||
""""""
|
||||
if research('yahoo.com', conf.host) is not None :
|
||||
self.DRAFTS = self.DRAFTS[:-1]
|
||||
self.conf = conf
|
||||
self.rootBox = box
|
||||
self.BOXS = {}
|
||||
self.cnx = None
|
||||
self.cnxusr = None
|
||||
self.switchAccount(self.conf, self.rootBox, True)
|
||||
|
||||
|
||||
@Log()
|
||||
def switchAccount(self, conf, box='INBOX', force=False):
|
||||
if force or self.cnx is None or self.cnxusr is not conf.user :
|
||||
try :
|
||||
Sys.print(' Attempt to login... ' , Sys.Clz.fgB7, False)
|
||||
Sys.print('(' , Sys.Clz.fgn7, False)
|
||||
Sys.print(conf.user , Sys.Clz.fgB2, False)
|
||||
Sys.print('@' , Sys.Clz.fgn7, False)
|
||||
Sys.print(conf.host , Sys.Clz.fgB4, False)
|
||||
Sys.print(':' , Sys.Clz.fgn7, False)
|
||||
Sys.print(conf.port , Sys.Clz.fgB3, False)
|
||||
Sys.print(')' , Sys.Clz.fgn7)
|
||||
self.cnx = ImapClient(conf.host,conf.port)
|
||||
except Exception as e :
|
||||
raise BadHostException()
|
||||
|
||||
try :
|
||||
status, resp = self.cnx.login(conf.user,conf.pwd)
|
||||
|
||||
except Exception as e :
|
||||
status = self.KO
|
||||
pass
|
||||
finally :
|
||||
if status == self.KO :
|
||||
self.cnxusr = None
|
||||
raise BadLoginException(' Cannot login with '+conf.user+':'+conf.pwd)
|
||||
else :
|
||||
Sys.print(' connected' , Sys.Clz.fgB2)
|
||||
self.cnxusr = conf.user
|
||||
try :
|
||||
status, resp = self.cnx.select(self.rootBox)
|
||||
if status == self.KO :
|
||||
self.createBox(self.rootBox)
|
||||
status, resp = self.cnx.select(self.rootBox)
|
||||
self.initBoxNames()
|
||||
except Exception as e :
|
||||
print(e)
|
||||
|
||||
|
||||
@Log()
|
||||
def createBox(self, box):
|
||||
""""""
|
||||
status, resp = self.cnx.create(encode(box))
|
||||
return status==self.OK
|
||||
|
||||
|
||||
@Log()
|
||||
def deleteBox(self, box):
|
||||
""""""
|
||||
status, resp = self.cnx.delete(encode(box))
|
||||
return status==self.OK
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def initBoxNames(self):
|
||||
""""""
|
||||
status, resp = self.cnx.xlist()
|
||||
if status == self.OK :
|
||||
bdef, bname, c = None, None, None
|
||||
for c in resp :
|
||||
bdef, bname = c[1:-1].split(b') "/" "')
|
||||
if bdef == Io.bytes(self.NO_SELECT+' '+self.CHILDREN) :
|
||||
self.BOXS['/'] = Io.str(bname)
|
||||
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.INBOX) :
|
||||
self.BOXS[self.INBOX] = self.INBOX[1:].upper()
|
||||
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.DRAFTS) :
|
||||
self.BOXS[self.DRAFTS] = Io.str(bname)
|
||||
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.TRASH) :
|
||||
self.BOXS[self.TRASH] = Io.str(bname)
|
||||
elif bdef == Io.bytes(self.NO_CHILDREN+' '+self.SENT) :
|
||||
self.BOXS[self.SENT] = Io.str(bname)
|
||||
else :
|
||||
self.BOXS = { '/' : '/', self.INBOX : self.INBOX[1:].upper(), self.DRAFTS : self.DRAFTS[1:], self.TRASH : self.TRASH[1:], self.SENT : self.SENT[1:] }
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def listBox(self, box='INBOX', pattern='*'):
|
||||
""""""
|
||||
status, resp = self.cnx.list(box,pattern)
|
||||
l = []
|
||||
for r in resp :
|
||||
if r is not None :
|
||||
name = Io.str(r).split(' "/" ')
|
||||
l.append((name[0][1:-1].split(' '),name[1][1:-1]))
|
||||
return l
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def status(self, box='INBOX'):
|
||||
""""""
|
||||
status, resp = self.cnx.status(box, '(MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)')
|
||||
if status == self.OK :
|
||||
data = research(self.REG_SATUS, Io.str(resp[self.K_HEAD]))
|
||||
l = resplit(' ',data.group(2))
|
||||
dic = {'BOX' : box}
|
||||
for i in range(len(l)):
|
||||
if i%2 == 0 : dic[l[i]] = int(l[i+1])
|
||||
else : dic = {}
|
||||
return dic
|
||||
|
||||
|
||||
@Log()
|
||||
def countSeen(self, box='INBOX'):
|
||||
""""""
|
||||
s = self.status(box)
|
||||
return s['MESSAGES']-s['UNSEEN']
|
||||
|
||||
|
||||
@Log()
|
||||
def countUnseen(self, box='INBOX'):
|
||||
""""""
|
||||
return self.status(box)['UNSEEN']
|
||||
|
||||
|
||||
@Log()
|
||||
def countMsg(self, box='INBOX'):
|
||||
""""""
|
||||
return self.status(box)['MESSAGES']
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def _ids(self, box='INBOX', search='ALL', charset=None, byUid=False):
|
||||
""""""
|
||||
status, resp = self.cnx.select(box)
|
||||
if status == self.KO :
|
||||
self.createBox(box)
|
||||
self.cnx.select(box)
|
||||
status, resp = self.cnx.search(charset, '(%s)' % search)
|
||||
return resplit(' ',Io.str(resp[self.K_HEAD]))
|
||||
|
||||
|
||||
@Log()
|
||||
def idsUnseen(self, box='INBOX', charset=None):
|
||||
""""""
|
||||
return self._ids(box,'UNSEEN', charset)
|
||||
|
||||
|
||||
@Log()
|
||||
def idsMsg(self, box='INBOX', charset=None):
|
||||
""""""
|
||||
return self._ids(box,'ALL', charset)
|
||||
|
||||
|
||||
@Log()
|
||||
def idsSeen(self, box='INBOX', charset=None):
|
||||
""""""
|
||||
return self._ids(box,'NOT UNSEEN', charset)
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def search(self, query, byUid=False):
|
||||
""""""
|
||||
if byUid :
|
||||
status, resp = self.cnx.uid('search', None, query)
|
||||
else :
|
||||
status, resp = self.cnx.search(None, query)
|
||||
ids = [m for m in resp[0].split()]
|
||||
return ids
|
||||
|
||||
|
||||
@Log()
|
||||
def searchBySubject(self, subject, byUid=False):
|
||||
""""""
|
||||
return self.search('(SUBJECT "%s")' % subject, byUid)
|
||||
|
||||
|
||||
@Log()
|
||||
def getUid(self, mid):
|
||||
""""""
|
||||
value = ''
|
||||
status, resp = self.cnx.fetch(mid, '(UID)')
|
||||
if status==self.OK :
|
||||
# '$mid (UID $uid)'
|
||||
value = resp[0][len(str(mid))+6:-1]
|
||||
return value
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def fetch(self, mid, query, byUid=False):
|
||||
""""""
|
||||
if not byUid :
|
||||
status, resp = self.cnx.fetch(mid, query)
|
||||
else:
|
||||
status, resp = self.cnx.uid('fetch', mid, query)
|
||||
return status, resp
|
||||
|
||||
|
||||
@Log()
|
||||
def headerField(self, mid, field, byUid=False):
|
||||
""""""
|
||||
value = ''
|
||||
field = field.upper()
|
||||
query = '(UID BODY[HEADER' + ('])' if field=='*' or field=='ALL' else '.FIELDS (%s)])' % field)
|
||||
status, resp = self.fetch(mid, query, byUid)
|
||||
if status==self.OK and resp[0]!=None:
|
||||
value = Io.str(resp[0][1][len(field)+2:-4])
|
||||
return value
|
||||
|
||||
|
||||
@Log()
|
||||
def getSubject(self, mid, byUid=False):
|
||||
""""""
|
||||
status, resp = self.fetch(mid, '(UID BODY[HEADER.FIELDS (SUBJECT)])', byUid)
|
||||
subject = decode_header(str(resp[self.K_HEAD][1][9:-4], 'utf-8'))[0]
|
||||
s = subject[0]
|
||||
if subject[1] :
|
||||
s = str(s,subject[1])
|
||||
return s
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _getIdsList(ids):
|
||||
idslist = None
|
||||
if isinstance(ids,list):
|
||||
if len(ids) > 0 and ids[0]!='' and ids[0]!=None:
|
||||
li = len(ids)-1
|
||||
if int(ids[0])+li == int(ids[li]):
|
||||
idslist = Io.str(ids[0]+b':'+ids[li]) if isinstance(ids[0],bytes) else str(ids[0])+':'+str(ids[li])
|
||||
else :
|
||||
idslist = Io.str(b','.join(ids)) if isinstance(ids[0],bytes) else ','.join(ids)
|
||||
elif isinstance(ids, int) and ids > 0:
|
||||
idslist = Io.str(ids)
|
||||
return idslist
|
||||
|
||||
|
||||
@Log()
|
||||
def delete(self, ids, byUid=False, expunge=True):
|
||||
""""""
|
||||
status, delids = None, ImapHelper._getIdsList(ids)
|
||||
#~ print(delids)
|
||||
if delids is not None :
|
||||
if byUid:
|
||||
status, resp = self.cnx.uid( 'store', delids, self.FLAGS, self.DELETED )
|
||||
else :
|
||||
status, resp = self.cnx.store(delids, self.FLAGS, self.DELETED)
|
||||
if expunge :
|
||||
self.cnx.expunge()
|
||||
return status == self.OK
|
||||
|
||||
|
||||
@Log()
|
||||
def clearTrash(self):
|
||||
""""""
|
||||
self.cnx.select(self.BOXS[self.TRASH])
|
||||
ids = self.search('ALL',True)
|
||||
if len(ids) > 0 and ids[0]!='' and ids[0]!=None:
|
||||
delids = ImapHelper._getIdsList(ids)
|
||||
status, resp = self.cnx.uid('store', delids, self.FLAGS, self.DELETED )
|
||||
Sys.print(' Deleting msg ', Sys.Clz.fgn7, False, False)
|
||||
Sys.print(delids , Sys.Clz.fgB1, False, False)
|
||||
Sys.print(' '+status , Sys.Clz.fgB7)
|
||||
self.cnx.expunge()
|
||||
self.cnx.select(self.rootBox)
|
||||
|
||||
|
||||
@Log()
|
||||
def getEmail(self, mid, byUid=False):
|
||||
""""""
|
||||
status, resp = self.fetch(mid,'(UID RFC822)', byUid)
|
||||
if status == self.OK and resp[0]!=None:
|
||||
msg = message_from_bytes(resp[0][1])
|
||||
else :
|
||||
msg = None
|
||||
return msg
|
||||
|
||||
|
||||
@Log(Const.LOG_APP)
|
||||
def getAttachment(self, msg, toDir='./', byUid=False):
|
||||
""""""
|
||||
if not isinstance(msg, Message) :
|
||||
msg = self.getEmail(msg, byUid)
|
||||
for part in msg.walk():
|
||||
filename = part.get_filename()
|
||||
if part.get_content_maintype() == 'multipart' or not filename : continue
|
||||
with Io.wfile(Sys.join(toDir, filename)) as fo :
|
||||
fo.write(part.get_payload(decode=True))
|
||||
|
||||
|
||||
@Log()
|
||||
def send(self, msg, box='INBOX'):
|
||||
""""""
|
||||
mid = None
|
||||
date = Time2Internaldate(Sys.time())
|
||||
status, resp = self.cnx.append(box, '\Draft', date, bytes(msg,'utf-8'))
|
||||
if status==self.OK:
|
||||
mid = str(resp[0],'utf-8')[11:-11].split(' ')
|
||||
return mid
|
||||
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ class BadLoginException ~~
|
||||
|
||||
class BadLoginException(BaseException):
|
||||
pass
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ class BadLoginException ~~
|
||||
|
||||
class BadHostException(BaseException):
|
||||
pass
|
170
psr/ini.py
Normal file
170
psr/ini.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
from re import split as regsplit
|
||||
from psr.sys import Sys, Io, Const
|
||||
from psr.log import Log
|
||||
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ~~ class IniFile ~~
|
||||
|
||||
class IniFile:
|
||||
"""Read and write inifile"""
|
||||
|
||||
@Log(Const.LOG_BUILD)
|
||||
def __init__(self, path):
|
||||
""""""
|
||||
self.path = path
|
||||
self.dic = {}
|
||||
self.read()
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def isEmpty(self):
|
||||
""""""
|
||||
return len(self.dic)==0
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def has(self, key, section='main'):
|
||||
""""""
|
||||
d = self.hasSection(section) and (key in self.dic[section])
|
||||
return d
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def hasSection(self, section):
|
||||
""""""
|
||||
d = (section in self.dic)
|
||||
return d
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def get(self, key, section='main'):
|
||||
""""""
|
||||
return self.dic[section][key]
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def set(self, key, val, section='main'):
|
||||
""""""
|
||||
v = None
|
||||
if not section in self.dic:
|
||||
self.dic[section] = {}
|
||||
if key in self.dic[section]:
|
||||
v = self.dic[section].pop(key)
|
||||
self.dic[section][key] = str(val)
|
||||
return v
|
||||
|
||||
|
||||
@Log()
|
||||
def rem(self, key, section):
|
||||
""""""
|
||||
v = None
|
||||
if section in self.dic :
|
||||
if key == '*' :
|
||||
v = self.dic.pop(section)
|
||||
elif key in self.dic[section]:
|
||||
v = self.dic[section].pop(key)
|
||||
return v
|
||||
|
||||
|
||||
@Log()
|
||||
def save(self,path=None):
|
||||
""""""
|
||||
Io.set_data(path if path is not None else self.path, '# last updated : '+str(Sys.datetime.now())+Const.LF+self.toString())
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def getSection(self, section):
|
||||
""""""
|
||||
data = {}
|
||||
for s in self.dic :
|
||||
if s.startswith(section, 0) : data[s[len(section)+1:]] = self.dic[s]
|
||||
return data
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def getSections(self):
|
||||
""""""
|
||||
l = {}
|
||||
for s in self.dic:
|
||||
section = s.split('.')
|
||||
if len(section)> 1 and not section[0] in l :
|
||||
l[section[0]] = 1
|
||||
return [k for i,k in enumerate(l)]
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def toString(self, section='*'):
|
||||
""""""
|
||||
content = ''
|
||||
main = ''
|
||||
for s in self.dic:
|
||||
if section=='*' or section+'.'==s[:len(section)+1]:
|
||||
if s!='main':
|
||||
content += Const.LF+'['+s+']'+Const.LF
|
||||
for k in sorted(self.dic[s]):
|
||||
k = k.rstrip(' ')
|
||||
v = self.dic[s][k] if self.dic[s][k] is not None else ''
|
||||
if s!='main' :
|
||||
content += k+' = '+str(v)+Const.LF
|
||||
else : main += k+' = '+str(v)+Const.LF
|
||||
return main + content
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def print(self, section='*', withoutSectionName=False):
|
||||
""""""
|
||||
if section=='main' or section=='*' :
|
||||
self.printSection('main', withoutSectionName)
|
||||
|
||||
for s in self.dic:
|
||||
if section=='*' or section+'.'==s[:len(section)+1]:
|
||||
if s!='main':
|
||||
self.printSection(s, withoutSectionName)
|
||||
|
||||
|
||||
@Log(Const.LOG_DEBUG)
|
||||
def printSection(self, sectionName, withoutSectionName=False):
|
||||
""""""
|
||||
if sectionName!='main':
|
||||
Sys.dprint()
|
||||
if not withoutSectionName :
|
||||
Sys.print('['+sectionName+']', Sys.Clz.fgB3)
|
||||
else:
|
||||
Sys.print('['+sectionName.split('.')[1]+']', Sys.Clz.fgB3)
|
||||
if sectionName in self.dic :
|
||||
for k in sorted(self.dic[sectionName]):
|
||||
k = k.rstrip(' ')
|
||||
a = ''
|
||||
Sys.print(k.ljust(10,' ')+' = ' , Sys.Clz.fgn7, False)
|
||||
if self.dic[sectionName][k] is not None :
|
||||
if len(self.dic[sectionName][k]) > 98: a = '…'
|
||||
if Sys.isUnix() or k is not 'key' :
|
||||
Sys.print(self.dic[sectionName][k][:98]+a, Sys.Clz.fgN2)
|
||||
else:
|
||||
Sys.print('key is masked', Sys.Clz.fgb1)
|
||||
|
||||
@Log()
|
||||
def read(self):
|
||||
""""""
|
||||
try:
|
||||
with Io.rfile(self.path, False) as fi:
|
||||
csection = 'main'
|
||||
self.dic[csection] = {}
|
||||
for l in fi:
|
||||
l = l.rstrip().lstrip()
|
||||
if len(l) > 0 and not l[0]=='#' :
|
||||
d = regsplit(' *= *', l , 1)
|
||||
if len(d)> 1:
|
||||
self.dic[csection][d[0]] = d[1] if d[1] is not None else ''
|
||||
elif len(l)>0 and l[0]=='[':
|
||||
csection = l.strip('[]')
|
||||
self.dic[csection] = {}
|
||||
except IOError :
|
||||
pass
|
||||
|
||||
|
||||
@Log()
|
||||
def delete(self):
|
||||
Io.removeFile(self.path)
|
||||
self.dic = {}
|
|
@ -86,7 +86,7 @@ class Log:
|
|||
if not (isinstance(a, str) or isinstance(a, bytes)):
|
||||
a = str(a)
|
||||
if len(a) > Sys.g.LOG_LIM_ARG_LENGTH :
|
||||
args[i] = a[:Sys.g.LOG_LIM_ARG_LENGTH]+'...' if isinstance(a, str) else b'...'
|
||||
args[i] = a[:Sys.g.LOG_LIM_ARG_LENGTH]+'…' if isinstance(a, str) else bytes('…','utf-8')
|
||||
args = str(args)[1:-1]
|
||||
if args[-1:] == ',' : args = args[:-1]
|
||||
return args
|
||||
|
|
14
psr/sys.py
14
psr/sys.py
|
@ -48,10 +48,10 @@ class Sys:
|
|||
""""""
|
||||
|
||||
from platform import system as getSysName
|
||||
from os import system as sysCall, remove as removeFile, makedirs, sep, getpid
|
||||
from os import system as sysCall, remove as removeFile, makedirs, sep, getpid, listdir
|
||||
from getpass import getuser as getUserLogin
|
||||
from time import strftime, mktime, time, localtime, sleep
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from sys import exit
|
||||
from os.path import abspath, dirname, join, realpath, basename, getsize, isdir, splitext
|
||||
from math import log, floor, ceil
|
||||
|
@ -164,6 +164,8 @@ class Sys:
|
|||
"""Give a human representation of bytes size `b`
|
||||
:Returns: `str`
|
||||
"""
|
||||
if b is None or b=='': return '0'
|
||||
else :b = int(b)
|
||||
units = [Const.UNIT_SHORT_B, Const.UNIT_SHORT_KIB, Const.UNIT_SHORT_MIB, Const.UNIT_SHORT_GIB, Const.UNIT_SHORT_TIB];
|
||||
b = max(b,0);
|
||||
if b == 0 : lb= 0
|
||||
|
@ -261,6 +263,7 @@ class Sys:
|
|||
@staticmethod
|
||||
def dprint(d='',end=Const.LF, dbcall=False):
|
||||
""""""
|
||||
dbcall = Sys.g.QUIET
|
||||
if not dbcall :
|
||||
if not Sys.g.GUI or Sys.g.GUI_PRINT_STDOUT :
|
||||
if Sys.g.RLOCK is not None :
|
||||
|
@ -309,11 +312,16 @@ class Sys:
|
|||
return bdata
|
||||
|
||||
|
||||
@staticmethod
|
||||
def getDelta(t):
|
||||
v = ''.join(['{:.5f}'.format(Sys.time()-(Sys.mktime(t.timetuple())+1e-6*t.microsecond)),' s'])
|
||||
return v
|
||||
|
||||
@staticmethod
|
||||
def pdelta(t, label='', dbcall= False):
|
||||
""""""
|
||||
if len(label)>0 and not dbcall : Sys.print(label+' ', Sys.CLZ_IO, False)
|
||||
v = ''.join(['{:.5f}'.format(Sys.time()-(Sys.mktime(t.timetuple())+1e-6*t.microsecond)),' s'])
|
||||
v = Sys.getDelta(t)
|
||||
if not dbcall :
|
||||
Sys.print(v, Sys.CLZ_DELTA)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user