new spanking

This commit is contained in:
Ville Rantanen
2020-12-28 22:51:17 +02:00
parent 9c1fab0d21
commit 906f6fd457

167
flit.py
View File

@@ -3,16 +3,14 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
import argparse import argparse
import os import os
import sys
import random import random
import shutil import shutil
import string import string
from urllib.parse import quote from urllib.parse import quote
import json import json
DEL_TIME = '.delete_in' CONFIG = ".flit.json"
DESCRIPTION = '.description'
CONFIG = '.flit.json'
def parse_opts(): def parse_opts():
class _HelpAction(argparse._HelpAction): class _HelpAction(argparse._HelpAction):
@@ -21,7 +19,8 @@ def parse_opts():
print("") print("")
# retrieve subparsers from parser # retrieve subparsers from parser
subparsers_actions = [ subparsers_actions = [
action for action in parser._actions action
for action in parser._actions
if isinstance(action, argparse._SubParsersAction) if isinstance(action, argparse._SubParsersAction)
] ]
for subparsers_action in subparsers_actions: for subparsers_action in subparsers_actions:
@@ -34,38 +33,35 @@ def parse_opts():
parser = argparse.ArgumentParser(add_help=False) parser = argparse.ArgumentParser(add_help=False)
parser.add_argument( parser.add_argument(
'--help', '-h', "--help", "-h", action=_HelpAction, help="Show this help message and exit"
action = _HelpAction,
help = 'Show this help message and exit'
) )
parser.add_argument( parser.add_argument(
'--verbose', '-v', "--verbose",
"-v",
action="store_true", action="store_true",
dest="verbose", dest="verbose",
default=False, default=False,
help = 'Increase verbosity' help="Increase verbosity",
) )
parser.add_argument( parser.add_argument(
'--root', '-r', "--root",
"-r",
action="store", action="store",
dest="root", dest="root",
type=str, type=str,
default="", default="",
help = 'Root address for printing URLS' help="Root address for printing URLS",
) )
subparsers = parser.add_subparsers( subparsers = parser.add_subparsers(dest="command", help="Command defaults to add")
dest="command", add_parser = subparsers.add_parser("add", add_help=False)
help = "Command defaults to add"
)
add_parser = subparsers.add_parser('add', add_help=False)
add_parser.add_argument( add_parser.add_argument(
"-d", "-d",
action="store", action="store",
type=int, type=int,
help="Days to keep files", help="Days to keep files",
default=30, default=30,
dest = 'days' dest="days",
) )
add_parser.add_argument( add_parser.add_argument(
"-m", "-m",
@@ -73,7 +69,7 @@ def parse_opts():
type=str, type=str,
help="Describe share", help="Describe share",
default="-", default="-",
dest = 'description' dest="description",
) )
add_parser.add_argument( add_parser.add_argument(
"files", "files",
@@ -81,27 +77,29 @@ def parse_opts():
type=str, type=str,
help="Copy files/folders under the new share", help="Copy files/folders under the new share",
default=[], default=[],
nargs = '*' nargs="*",
) )
list_parser = subparsers.add_parser('list', add_help=False) list_parser = subparsers.add_parser("list", add_help=False)
list_parser.add_argument( list_parser.add_argument(
'--verbose', '-v', "--verbose",
"-v",
action="store_true", action="store_true",
dest="verbose", dest="verbose",
default=False, default=False,
help = 'Print individual files too' help="Print individual files too",
) )
del_parser = subparsers.add_parser('del', add_help=False) del_parser = subparsers.add_parser("del", add_help=False)
return parser.parse_args() return parser.parse_args()
def random_char(): def random_char():
return random.choice(string.ascii_uppercase + string.digits) return random.choice(string.ascii_uppercase + string.digits)
def random_name(): def random_name():
while True: while True:
existing_names = get_folder_names() existing_names = [c["name"] for c in get_folders()]
index = 0 index = 0
for existing in existing_names: for existing in existing_names:
try: try:
@@ -112,7 +110,7 @@ def random_name():
name = "{:03d}-{}-{}".format( name = "{:03d}-{}-{}".format(
index, index,
"".join([random_char() for x in range(3)]), "".join([random_char() for x in range(3)]),
"".join([random_char() for x in range(3)]) "".join([random_char() for x in range(3)]),
) )
if not os.path.exists(name): if not os.path.exists(name):
break break
@@ -121,10 +119,14 @@ def random_name():
def create_new(p, days, description): def create_new(p, days, description):
os.mkdir(p) os.mkdir(p)
with open(os.path.join(p, DEL_TIME), 'wt') as fp: now = datetime.now()
fp.write(str(days)) del_delta = timedelta(days=days)
with open(os.path.join(p, DESCRIPTION), 'wt') as fp: del_time = now + del_delta
fp.write(description) config = {}
config["description"] = description
config["delete_time"] = del_time.isoformat()
config["created"] = now.isoformat()
write_config(p, config)
def copy_files(cwd, new_name, files): def copy_files(cwd, new_name, files):
@@ -133,10 +135,7 @@ def copy_files(cwd, new_name, files):
print(f"Copying: {f}") print(f"Copying: {f}")
source = os.path.join(cwd, f) source = os.path.join(cwd, f)
if os.path.isfile(source): if os.path.isfile(source):
shutil.copy2( shutil.copy2(source, target)
source,
target
)
else: else:
shutil.copytree( shutil.copytree(
source, source,
@@ -144,19 +143,20 @@ def copy_files(cwd, new_name, files):
symlinks=True, symlinks=True,
) )
def get_description(f):
try: # def get_description(f):
with open(f) as fp: # try:
return "".join(filter(lambda x: x in string.printable, fp.read(32).split("\n")[0])) # with open(f) as fp:
except: # return "".join(filter(lambda x: x in string.printable, fp.read(32).split("\n")[0]))
return "-" # except:
# return "-"
def get_stats(p): def get_stats(p):
# TODO: named tuple # TODO: named tuple
config = read_config(p) config = read_config(p)
if config is None: if config is None:
with open(os.path.join(p, DEL_TIME), 'rt') as fp: with open(os.path.join(p, DEL_TIME), "rt") as fp:
do_del = int(fp.read(64)) do_del = int(fp.read(64))
desc = get_description(os.path.join(p, DESCRIPTION)) desc = get_description(os.path.join(p, DESCRIPTION))
now = datetime.now() now = datetime.now()
@@ -166,19 +166,26 @@ def get_stats(p):
to_del_time = del_time - now to_del_time = del_time - now
is_due = now > del_time is_due = now > del_time
config = {} config = {}
config['description'] = desc config["description"] = desc
config['delete_time'] = del_time.isoformat() config["delete_time"] = del_time
config['created'] = mtime.isoformat() config["created"] = mtime
else: else:
desc = config['description'] desc = config["description"]
del_time = datetime.fromisoformat(config['delete_time']) del_time = datetime.fromisoformat(config["delete_time"])
now = datetime.now() now = datetime.now()
mtime = datetime.fromisoformat(config['created']) mtime = datetime.fromisoformat(config["created"])
to_del_time = del_time - now to_del_time = del_time - now
is_due = now > del_time is_due = now > del_time
config["delete_time"] = del_time
config["created"] = mtime
config["name"] = p
config["to_deletion"] = to_del_time
config["due"] = is_due
write_config(p, config) # mtime, del_time, to_del_time, is_due, desc
return mtime, del_time, to_del_time, is_due, desc # write_config(p, config)
return config
def get_sub_files(p): def get_sub_files(p):
@@ -188,67 +195,65 @@ def get_sub_files(p):
return dir_list + file_list return dir_list + file_list
def get_folder_names(): def get_folders():
dir_list = [(p,os.path.getmtime(os.path.join(p, DEL_TIME))) for p in os.listdir(".") if os.path.exists(os.path.join(p, DEL_TIME))] dir_list = [p for p in os.listdir(".") if os.path.exists(os.path.join(p, CONFIG))]
dir_list.sort(key = lambda t: -t[1]) configs = [get_stats(p) for p in dir_list]
return [p[0] for p in dir_list] configs.sort(key=lambda c: c["created"], reverse=True)
return configs
def list_folders(root_folder, verbose=False, filter_name=None): def list_folders(root_folder, verbose=False, filter_name=None):
names = get_folder_names() folders = get_folders()
print("Folder Created ToDelete InDays") print("Folder Created ToDelete InDays")
for p in names: for c in folders:
if filter_name is not None: if filter_name is not None:
if filter_name != p: if filter_name != c["name"]:
continue continue
stats = get_stats(p) due = "*" if c["due"] else " "
sub_files = get_sub_files(p) print(
due = "*" if stats[3] else " " "{}/{}/ {} {} {: 4d}d{} {}".format(
print("{}/{}/ {} {} {: 4d}d{} {}".format(
root_folder, root_folder,
p, c["name"],
stats[0].isoformat()[0:10], c["created"].isoformat()[0:10],
stats[1].isoformat()[0:10], c["delete_time"].isoformat()[0:10],
stats[2].days, c["to_deletion"].days,
due, due,
stats[4] c["description"],
)) )
)
if verbose: if verbose:
sub_files = get_sub_files(c["name"])
for sp in sub_files: for sp in sub_files:
print(" {}/{}/{}".format(root_folder,p,quote(sp,"/"))) print(" {}/{}/{}".format(root_folder, c["name"], quote(sp, "/")))
# print(p, stats, sub_files) # print(p, stats, sub_files)
def del_due_folders(): def del_due_folders():
names = get_folder_names() folders = get_folders()
for p in names: for c in folders:
stats = get_stats(p) if c["due"]:
due = stats[3] print("Deleting {}".format(c["name"]))
if due: shutil.rmtree(c["name"])
print("Deleting {}".format(p))
shutil.rmtree(p)
def read_config(p): def read_config(p):
try: try:
with open(os.path.join(p,CONFIG),'rt') as fp: with open(os.path.join(p, CONFIG), "rt") as fp:
return json.load(fp) return json.load(fp)
except: except:
return None return None
def write_config(p, config): def write_config(p, config):
with open(os.path.join(p,CONFIG),'wt') as fp: with open(os.path.join(p, CONFIG), "wt") as fp:
return json.dump(config, fp, indent=2, sort_keys=True) return json.dump(config, fp, indent=2, sort_keys=True)
if __name__ == "__main__":
if __name__ == '__main__':
opts = parse_opts() opts = parse_opts()
cwd = os.getcwd() cwd = os.getcwd()
os.chdir(os.path.dirname(__file__)) os.chdir(os.path.dirname(__file__))
if opts.command == 'add': if opts.command == "add":
new_name = random_name() new_name = random_name()
create_new(new_name, opts.days, opts.description) create_new(new_name, opts.days, opts.description)
print(os.path.abspath(new_name)) print(os.path.abspath(new_name))
@@ -261,5 +266,3 @@ if __name__ == '__main__':
if opts.command == "del": if opts.command == "del":
del_due_folders() del_due_folders()