annotate sat_frontends/jp/common.py @ 3254:6cf4bd6972c2

core, frontends: avatar refactoring: /!\ huge commit Avatar logic has been reworked around the IDENTITY plugin: plugins able to handle avatar or other identity related metadata (like nicknames) register to IDENTITY plugin in the same way as for other features like download/upload. Once registered, IDENTITY plugin will call them when suitable in order of priority, and handle caching. Methods to manage those metadata from frontend now use serialised data. For now `avatar` and `nicknames` are handled: - `avatar` is now a dict with `path` + metadata like `media_type`, instead of just a string path - `nicknames` is now a list of nicknames in order of priority. This list is never empty, and `nicknames[0]` should be the preferred nickname to use by frontends in most cases. In addition to contact specified nicknames, user set nickname (the one set in roster) is used in priority when available. Among the side changes done with this commit, there are: - a new `contactGet` bridge method to get roster metadata for a single contact - SatPresenceProtocol.send returns a Deferred to check when it has actually been sent - memory's methods to handle entities data now use `client` as first argument - metadata filter can be specified with `getIdentity` - `getAvatar` and `setAvatar` are now part of the IDENTITY plugin instead of XEP-0054 (and there signature has changed) - `isRoom` and `getBareOrFull` are now part of XEP-0045 plugin - jp avatar/get command uses `xdg-open` first when available for `--show` flag - `--no-cache` has been added to jp avatar/get and identity/get - jp identity/set has been simplified, explicit options (`--nickname` only for now) are used instead of `--field`. `--field` may come back in the future if necessary for extra data. - QuickContactList `SetContact` now handle None as a value, and doesn't use it to delete the metadata anymore - improved cache handling for `metadata` and `nicknames` in quick frontend - new `default` argument in QuickContactList `getCache`
author Goffi <goffi@goffi.org>
date Tue, 14 Apr 2020 21:00:33 +0200
parents 559a625a236b
children be6d91572633
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3137
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
1 #!/usr/bin/env python3
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
2
2269
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
3136
9d0df638c8b4 dates update
Goffi <goffi@goffi.org>
parents: 3121
diff changeset
5 # Copyright (C) 2009-2020 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
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
20 import json
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
21 import os
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
22 import os.path
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
23 import time
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
24 import tempfile
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
25 import asyncio
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
26 import shlex
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
27 import re
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
28 from pathlib import Path
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 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
30 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
31 from sat.core import exceptions
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from sat.tools.common import regex
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
33 from sat.tools.common.ansi import ANSI as A
2551
b27165bf160c jp (merge-request/set): if service and node are not specified, URIFinder is now used + ask confirmation before publishing
Goffi <goffi@goffi.org>
parents: 2532
diff changeset
34 from sat.tools.common import uri as xmpp_uri
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 from sat.tools import config
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
36 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
37 from collections import namedtuple
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
38
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 # 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
40 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
41 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
42 EDITOR_ARGS_MAGIC = {
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
43 "vim": VIM_SPLIT_ARGS + " {content_file} {metadata_file}",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
44 "gvim": VIM_SPLIT_ARGS + " --nofork {content_file} {metadata_file}",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
45 "emacs": EMACS_SPLIT_ARGS + " {content_file} {metadata_file}",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
46 "xemacs": EMACS_SPLIT_ARGS + " {content_file} {metadata_file}",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
47 "nano": " -F {content_file} {metadata_file}",
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
48 }
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
49
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 SECURE_UNLINK_MAX = 10
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 SECURE_UNLINK_DIR = ".backup"
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
52 METADATA_SUFF = "_metadata.json"
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
54
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
55 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
56 """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
57 cleaned = regex.ansiRemove(s)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
58 return s + " " * (width - len(cleaned))
2298
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
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
61 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
62 """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
63 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
64 diff = width - len(cleaned)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
65 half = diff / 2
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
66 return half * " " + s + (half + diff % 2) * " "
2298
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
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
69 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
70 """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
71 cleaned = regex.ansiRemove(s)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
72 return " " * (width - len(cleaned)) + s
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
73
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
74
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 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
76 """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
77
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 @param sat_conf(ConfigParser.ConfigParser): instance opened on sat configuration
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
79 @param cat_dir(str): 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
80 @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
81 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
82 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
83 initial str)
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
84 @return (Path): path to the dir
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
86 local_dir = config.getConfig(sat_conf, "", "local_dir", Exception)
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
87 path_elts = [local_dir, cat_dir]
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 if sub_dir is not None:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
89 path_elts.append(regex.pathEscape(sub_dir))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
90 return Path(*path_elts)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
91
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
92
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
93 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
94 """Parse command arguments
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
95
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
96 @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
97 @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
98 @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
99 """
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
100 try:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
101 # 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
102 # 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
103 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
104 except ValueError as e:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
105 host.disp(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
106 "Couldn't parse editor cmd [{cmd}]: {reason}".format(cmd=cmd_line, reason=e)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
107 )
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
108 return []
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
109
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
110
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 class BaseEdit(object):
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
112 """base class for editing commands
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
113
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 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
115 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
116 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
117
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
118 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
119 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 @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
121 @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
122 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
123 @param use_metadata(bool): True is edition need a second file for metadata
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
124 most of signature change with use_metadata with an additional metadata
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
125 argument.
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
126 This is done to raise error if a command needs metadata but forget the flag,
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
127 and vice versa
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 self.host = host
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
130 self.cat_dir = cat_dir
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 self.use_metadata = use_metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
132
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 def secureUnlink(self, path):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 """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
135
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 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
137 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
138 older file are deleted
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
139 @param path(Path, str): file to unlink
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
140 """
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
141 path = Path(path).resolve()
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
142 if not path.is_file:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
143 raise OSError("path must link to a regular file")
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
144 if path.parent != getTmpDir(self.sat_conf, self.cat_dir):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
145 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
146 f"File {path} is not in SàT temporary hierarchy, we do not remove "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
147 f"it",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
148 2,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
149 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 return
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 # 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
152 unlink_max = SECURE_UNLINK_MAX * 2 if self.use_metadata else SECURE_UNLINK_MAX
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
153 backup_dir = getTmpDir(self.sat_conf, self.cat_dir, SECURE_UNLINK_DIR)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 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
155 os.makedirs(backup_dir)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 filename = os.path.basename(path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 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
158 # we move file to backup dir
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
159 self.host.disp(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
160 "Backuping file {src} to {dst}".format(
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
161 src=path, dst=backup_path
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
162 ),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
163 1,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
164 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 os.rename(path, backup_path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 # 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
167 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
168 if len(backup_files) > unlink_max:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 backup_files.sort(key=lambda path: os.stat(path).st_mtime)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
170 for path in backup_files[: len(backup_files) - unlink_max]:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
171 self.host.disp("Purging backup file {}".format(path), 2)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 os.unlink(path)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
173
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
174 async def runEditor(self, editor_args_opt, content_file_path, content_file_obj,
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
175 meta_file_path=None, meta_ori=None):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
176 """Run editor to edit content and metadata
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
177
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 @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
179 specific args
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 @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
181 @param content_file_obj(file): opened file instance
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
182 @param meta_file_path(str, Path, None): metadata file path
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 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
184 @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
185 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
186 """
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 if not self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 assert meta_file_path is None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 assert meta_ori is None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
190
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 # 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
192 import hashlib
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
193
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 content_file_obj.seek(0)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 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
196 content_file_obj.close()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
197
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 # we prepare arguments
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
199 editor = config.getConfig(self.sat_conf, "jp", "editor") or os.getenv(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
200 "EDITOR", "vi"
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
201 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 # is there custom arguments in sat.conf ?
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
204 editor_args = config.getConfig(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
205 self.sat_conf, "jp", editor_args_opt, Exception
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
206 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 except (NoOptionError, NoSectionError):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 # 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
209 if self.use_metadata:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
210 editor_args = EDITOR_ARGS_MAGIC.get(os.path.basename(editor), "")
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
211 else:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
212 editor_args = ""
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
213 parse_kwargs = {"content_file": content_file_path}
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 if self.use_metadata:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
215 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
216 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
217 if not args:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 args = [content_file_path]
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
219
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 # actual editing
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
221 editor_process = await asyncio.create_subprocess_exec(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
222 editor, *[str(a) for a in args])
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
223 editor_exit = await editor_process.wait()
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
224
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 # 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
226 if editor_exit != 0:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
227 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
228 f"Editor exited with an error code, so temporary file has not be "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
229 f"deleted, and item is not published.\nYou can find temporary file "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
230 f"at {content_file_path}",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
231 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
232 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 else:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 # main content
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 try:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
236 with content_file_path.open("rb") as f:
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 content = f.read()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 except (OSError, IOError):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
239 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
240 f"Can read file at {content_file_path}, have it been deleted?\n"
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
241 f"Cancelling edition",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
242 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
243 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 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
245
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 # metadata
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 try:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
249 with meta_file_path.open("rb") as f:
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 metadata = json.load(f)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 except (OSError, IOError):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
252 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
253 f"Can read file at {meta_file_path}, have it been deleted?\n"
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
254 f"Cancelling edition",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
255 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
256 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 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
258 except ValueError:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
259 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
260 f"Can't parse metadata, please check it is correct JSON format. "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
261 f"Cancelling edition.\nYou can find tmp file at "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
262 f"{content_file_path} and temporary meta file at "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
263 f"{meta_file_path}.",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
264 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
265 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 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
267
2905
d9491cb81726 jp (common): `publish` is now a boolean
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
268 if self.use_metadata and not metadata.get("publish", True):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
269 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
270 f'Publication blocked by "publish" key in metadata, cancelling '
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
271 f'edition.\n\ntemporary file path:\t{content_file_path}\nmetadata '
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
272 f'file path:\t{meta_file_path}',
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
273 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
274 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
276
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 if len(content) == 0:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
278 self.disp("Content is empty, cancelling the edition")
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
279 if content_file_path.parent != getTmpDir(self.sat_conf, self.cat_dir):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
280 self.disp(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
281 "File are not in SàT temporary hierarchy, we do not remove them",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
282 2,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
283 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
284 self.host.quit()
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
285 self.disp(f"Deletion of {content_file_path}", 2)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 os.unlink(content_file_path)
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
287 if self.use_metadata:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
288 self.disp(f"Deletion of {meta_file_path}".format(meta_file_path), 2)
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
289 os.unlink(meta_file_path)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
290 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
291
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
292 # time to re-check the hash
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
293 elif tmp_ori_hash == hashlib.sha1(content).digest() and (
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
294 not self.use_metadata or meta_ori == metadata
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
295 ):
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
296 self.disp("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
297 self.host.quit()
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
298
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 # we can now send the item
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
301 content = content.decode("utf-8-sig") # we use utf-8-sig to avoid BOM
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
302 try:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 if self.use_metadata:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
304 await self.publish(content, metadata)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
305 else:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
306 await self.publish(content)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
307 except Exception as e:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
308 if self.use_metadata:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
309 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
310 f"Error while sending your item, the temporary files have "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
311 f"been kept at {content_file_path} and {meta_file_path}: "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
312 f"{e}",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
313 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
314 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
315 else:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
316 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
317 f"Error while sending your item, the temporary file has been "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
318 f"kept at {content_file_path}: {e}",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
319 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
320 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
322
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
323 self.secureUnlink(content_file_path)
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
324 if self.use_metadata:
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
325 self.secureUnlink(meta_file_path)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
326
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
327 async def publish(self, content):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
328 # 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
329 raise NotImplementedError
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
330
2351
3c0a3fae1862 jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
Goffi <goffi@goffi.org>
parents: 2345
diff changeset
331 def getTmpFile(self):
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
332 """Create a temporary file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
333
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
334 @return (tuple(file, Path)): opened (w+b) file object and file path
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
335 """
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
336 suff = "." + self.getTmpSuff()
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
337 cat_dir_str = self.cat_dir
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
338 tmp_dir = getTmpDir(self.sat_conf, self.cat_dir, self.profile)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
339 if not tmp_dir.exists():
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 try:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
341 tmp_dir.mkdir(parents=True)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
342 except OSError as e:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
343 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
344 f"Can't create {tmp_dir} directory: {e}",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
345 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
346 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 try:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
349 fd, path = tempfile.mkstemp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
350 suffix=suff,
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
351 prefix=time.strftime(cat_dir_str + "_%Y-%m-%d_%H:%M:%S_"),
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
352 dir=tmp_dir,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
353 text=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
354 )
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
355 return os.fdopen(fd, "w+b"), Path(path)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 except OSError as e:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
357 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
358 f"Can't create temporary file: {e}", error=True
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
359 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 self.host.quit(1)
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
361
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 def getCurrentFile(self, profile):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
363 """Get most recently edited file
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
364
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
365 @param profile(unicode): profile linked to the draft
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
366 @return(Path): full path of current file
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
367 """
2273
5f0dbf42aa9c jp (blog, common): various fixes in common and blog:
Goffi <goffi@goffi.org>
parents: 2270
diff changeset
368 # 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
369 # 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
370 # in tmp_dir, excluding metadata files
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
371 tmp_dir = getTmpDir(self.sat_conf, self.cat_dir, profile)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
372 available = [
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
373 p
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
374 for p in tmp_dir.glob(f'{self.cat_dir}_*')
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
375 if not p.match(f"*{METADATA_SUFF}")
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
376 ]
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 if not available:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
378 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
379 f"Could not find any content draft in {tmp_dir}",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
380 error=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
381 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
382 self.host.quit(1)
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
383 return max(available, key=lambda p: p.stat().st_mtime)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
384
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
385 async 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
386 """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
387 raise NotImplementedError
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
388
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 def getTmpSuff(self):
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 """return suffix used for content file"""
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
391 return "xml"
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
392
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
393 async def getItemPath(self):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
394 """Retrieve item path (i.e. service and node) from item argument
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
395
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 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
397 """
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
398 service = self.args.service
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
399 node = self.args.node
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
400 item = self.args.item
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
401 last_item = self.args.last_item
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
402
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
403 if self.args.current:
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
404 # user wants to continue current draft
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
405 content_file_path = self.getCurrentFile(self.profile)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
406 self.disp("Continuing edition of current draft", 2)
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
407 content_file_obj = content_file_path.open("r+b")
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
408 # we seek at the end of file in case of an item already exist
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
409 # this will write content of the existing item at the end of the draft.
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
410 # This way no data should be lost.
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
411 content_file_obj.seek(0, os.SEEK_END)
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
412 elif self.args.draft_path:
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
413 # there is an existing draft that we use
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
414 content_file_path = self.args.draft_path.expanduser()
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
415 content_file_obj = content_file_path.open("r+b")
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
416 # we seek at the end for the same reason as above
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
417 content_file_obj.seek(0, os.SEEK_END)
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
418 else:
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
419 # 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
420 content_file_obj, content_file_path = self.getTmpFile()
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
421
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
422 if item or last_item:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
423 self.disp("Editing requested published item", 2)
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
424 try:
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
425 if self.use_metadata:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
426 content, metadata, item = await self.getItemData(service, node, item)
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
427 else:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
428 content, item = await self.getItemData(service, node, item)
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
429 except Exception as e:
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
430 # FIXME: ugly but we have not good may to check errors in bridge
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
431 if "item-not-found" in str(e):
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
432 #  item doesn't exist, we create a new one with requested id
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
433 metadata = None
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
434 if last_item:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
435 self.disp(_("no item found at all, we create a new one"), 2)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
436 else:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
437 self.disp(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
438 _(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
439 f'item "{item}" not found, we create a new item with'
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
440 f'this id'
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
441 ),
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
442 2,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
443 )
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
444 content_file_obj.seek(0)
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
445 else:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
446 self.disp(f"Error while retrieving item: {e}")
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
447 self.host.quit(C.EXIT_ERROR)
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
448 else:
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
449 # item exists, we write content
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
450 if content_file_obj.tell() != 0:
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
451 # we already have a draft,
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
452 # we copy item content after it and add an indicator
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
453 content_file_obj.write("\n*****\n")
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
454 content_file_obj.write(content.encode("utf-8"))
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
455 content_file_obj.seek(0)
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
456 self.disp(
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
457 _(f'item "{item}" found, we edit it'), 2
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
458 )
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
459 else:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
460 self.disp("Editing a new item", 2)
2269
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
461 if self.use_metadata:
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
462 metadata = None
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
463
606ff34d30f2 jp (blog, common): moved and improved edit code from blog:
Goffi <goffi@goffi.org>
parents:
diff changeset
464 if self.use_metadata:
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
465 return service, node, 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
466 else:
2532
772447ec070f jp: pubsub options refactoring:
Goffi <goffi@goffi.org>
parents: 2523
diff changeset
467 return service, node, 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
468
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
469
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
470 class Table(object):
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
471 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
472 """
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
473 @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
474 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
475 @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
476 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
477 @param filters(iterable[(callable, unicode)], None): values filters
2610
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
478 the callable will get 2 arguments:
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
479 - current column value
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
480 - RowData with all columns values
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
481 if may also only use 1 argument, which will then be current col value.
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
482 the callable must return a string
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
483 if it's unicode, it will be used with .format and must countain u'{}' which
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
484 will be replaced with the string.
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
485 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
486 @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
487 """
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
488 self.host = host
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
489 self._buffer = [] if use_buffer else None
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
490 #  headers are columns names/titles, can be None
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
491 self.headers = headers
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
492 #  sizes fof columns without headers,
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
493 # 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
494 self.sizes = []
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
495 #  rows countains one list per row with columns values
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
496 self.rows = []
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
497
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
498 size = None
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
499 if headers:
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
500 # we use a namedtuple to make the value easily accessible from filters
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
501 headers_safe = [re.sub(r'[^a-zA-Z_]', '_', h) for h in headers]
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
502 row_cls = namedtuple("RowData", headers_safe)
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
503 else:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
504 row_cls = tuple
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
505
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
506 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
507 new_row = []
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
508 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
509 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
510 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
511 filter_ = filters[idx]
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
512 if isinstance(filter_, str):
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
513 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
514 else:
2610
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
515 try:
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
516 col_value = filter_(value, row_cls(*row_data_list))
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
517 except TypeError:
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
518 col_value = filter_(value)
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
519 # we count size without ANSI code as they will change length of the
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
520 # string when it's mostly style/color changes.
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
521 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
522 else:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
523 col_value = str(value)
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
524 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
525 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
526 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
527 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
528 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
529 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
530 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
531 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
532 if headers is not None and len(headers) != size:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
533 raise exceptions.DataError("headers size is not coherent with rows")
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
534 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
535 if len(new_row) != size:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
536 raise exceptions.DataError("rows size is not coherent")
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
537 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
538
2344
78ffb9ce57a4 jp (common): fixed empty table display when headers are specified
Goffi <goffi@goffi.org>
parents: 2334
diff changeset
539 if not data and headers is not None:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
540 #  the table is empty, we print headers at their lenght
2344
78ffb9ce57a4 jp (common): fixed empty table display when headers are specified
Goffi <goffi@goffi.org>
parents: 2334
diff changeset
541 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
542
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
543 @property
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
544 def string(self):
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
545 if self._buffer is None:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
546 raise exceptions.InternalError("buffer must be used to get a string")
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
547 return "\n".join(self._buffer)
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
548
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
549 @staticmethod
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
550 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
551 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
552 defaults = {}
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
553 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
554 try:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
555 yield data[key]
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
556 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
557 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
558 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
559 yield default
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
560 else:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
561 raise e
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
562
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
563 @classmethod
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
564 def fromListDict(
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
565 cls, host, data, keys=None, headers=None, filters=None, defaults=None):
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
566 """Create a table from a list of dictionaries
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
567
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
568 each dictionary is a row of the table, keys being columns names.
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
569 the whole data will be read and kept into memory, to be printed
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
570 @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
571 @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
572 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
573 @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
574 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
575 @param filters(dict[unicode, (callable,unicode)), None): filter to use on values
2610
c9dddf691d7b jp (common): allow tables filters callbacks to have only one argument
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
576 keys correspond to keys to filter, and value is the same as for Table.__init__
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
577 @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
578 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
579 """
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
580 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
581 # FIXME: keys are not needed with OrderedDict,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
582 raise exceptions.DataError("You must specify keys order to used headers")
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
583 if keys is None:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
584 keys = list(data[0].keys())
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
585 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
586 headers = keys
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
587 if filters is None:
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
588 filters = {}
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
589 filters = [filters.get(k) for k in keys]
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
590 return cls(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
591 host, (cls.readDictValues(d, keys, defaults) for d in data), headers, filters
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
592 )
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
593
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
594 def _headers(self, head_sep, headers, sizes, alignment="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
595 """Render headers
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 @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
598 @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
599 @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
600 @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
601 @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
602 """
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
603 rendered_headers = []
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
604 if isinstance(style, str):
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
605 style = [style]
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
606 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
607 size = sizes[idx]
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
608 if alignment == "left":
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
609 rendered = header[:size].ljust(size)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
610 elif alignment == "center":
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
611 rendered = header[:size].center(size)
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
612 elif alignment == "right":
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
613 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
614 else:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
615 raise exceptions.InternalError("bad alignment argument")
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
616 if style:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
617 args = style + [rendered]
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
618 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
619 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
620 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
621
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
622 def _disp(self, data):
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
623 """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
624 if self._buffer is not None:
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
625 self._buffer.append(data)
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
626 else:
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
627 self.host.disp(data)
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
628
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
629 def display(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
630 self,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
631 head_alignment="left",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
632 columns_alignment="left",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
633 head_style=None,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
634 show_header=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
635 show_borders=True,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
636 hide_cols=None,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
637 col_sep=" │ ",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
638 top_left="┌",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
639 top="─",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
640 top_sep="─┬─",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
641 top_right="┐",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
642 left="│",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
643 right=None,
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
644 head_sep=None,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
645 head_line="┄",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
646 head_line_left="├",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
647 head_line_sep="┄┼┄",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
648 head_line_right="┤",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
649 bottom_left="└",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
650 bottom=None,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
651 bottom_sep="─┴─",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
652 bottom_right="┘",
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
653 ):
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
654 """Print the table
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
655
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
656 @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
657 @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
658 @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
659 @param head_alignment(unicode): how to align headers, can be left, center or right
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
660 @param columns_alignment(unicode): how to align columns, can be left, center or
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
661 right
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
662 @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
663 @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
664 @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
665 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
666 """
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
667 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
668 # 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
669 return
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
670 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
671
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
672 # 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
673 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
674 headers = self.headers
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
675 sizes = self.sizes
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
676 else:
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
677 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
678 sizes = self.sizes[:]
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
679 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
680 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
681 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
682 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
683 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
684
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
685 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
686 right = left
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
687 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
688 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
689 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
690 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
691 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
692 bottom = top
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
693 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
694 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
695 if not show_borders:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
696 left = right = head_line_left = head_line_right = ""
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
697 # top border
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
698 if show_borders:
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
699 self._disp(
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
700 top_left + top_sep.join([top * size for size in sizes]) + top_right
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
701 )
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
702
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
703 # headers
3121
040ca99e25fe jp (common): various Table fixes:
Goffi <goffi@goffi.org>
parents: 3046
diff changeset
704 if show_header and self.headers is not None:
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
705 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
706 left
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
707 + 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
708 + right
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
709 )
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
710 # header line
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
711 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
712 head_line_left
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
713 + 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
714 + head_line_right
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
715 )
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
716
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
717 # content
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
718 if columns_alignment == "left":
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
719 alignment = lambda idx, s: ansi_ljust(s, sizes[idx])
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
720 elif columns_alignment == "center":
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
721 alignment = lambda idx, s: ansi_center(s, sizes[idx])
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
722 elif columns_alignment == "right":
2493
984792a451bc jp (common/table): a column can be hidden + fix for empty tables
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
723 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
724 else:
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
725 raise exceptions.InternalError("bad columns alignment argument")
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
726
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
727 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
728 if hide_cols:
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
729 row = [v for idx, v in enumerate(row) if idx not in ignore_idx]
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
730 self._disp(
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
731 left
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
732 + col_sep.join([alignment(idx, c) for idx, c in enumerate(row)])
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
733 + right
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
734 )
2298
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 if show_borders:
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
737 # bottom border
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
738 self._disp(
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
739 bottom_left
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
740 + 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
741 + bottom_right
2624
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
742 )
56f94936df1e code style reformatting using black
Goffi <goffi@goffi.org>
parents: 2610
diff changeset
743 #  we return self so string can be used after display (table.display().string)
2345
c57bc0fe17d9 jp (common): added use_buffer argument in Table:
Goffi <goffi@goffi.org>
parents: 2344
diff changeset
744 return self
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
745
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
746 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
747 """Display table without visible borders"""
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2905
diff changeset
748 kwargs_ = {"col_sep": " ", "head_line_sep": " ", "show_borders": False}
2298
276e546b7619 jp (common): new ansi_ljust, ansi_rjust and ansi_center command + table:
Goffi <goffi@goffi.org>
parents: 2280
diff changeset
749 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
750 return self.display(**kwargs_)
2551
b27165bf160c jp (merge-request/set): if service and node are not specified, URIFinder is now used + ask confirmation before publishing
Goffi <goffi@goffi.org>
parents: 2532
diff changeset
751
b27165bf160c jp (merge-request/set): if service and node are not specified, URIFinder is now used + ask confirmation before publishing
Goffi <goffi@goffi.org>
parents: 2532
diff changeset
752
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
753 async def fill_well_known_uri(command, path, key, meta_map=None):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
754 """Look for URIs in well-known location and fill appropriate args if suitable
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
755
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
756 @param command(CommandBase): command instance
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
757 args of this instance will be updated with found values
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
758 @param path(unicode): absolute path to use as a starting point to look for URIs
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
759 @param key(unicode): key to look for
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
760 @param meta_map(dict, None): if not None, map metadata to arg name
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
761 key is metadata used attribute name
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
762 value is name to actually use, or None to ignore
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
763 use empty dict to only retrieve URI
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
764 possible keys are currently:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
765 - labels
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
766 """
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
767 args = command.args
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
768 if args.service or args.node:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
769 # we only look for URIs if a service and a node are not already specified
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
770 return
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
771
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
772 host = command.host
2551
b27165bf160c jp (merge-request/set): if service and node are not specified, URIFinder is now used + ask confirmation before publishing
Goffi <goffi@goffi.org>
parents: 2532
diff changeset
773
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
774 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
775 uris_data = await host.bridge.URIFind(path, [key])
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
776 except Exception as e:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
777 host.disp(f"can't find {key} URI: {e}", error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
778 host.quit(C.EXIT_BRIDGE_ERRBACK)
2551
b27165bf160c jp (merge-request/set): if service and node are not specified, URIFinder is now used + ask confirmation before publishing
Goffi <goffi@goffi.org>
parents: 2532
diff changeset
779
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
780 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
781 uri_data = uris_data[key]
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
782 except KeyError:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
783 host.disp(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
784 _(f"No {key} URI specified for this project, please specify service and "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
785 f"node"),
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
786 error=True,
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
787 )
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
788 host.quit(C.EXIT_NOT_FOUND)
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
789
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
790 uri = uri_data["uri"]
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
791
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
792 # set extra metadata if they are specified
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
793 for data_key in ['labels']:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
794 new_values_json = uri_data.get(data_key)
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
795 if uri_data is not None:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
796 if meta_map is None:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
797 dest = data_key
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
798 else:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
799 dest = meta_map.get(data_key)
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
800 if dest is None:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
801 continue
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
802
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
803 try:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
804 values = getattr(args, data_key)
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
805 except AttributeError:
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
806 raise exceptions.InternalError(f'there is no {data_key!r} arguments')
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
807 else:
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
808 if values is None:
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
809 values = []
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
810 values.extend(json.loads(new_values_json))
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
811 setattr(args, dest, values)
2558
501b0f827f63 jp (merge-request,common): fixed URIFinder when metadata are not needed:
Goffi <goffi@goffi.org>
parents: 2554
diff changeset
812
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
813 parsed_uri = xmpp_uri.parseXMPPUri(uri)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
814 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
815 args.service = parsed_uri["path"]
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
816 args.node = parsed_uri["node"]
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
817 except KeyError:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
818 host.disp(_(f"Invalid URI found: {uri}"), error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3037
diff changeset
819 host.quit(C.EXIT_DATA_ERROR)