annotate frontends/src/jp/common.py @ 2528:65e278997715

component file sharing: comments metadata: new <comments> element is added to file metadata, it contains the URL to the comments virtual node and the count of comments (this way client knows if it make sense to request comments or not). Fixed triggers in plugin XEP-0264 (return value was missing). New trigger in plugin XEP-0329 to allow component to add metadata (used here for comments url).
author Goffi <goffi@goffi.org>
date Fri, 16 Mar 2018 18:43:11 +0100
parents 21d43eab3fb9
children 772447ec070f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python2
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # jp: a SàT command line tool
2483
0046283a285d dates update
Goffi <goffi@goffi.org>
parents: 2414
diff changeset
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
6
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
11
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from sat_frontends.jp.constants import Const as C
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from sat.core.i18n import _
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
22 from sat.core import exceptions
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from sat.tools.common import regex
2279
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
24 from sat.tools.common import uri
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
25 from sat.tools.common.ansi import ANSI as A
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from sat.tools import config
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from ConfigParser import NoSectionError, NoOptionError
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
28 from collections import namedtuple
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 import json
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 import os
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 import os.path
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 import time
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 import tempfile
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 import subprocess
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 import glob
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
36 import shlex
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
37
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 # defaut arguments used for some known editors (editing with metadata)
2523
21d43eab3fb9 jp (common): assure nosplitright in default commands for edition with vim
Goffi <goffi@goffi.org>
parents: 2493
diff changeset
39 VIM_SPLIT_ARGS = "-c 'set nospr|vsplit|wincmd w|next|wincmd w'"
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 EMACS_SPLIT_ARGS = '--eval "(split-window-horizontally)"'
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 EDITOR_ARGS_MAGIC = {
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 'vim': VIM_SPLIT_ARGS + ' {content_file} {metadata_file}',
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 'gvim': VIM_SPLIT_ARGS + ' --nofork {content_file} {metadata_file}',
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 'emacs': EMACS_SPLIT_ARGS + ' {content_file} {metadata_file}',
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 'xemacs': EMACS_SPLIT_ARGS + ' {content_file} {metadata_file}',
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 'nano': ' -F {content_file} {metadata_file}',
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 }
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
48
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 SECURE_UNLINK_MAX = 10
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 SECURE_UNLINK_DIR = ".backup"
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 METADATA_SUFF = '_metadata.json'
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
52
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
54 def ansi_ljust(s, width):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
55 """ljust method handling ANSI escape codes"""
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
56 cleaned = regex.ansiRemove(s)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
57 return s + u' ' * (width - len(cleaned))
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
58
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
59
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
60 def ansi_center(s, width):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
61 """ljust method handling ANSI escape codes"""
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
62 cleaned = regex.ansiRemove(s)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
63 diff = width - len(cleaned)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
64 half = diff/2
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
65 return half * u' ' + s + (half + diff % 2) * u' '
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
66
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
67
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
68 def ansi_rjust(s, width):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
69 """ljust method handling ANSI escape codes"""
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
70 cleaned = regex.ansiRemove(s)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
71 return u' ' * (width - len(cleaned)) + s
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
72
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
73
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 def getTmpDir(sat_conf, cat_dir, sub_dir=None):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 """Return directory used to store temporary files
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
76
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
78 @param cat_dir(unicode): directory of the category (e.g. "blog")
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 @param sub_dir(str): sub directory where data need to be put
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 profile can be used here, or special directory name
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 sub_dir will be escaped to be usable in path (use regex.pathUnescape to find
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 initial str)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 @return (str): path to the dir
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 local_dir = config.getConfig(sat_conf, '', 'local_dir', Exception)
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
86 path = [local_dir.encode('utf-8'), cat_dir.encode('utf-8')]
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 if sub_dir is not None:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 path.append(regex.pathEscape(sub_dir))
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 return os.path.join(*path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
90
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
91
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
92 def parse_args(host, cmd_line, **format_kw):
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
93 """Parse command arguments
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
94
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
95 @param cmd_line(unicode): command line as found in sat.conf
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
96 @param format_kw: keywords used for formating
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
97 @return (list(unicode)): list of arguments to pass to subprocess function
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
98 """
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
99 try:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
100 # we split the arguments and add the known fields
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
101 # we split arguments first to avoid escaping issues in file names
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
102 return [a.format(**format_kw) for a in shlex.split(cmd_line)]
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
103 except ValueError as e:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
104 host.disp(u"Couldn't parse editor cmd [{cmd}]: {reason}".format(cmd=cmd_line, reason=e))
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
105 return []
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
106
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
107
2279
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
108 def checkURI(args):
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
109 """check if args.node is an URI
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
110
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
111 if a valid xmpp: URI is found, args.service, args.node and args.item will be set
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
112 """
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
113 # FIXME: Q&D way to handle xmpp: uris, a generic way is needed
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
114 # and it should be merged with code in BaseEdit
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
115 if not args.service and args.node.startswith('xmpp:'):
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
116 try:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
117 uri_data = uri.parseXMPPUri(args.node)
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
118 except ValueError:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
119 pass
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
120 else:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
121 if uri_data[u'type'] == 'pubsub':
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
122 args.service = uri_data[u'path']
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
123 args.node = uri_data[u'node']
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
124 if u'item' in uri_data:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
125 try:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
126 item = getattr(uri_data, 'item')
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
127 except AttributeError:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
128 pass
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
129 else:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
130 if item is None:
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
131 args.item = uri_data
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
132
e2f96cd1887b jp (cmd_pubsub): xmpp: uri handling, first draft
Goffi <goffi@goffi.org>
parents: 2276
diff changeset
133
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 class BaseEdit(object):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 u"""base class for editing commands
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
136
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 This class allows to edit file for PubSub or something else.
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 It works with temporary files in SàT local_dir, in a "cat_dir" subdir
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 """
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
140 # use_items(bool): True if items are used, will then add item related options
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
141 use_items=True
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
142
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
143 def __init__(self, host, cat_dir, use_metadata=False):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 @param cat_dir(unicode): directory to use for drafts
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 this will be a sub-directory of SàT's local_dir
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 @param use_metadata(bool): True is edition need a second file for metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 most of signature change with use_metadata with an additional metadata argument.
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 This is done to raise error if a command needs metadata but forget the flag, and vice versa
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 self.host = host
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 self.sat_conf = config.parseMainConf()
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
154 self.cat_dir_str = cat_dir.encode('utf-8')
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 self.use_metadata = use_metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
156
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
157 def add_parser_options(self):
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
158 if self.use_items:
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
159 group = self.parser.add_mutually_exclusive_group()
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
160 group.add_argument("--force-item", action='store_true', help=_(u"don't use magic and take item argument as an actual item"))
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
161 group.add_argument("--last-item", action='store_true', help=_(u"take last item instead of creating a new one if no item id is found"))
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
162
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 def secureUnlink(self, path):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 """Unlink given path after keeping it for a while
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
165
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 This method is used to prevent accidental deletion of a draft
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 If there are more file in SECURE_UNLINK_DIR than SECURE_UNLINK_MAX,
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 older file are deleted
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 @param path(str): file to unlink
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 if not os.path.isfile(path):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 raise OSError(u"path must link to a regular file")
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
173 if not path.startswith(getTmpDir(self.sat_conf, self.cat_dir_str)):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 self.disp(u"File {} is not in SàT temporary hierarchy, we do not remove it".format(path.decode('utf-8')), 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 return
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 # we have 2 files per draft with use_metadata, so we double max
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 unlink_max = SECURE_UNLINK_MAX * 2 if self.use_metadata else SECURE_UNLINK_MAX
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
178 backup_dir = getTmpDir(self.sat_conf, self.cat_dir_str, SECURE_UNLINK_DIR)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 if not os.path.exists(backup_dir):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 os.makedirs(backup_dir)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 filename = os.path.basename(path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 backup_path = os.path.join(backup_dir, filename)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 # we move file to backup dir
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 self.host.disp(u"Backuping file {src} to {dst}".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 src=path.decode('utf-8'), dst=backup_path.decode('utf-8')), 1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 os.rename(path, backup_path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 # and if we exceeded the limit, we remove older file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 backup_files = [os.path.join(backup_dir, f) for f in os.listdir(backup_dir)]
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 if len(backup_files) > unlink_max:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 backup_files.sort(key=lambda path: os.stat(path).st_mtime)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 for path in backup_files[:len(backup_files) - unlink_max]:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 self.host.disp(u"Purging backup file {}".format(path.decode('utf-8')), 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 os.unlink(path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
194
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 def runEditor(self, editor_args_opt, content_file_path,
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 content_file_obj, meta_file_path=None, meta_ori=None):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 """run editor to edit content and metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
198
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 @param editor_args_opt(unicode): option in [jp] section in configuration for
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 specific args
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 @param content_file_path(str): path to the content file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 @param content_file_obj(file): opened file instance
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 @param meta_file_path(str, None): metadata file path
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 if None metadata will not be used
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 @param meta_ori(dict, None): original cotent of metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 can't be used if use_metadata is False
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 if not self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 assert meta_file_path is None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 assert meta_ori is None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
211
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 # we calculate hashes to check for modifications
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 import hashlib
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 content_file_obj.seek(0)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 tmp_ori_hash = hashlib.sha1(content_file_obj.read()).digest()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 content_file_obj.close()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
217
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 # we prepare arguments
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 editor = config.getConfig(self.sat_conf, 'jp', 'editor') or os.getenv('EDITOR', 'vi')
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 # is there custom arguments in sat.conf ?
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 editor_args = config.getConfig(self.sat_conf, 'jp', editor_args_opt, Exception)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 except (NoOptionError, NoSectionError):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
224 # no, we check if we know the editor and have special arguments
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
225 if self.use_metadata:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
226 editor_args = EDITOR_ARGS_MAGIC.get(os.path.basename(editor), '')
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
227 else:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
228 editor_args = ''
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 parse_kwargs = {'content_file': content_file_path}
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 parse_kwargs['metadata_file'] = meta_file_path
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
232 args = parse_args(self.host, editor_args, **parse_kwargs)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 if not args:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 args = [content_file_path]
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
235
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 # actual editing
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 editor_exit = subprocess.call([editor] + args)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
238
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 # edition will now be checked, and data will be sent if it was a success
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 if editor_exit != 0:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 self.disp(u"Editor exited with an error code, so temporary file has not be deleted, and item is not published.\nYou can find temporary file at {path}".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 path=content_file_path), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 # main content
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 with open(content_file_path, 'rb') as f:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 content = f.read()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 except (OSError, IOError):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 self.disp(u"Can read file at {content_path}, have it been deleted?\nCancelling edition".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 content_path=content_file_path), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 self.host.quit(C.EXIT_NOT_FOUND)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
252
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 # metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 with open(meta_file_path, 'rb') as f:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 metadata = json.load(f)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 except (OSError, IOError):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 self.disp(u"Can read file at {meta_file_path}, have it been deleted?\nCancelling edition".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 content_path=content_file_path, meta_path=meta_file_path), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 self.host.quit(C.EXIT_NOT_FOUND)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 except ValueError:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 self.disp(u"Can't parse metadata, please check it is correct JSON format. Cancelling edition.\n" +
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 "You can find tmp file at {content_path} and temporary meta file at {meta_path}.".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 content_path=content_file_path,
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 meta_path=meta_file_path), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 self.host.quit(C.EXIT_DATA_ERROR)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
268
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 if self.use_metadata and not C.bool(metadata.get('publish', "true")):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 self.disp(u'Publication blocked by "publish" key in metadata, cancelling edition.\n\n' +
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 "temporary file path:\t{content_path}\nmetadata file path:\t{meta_path}".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 content_path=content_file_path, meta_path=meta_file_path), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
274
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 if len(content) == 0:
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
276 self.disp(u"Content is empty, cancelling the edition")
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
277 if not content_file_path.startswith(getTmpDir(self.sat_conf, self.cat_dir_str)):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
278 self.disp(u"File are not in SàT temporary hierarchy, we do not remove them", 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
279 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 self.disp(u"Deletion of {}".format(content_file_path.decode('utf-8')), 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
281 os.unlink(content_file_path)
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
282 if self.use_metadata:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
283 self.disp(u"Deletion of {}".format(meta_file_path.decode('utf-8')), 2)
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
284 os.unlink(meta_file_path)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
285 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
286
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 # time to re-check the hash
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 elif (tmp_ori_hash == hashlib.sha1(content).digest() and
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
289 (not self.use_metadata or meta_ori == metadata)):
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
290 self.disp(u"The content has not been modified, cancelling the edition")
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
291 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
292
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 # we can now send the item
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
295 content = content.decode('utf-8-sig') # we use utf-8-sig to avoid BOM
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
298 self.publish(content, metadata)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
299 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
300 self.publish(content)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
301 except Exception as e:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
302 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 self.disp(u"Error while sending your item, the temporary files have been kept at {content_path} and {meta_path}: {reason}".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
304 content_path=content_file_path, meta_path=meta_file_path, reason=e), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
305 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
306 self.disp(u"Error while sending your item, the temporary file has been kept at {content_path}: {reason}".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
307 content_path=content_file_path, reason=e), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
308 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
309
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
310 self.secureUnlink(content_file_path)
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
311 if self.use_metadata:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
312 self.secureUnlink(meta_file_path)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
313
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
314 def publish(self, content):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
315 # if metadata is needed, publish will be called with it last argument
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
316 raise NotImplementedError
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
317
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
318 def getTmpFile(self):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
319 """Create a temporary file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
320
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 @param suff (str): suffix to use for the filename
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
322 @return (tuple(file, str)): opened (w+b) file object and file path
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
323 """
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
324 suff = '.' + self.getTmpSuff()
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
325 cat_dir_str = self.cat_dir_str
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
326 tmp_dir = getTmpDir(self.sat_conf, self.cat_dir_str, self.profile.encode('utf-8'))
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
327 if not os.path.exists(tmp_dir):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
328 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
329 os.makedirs(tmp_dir)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
330 except OSError as e:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
331 self.disp(u"Can't create {path} directory: {reason}".format(
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
332 path=tmp_dir, reason=e), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
333 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
334 try:
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
335 fd, path = tempfile.mkstemp(suffix=suff.encode('utf-8'),
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
336 prefix=time.strftime(cat_dir_str + '_%Y-%m-%d_%H:%M:%S_'),
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
337 dir=tmp_dir, text=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
338 return os.fdopen(fd, 'w+b'), path
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
339 except OSError as e:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 self.disp(u"Can't create temporary file: {reason}".format(reason=e), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
341 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
342
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
343 def getCurrentFile(self, profile):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
344 """Get most recently edited file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
345
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
346 @param profile(unicode): profile linked to the draft
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 @return(str): full path of current file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 """
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
349 # we guess the item currently edited by choosing
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
350 # the most recent file corresponding to temp file pattern
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 # in tmp_dir, excluding metadata files
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
352 cat_dir_str = self.cat_dir_str
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
353 tmp_dir = getTmpDir(self.sat_conf, self.cat_dir_str, profile.encode('utf-8'))
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
354 available = [path for path in glob.glob(os.path.join(tmp_dir, cat_dir_str + '_*')) if not path.endswith(METADATA_SUFF)]
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
355 if not available:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 self.disp(u"Could not find any content draft in {path}".format(path=tmp_dir), error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
357 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
358 return max(available, key=lambda path: os.stat(path).st_mtime)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
359
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 def getItemData(self, service, node, item):
2280
4bc9a2c2d6c9 jp (pubsub, common): fixed last item edition (keep item id instead of creating a new one)
Goffi <goffi@goffi.org>
parents: 2279
diff changeset
361 """return formatted content, metadata (or not if use_metadata is false), and item id"""
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 raise NotImplementedError
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
363
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
364 def getTmpSuff(self):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
365 """return suffix used for content file"""
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
366 return u'xml'
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
367
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
368 def getItemPath(self, item):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
369 """retrieve item path (i.e. service and node) from item argument
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
370
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
371 This method is obviously only useful for edition of PubSub based features
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
372 service, node and item must be named like this in args
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
373 @param item(unicode): item to get or url or magic keyword
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
374 item argument can be used to specify :
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
375 - HTTP(S) URL
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
376 - XMPP URL
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 - keyword, which can be:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
378 - new: create new item
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 - last: retrieve last published item
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 - current: continue current local draft
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
381 - file path
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
382 - item id
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
383 """
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
384 force_item = self.args.force_item
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
385 if force_item and not item:
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
386 self.parser.error(_(u"an item id must be specified if you use --force-item"))
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 command = item.lower()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
388 pubsub_service = self.args.service
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 pubsub_node = self.args.node
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 pubsub_item = None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
391
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
392 if not force_item and command not in ('new', 'last', 'current'):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
393 # we have probably an URL, we try to parse it
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
394 import urlparse
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
395 url = self.args.item
2329
f15b428852a0 jp (common): fixed encoding issue in URLs
Goffi <goffi@goffi.org>
parents: 2306
diff changeset
396 parsed_url = urlparse.urlsplit(url.encode('utf-8'))
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 if parsed_url.scheme.startswith('http'):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
398 self.disp(u"{} URL found, trying to find associated xmpp: URI".format(parsed_url.scheme.upper()),1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
399 # HTTP URL, we try to find xmpp: links
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
400 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
401 from lxml import etree
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
402 except ImportError:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
403 self.disp(u"lxml module must be installed to use http(s) scheme, please install it with \"pip install lxml\"", error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
404 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
405 import urllib2
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
406 parser = etree.HTMLParser()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
407 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
408 root = etree.parse(urllib2.urlopen(url), parser)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
409 except etree.XMLSyntaxError as e:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
410 self.disp(_(u"Can't parse HTML page : {msg}").format(msg=e))
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
411 links = []
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
412 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
413 links = root.xpath("//link[@rel='alternate' and starts-with(@href, 'xmpp:')]")
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
414 if not links:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
415 self.disp(u'Could not find alternate "xmpp:" URI, can\'t find associated XMPP PubSub node/item', error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
416 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
417 url = links[0].get('href')
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
418 parsed_url = urlparse.urlsplit(url)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
419
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
420 if parsed_url.scheme == 'xmpp':
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
421 if self.args.service or self.args.node:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
422 self.parser.error(_(u"You can't use URI and --service or --node at the same time"))
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
423
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
424 self.disp(u"XMPP URI used: {}".format(url),2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
425 # XXX: if we have not xmpp: URI here, we'll take the data as a file path
2329
f15b428852a0 jp (common): fixed encoding issue in URLs
Goffi <goffi@goffi.org>
parents: 2306
diff changeset
426 pubsub_service = parsed_url.path.decode('utf-8')
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
427 pubsub_data = urlparse.parse_qs(parsed_url.query)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
428 try:
2329
f15b428852a0 jp (common): fixed encoding issue in URLs
Goffi <goffi@goffi.org>
parents: 2306
diff changeset
429 pubsub_node = pubsub_data['node'][0].decode('utf-8')
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
430 except KeyError:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
431 self.disp(u'No node found in xmpp: URI, can\'t retrieve item', error=True)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
432 self.host.quit(1)
2334
ca14e1ced3b5 jp (common): fixed decode error when item is not specified
Goffi <goffi@goffi.org>
parents: 2329
diff changeset
433 pubsub_item = pubsub_data.get('item',[None])[0]
ca14e1ced3b5 jp (common): fixed decode error when item is not specified
Goffi <goffi@goffi.org>
parents: 2329
diff changeset
434 if pubsub_item is not None:
ca14e1ced3b5 jp (common): fixed decode error when item is not specified
Goffi <goffi@goffi.org>
parents: 2329
diff changeset
435 pubsub_item = pubsub_item.decode('utf-8')
2276
5cd45a79775b jp (common): added --last-item to take last item when no item id is found/given
Goffi <goffi@goffi.org>
parents: 2273
diff changeset
436 if pubsub_item is None and self.args.last_item:
5cd45a79775b jp (common): added --last-item to take last item when no item id is found/given
Goffi <goffi@goffi.org>
parents: 2273
diff changeset
437 command = 'last'
5cd45a79775b jp (common): added --last-item to take last item when no item id is found/given
Goffi <goffi@goffi.org>
parents: 2273
diff changeset
438 elif pubsub_item is not None:
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
439 command = 'edit' # XXX: edit command is only used internaly, it similar to last, but with the item given in the URL
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
440 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
441 command = 'new'
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
442
2306
07deebea71f3 jp (common): fixed the use of --last-item when "-n [node]" is used
Goffi <goffi@goffi.org>
parents: 2298
diff changeset
443 if self.args.last_item:
07deebea71f3 jp (common): fixed the use of --last-item when "-n [node]" is used
Goffi <goffi@goffi.org>
parents: 2298
diff changeset
444 if pubsub_item is None:
07deebea71f3 jp (common): fixed the use of --last-item when "-n [node]" is used
Goffi <goffi@goffi.org>
parents: 2298
diff changeset
445 command = 'last'
07deebea71f3 jp (common): fixed the use of --last-item when "-n [node]" is used
Goffi <goffi@goffi.org>
parents: 2298
diff changeset
446 elif command != 'last':
07deebea71f3 jp (common): fixed the use of --last-item when "-n [node]" is used
Goffi <goffi@goffi.org>
parents: 2298
diff changeset
447 self.parser.error(_(u"--last-item can't be used with a specified item"))
2276
5cd45a79775b jp (common): added --last-item to take last item when no item id is found/given
Goffi <goffi@goffi.org>
parents: 2273
diff changeset
448
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
449 if not force_item and command in ('new', 'last', 'edit'):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
450 # we need a temporary file
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
451 content_file_obj, content_file_path = self.getTmpFile()
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
452 if command == 'new':
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
453 self.disp(u'Editing a new item', 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
454 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
455 metadata = None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
456 elif command in ('last', 'edit'):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
457 self.disp(u'Editing requested published item', 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
458 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
459 if self.use_metadata:
2280
4bc9a2c2d6c9 jp (pubsub, common): fixed last item edition (keep item id instead of creating a new one)
Goffi <goffi@goffi.org>
parents: 2279
diff changeset
460 content, metadata, pubsub_item = self.getItemData(pubsub_service, pubsub_node, pubsub_item)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
461 else:
2280
4bc9a2c2d6c9 jp (pubsub, common): fixed last item edition (keep item id instead of creating a new one)
Goffi <goffi@goffi.org>
parents: 2279
diff changeset
462 content, pubsub_item = self.getItemData(pubsub_service, pubsub_node, pubsub_item)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
463 except Exception as e:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
464 self.disp(u"Error while retrieving last item: {}".format(e))
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
465 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
466 content_file_obj.write(content.encode('utf-8'))
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
467 content_file_obj.seek(0)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
468 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
469 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
470 metadata = None
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
471 if not force_item and command == 'current':
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
472 # user wants to continue current draft
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
473 content_file_path = self.getCurrentFile(self.profile)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
474 self.disp(u'Continuing edition of current draft', 2)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
475 content_file_obj = open(content_file_path, 'r+b')
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
476 elif not force_item and os.path.isfile(self.args.item):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
477 # there is an existing draft that we use
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
478 content_file_path = os.path.expanduser(self.args.item)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
479 content_file_obj = open(content_file_path, 'r+b')
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
480 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
481 # last chance, it should be an item
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
482 content_file_obj, content_file_path = self.getTmpFile()
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
483 pubsub_item = self.args.item
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
484
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
485 try:
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
486 # we try to get existing item
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
487 if self.use_metadata:
2280
4bc9a2c2d6c9 jp (pubsub, common): fixed last item edition (keep item id instead of creating a new one)
Goffi <goffi@goffi.org>
parents: 2279
diff changeset
488 content, metadata, pubsub_item = self.getItemData(pubsub_service, pubsub_node, self.args.item)
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
489 else:
2280
4bc9a2c2d6c9 jp (pubsub, common): fixed last item edition (keep item id instead of creating a new one)
Goffi <goffi@goffi.org>
parents: 2279
diff changeset
490 content, pubsub_item = self.getItemData(pubsub_service, pubsub_node, self.args.item)
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
491 except Exception as e:
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
492 # FIXME: ugly but we have not good may to check errors in bridge
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
493 if u'item-not-found' in unicode(e):
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
494 # item doesn't exist, we create a new one with requested id
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
495 metadata = None
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
496 self.disp(_(u'item "{item_id}" not found, we create a new item with this id').format(item_id=pubsub_item), 2)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
497 else:
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
498 # item exists, we write content if content file
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
499 content_file_obj.write(content.encode('utf-8'))
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
500 content_file_obj.seek(0)
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
501 self.disp(_(u'item "{item_id}" found, we edit it').format(item_id=pubsub_item), 2)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
502
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
503 if self.use_metadata:
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
504 return pubsub_service, pubsub_node, pubsub_item, content_file_path, content_file_obj, metadata
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
505 else:
2270
07caa12be945 jp (blog, common): added --force-item option to avoid magic and use argument as actual item id:
Goffi <goffi@goffi.org>
parents: 2269
diff changeset
506 return pubsub_service, pubsub_node, pubsub_item, content_file_path, content_file_obj
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
507
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
508
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
509 class Table(object):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
510
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
511 def __init__(self, host, data, headers=None, filters=None, use_buffer=False):
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
512 """
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
513 @param data(iterable[list]): table data
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
514 all lines must have the same number of columns
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
515 @param headers(iterable[unicode], None): names/titles of the columns
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
516 if not None, must have same number of columns as data
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
517 @param filters(iterable[(callable, unicode)], None): values filters
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
518 the callable will get col value as argument and must return a string
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
519 if it's unicode, it will be used with .format and must countain u'{}' which will be replaced with the string
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
520 if not None, must have same number of columns as data
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
521 @param use_buffer(bool): if True, bufferise output instead of printing it directly
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
522 """
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
523 self.host = host
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
524 self._buffer = [] if use_buffer else None
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
525 # headers are columns names/titles, can be None
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
526 self.headers = headers
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
527 # sizes fof columns without headers,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
528 # headers may be larger
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
529 self.sizes = []
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
530 # rows countains one list per row with columns values
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
531 self.rows = []
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
532
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
533 size = None
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
534 if headers:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
535 row_cls = namedtuple('RowData', headers)
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
536 else:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
537 row_cls = tuple
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
538
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
539 for row_data in data:
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
540 new_row = []
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
541 row_data_list = list(row_data)
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
542 for idx, value in enumerate(row_data_list):
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
543 if filters is not None and filters[idx] is not None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
544 filter_ = filters[idx]
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
545 if isinstance(filter_, basestring):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
546 col_value = filter_.format(value)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
547 else:
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
548 col_value = filter_(value, row_cls(*row_data_list))
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
549 # we count size without ANSI code as they will change length of the string
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
550 # when it's mostly style/color changes.
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
551 col_size = len(regex.ansiRemove(col_value))
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
552 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
553 col_value = unicode(value)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
554 col_size = len(col_value)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
555 new_row.append(col_value)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
556 if size is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
557 self.sizes.append(col_size)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
558 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
559 self.sizes[idx] = max(self.sizes[idx], col_size)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
560 if size is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
561 size = len(new_row)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
562 if headers is not None and len(headers) != size:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
563 raise exceptions.DataError(u'headers size is not coherent with rows')
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
564 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
565 if len(new_row) != size:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
566 raise exceptions.DataError(u'rows size is not coherent')
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
567 self.rows.append(new_row)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
568
2344
78ffb9ce57a4 jp (common): fixed empty table display when headers are specified
Goffi <goffi@goffi.org>
parents: 2334
diff changeset
569 if not data and headers is not None:
78ffb9ce57a4 jp (common): fixed empty table display when headers are specified
Goffi <goffi@goffi.org>
parents: 2334
diff changeset
570 # the table is empty, we print headers at their lenght
78ffb9ce57a4 jp (common): fixed empty table display when headers are specified
Goffi <goffi@goffi.org>
parents: 2334
diff changeset
571 self.sizes = [len(h) for h in headers]
78ffb9ce57a4 jp (common): fixed empty table display when headers are specified
Goffi <goffi@goffi.org>
parents: 2334
diff changeset
572
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
573 @property
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
574 def string(self):
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
575 if self._buffer is None:
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
576 raise exceptions.InternalError(u'buffer must be used to get a string')
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
577 return u'\n'.join(self._buffer)
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
578
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
579 @staticmethod
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
580 def readDictValues(data, keys, defaults=None):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
581 if defaults is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
582 defaults = {}
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
583 for key in keys:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
584 try:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
585 yield data[key]
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
586 except KeyError as e:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
587 default = defaults.get(key)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
588 if default is not None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
589 yield default
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
590 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
591 raise e
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
592
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
593 @classmethod
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
594 def fromDict(cls, host, data, keys=None, headers=None, filters=None, defaults=None):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
595 """Prepare a table to display it
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
596
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
597 the whole data will be read and kept into memory,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
598 to be printed
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
599 @param data(list[dict[unicode, unicode]]): data to create the table from
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
600 @param keys(iterable[unicode], None): keys to get
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
601 if None, all keys will be used
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
602 @param headers(iterable[unicode], None): name of the columns
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
603 names must be in same order as keys
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
604 @param filters(dict[unicode, (callable,unicode)), None): filter to use on values
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
605 keys correspond to keys to filter, and value is a callable or unicode which
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
606 will get the value as argument and must return a string
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
607 @param defaults(dict[unicode, unicode]): default value to use
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
608 if None, an exception will be raised if not value is found
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
609 """
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
610 if keys is None and headers is not None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
611 # FIXME: keys are not needed with OrderedDict,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
612 raise exceptions.DataError(u'You must specify keys order to used headers')
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
613 if keys is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
614 keys = data[0].keys()
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
615 if headers is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
616 headers = keys
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
617 filters = [filters.get(k) for k in keys]
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
618 return cls(host, (cls.readDictValues(d, keys, defaults) for d in data), headers, filters)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
619
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
620 def _headers(self, head_sep, headers, sizes, alignment=u'left', style=None):
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
621 """Render headers
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
622
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
623 @param head_sep(unicode): sequence to use as separator
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
624 @param alignment(unicode): how to align, can be left, center or right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
625 @param style(unicode, iterable[unicode], None): ANSI escape sequences to apply
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
626 @param headers(list[unicode]): headers to show
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
627 @param sizes(list[int]): sizes of columns
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
628 """
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
629 rendered_headers = []
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
630 if isinstance(style, basestring):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
631 style = [style]
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
632 for idx, header in enumerate(headers):
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
633 size = sizes[idx]
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
634 if alignment == u'left':
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
635 rendered = header[:size].ljust(size)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
636 elif alignment == u'center':
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
637 rendered = header[:size].center(size)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
638 elif alignment == u'right':
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
639 rendered = header[:size].rjust(size)
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
640 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
641 raise exceptions.InternalError(u'bad alignment argument')
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
642 if style:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
643 args = style + [rendered]
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
644 rendered = A.color(*args)
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
645 rendered_headers.append(rendered)
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
646 return head_sep.join(rendered_headers)
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
647
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
648 def _disp(self, data):
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
649 """output data (can be either bufferised or printed)"""
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
650 if self._buffer is not None:
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
651 self._buffer.append(data)
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
652 else:
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
653 self.host.disp(data)
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
654
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
655 def display(self,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
656 head_alignment = u'left',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
657 columns_alignment = u'left',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
658 head_style = None,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
659 show_header=True,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
660 show_borders=True,
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
661 hide_cols=None,
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
662 col_sep=u' │ ',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
663 top_left=u'┌',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
664 top=u'─',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
665 top_sep=u'─┬─',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
666 top_right=u'┐',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
667 left=u'│',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
668 right=None,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
669 head_sep=None,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
670 head_line=u'┄',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
671 head_line_left=u'├',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
672 head_line_sep=u'┄┼┄',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
673 head_line_right=u'┤',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
674 bottom_left=u'└',
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
675 bottom=None,
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
676 bottom_sep=u'─┴─',
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
677 bottom_right=u'┘',
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
678 ):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
679 """Print the table
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
680
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
681 @param show_header(bool): True if header need no be shown
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
682 @param show_borders(bool): True if borders need no be shown
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
683 @param hide_cols(None, iterable(unicode)): columns which should not be displayed
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
684 @param head_alignment(unicode): how to align headers, can be left, center or right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
685 @param columns_alignment(unicode): how to align columns, can be left, center or right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
686 @param col_sep(unicode): separator betweens columns
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
687 @param head_line(unicode): character to use to make line under head
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
688 @param disp(callable, None): method to use to display the table
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
689 None to use self.host.disp
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
690 """
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
691 if not self.sizes:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
692 # the table is empty
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
693 return
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
694 col_sep_size = len(regex.ansiRemove(col_sep))
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
695
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
696 # if we have columns to hide, we remove them from headers and size
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
697 if not hide_cols:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
698 headers = self.headers
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
699 sizes = self.sizes
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
700 else:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
701 headers = list(self.headers)
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
702 sizes = self.sizes[:]
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
703 ignore_idx = [headers.index(to_hide) for to_hide in hide_cols]
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
704 for to_hide in hide_cols:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
705 hide_idx = headers.index(to_hide)
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
706 del headers[hide_idx]
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
707 del sizes[hide_idx]
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
708
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
709 if right is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
710 right = left
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
711 if top_sep is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
712 top_sep = col_sep_size * top
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
713 if head_sep is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
714 head_sep = col_sep
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
715 if bottom is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
716 bottom = top
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
717 if bottom_sep is None:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
718 bottom_sep = col_sep_size * bottom
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
719 if not show_borders:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
720 left = right = head_line_left = head_line_right = u''
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
721 # top border
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
722 if show_borders:
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
723 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
724 top_left
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
725 + top_sep.join([top*size for size in sizes])
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
726 + top_right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
727 )
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
728
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
729 # headers
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
730 if show_header:
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
731 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
732 left
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
733 + self._headers(head_sep, headers, sizes, head_alignment, head_style)
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
734 + right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
735 )
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
736 # header line
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
737 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
738 head_line_left
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
739 + head_line_sep.join([head_line*size for size in sizes])
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
740 + head_line_right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
741 )
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
742
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
743 # content
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
744 if columns_alignment == u'left':
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
745 alignment = lambda idx, s: ansi_ljust(s, sizes[idx])
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
746 elif columns_alignment == u'center':
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
747 alignment = lambda idx, s: ansi_center(s, sizes[idx])
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
748 elif columns_alignment == u'right':
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
749 alignment = lambda idx, s: ansi_rjust(s, sizes[idx])
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
750 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
751 raise exceptions.InternalError(u'bad columns alignment argument')
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
752
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
753 for row in self.rows:
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
754 if hide_cols:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
755 row = [v for idx,v in enumerate(row) if idx not in ignore_idx]
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
756 self._disp(left + col_sep.join([alignment(idx,c) for idx,c in enumerate(row)]) + right)
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
757
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
758 if show_borders:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
759 # bottom border
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
760 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
761 bottom_left
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
762 + bottom_sep.join([bottom*size for size in sizes])
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
763 + bottom_right
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
764 )
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
765 # we return self so string can be used after display (table.display().string)
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
766 return self
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
767
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
768 def display_blank(self, **kwargs):
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
769 """Display table without visible borders"""
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
770 kwargs_ = {'col_sep':u' ', 'head_line_sep':u' ', 'show_borders':False}
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
771 kwargs_.update(kwargs)
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
772 return self.display(**kwargs_)