Big migrations and linting.
With pathclass.glob_many, we can clean up and feel more confident about many programs that use pipeable to take glob patterns. Added return 0 to all programs that didn't have it, so we have consistent and explicit command line return values. Other linting and whitespace.
This commit is contained in:
parent
6751a5d6c9
commit
4a9051e617
64 changed files with 345 additions and 228 deletions
|
@ -1,37 +1,24 @@
|
|||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from voussoirkit import interactive
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import stringtools
|
||||
from voussoirkit import vlogging
|
||||
from voussoirkit import winglob
|
||||
|
||||
log = vlogging.getLogger(__name__, 'adbinstall')
|
||||
|
||||
def natural_sorter(x):
|
||||
'''
|
||||
Used for sorting files in 'natural' order instead of lexicographic order,
|
||||
so that you get 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
|
||||
instead of 1 10 11 12 13 2 3 4 5 ...
|
||||
Thank you Mark Byers
|
||||
http://stackoverflow.com/a/11150413
|
||||
'''
|
||||
convert = lambda text: int(text) if text.isdigit() else text.lower()
|
||||
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
|
||||
return alphanum_key(x)
|
||||
|
||||
def adbinstall_argparse(args):
|
||||
patterns = pipeable.input_many(args.apks, skip_blank=True, strip=True)
|
||||
apks = [file for pattern in patterns for file in winglob.glob(pattern)]
|
||||
apks = pathclass.glob_many(patterns, files=True)
|
||||
installs = []
|
||||
for apk in apks:
|
||||
apk = pathclass.Path(apk)
|
||||
if apk.is_dir:
|
||||
files = apk.glob('*.apk')
|
||||
files.sort(key=lambda x: natural_sorter(x.basename.lower()))
|
||||
files.sort(key=lambda x: stringtools.natural_sorter(x.basename.lower()))
|
||||
apk = files[-1]
|
||||
installs.append(apk)
|
||||
|
||||
|
@ -46,6 +33,8 @@ def adbinstall_argparse(args):
|
|||
log.info(command)
|
||||
os.system(command)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -2,6 +2,7 @@ import os
|
|||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
|
||||
def windows():
|
||||
paths = os.getenv('PATH').strip(' ;').split(';')
|
||||
|
@ -30,7 +31,9 @@ def main(argv):
|
|||
executables = linux()
|
||||
|
||||
for executable in executables:
|
||||
print(executable.absolute_path)
|
||||
pipeable.stdout(executable.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -7,16 +7,13 @@ Merge two or more files by performing bitwise or on their bits.
|
|||
> bitwise_or file1 file2 --output file3
|
||||
'''
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from voussoirkit import betterhelp
|
||||
from voussoirkit import interactive
|
||||
from voussoirkit import operatornotify
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import vlogging
|
||||
from voussoirkit import winglob
|
||||
|
||||
log = vlogging.getLogger(__name__, 'bitwise_or')
|
||||
|
||||
|
@ -24,8 +21,7 @@ CHUNK_SIZE = 2**20
|
|||
|
||||
def bitwise_or_argparse(args):
|
||||
patterns = pipeable.input_many(args.files, skip_blank=True, strip=True)
|
||||
files = [file for pattern in patterns for file in winglob.glob(pattern)]
|
||||
files = [pathclass.Path(file) for file in files]
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
|
||||
if len(files) < 2:
|
||||
log.fatal('Need at least two input files.')
|
||||
|
|
|
@ -23,6 +23,8 @@ def breplace_argparse(args):
|
|||
command = f'x.replace("{replace_from}", "{replace_to}")'
|
||||
brename.brename(command, autoyes=args.autoyes, recurse=args.recurse)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(__doc__)
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ def clipboard_argparse(args):
|
|||
text = text.replace('\r', '')
|
||||
print(text)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import argparse
|
||||
import codecs
|
||||
import os
|
||||
import pyperclip
|
||||
import re
|
||||
import sys
|
||||
|
@ -71,6 +70,8 @@ def contentreplace_argparse(args):
|
|||
except UnicodeDecodeError:
|
||||
log.error('%s encountered unicode decode error.', file.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
26
crc32.py
26
crc32.py
|
@ -1,26 +1,32 @@
|
|||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import zlib
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
from voussoirkit import vlogging
|
||||
|
||||
log = vlogging.getLogger(__name__, 'crc32')
|
||||
|
||||
def crc32_argparse(args):
|
||||
files = (
|
||||
file
|
||||
for pattern in pipeable.input_many(args.patterns)
|
||||
for file in winglob.glob(pattern)
|
||||
if os.path.isfile(file)
|
||||
)
|
||||
return_status = 0
|
||||
|
||||
patterns = pipeable.input_many(args.patterns, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
|
||||
for file in files:
|
||||
try:
|
||||
with open(file, 'rb') as handle:
|
||||
crc = zlib.crc32(handle.read())
|
||||
print(hex(crc)[2:].rjust(8, '0'), file)
|
||||
crc = hex(crc)[2:].rjust(8, '0')
|
||||
pipeable.stdout(f'{crc} {file}')
|
||||
except Exception as e:
|
||||
print(file, e)
|
||||
log.error('%s %s', file, e)
|
||||
return_status = 1
|
||||
|
||||
return return_status
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
36
crlf.py
36
crlf.py
|
@ -1,28 +1,46 @@
|
|||
'''
|
||||
Convert LF line endings to CRLF.
|
||||
'''
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
CR = b'\x0D'
|
||||
LF = b'\x0A'
|
||||
CRLF = CR + LF
|
||||
|
||||
def crlf(filename):
|
||||
with open(filename, 'rb') as handle:
|
||||
def crlf(file):
|
||||
with file.open('rb') as handle:
|
||||
content = handle.read()
|
||||
|
||||
original = content
|
||||
content = content.replace(CRLF, LF)
|
||||
content = content.replace(LF, CRLF)
|
||||
with open(filename, 'wb') as handle:
|
||||
if content == original:
|
||||
return
|
||||
|
||||
with file.open('wb') as handle:
|
||||
handle.write(content)
|
||||
|
||||
def main(args):
|
||||
for line in pipeable.go(args, strip=True, skip_blank=True):
|
||||
for filename in winglob.glob(line):
|
||||
pipeable.stdout(filename)
|
||||
crlf(filename)
|
||||
def crlf_argparse(args):
|
||||
patterns = pipeable.input_many(args.patterns, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns)
|
||||
for file in files:
|
||||
crlf(file)
|
||||
pipeable.stdout(file)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
parser.add_argument('patterns')
|
||||
parser.set_defaults(func=crlf_argparse)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
return args.func(args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
26
crop.py
26
crop.py
|
@ -1,13 +1,12 @@
|
|||
import argparse
|
||||
import os
|
||||
import PIL.Image
|
||||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
def crop(filename, crops, *, inplace=False):
|
||||
image = PIL.Image.open(filename)
|
||||
def crop(file, crops, *, inplace=False):
|
||||
image = PIL.Image.open(file.absolute_path)
|
||||
if len(crops) == 2:
|
||||
crops.extend(image.size)
|
||||
|
||||
|
@ -20,24 +19,27 @@ def crop(filename, crops, *, inplace=False):
|
|||
|
||||
image = image.crop(crops)
|
||||
if inplace:
|
||||
newname = filename
|
||||
newname = file
|
||||
else:
|
||||
suffix = '_'.join(str(x) for x in crops)
|
||||
suffix = f'_{suffix}'
|
||||
(base, extension) = os.path.splitext(filename)
|
||||
newname = base + suffix + extension
|
||||
base = file.replace_extension('').basename
|
||||
newname = file.parent.with_child(base + suffix).add_extension(file.extension)
|
||||
|
||||
pipeable.stdout(newname)
|
||||
image.save(newname, exif=image.info.get('exif', b''), quality=100)
|
||||
pipeable.stdout(newname.absolute_path)
|
||||
image.save(newname.absolute_path, exif=image.info.get('exif', b''), quality=100)
|
||||
|
||||
def crop_argparse(args):
|
||||
filenames = winglob.glob(args.pattern)
|
||||
for filename in filenames:
|
||||
patterns = pipeable.input(args.pattern, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
|
||||
for file in files:
|
||||
crop(
|
||||
filename,
|
||||
file,
|
||||
crops=args.crops,
|
||||
inplace=args.inplace,
|
||||
)
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
23
delete.py
23
delete.py
|
@ -1,14 +1,19 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
for pattern in pipeable.go(skip_blank=True):
|
||||
for name in winglob.glob(pattern):
|
||||
if os.path.isfile(name):
|
||||
pipeable.stdout(name)
|
||||
os.remove(name)
|
||||
elif os.path.isdir(name):
|
||||
pipeable.stdout(name)
|
||||
shutil.rmtree(name)
|
||||
def main(argv):
|
||||
for path in pathclass.glob_many(pipeable.go(argv, skip_blank=True)):
|
||||
if path.is_file:
|
||||
pipeable.stdout(path.absolute_path)
|
||||
os.remove(path.absolute_path)
|
||||
elif path.is_dir:
|
||||
pipeable.stdout(path.absolute_path)
|
||||
shutil.rmtree(path.absolute_path)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -45,6 +45,8 @@ def directory_discrepancy_argparse(args):
|
|||
for discrepancy in sorted(files2.difference(files1)):
|
||||
print(discrepancy)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -55,6 +55,8 @@ def drawquarter_argparse(args):
|
|||
print(output_filename.relative_path)
|
||||
piece.save(output_filename.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
|
|
|
@ -3,17 +3,17 @@ import sys
|
|||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
def empty_directories_argparse(args):
|
||||
patterns = pipeable.input_many(args.patterns, skip_blank=True, strip=True)
|
||||
directories = (pathclass.Path(d) for pattern in patterns for d in winglob.glob(pattern))
|
||||
directories = (d for d in directories if d.is_dir)
|
||||
directories = pathclass.glob_many(patterns, directories=True)
|
||||
|
||||
for directory in directories:
|
||||
if len(directory.listdir()) == 0:
|
||||
pipeable.stdout(directory.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
2
eval.py
2
eval.py
|
@ -25,6 +25,8 @@ def eval_argparse(args):
|
|||
x = line
|
||||
pipeable.stdout(eval(args.eval_string))
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import bs4
|
|||
import requests
|
||||
import sys
|
||||
import tenacity
|
||||
import time
|
||||
|
||||
from voussoirkit import betterhelp
|
||||
from voussoirkit import downloady
|
||||
|
|
|
@ -138,6 +138,8 @@ def ffstreams_argparse(args):
|
|||
moveto=args.moveto,
|
||||
)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -16,11 +16,10 @@ argv = sys.argv[1:]
|
|||
|
||||
randname = [random.choice(string.digits) for x in range(12)]
|
||||
randname = int(''.join(randname))
|
||||
for pattern in argv:
|
||||
for path in winglob.glob(pattern):
|
||||
path = pathclass.Path(path)
|
||||
newname = str(randname).rjust(12, '0') + path.dot_extension
|
||||
randname += 1
|
||||
newname = path.parent.with_child(newname)
|
||||
os.rename(path.absolute_path, newname.absolute_path)
|
||||
print('%s -> %s' % (path.absolute_path, newname.basename))
|
||||
|
||||
for path in pathclass.glob_many(argv):
|
||||
newname = str(randname).rjust(12, '0') + path.dot_extension
|
||||
randname += 1
|
||||
newname = path.parent.with_child(newname)
|
||||
os.rename(path.absolute_path, newname.absolute_path)
|
||||
print('%s -> %s' % (path.absolute_path, newname.basename))
|
||||
|
|
|
@ -9,15 +9,12 @@ import string
|
|||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import winglob
|
||||
|
||||
argv = sys.argv[1:]
|
||||
|
||||
for pattern in argv:
|
||||
for path in winglob.glob(pattern):
|
||||
path = pathclass.Path(path)
|
||||
newname = [random.choice(string.ascii_lowercase) for x in range(9)]
|
||||
newname = ''.join(newname) + path.dot_extension
|
||||
newname = path.parent.with_child(newname)
|
||||
os.rename(path.absolute_path, newname.absolute_path)
|
||||
print('%s -> %s' % (path.absolute_path, newname.basename))
|
||||
for path in pathclass.glob_many(argv):
|
||||
newname = [random.choice(string.ascii_lowercase) for x in range(9)]
|
||||
newname = ''.join(newname) + path.dot_extension
|
||||
newname = path.parent.with_child(newname)
|
||||
os.rename(path.absolute_path, newname.absolute_path)
|
||||
print('%s -> %s' % (path.absolute_path, newname.basename))
|
||||
|
|
|
@ -9,15 +9,12 @@ import string
|
|||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import winglob
|
||||
|
||||
argv = sys.argv[1:]
|
||||
|
||||
for pattern in argv:
|
||||
for path in winglob.glob(pattern):
|
||||
path = pathclass.Path(path)
|
||||
newname = [random.choice(string.digits) for x in range(12)]
|
||||
newname = ''.join(newname) + path.dot_extension
|
||||
newname = path.parent.with_child(newname)
|
||||
os.rename(path.absolute_path, newname.absolute_path)
|
||||
print('%s -> %s' % (path.absolute_path, newname.basename))
|
||||
for path in pathclass.glob_many(argv):
|
||||
newname = [random.choice(string.digits) for x in range(12)]
|
||||
newname = ''.join(newname) + path.dot_extension
|
||||
newname = path.parent.with_child(newname)
|
||||
os.rename(path.absolute_path, newname.absolute_path)
|
||||
print('%s -> %s' % (path.absolute_path, newname.basename))
|
||||
|
|
|
@ -42,6 +42,7 @@ def filepull(pull_from='.', autoyes=False):
|
|||
|
||||
def filepull_argparse(args):
|
||||
filepull(pull_from=args.pull_from, autoyes=args.autoyes)
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
|
|
17
grayscale.py
17
grayscale.py
|
@ -3,7 +3,7 @@ import PIL.Image
|
|||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import winglob
|
||||
from voussoirkit import pipeable
|
||||
|
||||
def grayscale(filename, *, inplace=False):
|
||||
filename = pathclass.Path(filename)
|
||||
|
@ -20,18 +20,23 @@ def grayscale(filename, *, inplace=False):
|
|||
|
||||
image = PIL.Image.open(filename.absolute_path)
|
||||
image = image.convert('LA').convert(image.mode)
|
||||
print(f'{new_filename.absolute_path}')
|
||||
image.save(new_filename.absolute_path, exif=image.info.get('exif', b''))
|
||||
return new_filename
|
||||
|
||||
def grayscale_argparse(args):
|
||||
filenames = winglob.glob(args.pattern)
|
||||
for filename in filenames:
|
||||
grayscale(filename, inplace=args.inplace)
|
||||
patterns = pipeable.input_many(args.patterns, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
for file in files:
|
||||
new_filename = grayscale(file, inplace=args.inplace)
|
||||
if new_filename:
|
||||
pipeable.stdout(new_filename.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
parser.add_argument('pattern')
|
||||
parser.add_argument('patterns', nargs='+')
|
||||
parser.add_argument('--inplace', action='store_true')
|
||||
parser.set_defaults(func=grayscale_argparse)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ def groupsof_argparse(args):
|
|||
for chunk in chunks:
|
||||
chunk = args.separator.join(chunk)
|
||||
pipeable.stdout(chunk)
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -65,6 +65,8 @@ def hash_hardlink_argparse(args):
|
|||
send2trash.send2trash(follower.absolute_path)
|
||||
os.link(leader.absolute_path, follower.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -27,7 +27,11 @@ def root():
|
|||
|
||||
def heresmyclipboard_argparse(args):
|
||||
log.info(f'Starting server on port {args.port}, pid={os.getpid()}')
|
||||
site.run(host='0.0.0.0', port=args.port)
|
||||
try:
|
||||
site.run(host='0.0.0.0', port=args.port)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
|
|
|
@ -5,7 +5,6 @@ import argparse
|
|||
import PIL.Image
|
||||
import sys
|
||||
|
||||
|
||||
def full_hex(h):
|
||||
h = h.replace('#', '')
|
||||
if len(h) in [3, 4]:
|
||||
|
@ -28,6 +27,7 @@ def make_hexpng(h, width=1, height=1):
|
|||
|
||||
def hexpng_argparse(args):
|
||||
make_hexpng(args.hex_value, width=args.width, height=args.height)
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -131,43 +131,59 @@ def load_image(filename):
|
|||
return image
|
||||
|
||||
def build_ico_header_blob(image_count):
|
||||
datablob = (b''
|
||||
+ little(0, 2) # reserved
|
||||
+ little(1, 2) # 1 = ico type
|
||||
+ little(image_count, 2)
|
||||
)
|
||||
datablob = b''.join([
|
||||
# reserved
|
||||
little(0, 2),
|
||||
# 1 = ico type
|
||||
little(1, 2),
|
||||
little(image_count, 2),
|
||||
])
|
||||
return datablob
|
||||
|
||||
def build_icon_directory_blob(image, offset_from_start):
|
||||
(width, height) = image.size
|
||||
datablob = (b''
|
||||
+ little(width if width < 256 else 0, 1)
|
||||
+ little(height if height < 256 else 0, 1)
|
||||
+ little(0, 1) # colors in palette
|
||||
+ little(0, 1) # reserved
|
||||
+ little(1, 2) # color planes
|
||||
+ little(32, 2) # bit depth
|
||||
+ little((width * height * 4) + BMP_HEADER_LENGTH, 4) # image bytes length
|
||||
+ little(offset_from_start, 4)
|
||||
)
|
||||
datablob = b''.join([
|
||||
little(width if width < 256 else 0, 1),
|
||||
little(height if height < 256 else 0, 1),
|
||||
# colors in palette
|
||||
little(0, 1),
|
||||
# reserved
|
||||
little(0, 1),
|
||||
# color planes
|
||||
little(1, 2),
|
||||
# bit depth
|
||||
little(32, 2),
|
||||
# image bytes length
|
||||
little((width * height * 4) + BMP_HEADER_LENGTH, 4),
|
||||
little(offset_from_start, 4),
|
||||
])
|
||||
return datablob
|
||||
|
||||
def build_image_data_blob(image):
|
||||
datablob = (b''
|
||||
+ little(40, 4) # header size
|
||||
+ little(image.size[0], 4)
|
||||
datablob = b''.join([
|
||||
# header size
|
||||
little(40, 4),
|
||||
little(image.size[0], 4),
|
||||
# "Even if the AND mask is not supplied, if the image is in Windows BMP
|
||||
# format, the BMP header must still specify a doubled height." - wikipedia
|
||||
+ little(image.size[1] * 2, 4)
|
||||
+ little(1, 2) # color planes
|
||||
+ little(32, 2) # bit depth
|
||||
+ little(0, 4) # no compression
|
||||
+ little(0, 4) # bytes length, inferred
|
||||
+ little(0, 4) # hor print
|
||||
+ little(0, 4) # ver print
|
||||
+ little(0, 4) # palette
|
||||
+ little(0, 4) # important palette
|
||||
)
|
||||
little(image.size[1] * 2, 4),
|
||||
# color planes
|
||||
little(1, 2),
|
||||
# bit depth
|
||||
little(32, 2),
|
||||
# no compression
|
||||
little(0, 4),
|
||||
# bytes length, inferred
|
||||
little(0, 4),
|
||||
# hor print
|
||||
little(0, 4),
|
||||
# ver print
|
||||
little(0, 4),
|
||||
# palette
|
||||
little(0, 4),
|
||||
# important palette
|
||||
little(0, 4),
|
||||
])
|
||||
pixeldata = []
|
||||
# Image.getdata() is a list of (r, g, b, a) channels
|
||||
# But the BMP are written (b, g, r, a)
|
||||
|
@ -214,11 +230,10 @@ def images_to_ico(images):
|
|||
final_data = b''.join(datablobs)
|
||||
return final_data
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
inputfiles = sys.argv[1:]
|
||||
except:
|
||||
except Exception:
|
||||
print('Please provide an image file')
|
||||
raise SystemExit
|
||||
print('Iconifying', inputfiles)
|
||||
|
|
20
inodes.py
20
inodes.py
|
@ -1,12 +1,24 @@
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
from voussoirkit import betterhelp
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
|
||||
def inodes_argparse(args):
|
||||
patterns = pipeable.input_many(args.patterns, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
for file in files:
|
||||
pipeable.stdout(f'{file.stat.st_dev} {file.stat.st_ino} {file.relative_path}')
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
for file in pathclass.cwd().listdir():
|
||||
if not file.is_file:
|
||||
continue
|
||||
print(file.stat.st_dev, file.stat.st_ino, file.relative_path)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
parser.add_argument('patterns', nargs='+')
|
||||
parser.set_defaults(func=inodes_argparse)
|
||||
|
||||
return betterhelp.single_main(argv, parser, __doc__)
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -17,7 +17,7 @@ def inputrename_argparse(args):
|
|||
files = (file for file in pathclass.cwd().listdir() if args.keyword in file.basename)
|
||||
prev = None
|
||||
for file in files:
|
||||
print(file.relative_path)
|
||||
pipeable.stderr(file.relative_path)
|
||||
this = input('> ')
|
||||
if this == '' and prev is not None:
|
||||
this = prev
|
||||
|
@ -27,6 +27,8 @@ def inputrename_argparse(args):
|
|||
os.rename(file.absolute_path, new_name.absolute_path)
|
||||
prev = this
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ def main(argv):
|
|||
check_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -12,7 +12,9 @@ def linenumbers_argparse(args):
|
|||
digits = len(str(len(lines)))
|
||||
form = '{no:>0%d} | {line}' % digits
|
||||
for (index, line) in enumerate(lines):
|
||||
print(form.format(no=index+1, line=line))
|
||||
pipeable.stdout(form.format(no=index+1, line=line))
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -3,7 +3,6 @@ lint_argparse_returns
|
|||
=====================
|
||||
'''
|
||||
import ast
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from voussoirkit import pipeable
|
||||
|
||||
|
||||
for line in pipeable.go():
|
||||
pipeable.stdout(line.lower())
|
||||
|
|
16
move_all.py
16
move_all.py
|
@ -8,17 +8,15 @@ import sys
|
|||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
def moveall_argparse(args):
|
||||
files = (
|
||||
pathclass.Path(file)
|
||||
for pattern in pipeable.input(args.source)
|
||||
for file in winglob.glob(pattern)
|
||||
)
|
||||
destination = pathclass.Path(args.destination)
|
||||
patterns = pipeable.input(args.source, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns)
|
||||
|
||||
if not destination.is_dir:
|
||||
destination = pathclass.Path(args.destination)
|
||||
try:
|
||||
destination.assert_is_directory()
|
||||
except pathclass.NotDirectory:
|
||||
pipeable.stderr('destination must be a directory.')
|
||||
return 1
|
||||
|
||||
|
@ -39,6 +37,8 @@ def moveall_argparse(args):
|
|||
pipeable.stdout(new_path.absolute_path)
|
||||
shutil.move(file.absolute_path, new_path.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ import sys
|
|||
|
||||
from voussoirkit import bytestring
|
||||
|
||||
|
||||
def parse_rules(lines):
|
||||
rules = []
|
||||
for (times, title) in lines[::-1]:
|
||||
|
@ -125,7 +124,7 @@ def _unitconvert(value):
|
|||
else:
|
||||
return bytestring.parsebytes(value)
|
||||
|
||||
def example_argparse(args):
|
||||
def mp3slice_argparse(args):
|
||||
if len(args.rules) == 1 and os.path.isfile(args.rules[0]):
|
||||
rules = read_rulefile(args.rules[0])
|
||||
else:
|
||||
|
@ -155,14 +154,14 @@ def example_argparse(args):
|
|||
command = 'ffmpeg -i "%s" %s' % (args.input_filename, outputters)
|
||||
print(command)
|
||||
os.system(command)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('input_filename')
|
||||
parser.add_argument('rules', nargs='+', default=None)
|
||||
parser.set_defaults(func=example_argparse)
|
||||
parser.set_defaults(func=mp3slice_argparse)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
return args.func(args)
|
||||
|
|
|
@ -3,17 +3,17 @@ import sys
|
|||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
def nonempty_directories_argparse(args):
|
||||
patterns = pipeable.input_many(args.patterns, skip_blank=True, strip=True)
|
||||
directories = (pathclass.Path(d) for pattern in patterns for d in winglob.glob(pattern))
|
||||
directories = (d for d in directories if d.is_dir)
|
||||
directories = pathclass.glob_many(patterns, directories=True)
|
||||
|
||||
for directory in directories:
|
||||
if len(directory.listdir()) != 0:
|
||||
pipeable.stdout(directory.absolute_path)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
15
pickn.py
15
pickn.py
|
@ -1,26 +1,31 @@
|
|||
import argparse
|
||||
import itertools
|
||||
import sys
|
||||
|
||||
from voussoirkit import pipeable
|
||||
|
||||
def shuffle_argparse(args):
|
||||
def pickn_argparse(args):
|
||||
if args.count < 1:
|
||||
pipeable.stderr('count must be >= 1.')
|
||||
return 1
|
||||
|
||||
lines = pipeable.input(args.source, read_files=True, skip_blank=True, strip=True)
|
||||
lines = list(lines)
|
||||
lines = lines[:args.count]
|
||||
|
||||
for line in lines:
|
||||
for line in itertools.islice(lines, args.count):
|
||||
pipeable.stdout(line)
|
||||
|
||||
# Exhaust the rest of stdin so we don't get Broken Pipe error
|
||||
for line in lines:
|
||||
pass
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
parser.add_argument('source')
|
||||
parser.add_argument('count', type=int)
|
||||
parser.set_defaults(func=shuffle_argparse)
|
||||
parser.set_defaults(func=pickn_argparse)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
return args.func(args)
|
||||
|
|
|
@ -38,11 +38,12 @@ def pip_download(package):
|
|||
os.rename(os.path.join(tmpdir.name, filename), os.path.join(new_directory, filename))
|
||||
tmpdir.cleanup()
|
||||
|
||||
|
||||
def pip_download_argparse(args):
|
||||
for package in args.packages:
|
||||
pip_download(package)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ from voussoirkit import betterhelp
|
|||
from voussoirkit import spinal
|
||||
from voussoirkit import pathclass
|
||||
|
||||
|
||||
def prune_dirs(starting):
|
||||
starting = pathclass.Path(starting)
|
||||
walker = spinal.walk(starting, yield_directories=True, yield_files=False)
|
||||
|
@ -36,7 +35,6 @@ def prune_dirs(starting):
|
|||
directory = double_check.pop()
|
||||
pruneme(directory)
|
||||
|
||||
|
||||
def prune_dirs_argparse(args):
|
||||
return prune_dirs(args.starting)
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ def make_randomfile(length, filename=None):
|
|||
f.close()
|
||||
print('Created %s' % filename)
|
||||
|
||||
|
||||
bytes = listget(sys.argv, 1, None)
|
||||
if bytes is None:
|
||||
bytes = 2 ** 10
|
||||
|
|
17
recycle.py
17
recycle.py
|
@ -1,11 +1,14 @@
|
|||
import os
|
||||
import send2trash
|
||||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import winglob
|
||||
|
||||
for pattern in pipeable.go(skip_blank=True):
|
||||
for name in winglob.glob(pattern):
|
||||
name = os.path.abspath(name)
|
||||
pipeable.stdout(name)
|
||||
send2trash.send2trash(name)
|
||||
def main(argv):
|
||||
for path in pathclass.glob_many(pipeable.go(argv, skip_blank=True)):
|
||||
pipeable.stdout(path.absolute_path)
|
||||
send2trash.send2trash(path.absolute_path)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -5,7 +5,7 @@ from voussoirkit import pipeable
|
|||
|
||||
for line in pipeable.go():
|
||||
if os.path.isfile(line):
|
||||
print('Recycling', line)
|
||||
pipeable.stdout(line)
|
||||
send2trash.send2trash(line)
|
||||
else:
|
||||
print('Not a file', line)
|
||||
pipeable.stderr('Not a file', line)
|
||||
|
|
11
rejpg.py
11
rejpg.py
|
@ -12,6 +12,9 @@ from voussoirkit import bytestring
|
|||
from voussoirkit import imagetools
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import spinal
|
||||
from voussoirkit import vlogging
|
||||
|
||||
log = vlogging.getLogger(__name__, 'rejpg')
|
||||
|
||||
PIL.ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
|
||||
|
@ -24,7 +27,7 @@ def rejpg_argparse(args):
|
|||
bytes_saved = 0
|
||||
remaining_size = 0
|
||||
for filename in files:
|
||||
print(filename)
|
||||
log.info('Processing %s.', filename)
|
||||
bytesio = io.BytesIO()
|
||||
image = PIL.Image.open(filename)
|
||||
|
||||
|
@ -43,9 +46,11 @@ def rejpg_argparse(args):
|
|||
f.write(new_bytes)
|
||||
f.close()
|
||||
|
||||
print('Saved', bytestring.bytestring(bytes_saved))
|
||||
print('Remaining are', bytestring.bytestring(remaining_size))
|
||||
log.info('Saved', bytestring.bytestring(bytes_saved))
|
||||
log.info('Remaining are', bytestring.bytestring(remaining_size))
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
49
repeat.py
49
repeat.py
|
@ -2,6 +2,9 @@
|
|||
Repeat the input as many times as you want.
|
||||
|
||||
> repeat "hello" 8
|
||||
|
||||
> repeat "yowza" inf
|
||||
|
||||
> echo hi | repeat !i 4
|
||||
'''
|
||||
import argparse
|
||||
|
@ -9,30 +12,36 @@ import sys
|
|||
|
||||
from voussoirkit import pipeable
|
||||
|
||||
def repeat_inf(text):
|
||||
try:
|
||||
while True:
|
||||
pipeable.stdout(text)
|
||||
except KeyboardInterrupt:
|
||||
return 0
|
||||
|
||||
def repeat_times(text, times):
|
||||
try:
|
||||
times = int(times)
|
||||
except ValueError:
|
||||
pipeable.stderr('times should be an integer >= 1.')
|
||||
return 1
|
||||
|
||||
if times < 1:
|
||||
pipeable.stderr('times should be >= 1.')
|
||||
return 1
|
||||
|
||||
try:
|
||||
for t in range(times):
|
||||
pipeable.stdout(text)
|
||||
except KeyboardInterrupt:
|
||||
return 1
|
||||
|
||||
def repeat_argparse(args):
|
||||
text = pipeable.input(args.text, split_lines=False)
|
||||
if args.times == 'inf':
|
||||
try:
|
||||
while True:
|
||||
print(text)
|
||||
except KeyboardInterrupt:
|
||||
return 0
|
||||
return repeat_inf(text)
|
||||
else:
|
||||
try:
|
||||
times = int(args.times)
|
||||
except ValueError:
|
||||
pipeable.stderr('times should be an integer >= 1.')
|
||||
return 1
|
||||
|
||||
if times < 1:
|
||||
pipeable.stderr('times should be >= 1.')
|
||||
return 1
|
||||
|
||||
try:
|
||||
for t in range(times):
|
||||
print(text)
|
||||
except KeyboardInterrupt:
|
||||
return 1
|
||||
return repeat_times(text, args.times)
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -2,7 +2,6 @@ import sys
|
|||
|
||||
from voussoirkit import pipeable
|
||||
|
||||
|
||||
lines = pipeable.input(sys.argv[1])
|
||||
replace_from = sys.argv[2]
|
||||
replace_to = sys.argv[3]
|
||||
|
|
1
repr.py
1
repr.py
|
@ -1,5 +1,4 @@
|
|||
from voussoirkit import pipeable
|
||||
|
||||
|
||||
for line in pipeable.go():
|
||||
print(repr(line))
|
||||
|
|
10
resize.py
10
resize.py
|
@ -38,7 +38,6 @@ from voussoirkit import imagetools
|
|||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import vlogging
|
||||
from voussoirkit import winglob
|
||||
|
||||
log = vlogging.getLogger(__name__, 'resize')
|
||||
|
||||
|
@ -102,10 +101,11 @@ def resize(
|
|||
image.save(new_name.absolute_path, exif=image.info.get('exif', b''), quality=quality)
|
||||
|
||||
def resize_argparse(args):
|
||||
filenames = winglob.glob(args.pattern)
|
||||
for filename in filenames:
|
||||
patterns = pipeable.input(args.pattern, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
for file in files:
|
||||
resize(
|
||||
filename,
|
||||
file,
|
||||
args.new_w,
|
||||
args.new_h,
|
||||
inplace=args.inplace,
|
||||
|
@ -115,6 +115,8 @@ def resize_argparse(args):
|
|||
quality=args.quality,
|
||||
)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -4,13 +4,17 @@ Reverse a string.
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
from voussoirkit import pipeable
|
||||
|
||||
def reverse_argparse(args):
|
||||
print(''.join(reversed(args.string)))
|
||||
text = pipeable.input(args.text, split_lines=False)
|
||||
pipeable.stdout(''.join(reversed(text)))
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
parser.add_argument('string')
|
||||
parser.add_argument('text')
|
||||
parser.set_defaults(func=reverse_argparse)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
|
|
@ -8,8 +8,8 @@ from voussoirkit import pipeable
|
|||
|
||||
def reverse_argparse(args):
|
||||
lines = list(pipeable.input(args.lines))
|
||||
lines.reverse()
|
||||
print('\n'.join(lines))
|
||||
pipeable.stdout('\n'.join(reversed(lines)))
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
26
rotate.py
26
rotate.py
|
@ -1,28 +1,29 @@
|
|||
import argparse
|
||||
import os
|
||||
import PIL.Image
|
||||
import sys
|
||||
|
||||
from voussoirkit import imagetools
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import vlogging
|
||||
from voussoirkit import winglob
|
||||
|
||||
log = vlogging.getLogger(__name__, 'rotate')
|
||||
|
||||
def rotate_argparse(args):
|
||||
if args.angle is None and not args.exif:
|
||||
pipeable.stderr('Either an angle or --exif must be provided.')
|
||||
log.fatal('Either an angle or --exif must be provided.')
|
||||
return 1
|
||||
|
||||
filenames = winglob.glob(args.pattern)
|
||||
for filename in filenames:
|
||||
image = PIL.Image.open(filename)
|
||||
patterns = pipeable.input(args.pattern, skip_blank=True, strip=True)
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
|
||||
for file in files:
|
||||
image = PIL.Image.open(file.absolute_path)
|
||||
|
||||
if args.exif:
|
||||
(new_image, exif) = imagetools.rotate_by_exif(image)
|
||||
if new_image is image:
|
||||
log.debug('%s doesn\'t need exif rotation.', filename)
|
||||
log.debug('%s doesn\'t need exif rotation.', file.absolute_path)
|
||||
continue
|
||||
image = new_image
|
||||
else:
|
||||
|
@ -30,16 +31,19 @@ def rotate_argparse(args):
|
|||
image = image.rotate(args.angle, expand=True)
|
||||
|
||||
if args.inplace:
|
||||
newname = filename
|
||||
newname = file
|
||||
else:
|
||||
if args.exif:
|
||||
suffix = f'_exifrot'
|
||||
else:
|
||||
suffix = f'_{args.angle}'
|
||||
(base, extension) = os.path.splitext(filename)
|
||||
newname = base + suffix + extension
|
||||
|
||||
base = file.replace_extension('').basename
|
||||
newname = base + suffix
|
||||
newname = file.parent.with_child(newname).add_extension(file.extension)
|
||||
|
||||
pipeable.stdout(newname)
|
||||
image.save(newname, exif=exif, quality=args.quality)
|
||||
image.save(file.absolute_path, exif=exif, quality=args.quality)
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
|
|
|
@ -251,6 +251,7 @@ def _search_argparse(args):
|
|||
result_count += 1
|
||||
if args.show_count:
|
||||
print('%d items.' % result_count)
|
||||
return 0
|
||||
|
||||
@pipeable.ctrlc_return1
|
||||
def search_argparse(args):
|
||||
|
|
|
@ -12,6 +12,8 @@ def shuffle_argparse(args):
|
|||
for line in lines:
|
||||
pipeable.stdout(line)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
3
size.py
3
size.py
|
@ -14,7 +14,8 @@ def main(argv):
|
|||
elif path.is_dir:
|
||||
total += spinal.get_dir_size(path)
|
||||
|
||||
print(total)
|
||||
pipeable.stdout(total)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
|
@ -53,6 +53,8 @@ def sole_lift_argparse(args):
|
|||
os.rmdir(temp_dir.absolute_path)
|
||||
queue.append(directory.parent)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -14,6 +14,8 @@ def sorted_argparse(args):
|
|||
for line in lines:
|
||||
pipeable.stdout(line)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ def printstderr_argparse(args):
|
|||
for line in text:
|
||||
pipeable.stderr(line)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -12,6 +12,8 @@ def printstdout_argparse(args):
|
|||
for line in text:
|
||||
pipeable.stdout(line)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -2,10 +2,10 @@ import PIL.Image
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import sentinel
|
||||
from voussoirkit import vlogging
|
||||
from voussoirkit import winglob
|
||||
|
||||
log = vlogging.getLogger(__name__, 'stitch')
|
||||
|
||||
|
@ -14,8 +14,8 @@ HORIZONTAL = sentinel.Sentinel('horizontal')
|
|||
|
||||
def stitch_argparse(args):
|
||||
patterns = pipeable.input_many(args.image_files, skip_blank=True, strip=True)
|
||||
files = [file for pattern in patterns for file in winglob.glob(pattern)]
|
||||
images = [PIL.Image.open(file) for file in files]
|
||||
files = pathclass.glob_many(patterns, files=True)
|
||||
images = [PIL.Image.open(file.absolute_path) for file in files]
|
||||
if args.vertical:
|
||||
direction = VERTICAL
|
||||
else:
|
||||
|
@ -42,6 +42,7 @@ def stitch_argparse(args):
|
|||
|
||||
log.info(args.output)
|
||||
final_image.save(args.output)
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
|
|
3
sum.py
3
sum.py
|
@ -1,5 +1,4 @@
|
|||
from voussoirkit import pipeable
|
||||
|
||||
|
||||
total = sum(float(x) for x in pipeable.go() if x.strip())
|
||||
pipeable.stdout(f'{total}\n')
|
||||
pipeable.stdout(f'{total}')
|
||||
|
|
|
@ -88,6 +88,8 @@ def svgrender_argparse(args):
|
|||
axis='y' if args.y else 'x',
|
||||
)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -8,6 +8,10 @@ import time
|
|||
from voussoirkit import bytestring
|
||||
from voussoirkit import downloady
|
||||
from voussoirkit import pipeable
|
||||
from voussoirkit import vlogging
|
||||
|
||||
log = vlogging.getLogger(__name__, 'threaded_dl')
|
||||
downloady.log.setLevel(vlogging.WARNING)
|
||||
|
||||
def clean_url_list(urls):
|
||||
for url in urls:
|
||||
|
@ -29,7 +33,7 @@ def clean_url_list(urls):
|
|||
yield url
|
||||
|
||||
def download_thread(url, filename, *, bytespersecond=None, headers=None, timeout=None):
|
||||
print(f' Starting "{filename}"')
|
||||
log.info(f'Starting "{filename}"')
|
||||
downloady.download_file(
|
||||
url,
|
||||
filename,
|
||||
|
@ -37,7 +41,7 @@ def download_thread(url, filename, *, bytespersecond=None, headers=None, timeout
|
|||
headers=headers,
|
||||
timeout=timeout,
|
||||
)
|
||||
print(f'+Finished "{filename}"')
|
||||
log.info(f'Finished "{filename}"')
|
||||
|
||||
def remove_finished(threads):
|
||||
return [t for t in threads if t.is_alive()]
|
||||
|
@ -87,7 +91,7 @@ def threaded_dl(
|
|||
)
|
||||
|
||||
if os.path.exists(filename):
|
||||
print(f'Skipping existing file "{filename}"')
|
||||
log.info(f'Skipping existing file "{filename}"')
|
||||
|
||||
else:
|
||||
kwargs = {
|
||||
|
@ -103,7 +107,7 @@ def threaded_dl(
|
|||
|
||||
while len(threads) > 0:
|
||||
threads = remove_finished(threads)
|
||||
print(f'{len(threads)} threads remaining\r', end='', flush=True)
|
||||
pipeable.stderr(f'{len(threads)} threads remaining\r', end='')
|
||||
time.sleep(0.1)
|
||||
|
||||
def threaded_dl_argparse(args):
|
||||
|
@ -132,6 +136,9 @@ def threaded_dl_argparse(args):
|
|||
timeout=args.timeout,
|
||||
)
|
||||
|
||||
return 0
|
||||
|
||||
@vlogging.main_decorator
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
2
touch.py
2
touch.py
|
@ -21,6 +21,8 @@ def touch_argparse(args):
|
|||
os.utime(filename)
|
||||
pipeable.stdout(filename)
|
||||
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ def unique_argparse(args):
|
|||
if line not in seen:
|
||||
pipeable.stdout(line)
|
||||
seen.add(line)
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -42,6 +42,7 @@ def watchforlinks_argparse(args):
|
|||
loop_forever(extension=args.extension, regex=args.regex)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
|
|
|
@ -4,10 +4,8 @@ import sys
|
|||
|
||||
from voussoirkit import bytestring
|
||||
|
||||
|
||||
filename = os.path.abspath(sys.argv[1])
|
||||
|
||||
|
||||
def zerofile(filename, length):
|
||||
if os.path.exists(filename):
|
||||
raise ValueError(f'{filename} already exists.')
|
||||
|
|
Loading…
Reference in a new issue