mirror of
https://github.com/chatmail/relay.git
synced 2026-05-20 12:58:04 +00:00
strike superflous code
This commit is contained in:
@@ -4,6 +4,7 @@ Expire old messages and addresses.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -13,27 +14,19 @@ from chatmaild.config import read_config
|
|||||||
|
|
||||||
|
|
||||||
class FileEntry:
|
class FileEntry:
|
||||||
def __init__(self, basedir, relpath, mtime, size):
|
def __init__(self, relpath, mtime, size):
|
||||||
self.basedir = basedir
|
|
||||||
self.relpath = relpath
|
self.relpath = relpath
|
||||||
self.mtime = mtime
|
self.mtime = mtime
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self.relpath)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<FileEntry size={self.size} '{self.relpath}' >"
|
return f"<FileEntry size={self.size} '{self.relpath}' >"
|
||||||
|
|
||||||
def __str__(self):
|
def get_path(self, basedir):
|
||||||
return self.get_path()
|
return joinpath(basedir, self.relpath)
|
||||||
|
|
||||||
def get_path(self):
|
|
||||||
return joinpath(self.basedir, self.relpath)
|
|
||||||
|
|
||||||
def fmt_size(self):
|
|
||||||
return f"{int(self.size/1000):5.0f}K"
|
|
||||||
|
|
||||||
def fmt_since(self, now):
|
|
||||||
diff_seconds = int(now) - int(self.mtime)
|
|
||||||
return f"{int(diff_seconds / 86400):2.0f}d"
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (
|
return (
|
||||||
@@ -50,7 +43,6 @@ def joinpath(name, extra):
|
|||||||
class Stats:
|
class Stats:
|
||||||
def __init__(self, basedir, maxnum=None):
|
def __init__(self, basedir, maxnum=None):
|
||||||
self.basedir = str(basedir)
|
self.basedir = str(basedir)
|
||||||
self.mailboxes = []
|
|
||||||
self.maxnum = maxnum
|
self.maxnum = maxnum
|
||||||
|
|
||||||
def iter_mailboxes(self, callback=None):
|
def iter_mailboxes(self, callback=None):
|
||||||
@@ -58,7 +50,6 @@ class Stats:
|
|||||||
if "@" in name:
|
if "@" in name:
|
||||||
basedir = joinpath(self.basedir, name)
|
basedir = joinpath(self.basedir, name)
|
||||||
mailbox = MailboxStat(basedir)
|
mailbox = MailboxStat(basedir)
|
||||||
self.mailboxes.append(mailbox)
|
|
||||||
if callback is not None:
|
if callback is not None:
|
||||||
callback(mailbox)
|
callback(mailbox)
|
||||||
|
|
||||||
@@ -86,17 +77,13 @@ class MailboxStat:
|
|||||||
st = os.stat(msg_path)
|
st = os.stat(msg_path)
|
||||||
relpath = joinpath(name, msg_name)
|
relpath = joinpath(name, msg_name)
|
||||||
self.messages.append(
|
self.messages.append(
|
||||||
FileEntry(
|
FileEntry(relpath, mtime=st.st_mtime, size=st.st_size)
|
||||||
self.basedir, relpath, mtime=st.st_mtime, size=st.st_size
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
self.totalsize += st.st_size
|
self.totalsize += st.st_size
|
||||||
else:
|
else:
|
||||||
st = os.stat(fpath)
|
st = os.stat(fpath)
|
||||||
if S_ISREG(st.st_mode):
|
if S_ISREG(st.st_mode):
|
||||||
self.extrafiles.append(
|
self.extrafiles.append(FileEntry(name, st.st_mtime, st.st_size))
|
||||||
FileEntry(self.basedir, name, st.st_mtime, st.st_size)
|
|
||||||
)
|
|
||||||
if name == "password":
|
if name == "password":
|
||||||
self.last_login = st.st_mtime
|
self.last_login = st.st_mtime
|
||||||
self.totalsize += st.st_size
|
self.totalsize += st.st_size
|
||||||
@@ -108,8 +95,9 @@ def print_info(msg):
|
|||||||
|
|
||||||
|
|
||||||
class Expiry:
|
class Expiry:
|
||||||
def __init__(self, config, stat, dry, now):
|
def __init__(self, config, stats, dry, now):
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.stats = stats
|
||||||
self.dry = dry
|
self.dry = dry
|
||||||
self.now = now
|
self.now = now
|
||||||
self.del_files = []
|
self.del_files = []
|
||||||
@@ -119,13 +107,14 @@ class Expiry:
|
|||||||
for mboxdir in self.del_mailboxes:
|
for mboxdir in self.del_mailboxes:
|
||||||
print_info(f"removing {mboxdir}")
|
print_info(f"removing {mboxdir}")
|
||||||
if not self.dry:
|
if not self.dry:
|
||||||
self.rmtree(mboxdir)
|
shutil.rmtree(mboxdir)
|
||||||
for path in self.del_files:
|
for path in self.del_files:
|
||||||
print_info(f"removing {path}")
|
print_info(f"removing {path}")
|
||||||
if not self.dry:
|
if not self.dry:
|
||||||
try:
|
try:
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
print_info(f"delete failed, file vanished? {path}")
|
||||||
pass # it's gone already, fine
|
pass # it's gone already, fine
|
||||||
|
|
||||||
def process_mailbox_stat(self, mbox):
|
def process_mailbox_stat(self, mbox):
|
||||||
@@ -143,9 +132,9 @@ class Expiry:
|
|||||||
|
|
||||||
for message in mbox.messages:
|
for message in mbox.messages:
|
||||||
if message.mtime < cutoff_mails:
|
if message.mtime < cutoff_mails:
|
||||||
self.del_files.append(message.get_path())
|
self.del_files.append(joinpath(mbox.basedir, message.relpath))
|
||||||
elif message.size > 200000 and message.mtime < cutoff_large_mails:
|
elif message.size > 200000 and message.mtime < cutoff_large_mails:
|
||||||
self.del_files.append(message.get_path())
|
self.del_files.append(joinpath(mbox.basedir, message.relpath))
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
changed = True
|
changed = True
|
||||||
@@ -187,9 +176,9 @@ def main(args):
|
|||||||
now = now - 86400 * int(args.days)
|
now = now - 86400 * int(args.days)
|
||||||
|
|
||||||
maxnum = int(args.maxnum) if args.maxnum else None
|
maxnum = int(args.maxnum) if args.maxnum else None
|
||||||
stat = Stats(args.mailboxes_dir, maxnum=maxnum)
|
stats = Stats(args.mailboxes_dir, maxnum=maxnum)
|
||||||
exp = Expiry(config, stat, dry=not args.remove, now=now)
|
exp = Expiry(config, stats, dry=not args.remove, now=now)
|
||||||
stat.iter_mailboxes(exp.process_mailbox_stat)
|
stats.iter_mailboxes(exp.process_mailbox_stat)
|
||||||
exp.perform_removes()
|
exp.perform_removes()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class Report:
|
|||||||
self.sum_extra = 0
|
self.sum_extra = 0
|
||||||
self.sum_all_messages = 0
|
self.sum_all_messages = 0
|
||||||
self.messages = []
|
self.messages = []
|
||||||
|
self.mailboxes = []
|
||||||
self.user_logins = []
|
self.user_logins = []
|
||||||
self.ci_logins = []
|
self.ci_logins = []
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
@@ -52,6 +53,7 @@ class Report:
|
|||||||
else:
|
else:
|
||||||
self.user_logins.append(last_login)
|
self.user_logins.append(last_login)
|
||||||
self.messages.extend(mailbox.messages)
|
self.messages.extend(mailbox.messages)
|
||||||
|
self.mailboxes.append(mailbox)
|
||||||
self.sum_all_messages += sum(msg.size for msg in mailbox.messages)
|
self.sum_all_messages += sum(msg.size for msg in mailbox.messages)
|
||||||
self.sum_extra += sum(entry.size for entry in mailbox.extrafiles)
|
self.sum_extra += sum(entry.size for entry in mailbox.extrafiles)
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ class Report:
|
|||||||
# list all 160K files of people who haven't logged in for a while
|
# list all 160K files of people who haven't logged in for a while
|
||||||
messages = []
|
messages = []
|
||||||
cutoff_date_login = self.now - 30 * DAYSECONDS
|
cutoff_date_login = self.now - 30 * DAYSECONDS
|
||||||
for mstat in self.stats.mailboxes:
|
for mstat in self.mailboxes:
|
||||||
if mstat.last_login and mstat.last_login < cutoff_date_login:
|
if mstat.last_login and mstat.last_login < cutoff_date_login:
|
||||||
for msg in mstat.messages:
|
for msg in mstat.messages:
|
||||||
if msg.size > 160000:
|
if msg.size > 160000:
|
||||||
@@ -132,7 +134,10 @@ def main(args=None):
|
|||||||
"mailboxes_dir", action="store", help="path to directory of mailboxes"
|
"mailboxes_dir", action="store", help="path to directory of mailboxes"
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--days", default=0, action="store", help="assume date to be days older than now"
|
"--days",
|
||||||
|
default=0,
|
||||||
|
action="store",
|
||||||
|
help="assume date to be days older than now",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from chatmaild.doveauth import AuthDictProxy
|
from chatmaild.doveauth import AuthDictProxy
|
||||||
from chatmaild.expire import run_expire
|
from chatmaild.expire import main as main_expire
|
||||||
|
|
||||||
|
|
||||||
def test_login_timestamps(example_config):
|
def test_login_timestamps(example_config):
|
||||||
@@ -45,7 +45,13 @@ def test_delete_inactive_users(example_config):
|
|||||||
for addr in to_remove:
|
for addr in to_remove:
|
||||||
assert example_config.get_user(addr).maildir.exists()
|
assert example_config.get_user(addr).maildir.exists()
|
||||||
|
|
||||||
run_expire(example_config, example_config.mailboxes_dir)
|
main_expire(
|
||||||
|
args=[
|
||||||
|
"--remove",
|
||||||
|
str(example_config._inipath),
|
||||||
|
str(example_config.mailboxes_dir),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
for p in example_config.mailboxes_dir.iterdir():
|
for p in example_config.mailboxes_dir.iterdir():
|
||||||
assert not p.name.startswith("old")
|
assert not p.name.startswith("old")
|
||||||
|
|||||||
@@ -46,10 +46,7 @@ def mbox1(basedir1):
|
|||||||
|
|
||||||
|
|
||||||
def test_filentry_ordering(tmp_path):
|
def test_filentry_ordering(tmp_path):
|
||||||
l = [
|
l = [FileEntry(f"x{i}", size=i + 10, mtime=1000 - i) for i in range(10)]
|
||||||
FileEntry(str(tmp_path), f"x{i}", size=i + 10, mtime=1000 - i)
|
|
||||||
for i in range(10)
|
|
||||||
]
|
|
||||||
sorted = list(l)
|
sorted = list(l)
|
||||||
random.shuffle(l)
|
random.shuffle(l)
|
||||||
l.sort(key=lambda x: x.size)
|
l.sort(key=lambda x: x.size)
|
||||||
@@ -93,8 +90,6 @@ def test_expiry_cli_basic(example_config, mbox1):
|
|||||||
|
|
||||||
|
|
||||||
def test_expiry_cli_old_files(capsys, example_config, mbox1):
|
def test_expiry_cli_old_files(capsys, example_config, mbox1):
|
||||||
args = example_config._inipath, Path(mbox1.basedir).parent
|
|
||||||
|
|
||||||
relpaths_old = ["cur/msg_old1", "cur/msg_old1"]
|
relpaths_old = ["cur/msg_old1", "cur/msg_old1"]
|
||||||
cutoff_days = int(example_config.delete_mails_after) + 1
|
cutoff_days = int(example_config.delete_mails_after) + 1
|
||||||
create_new_messages(mbox1.basedir, relpaths_old, size=1000, days=cutoff_days)
|
create_new_messages(mbox1.basedir, relpaths_old, size=1000, days=cutoff_days)
|
||||||
@@ -107,6 +102,7 @@ def test_expiry_cli_old_files(capsys, example_config, mbox1):
|
|||||||
|
|
||||||
create_new_messages(mbox1.basedir, ["cur/shouldstay"], size=1000 * 300, days=1)
|
create_new_messages(mbox1.basedir, ["cur/shouldstay"], size=1000 * 300, days=1)
|
||||||
|
|
||||||
|
args = example_config._inipath, Path(mbox1.basedir).parent, "--remove"
|
||||||
expiry_main(args)
|
expiry_main(args)
|
||||||
out, err = capsys.readouterr()
|
out, err = capsys.readouterr()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user