class EcogClient(object): def __init__(self, ecoghost, authfile): self.authfile = authfile # saved for later self.access_token = EcogClient.read_auth(authfile) # self.ecog = EcogWiki(ecoghost, self.access_token) @staticmethod def parse_args(): parser = argparse.ArgumentParser( prog='ecog', description='Ecogwiki client - Information in your fingertips', epilog=' ') parser.add_argument('--auth', metavar='FILE', dest='authfile', default='.auth', help='auth file storing access token') parser.add_argument('--host', metavar='HOST', dest='ecoghost', default='www.ecogwiki.com', help='ecogwiki server host') parser.add_argument('--version', action='version', version='%(prog)s ' + __version__, default=None) subparsers = parser.add_subparsers(metavar='COMMAND', dest='command', title='ecogwiki commands') cat_parser = subparsers.add_parser('cat', help='print page in markdown') get_parser = subparsers.add_parser('get', help='print page in json') list_parser = subparsers.add_parser('list', help="list pages info") title_parser = subparsers.add_parser('title', help='list all titles') recent_parser = subparsers.add_parser( 'recent', help='list recent modified pages') edit_parser = subparsers.add_parser( 'edit', help='edit page with editor', description='Edit page with your favorite editor ($EDITOR)') append_parser = subparsers.add_parser( 'append', help='only append text', description='Quickly append to page') memo_parser = subparsers.add_parser('memo', help='quick memo', description='Edit your daily memo') edit_parser.add_argument('title', metavar='TITLE', help='page title') edit_parser.add_argument('--template', metavar='TEXT', help='text on new file', default=None) edit_parser.add_argument('--comment', metavar='MSG', help='edit comment message', default='') memo_parser.add_argument('--comment', metavar='MSG', help='edit comment message', default='') get_parser.add_argument('title', metavar='TITLE', help='page title') cat_parser.add_argument('title', metavar='TITLE', help='page title') get_parser.add_argument('--revision', metavar='REV', help='specific revision number', type=int) cat_parser.add_argument('--revision', metavar='REV', help='specific revision number', type=int) get_parser.add_argument( '--format', metavar='FORMAT', help='one of [json|html|markdown|atom], json by default', choices=['json', 'txt', 'atom', 'markdown', 'html'], default='json') append_parser.add_argument('title', metavar='TITLE', help='page title') append_parser.add_argument('body', nargs='?', metavar='TEXT', help='body text. fires editor if not given', default='') append_parser.add_argument('--comment', metavar='MSG', help='comment message', default='') # args = parser.parse_args() if '://' not in args.ecoghost: args.ecoghost = 'http://' + args.ecoghost if not args.authfile.startswith('/'): args.authfile = os.path.join(CWD, args.authfile) if args.version: output(__version__) sys.exit(0) return args @staticmethod def read_auth(authfile): access_token = None if os.path.exists(authfile): # read from auth file logger.debug('found auth file at: %s', authfile) token, secret = open(authfile).read().strip().split('\n') access_token = oauth.Token(token, secret) logger.debug('access token: %s', access_token.key) return access_token @command def get(self, title, revision=None, format=None, **options): @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError @try_auth_on_forbidden(self.ecog, self.authfile) def _command(title, revision, format): if format == 'markdown': format = 'txt' # _resp, content = self.ecog.get(title=title, revision=revision, format=format) if format == 'json': # sort by some key order key_order = [ "title", "revision", "updated_at", "modifier", "acl_read", "acl_write", "data", "body" ] content = collections.OrderedDict( sorted(content.items(), key=lambda (k, v): key_order.index(k))) # trim body if len( content['body'] ) > 62: # 79 - 4(indent) - 6("body") - 2(: ) - 2("") - 3(...) content['body'] = content['body'][:62] + '...' content = json.dumps(content, indent=4) output(content) _command(title=title, revision=revision, format=format) @command def cat(self, title, revision=None, **options): @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError @try_auth_on_forbidden(self.ecog, self.authfile) def _command(title, revision): _resp, content = self.ecog.cat(title=title, revision=revision) output(content) _command(title=title, revision=revision) @command def list(self, **options): @exit_on_exception @terminate_on_KeyboardInterrupt def _command(): entries = self.ecog.list().entries max_author_width = max(len(e.author) for e in entries) for entry in entries: output("%s %s %s" % (entry.author.ljust(max_author_width), format_updated_datetime(entry), entry.title)) _command() @command def title(self, **options): @exit_on_exception @terminate_on_KeyboardInterrupt def _command(): for title in self.ecog.all(): output(title) _command() @command def recent(self, **options): @exit_on_exception @terminate_on_KeyboardInterrupt def _command(): entries = self.ecog.recent().entries def summary_size(entry): size = 0 try: size = len(entry.summary) except: logger.warning('no summary for entry: %s', entry.title) return size max_author_width = max(len(e.author) for e in entries) summary_sizes = [summary_size(e) for e in entries] max_size_width = len(str(max(summary_sizes))) for i, entry in enumerate(entries): output("%s %s %s %s" % (entry.author.ljust(max_author_width), str(summary_size(entry)).rjust(max_size_width), format_updated_datetime(entry), entry.title)) output() _command() @contextmanager def working_with_tempdir(self, prefix=None, **options): local_logger, logger_heading = logger, '' logger_option = options.get('logger', True) if logger_option is False: local_logger = None elif logger_option is True: local_logger = logger elif isinstance(logger_option, basestring): logger_heading = '[' + logger_option + '] ' # create temp directory temp_dir = tempfile.mkdtemp(prefix=prefix) logger.debug('[edit] temp directory: %s', temp_dir) local_logger and local_logger.debug('%stemp directory: %s', logger_heading, temp_dir) try: yield temp_dir finally: try: os.removedirs(temp_dir) local_logger and local_logger.debug('%sremoved %s', logger_heading, temp_dir) except OSError as e: local_logger and local_logger.debug( '%sfailed removing temp directory %s, %s', logger_heading, temp_dir, e) @contextmanager def working_with_tempfile(self, dir=None, prefix=None, suffix=None, **options): local_logger, logger_heading = logger, '' logger_option = options.get('logger', True) if logger_option is False: local_logger = None elif logger_option is True: local_logger = logger elif isinstance(logger_option, basestring): logger_heading = '[' + logger_option + '] ' remove_on_final = options.get('remove_on_final', True) # create temp file fd, temp_file = tempfile.mkstemp(dir=dir, prefix=prefix, suffix=suffix) local_logger and local_logger.debug('%smeta file: %s', logger_heading, temp_file) try: yield temp_file finally: if remove_on_final: try: os.remove(temp_file) logger.debug('%sremoved %s', logger_heading, temp_file) except OSError as e: logger.error('%sfailed removing temp json file %s (%s)', logger_heading, temp_file, e) @command def edit(self, title, template, comment, **options): ecog_get = try_auth_on_forbidden(self.ecog, self.authfile)(self.ecog.get) ecog_put = try_auth_on_forbidden(self.ecog, self.authfile)(self.ecog.put) @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError def _command(title, r0_template, comment=''): ''' open editor and send put after save 1. [GET] get page metadata and save temp file 2. [GET] get page rawdata with revision and save temp file 3. open tempfile with rawbody, and let user edit 4. after edit is finished, confirm tempfile 5. ask for comment 6. [PUT] put page with new content 7. remove temp files ''' logger.info('[edit] %s', title) if r0_template and not r0_template.endswith("\n"): r0_template += "\n\n" #tempdir = tempfile.mkdtemp(prefix='ecogwiki-') #logger.debug('[edit] temp directory: %s', tempdir) #try: with self.working_with_tempdir(prefix='ecogwiki-', logger='edit') as tempdir: # 1. [GET] get page metadata _resp, jsondata = ecog_get(title, format='json') revision = jsondata['revision'] updated_at = updated_datetime( jsondata['updated_at']) if jsondata['updated_at'] else None safe_title = urllib.quote_plus(title) #fd, temp_json = tempfile.mkstemp(dir=tempdir, prefix=safe_title+'-', suffix='.json') #logger.debug('[edit] "%s" meta file: %s', title, temp_json) #try: with self.working_with_tempfile(dir=tempdir, prefix=safe_title + '-', suffix='.json', logger='edit') as temp_json: with open(temp_json, 'w') as f: json.dump(jsondata, f, indent=4) # 2. [GET] get page rawdata _resp, rawbody = ecog_get(title, format='txt', revision=revision) fd, temp_rawbody0 = tempfile.mkstemp( dir=tempdir, prefix='%s.r%d-' % (safe_title, revision), suffix='.markdown') logger.debug('[edit] "%s" rawbody file: %s', title, temp_rawbody0) with open(temp_rawbody0, 'w') as f: if revision > 0: f.write(rawbody) elif r0_template: f.write(r0_template) # copy tempfile temp_rawbody = os.path.splitext(temp_rawbody0) temp_rawbody = temp_rawbody[0] + '.edit' + temp_rawbody[1] shutil.copy(temp_rawbody0, temp_rawbody) logger.debug('[edit] copy %s => %s', temp_rawbody0, temp_rawbody) try: # 3. open temp file with editor ret = subprocess.call(editor.split() + [temp_rawbody]) if ret != 0: output( 'editor %s failed with status %d, aborting.' % (editor, ret)) return # 4. confirm content content = '' with open(temp_rawbody) as f: content = f.read() if (revision > 0 and content == rawbody) or ( revision == 0 and content == r0_template): output('nothing new, aborting.') return if len(content) == 0: output('empty content, aborting.') return # 5. ask comment if not comment: def diff_lines(a_str, b_str, fromfile, tofile, fromfiledate=None, tofiledate=None): options = {'n': 0} if fromfile: options['fromfile'] = fromfile if tofile: options['tofile'] = tofile if fromfiledate: options['fromfiledate'] = fromfiledate if tofiledate: options['tofiledate'] = tofiledate diff = difflib.unified_diff( a_str.splitlines(True), b_str.splitlines(True), **options) return diff # display diff lines fromfile, fromfiledate = '%s (rev %d)' % ( title, revision), updated_at.strftime( "%Y/%m/%d %H-%M") for line in diff_lines( rawbody, content, fromfile=fromfile, tofile='EDIT', fromfiledate=updated_at.strftime( "%Y/%m/%d %H-%M")): output(line, end='') comment = raw_input( 'comment message (default: %s): ' % self.ecog.DEFAULT_COMMENT) comment = comment or self.ecog.DEFAULT_COMMENT # 6. [PUT] put page with new content resp, result = ecog_put(title, content, revision=revision, comment=comment) logger.debug('[edit] %s', resp) logger.debug('[edit] %s', result) # TODO: add content-location #output('updated "%s" to revision %d: %s' % (title, int(result['revision']), resp['content-location'])) output('updated "%s" to revision %d' % (title, int(result['revision']))) # 7. remove temp file on success try: os.remove(temp_rawbody) logger.debug('[edit] removed %s', temp_rawbody) except OSError as e: logger.error( '[edit] failed removing temp rawbody file %s, %s', temp_rawbody, e) try: os.remove(temp_rawbody0) logger.debug('[edit] removed %s', temp_rawbody0) except OSError as e: logger.error( '[edit] failed removing temp rawbody file %s, %s', temp_rawbody0, e) return result except Exception as e: output( 'error during edit. temporary file is saved at: %s' % temp_rawbody) logger.error('[edit] %s', e) raise finally: pass #finally: # try: # os.remove(temp_json) # logger.debug('[edit] removed %s', temp_json) # except OSError as e: # logger.error('[edit] failed removing temp json file %s (%s)', temp_json, e) #finally: # try: # os.removedirs(tempdir) # logger.debug('[edit] removed %s', tempdir) # except OSError as e: # logger.error('[edit] failed removing temp directory %s, %s', tempdir, e) _command(title=title, r0_template=template, comment=comment) @command def memo(self, template='', comment='', **options): now = datetime.datetime.now(dateutil.tz.tzlocal()) title = 'memo/%s' % now.strftime("%Y-%m-%d") # TODO: add default .write ME to template self.edit(title=title, template=template, comment=comment) @command def append(self, title, body='', comment='', **options): @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError @try_auth_on_forbidden(self.ecog, self.authfile) def _command(title, body='', comment=''): ''' if body is given, send post right away if not, open editor and send post after save ''' logger.info('[append] %s', title) if body: body = body.rstrip('\n') + '\n' self.ecog.post(title=title, body=body, comment=comment) return tempdir = tempfile.mkdtemp(prefix='ecogwiki-') logger.debug('[append] temp directory: %s', tempdir) try: safe_title = urllib.quote_plus(title) fd, temp_part = tempfile.mkstemp(dir=tempdir, prefix=safe_title + '.part-', suffix='.markdown') logger.debug('[append] "%s" partial file: %s', title, temp_part) try: # 3. open temp file with editor ret = subprocess.call(editor.split() + [temp_part]) if ret != 0: output('editor %s failed with status %d, aborting.' % (editor, ret)) return # 4. confirm content content = '' with open(temp_part) as f: content = f.read() if len(content) == 0: output('empty content, aborting.') return # 5. ask comment if not comment: comment = raw_input('comment message (default: %s): ' % self.ecog.DEFAULT_COMMENT) comment = comment or self.ecog.DEFAULT_COMMENT # 6. [PUT] put page with new content resp, result = self.ecog.post(title, content, comment=comment) logger.debug('[append] %s', resp) logger.debug('[append] %s', result) # TODO: add content-location #output('updated "%s" to revision %d: %s' % (title, int(result['revision']), resp['content-location'])) output('append to "%s"' % (title)) # 7. remove temp file on success try: os.remove(temp_part) logger.debug('[append] removed %s', temp_part) except OSError as e: logger.error( '[append] failed removing temp partial file %s, %s', temp_part, e) return result except Exception as e: output( 'error during edit. temporary file is saved at: %s' % temp_part) logger.error('[append] %s', e) raise finally: pass finally: try: os.removedirs(tempdir) logger.debug('[append] removed %s', tempdir) except OSError as e: logger.error( '[append] failed removing temp directory %s, %s', tempdir, e) _command(title, body=body, comment=comment)
class EcogClient(object): def __init__(self, ecoghost, authfile): self.authfile = authfile # saved for later self.access_token = EcogClient.read_auth(authfile) # self.ecog = EcogWiki(ecoghost, self.access_token) @staticmethod def parse_args(): parser = argparse.ArgumentParser(prog='ecog', description='Ecogwiki client - Information in your fingertips', epilog=' ') parser.add_argument('--auth', metavar='FILE', dest='authfile', default='.auth', help='auth file storing access token') parser.add_argument('--host', metavar='HOST', dest='ecoghost', default='www.ecogwiki.com', help='ecogwiki server host') parser.add_argument('--version', action='version', version='%(prog)s ' + __version__, default=None) subparsers = parser.add_subparsers(metavar='COMMAND', dest='command', title='ecogwiki commands') cat_parser = subparsers.add_parser('cat', help='print page in markdown') get_parser = subparsers.add_parser('get', help='print page in json') list_parser = subparsers.add_parser('list', help="list pages info") title_parser = subparsers.add_parser('title', help='list all titles') recent_parser = subparsers.add_parser('recent', help='list recent modified pages') edit_parser = subparsers.add_parser('edit', help='edit page with editor', description='Edit page with your favorite editor ($EDITOR)') append_parser = subparsers.add_parser('append', help='only append text', description='Quickly append to page') memo_parser = subparsers.add_parser('memo', help='quick memo', description='Edit your daily memo') edit_parser.add_argument('title', metavar='TITLE', help='page title') edit_parser.add_argument('--template', metavar='TEXT', help='text on new file', default=None) edit_parser.add_argument('--comment', metavar='MSG', help='edit comment message', default='') memo_parser.add_argument('--comment', metavar='MSG', help='edit comment message', default='') get_parser.add_argument('title', metavar='TITLE', help='page title') cat_parser.add_argument('title', metavar='TITLE', help='page title') get_parser.add_argument('--revision', metavar='REV', help='specific revision number', type=int) cat_parser.add_argument('--revision', metavar='REV', help='specific revision number', type=int) get_parser.add_argument('--format', metavar='FORMAT', help='one of [json|html|markdown|atom], json by default', choices=['json', 'txt', 'atom', 'markdown', 'html'], default='json') append_parser.add_argument('title', metavar='TITLE', help='page title') append_parser.add_argument('body', nargs='?', metavar='TEXT', help='body text. fires editor if not given', default='') append_parser.add_argument('--comment', metavar='MSG', help='comment message', default='') # args = parser.parse_args() if '://' not in args.ecoghost: args.ecoghost = 'http://' + args.ecoghost if not args.authfile.startswith('/'): args.authfile = os.path.join(CWD, args.authfile) if args.version: output(__version__) sys.exit(0) return args @staticmethod def read_auth(authfile): access_token = None if os.path.exists(authfile): # read from auth file logger.debug('found auth file at: %s', authfile) token, secret = open(authfile).read().strip().split('\n') access_token = oauth.Token(token, secret) logger.debug('access token: %s', access_token.key) return access_token @command def get(self, title, revision=None, format=None, **options): @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError @try_auth_on_forbidden(self.ecog, self.authfile) def _command(title, revision, format): if format == 'markdown': format = 'txt' # _resp,content = self.ecog.get(title=title, revision=revision, format=format) if format == 'json': # sort by some key order key_order = ["title", "revision", "updated_at", "modifier", "acl_read", "acl_write", "data", "body"] content = collections.OrderedDict(sorted(content.items(), key=lambda (k,v): key_order.index(k))) # trim body if len(content['body']) > 62: # 79 - 4(indent) - 6("body") - 2(: ) - 2("") - 3(...) content['body'] = content['body'][:62] + '...' content = json.dumps(content, indent=4) output(content) _command(title=title, revision=revision, format=format) @command def cat(self, title, revision=None, **options): @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError @try_auth_on_forbidden(self.ecog, self.authfile) def _command(title, revision): _resp,content = self.ecog.cat(title=title, revision=revision) output(content) _command(title=title, revision=revision) @command def list(self, **options): @exit_on_exception @terminate_on_KeyboardInterrupt def _command(): entries = self.ecog.list().entries max_author_width = max(len(e.author) for e in entries) for entry in entries: output("%s %s %s" % ( entry.author.ljust(max_author_width), format_updated_datetime(entry), entry.title )) _command() @command def title(self, **options): @exit_on_exception @terminate_on_KeyboardInterrupt def _command(): for title in self.ecog.all(): output(title) _command() @command def recent(self, **options): @exit_on_exception @terminate_on_KeyboardInterrupt def _command(): entries = self.ecog.recent().entries def summary_size(entry): size = 0 try: size = len(entry.summary) except: logger.warning('no summary for entry: %s', entry.title) return size max_author_width = max(len(e.author) for e in entries) summary_sizes = [summary_size(e) for e in entries] max_size_width = len(str(max(summary_sizes))) for i,entry in enumerate(entries): output("%s %s %s %s" % ( entry.author.ljust(max_author_width), str(summary_size(entry)).rjust(max_size_width), format_updated_datetime(entry), entry.title )) output() _command() @contextmanager def working_with_tempdir(self, prefix=None, **options): local_logger, logger_heading = logger, '' logger_option = options.get('logger', True) if logger_option is False: local_logger = None elif logger_option is True: local_logger = logger elif isinstance(logger_option, basestring): logger_heading = '[' + logger_option + '] ' # create temp directory temp_dir = tempfile.mkdtemp(prefix=prefix) logger.debug('[edit] temp directory: %s', temp_dir) local_logger and local_logger.debug('%stemp directory: %s', logger_heading, temp_dir) try: yield temp_dir finally: try: os.removedirs(temp_dir) local_logger and local_logger.debug('%sremoved %s', logger_heading, temp_dir) except OSError as e: local_logger and local_logger.debug('%sfailed removing temp directory %s, %s', logger_heading, temp_dir, e) @contextmanager def working_with_tempfile(self, dir=None, prefix=None, suffix=None, **options): local_logger, logger_heading = logger, '' logger_option = options.get('logger', True) if logger_option is False: local_logger = None elif logger_option is True: local_logger = logger elif isinstance(logger_option, basestring): logger_heading = '[' + logger_option + '] ' remove_on_final = options.get('remove_on_final', True) # create temp file fd, temp_file = tempfile.mkstemp(dir=dir, prefix=prefix, suffix=suffix) local_logger and local_logger.debug('%smeta file: %s', logger_heading, temp_file) try: yield temp_file finally: if remove_on_final: try: os.remove(temp_file) logger.debug('%sremoved %s', logger_heading, temp_file) except OSError as e: logger.error('%sfailed removing temp json file %s (%s)', logger_heading, temp_file, e) @command def edit(self, title, template, comment, **options): ecog_get = try_auth_on_forbidden(self.ecog, self.authfile)(self.ecog.get) ecog_put = try_auth_on_forbidden(self.ecog, self.authfile)(self.ecog.put) @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError def _command(title, r0_template, comment=''): ''' open editor and send put after save 1. [GET] get page metadata and save temp file 2. [GET] get page rawdata with revision and save temp file 3. open tempfile with rawbody, and let user edit 4. after edit is finished, confirm tempfile 5. ask for comment 6. [PUT] put page with new content 7. remove temp files ''' logger.info('[edit] %s', title) if r0_template and not r0_template.endswith("\n"): r0_template += "\n\n" #tempdir = tempfile.mkdtemp(prefix='ecogwiki-') #logger.debug('[edit] temp directory: %s', tempdir) #try: with self.working_with_tempdir(prefix='ecogwiki-', logger='edit') as tempdir: # 1. [GET] get page metadata _resp,jsondata = ecog_get(title, format='json') revision = jsondata['revision'] updated_at = updated_datetime(jsondata['updated_at']) if jsondata['updated_at'] else None safe_title = urllib.quote_plus(title) #fd, temp_json = tempfile.mkstemp(dir=tempdir, prefix=safe_title+'-', suffix='.json') #logger.debug('[edit] "%s" meta file: %s', title, temp_json) #try: with self.working_with_tempfile(dir=tempdir, prefix=safe_title+'-', suffix='.json', logger='edit') as temp_json: with open(temp_json, 'w') as f: json.dump(jsondata, f, indent=4) # 2. [GET] get page rawdata _resp,rawbody = ecog_get(title, format='txt', revision=revision) fd, temp_rawbody0 = tempfile.mkstemp(dir=tempdir, prefix='%s.r%d-' % (safe_title, revision), suffix='.markdown') logger.debug('[edit] "%s" rawbody file: %s', title, temp_rawbody0) with open(temp_rawbody0, 'w') as f: if revision > 0: f.write(rawbody) elif r0_template: f.write(r0_template) # copy tempfile temp_rawbody = os.path.splitext(temp_rawbody0) temp_rawbody = temp_rawbody[0] + '.edit' + temp_rawbody[1] shutil.copy(temp_rawbody0, temp_rawbody) logger.debug('[edit] copy %s => %s', temp_rawbody0, temp_rawbody) try: # 3. open temp file with editor ret = subprocess.call(editor.split() + [temp_rawbody]) if ret != 0: output('editor %s failed with status %d, aborting.' % (editor, ret)) return # 4. confirm content content = '' with open(temp_rawbody) as f: content = f.read() if (revision > 0 and content == rawbody) or (revision == 0 and content == r0_template): output('nothing new, aborting.') return if len(content) == 0: output('empty content, aborting.') return # 5. ask comment if not comment: def diff_lines(a_str,b_str,fromfile,tofile,fromfiledate=None,tofiledate=None): options = { 'n': 0 } if fromfile: options['fromfile'] = fromfile if tofile: options['tofile'] = tofile if fromfiledate: options['fromfiledate'] = fromfiledate if tofiledate: options['tofiledate'] = tofiledate diff = difflib.unified_diff(a_str.splitlines(True),b_str.splitlines(True), **options) return diff # display diff lines fromfile,fromfiledate = '%s (rev %d)' % (title, revision), updated_at.strftime("%Y/%m/%d %H-%M") for line in diff_lines(rawbody,content, fromfile=fromfile, tofile='EDIT', fromfiledate=updated_at.strftime("%Y/%m/%d %H-%M")): output(line, end='') comment = raw_input('comment message (default: %s): ' % self.ecog.DEFAULT_COMMENT) comment = comment or self.ecog.DEFAULT_COMMENT # 6. [PUT] put page with new content resp,result = ecog_put(title, content, revision=revision, comment=comment) logger.debug('[edit] %s', resp) logger.debug('[edit] %s', result) # TODO: add content-location #output('updated "%s" to revision %d: %s' % (title, int(result['revision']), resp['content-location'])) output('updated "%s" to revision %d' % (title, int(result['revision']))) # 7. remove temp file on success try: os.remove(temp_rawbody) logger.debug('[edit] removed %s', temp_rawbody) except OSError as e: logger.error('[edit] failed removing temp rawbody file %s, %s', temp_rawbody, e) try: os.remove(temp_rawbody0) logger.debug('[edit] removed %s', temp_rawbody0) except OSError as e: logger.error('[edit] failed removing temp rawbody file %s, %s', temp_rawbody0, e) return result except Exception as e: output('error during edit. temporary file is saved at: %s' % temp_rawbody) logger.error('[edit] %s', e) raise finally: pass #finally: # try: # os.remove(temp_json) # logger.debug('[edit] removed %s', temp_json) # except OSError as e: # logger.error('[edit] failed removing temp json file %s (%s)', temp_json, e) #finally: # try: # os.removedirs(tempdir) # logger.debug('[edit] removed %s', tempdir) # except OSError as e: # logger.error('[edit] failed removing temp directory %s, %s', tempdir, e) _command(title=title, r0_template=template, comment=comment) @command def memo(self, template='', comment='', **options): now = datetime.datetime.now(dateutil.tz.tzlocal()) title = 'memo/%s' % now.strftime("%Y-%m-%d") # TODO: add default .write ME to template self.edit(title=title, template=template, comment=comment) @command def append(self, title, body='', comment='', **options): @exit_on_exception @terminate_on_KeyboardInterrupt @exit_on_HTTPError @try_auth_on_forbidden(self.ecog, self.authfile) def _command(title, body='', comment=''): ''' if body is given, send post right away if not, open editor and send post after save ''' logger.info('[append] %s', title) if body: body = body.rstrip('\n') + '\n' self.ecog.post(title=title, body=body, comment=comment) return tempdir = tempfile.mkdtemp(prefix='ecogwiki-') logger.debug('[append] temp directory: %s', tempdir) try: safe_title = urllib.quote_plus(title) fd, temp_part = tempfile.mkstemp(dir=tempdir, prefix=safe_title+'.part-', suffix='.markdown') logger.debug('[append] "%s" partial file: %s', title, temp_part) try: # 3. open temp file with editor ret = subprocess.call(editor.split() + [temp_part]) if ret != 0: output('editor %s failed with status %d, aborting.' % (editor, ret)) return # 4. confirm content content = '' with open(temp_part) as f: content = f.read() if len(content) == 0: output('empty content, aborting.') return # 5. ask comment if not comment: comment = raw_input('comment message (default: %s): ' % self.ecog.DEFAULT_COMMENT) comment = comment or self.ecog.DEFAULT_COMMENT # 6. [PUT] put page with new content resp,result = self.ecog.post(title, content, comment=comment) logger.debug('[append] %s', resp) logger.debug('[append] %s', result) # TODO: add content-location #output('updated "%s" to revision %d: %s' % (title, int(result['revision']), resp['content-location'])) output('append to "%s"' % (title)) # 7. remove temp file on success try: os.remove(temp_part) logger.debug('[append] removed %s', temp_part) except OSError as e: logger.error('[append] failed removing temp partial file %s, %s', temp_part, e) return result except Exception as e: output('error during edit. temporary file is saved at: %s' % temp_part) logger.error('[append] %s', e) raise finally: pass finally: try: os.removedirs(tempdir) logger.debug('[append] removed %s', tempdir) except OSError as e: logger.error('[append] failed removing temp directory %s, %s', tempdir, e) _command(title, body=body, comment=comment)