Mercurial > libervia-backend
comparison frontends/src/jp/cmd_blog.py @ 1877:a97db84c048d
jp (blog): moved common method in a BlogCommon class + added "current" as an item keyword for blog/edit
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 04 Mar 2016 11:22:41 +0100 |
parents | 1088bf7b28e7 |
children | 386d61abfac2 |
comparison
equal
deleted
inserted
replaced
1876:1088bf7b28e7 | 1877:a97db84c048d |
---|---|
60 KEY_TO_REMOVE_METADATA = ('id','content', 'content_xhtml', 'comments_node', 'comments_service') | 60 KEY_TO_REMOVE_METADATA = ('id','content', 'content_xhtml', 'comments_node', 'comments_service') |
61 | 61 |
62 URL_REDIRECT_PREFIX = 'url_redirect_' | 62 URL_REDIRECT_PREFIX = 'url_redirect_' |
63 | 63 |
64 | 64 |
65 def getTmpDir(sat_conf): | 65 class BlogCommon(object): |
66 """Return directory used to store temporary files | 66 def getTmpDir(self, sat_conf): |
67 | 67 """Return directory used to store temporary files |
68 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration | 68 |
69 @return (str): path to the dir | 69 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration |
70 """ | 70 @return (str): path to the dir |
71 local_dir = config.getConfig(sat_conf, '', 'local_dir', Exception) | 71 """ |
72 return os.path.join(local_dir, BLOG_TMP_DIR) | 72 local_dir = config.getConfig(sat_conf, '', 'local_dir', Exception) |
73 | 73 return os.path.join(local_dir, BLOG_TMP_DIR) |
74 | 74 |
75 class Edit(base.CommandBase): | 75 def getCurrentFile(self, sat_conf): |
76 # we guess the blog item currently edited by choosing | |
77 # the most recent file corresponding to temp file pattern | |
78 # in tmp_dir, excluding metadata files | |
79 tmp_dir = self.getTmpDir(sat_conf) | |
80 available = [path for path in glob.glob(os.path.join(tmp_dir, 'blog_*')) if not path.endswith(METADATA_SUFF)] | |
81 if not available: | |
82 self.disp(u"Counldn't find any content draft in {path}".format(path=tmp_dir), error=True) | |
83 self.host.quit(1) | |
84 return max(available, key=lambda path: os.stat(path).st_mtime) | |
85 | |
86 def guessSyntaxFromPath(self, sat_conf, path): | |
87 """Return syntax guessed according to filename extension | |
88 | |
89 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration | |
90 @param path(str): path to the content file | |
91 @return(unicode): syntax to use | |
92 """ | |
93 # we first try to guess syntax with extension | |
94 ext = os.path.splitext(path)[1][1:] # we get extension without the '.' | |
95 if ext: | |
96 for k,v in SYNTAX_EXT.iteritems(): | |
97 if ext == v: | |
98 return v | |
99 | |
100 # if not found, we use current syntax | |
101 return self.host.bridge.getParamA("Syntax", "Composition", "value", self.profile) | |
102 | |
103 | |
104 class Edit(base.CommandBase, BlogCommon): | |
76 | 105 |
77 def __init__(self, host): | 106 def __init__(self, host): |
78 super(Edit, self).__init__(host, 'edit', use_verbose=True, help=_(u'edit an existing or new blog post')) | 107 super(Edit, self).__init__(host, 'edit', use_verbose=True, help=_(u'edit an existing or new blog post')) |
79 | 108 |
80 def add_parser_options(self): | 109 def add_parser_options(self): |
88 | 117 |
89 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration | 118 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration |
90 @param tmp_suff (str): suffix to use for the filename | 119 @param tmp_suff (str): suffix to use for the filename |
91 @return (tuple(file, str)): opened (w+b) file object and file path | 120 @return (tuple(file, str)): opened (w+b) file object and file path |
92 """ | 121 """ |
93 tmp_dir = getTmpDir(sat_conf) | 122 tmp_dir = self.getTmpDir(sat_conf) |
94 if not os.path.exists(tmp_dir): | 123 if not os.path.exists(tmp_dir): |
95 try: | 124 try: |
96 os.makedirs(tmp_dir) | 125 os.makedirs(tmp_dir) |
97 except OSError as e: | 126 except OSError as e: |
98 self.disp(u"Can't create {path} directory: {reason}".format( | 127 self.disp(u"Can't create {path} directory: {reason}".format( |
236 | 265 |
237 os.unlink(content_file_path) | 266 os.unlink(content_file_path) |
238 os.unlink(meta_file_path) | 267 os.unlink(meta_file_path) |
239 | 268 |
240 def start(self): | 269 def start(self): |
241 # we get current syntax to determine file extension | 270 item_lower = self.args.item.lower() |
242 current_syntax = self.host.bridge.getParamA("Syntax", "Composition", "value", self.profile) | |
243 self.disp(u"Current syntax: {}".format(current_syntax), 1) | |
244 sat_conf = config.parseMainConf() | 271 sat_conf = config.parseMainConf() |
245 # if there are user defined extension, we use them | 272 # if there are user defined extension, we use them |
246 SYNTAX_EXT.update(config.getConfig(sat_conf, 'jp', CONF_SYNTAX_EXT, {})) | 273 SYNTAX_EXT.update(config.getConfig(sat_conf, 'jp', CONF_SYNTAX_EXT, {})) |
247 | 274 current_syntax = None |
248 # we now create a temporary file | 275 |
249 tmp_suff = '.' + SYNTAX_EXT.get(current_syntax, SYNTAX_EXT['']) | 276 if item_lower == 'current': |
250 content_file_obj, content_file_path = self.getTmpFile(sat_conf, tmp_suff) | 277 # use wants to continue current draft |
251 | 278 content_file_path = self.getCurrentFile(sat_conf) |
252 item_lower = self.args.item.lower() | 279 content_file_obj = open(content_file_path, 'r+b') |
280 current_syntax = self.guessSyntaxFromPath(sat_conf, content_file_path) | |
281 else: | |
282 # we get current syntax to determine file extension | |
283 current_syntax = self.host.bridge.getParamA("Syntax", "Composition", "value", self.profile) | |
284 # we now create a temporary file | |
285 tmp_suff = '.' + SYNTAX_EXT.get(current_syntax, SYNTAX_EXT['']) | |
286 content_file_obj, content_file_path = self.getTmpFile(sat_conf, tmp_suff) | |
287 | |
288 self.disp(u"Syntax used: {}".format(current_syntax), 1) | |
289 | |
253 if item_lower == 'new': | 290 if item_lower == 'new': |
254 self.disp(u'Editing a new blog item', 2) | 291 self.disp(u'Editing a new blog item', 2) |
255 self.edit(sat_conf, content_file_path, content_file_obj) | 292 mb_data = None |
293 elif item_lower == 'current': | |
294 self.disp(u'Continuing edition of current draft', 2) | |
295 mb_data = None | |
256 elif item_lower == 'last': | 296 elif item_lower == 'last': |
257 self.disp(u'Editing last published item', 2) | 297 self.disp(u'Editing last published item', 2) |
258 try: | 298 try: |
259 mb_data = self.host.bridge.mbGet('', '', 1, [], {}, self.profile)[0][0] | 299 mb_data = self.host.bridge.mbGet('', '', 1, [], {}, self.profile)[0][0] |
260 except Exception as e: | 300 except Exception as e: |
264 content = mb_data['content_xhtml'] | 304 content = mb_data['content_xhtml'] |
265 if current_syntax != 'XHTML': | 305 if current_syntax != 'XHTML': |
266 content = self.host.bridge.syntaxConvert(content, 'XHTML', current_syntax, False, self.profile) | 306 content = self.host.bridge.syntaxConvert(content, 'XHTML', current_syntax, False, self.profile) |
267 content_file_obj.write(content.encode('utf-8')) | 307 content_file_obj.write(content.encode('utf-8')) |
268 content_file_obj.seek(0) | 308 content_file_obj.seek(0) |
269 self.edit(sat_conf, content_file_path, content_file_obj, mb_data=mb_data) | 309 |
270 | 310 self.edit(sat_conf, content_file_path, content_file_obj, mb_data=mb_data) |
271 | 311 |
272 class Preview(base.CommandBase): | 312 |
313 class Preview(base.CommandBase, BlogCommon): | |
273 | 314 |
274 def __init__(self, host): | 315 def __init__(self, host): |
275 super(Preview, self).__init__(host, 'preview', use_verbose=True, help=_(u'preview a blog content')) | 316 super(Preview, self).__init__(host, 'preview', help=_(u'preview a blog content')) |
276 | 317 |
277 def add_parser_options(self): | 318 def add_parser_options(self): |
278 self.parser.add_argument("file", type=base.unicode_decoder, nargs='?', default=u'current', help=_(u"path to the content file")) | 319 self.parser.add_argument("file", type=base.unicode_decoder, nargs='?', default=u'current', help=_(u"path to the content file")) |
279 | 320 |
321 def showPreview(self, content_xhtml, file_obj): | |
322 import webbrowser | |
323 import urllib | |
324 xhtml = (u'<html xmlns="http://www.w3.org/1999/xhtml">' + | |
325 u'<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /></head>'+ | |
326 '<body>{}</body>' + | |
327 u'</html>').format(content_xhtml) | |
328 file_obj.write(xhtml.encode('utf-8')) | |
329 url = 'file:{}'.format(urllib.quote(file_obj.name)) | |
330 webbrowser.open_new_tab(url) | |
331 | |
280 def start(self): | 332 def start(self): |
281 sat_conf = config.parseMainConf() | 333 sat_conf = config.parseMainConf() |
334 SYNTAX_EXT.update(config.getConfig(sat_conf, 'jp', CONF_SYNTAX_EXT, {})) | |
282 | 335 |
283 # which file do we need to edit? | 336 # which file do we need to edit? |
284 if self.args.file == 'current': | 337 if self.args.file == 'current': |
285 # we guess the blog item currently edited by choosing | 338 current_file_path = self.getCurrentFile(sat_conf) |
286 # the most recent file corresponding to temp file pattern | |
287 # in tmp_dir, excluding metadata files | |
288 tmp_dir = getTmpDir(sat_conf) | |
289 available = [path for path in glob.glob(os.path.join(tmp_dir, 'blog_*')) if not path.endswith(METADATA_SUFF)] | |
290 if not available: | |
291 self.disp(u"Counldn't find any content draft in {path}".format(path=tmp_dir), error=True) | |
292 self.host.quit(1) | |
293 current_path = max(available, key=lambda path: os.stat(path).st_mtime) | |
294 else: | 339 else: |
295 current_path = os.path.abspath(self.args.file) | 340 current_file_path = os.path.abspath(self.args.file) |
296 | 341 |
297 # we first try to guess syntax with extension | 342 syntax = self.guessSyntaxFromPath(sat_conf, current_file_path) |
298 SYNTAX_EXT.update(config.getConfig(sat_conf, 'jp', CONF_SYNTAX_EXT, {})) | 343 |
299 ext = os.path.splitext(current_path)[1][1:] # we get extension without the '.' | |
300 syntax = None | |
301 if ext: | |
302 for k,v in SYNTAX_EXT.iteritems(): | |
303 if ext == v: | |
304 syntax = k | |
305 break | |
306 | |
307 # if not found, we use current syntax | |
308 if syntax is None: | |
309 syntax = self.host.bridge.getParamA("Syntax", "Composition", "value", self.profile) | |
310 if syntax != 'XHTML': | 344 if syntax != 'XHTML': |
311 with open(current_path, 'rb') as f: | 345 with open(current_file_path, 'rb') as f: |
312 content_xhtml = self.host.bridge.syntaxConvert(f.read(), syntax, 'XHTML', False, self.profile) | 346 content_xhtml = self.host.bridge.syntaxConvert(f.read(), syntax, 'XHTML', False, self.profile) |
313 import webbrowser | 347 |
314 import urllib | 348 # at this point the syntax is converted, we can display the preview |
349 | |
315 with tempfile.NamedTemporaryFile(suffix='.xhtml', delete=False) as f: | 350 with tempfile.NamedTemporaryFile(suffix='.xhtml', delete=False) as f: |
316 # XXX: we don't delete file automatically because browser need it (and webbrowser.open can return before it is read) | 351 # XXX: we don't delete file automatically because browser need it (and webbrowser.open can return before it is read) |
317 self.disp(u'temporary file created at {}\nthis file will NOT BE DELETED AUTOMATICALLY, please delete it yourself when you have finished'.format(f.name)) | 352 self.disp(u'temporary file created at {}\nthis file will NOT BE DELETED AUTOMATICALLY, please delete it yourself when you have finished'.format(f.name)) |
318 xhtml = (u'<html xmlns="http://www.w3.org/1999/xhtml">' + | 353 self.showPreview(content_xhtml, f) |
319 u'<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /></head>'+ | |
320 '<body>{}</body>' + | |
321 u'</html>').format(content_xhtml) | |
322 f.write(xhtml.encode('utf-8')) | |
323 url = 'file:{}'.format(urllib.quote(f.name)) | |
324 webbrowser.open_new_tab(url) | |
325 | 354 |
326 | 355 |
327 class Import(base.CommandAnswering): | 356 class Import(base.CommandAnswering): |
328 def __init__(self, host): | 357 def __init__(self, host): |
329 super(Import, self).__init__(host, 'import', use_progress=True, help=_(u'import an external blog')) | 358 super(Import, self).__init__(host, 'import', use_progress=True, help=_(u'import an external blog')) |