commit 3375325620af7d5c30dfb0f44eb83966c5038995
parent 798fdbd5e8a4be6a6d940cb53c7fc5cca9edb43d
Author: nolash <dev@holbrook.no>
Date: Fri, 28 Aug 2020 00:19:07 +0200
Add add subcmd for adding directly with editor
Diffstat:
8 files changed, 127 insertions(+), 18 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,3 +1,5 @@
+* 0.4.1
+ - Add list feeds subcommand
* 0.4.0
- Consolidate put and get methods on same adapter interface
- Resolve uncompressed path bug
diff --git a/ROADMAP b/ROADMAP
@@ -0,0 +1,3 @@
+- Add attachments to add command
+- Auto-resolve taskwarrior task numbers to uuids and add to X header
+- Sign entries with PGP
diff --git a/feedwarrior/cmd/add.py b/feedwarrior/cmd/add.py
@@ -0,0 +1,81 @@
+# standard imports
+import os
+from email.message import EmailMessage
+from email.mime.multipart import MIMEMultipart
+import email
+import logging
+import uuid
+import json
+import gzip
+import tempfile
+import base64
+
+# local imports
+import feedwarrior
+from feedwarrior import entry as feedentry
+from feedwarrior.adapters import fileadapter
+
+logg = logging.getLogger()
+
+
+def get_editor():
+ return 'vim'
+
+def parse_args(argparser):
+ argparser.add_argument('-z', action='store_true', help='compress entry with gzip')
+ argparser.add_argument('--task', action='append', help='add taskwarrior task uuid relation')
+ argparser.add_argument('-s', type=str, help='entry subject')
+ return True
+
+
+def check_args(args):
+ pass
+
+
+# TODO: move logic to package to get symmetry with the show.py logic
+def execute(config, feed, args):
+ d = tempfile.TemporaryDirectory()
+ t = tempfile.NamedTemporaryFile(mode='w+', dir=d.name)
+ editor_path = get_editor()
+ os.system('{} {}'.format(get_editor(), t.name))
+ f = open(t.name, 'rb')
+ s = os.stat(t.name)
+ t.close()
+ logg.debug('file {} {}'.format(t.name, s.st_size))
+ content = f.read(s.st_size)
+ f.close()
+
+ entry_date = str(email.utils.formatdate())
+ subject = args.s
+ if subject == None:
+ subject = entry_date
+ m = EmailMessage()
+ m.add_header('Content-Type', 'text/plain')
+ m.add_header('Content-Disposition', 'inline')
+ m.add_header('Content-Transfer-Encoding', 'base64')
+ m.set_param('filename', subject)
+ m.set_param('filename', subject, 'Content-Disposition')
+ bsf = base64.encodebytes(content)
+ m.set_payload(bsf.decode('utf-8'))
+
+
+ mm = MIMEMultipart()
+ mm.attach(m)
+ mm.add_header('Subject', subject)
+ mm.add_header('Date', entry_date)
+ print(mm)
+
+ entry = feedentry.from_multipart(mm)
+ #entry = feedentry.from_multipart_file(args.path)
+ if args.task != None:
+ for t in args.task:
+ uu = feedwarrior.common.parse_uuid(t)
+ entry.add_extension(feedwarrior.extension.TASKWARRIOR, uu)
+
+ uu = str(entry.uuid)
+ logg.debug('adding entry {}'.format(uu))
+
+ fa = fileadapter(config.data_dir, feed.uuid)
+ fa.put(entry.uuid, entry, compress=args.z)
+
+ feed.add(entry)
diff --git a/feedwarrior/cmd/show.py b/feedwarrior/cmd/show.py
@@ -2,6 +2,10 @@
import json
import email
import time
+import sys
+import logging
+
+logg = logging.getLogger(__file__)
def parse_args(argparser):
pass
@@ -16,7 +20,7 @@ def execute(config, feed, args):
while 1:
try:
e = feed.next_entry()
- except IndexError:
+ except IndexError as e:
break
j = json.loads(e)
m = email.message_from_string(j['payload'])
@@ -42,16 +46,16 @@ def execute(config, feed, args):
body += '>>> {}\n\n{}\n\n\n'.format(subject, p.get_payload(decode=True).decode('utf-8'))
if i > 0:
- print('----')
+ sys.stdout.write('----\n')
if body != None:
if args.headers:
for k in m.keys():
print('{}: {}'.format(k, m.get(k)))
- print('{} - {}\n'.format(ts, j['uuid']))
- print(body)
+ sys.stdout.write('{} - {}\n'.format(ts, j['uuid']))
+ sys.stdout.write('{}'.format(body))
for a in attachments:
- print('+ {}'.format(a))
+ sys.stdout.write('+ {}'.format(a))
i += 1
- pass
+ sys.stdout.flush()
diff --git a/feedwarrior/entry.py b/feedwarrior/entry.py
@@ -52,6 +52,7 @@ class entry:
logg.debug('complete message {}'.format(self.message))
d = email.utils.parsedate(self.message.get('Date'))
+ logg.debug('date {} {}'.format(d, self.message.get('Date')))
ts = time.mktime(d)
return {
@@ -70,6 +71,10 @@ def from_multipart_file(filename, hashers=defaulthashers):
f = gzip.open(filename + '.gz', 'rb')
m = email.message_from_file(f)
f.close()
+ return from_multipart(m, hashers)
+
+
+def from_multipart(m, hashers=defaulthashers):
if not m.is_multipart():
raise ValueError('{} is not a MIME multipart message'.format(filename))
diff --git a/feedwarrior/feed.py b/feedwarrior/feed.py
@@ -66,7 +66,7 @@ class feed:
def _sort_entries(self):
- logg.debug('entries for {}'.format(self.uuid), self.entries)
+ logg.debug('entries for {} {}'.format(self.uuid, self.entries))
new_entries = []
for e in self.entries:
entry = self.getter.get(e)
diff --git a/scripts/feedwarrior b/scripts/feedwarrior
@@ -18,11 +18,19 @@ from feedwarrior.cmd import create as cmd_create
from feedwarrior.cmd import entry as cmd_entry
from feedwarrior.cmd import show as cmd_show
from feedwarrior.cmd import ls as cmd_list
+from feedwarrior.cmd import add as cmd_add
logging.basicConfig(level=logging.ERROR)
logg = logging.getLogger()
+def matches_part(full, part):
+ if len(part) > len(full):
+ return False
+ return full[:len(part)] == part
+
+
+
argparser = argparse.ArgumentParser(description='create and manipulate feedwarrior feeds')
argparser.add_argument('-l', help='feed log to operate on')
argparser.add_argument('-c', type=str, help='configuration file')
@@ -39,7 +47,8 @@ sub_create = sub.add_parser('create', help='create new feed')
cmd_create.parse_args(sub_create)
sub_list = sub.add_parser('list', help='list feeds')
cmd_list.parse_args(sub_list)
-
+sub_add = sub.add_parser('add', help='add new entry with editor')
+cmd_add.parse_args(sub_add)
args = argparser.parse_known_args()
@@ -72,20 +81,23 @@ if args.l != None:
sys.exit(1)
+
cmd_mod = None
-if args.command == 'create':
- feed_current = feedwarrior.feed(parent=feed_current)
- cmd_mod = cmd_create
-elif args.command == 'entry':
- cmd_mod = cmd_entry
-elif args.command == 'list':
- cmd_mod = cmd_list
-elif args.command == 'show' or args.command == None:
+if args.command == None or matches_part('show', args.command):
if feed_current == None:
sys.stderr.write('plesae speficy a feed for showing\n')
sys.exit(1)
feed_current = feedwarrior.load_feed(config.data_dir, feed_current.uuid)
cmd_mod = cmd_show
+elif matches_part('create', args.command):
+ feed_current = feedwarrior.feed(parent=feed_current)
+ cmd_mod = cmd_create
+elif matches_part('entry', args.command):
+ cmd_mod = cmd_entry
+elif matches_part('list', args.command) or args.command == 'ls':
+ cmd_mod = cmd_list
+elif matches_part('add', args.command):
+ cmd_mod = cmd_add
else:
sys.stderr.write('invalid command {}\n'.format(args.command))
sys.exit(1)
diff --git a/setup.py b/setup.py
@@ -2,12 +2,14 @@ from setuptools import setup
setup(
name='feedwarrior',
- version='0.4.0',
+ version='0.4.1',
description='feeds, warrior style',
author='Louis Holbrook',
author_email='dev@holbrook.no',
packages=['feedwarrior', 'feedwarrior.cmd'],
- install_requires=['xdg'],
+ install_requires=[
+ 'xdg'
+ ],
scripts = [
'scripts/feedwarrior',
]