comparison sat/tools/utils.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 181735d1b062
children d62fceccff22
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
1 #!/usr/bin/env python2 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT: a jabber client 4 # SAT: a jabber client
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
6 6
34 from sat.core.log import getLogger 34 from sat.core.log import getLogger
35 35
36 log = getLogger(__name__) 36 log = getLogger(__name__)
37 37
38 38
39 NO_REPOS_DATA = u"repository data unknown" 39 NO_REPOS_DATA = "repository data unknown"
40 repos_cache_dict = None 40 repos_cache_dict = None
41 repos_cache = None 41 repos_cache = None
42 42
43 43
44 def clean_ustr(ustr): 44 def clean_ustr(ustr):
97 the string returned by this method is valid with RFC 3339 97 the string returned by this method is valid with RFC 3339
98 @param timestamp(None, float): posix timestamp. If None current time will be used 98 @param timestamp(None, float): posix timestamp. If None current time will be used
99 @param with_time(bool): if True include the time 99 @param with_time(bool): if True include the time
100 @return(unicode): XEP-0082 formatted date and time 100 @return(unicode): XEP-0082 formatted date and time
101 """ 101 """
102 template_date = u"%Y-%m-%d" 102 template_date = "%Y-%m-%d"
103 template_time = u"%H:%M:%SZ" 103 template_time = "%H:%M:%SZ"
104 template = ( 104 template = (
105 u"{}T{}".format(template_date, template_time) if with_time else template_date 105 "{}T{}".format(template_date, template_time) if with_time else template_date
106 ) 106 )
107 return datetime.datetime.utcfromtimestamp( 107 return datetime.datetime.utcfromtimestamp(
108 time.time() if timestamp is None else timestamp 108 time.time() if timestamp is None else timestamp
109 ).strftime(template) 109 ).strftime(template)
110 110
117 @return (unicode): generated password 117 @return (unicode): generated password
118 """ 118 """
119 random.seed() 119 random.seed()
120 if vocabulary is None: 120 if vocabulary is None:
121 vocabulary = [ 121 vocabulary = [
122 chr(i) for i in range(0x30, 0x3A) + range(0x41, 0x5B) + range(0x61, 0x7B) 122 chr(i) for i in list(range(0x30, 0x3A)) + list(range(0x41, 0x5B)) + list(range(0x61, 0x7B))
123 ] 123 ]
124 return u"".join([random.choice(vocabulary) for i in range(15)]) 124 return "".join([random.choice(vocabulary) for i in range(15)])
125 125
126 126
127 def getRepositoryData(module, as_string=True, is_path=False): 127 def getRepositoryData(module, as_string=True, is_path=False):
128 """Retrieve info on current mecurial repository 128 """Retrieve info on current mecurial repository
129 129
155 if repos_cache_dict is not None: 155 if repos_cache_dict is not None:
156 return repos_cache_dict 156 return repos_cache_dict
157 157
158 if sys.platform == "android": 158 if sys.platform == "android":
159 #  FIXME: workaround to avoid trouble on android, need to be fixed properly 159 #  FIXME: workaround to avoid trouble on android, need to be fixed properly
160 repos_cache = u"Cagou android build" 160 repos_cache = "Cagou android build"
161 return repos_cache 161 return repos_cache
162 162
163 KEYS = ("node", "node_short", "branch", "date", "tag", "distance") 163 KEYS = ("node", "node_short", "branch", "date", "tag", "distance")
164 ori_cwd = os.getcwd() 164 ori_cwd = os.getcwd()
165 165
169 repos_root = os.path.abspath(os.path.dirname(module.__file__)) 169 repos_root = os.path.abspath(os.path.dirname(module.__file__))
170 170
171 try: 171 try:
172 hg_path = procutils.which("hg")[0] 172 hg_path = procutils.which("hg")[0]
173 except IndexError: 173 except IndexError:
174 log.warning(u"Can't find hg executable") 174 log.warning("Can't find hg executable")
175 hg_path = None 175 hg_path = None
176 hg_data = {} 176 hg_data = {}
177 177
178 if hg_path is not None: 178 if hg_path is not None:
179 os.chdir(repos_root) 179 os.chdir(repos_root)
189 "{node|short}\n" 189 "{node|short}\n"
190 "{branch}\n" 190 "{branch}\n"
191 "{date|isodate}\n" 191 "{date|isodate}\n"
192 "{latesttag}\n" 192 "{latesttag}\n"
193 "{latesttagdistance}", 193 "{latesttagdistance}",
194 ] 194 ],
195 text=True
195 ) 196 )
196 except subprocess.CalledProcessError: 197 except subprocess.CalledProcessError:
197 hg_data = {} 198 hg_data = {}
198 else: 199 else:
199 hg_data = dict(zip(KEYS, hg_data_raw.split("\n"))) 200 hg_data = dict(list(zip(KEYS, hg_data_raw.split("\n"))))
200 try: 201 try:
201 hg_data["modified"] = "+" in subprocess.check_output(["hg", "id", "-i"]) 202 hg_data["modified"] = "+" in subprocess.check_output(["hg", "id", "-i"], text=True)
202 except subprocess.CalledProcessError: 203 except subprocess.CalledProcessError:
203 pass 204 pass
204 else: 205 else:
205 hg_data = {} 206 hg_data = {}
206 207
207 if not hg_data: 208 if not hg_data:
208 # .hg/dirstate method 209 # .hg/dirstate method
209 log.debug(u"trying dirstate method") 210 log.debug("trying dirstate method")
210 if is_path: 211 if is_path:
211 os.chdir(repos_root) 212 os.chdir(repos_root)
212 else: 213 else:
213 os.chdir(os.path.abspath(os.path.dirname(repos_root))) 214 os.chdir(os.path.abspath(os.path.dirname(repos_root)))
214 try: 215 try:
215 with open(".hg/dirstate") as hg_dirstate: 216 with open(".hg/dirstate") as hg_dirstate:
216 hg_data["node"] = hg_dirstate.read(20).encode("hex") 217 hg_data["node"] = hg_dirstate.read(20).encode("hex")
217 hg_data["node_short"] = hg_data["node"][:12] 218 hg_data["node_short"] = hg_data["node"][:12]
218 except IOError: 219 except IOError:
219 log.debug(u"Can't access repository data") 220 log.debug("Can't access repository data")
220 221
221 # we restore original working dir 222 # we restore original working dir
222 os.chdir(ori_cwd) 223 os.chdir(ori_cwd)
223 224
224 if not hg_data: 225 if not hg_data:
225 log.debug(u"Mercurial not available or working, trying package version") 226 log.debug("Mercurial not available or working, trying package version")
226 try: 227 try:
227 import pkg_resources 228 import pkg_resources
228 229
229 pkg_version = pkg_resources.get_distribution(C.APP_NAME_FILE).version 230 pkg_version = pkg_resources.get_distribution(C.APP_NAME_FILE).version
230 version, local_id = pkg_version.split("+", 1) 231 version, local_id = pkg_version.split("+", 1)
232 log.warning("pkg_resources not available, can't get package data") 233 log.warning("pkg_resources not available, can't get package data")
233 except pkg_resources.DistributionNotFound: 234 except pkg_resources.DistributionNotFound:
234 log.warning("can't retrieve package data") 235 log.warning("can't retrieve package data")
235 except ValueError: 236 except ValueError:
236 log.info( 237 log.info(
237 u"no local version id in package: {pkg_version}".format( 238 "no local version id in package: {pkg_version}".format(
238 pkg_version=pkg_version 239 pkg_version=pkg_version
239 ) 240 )
240 ) 241 )
241 else: 242 else:
242 version = version.replace(".dev0", "D") 243 version = version.replace(".dev0", "D")
257 258
258 if as_string: 259 if as_string:
259 if not hg_data: 260 if not hg_data:
260 repos_cache = NO_REPOS_DATA 261 repos_cache = NO_REPOS_DATA
261 else: 262 else:
262 strings = [u"rev", hg_data["node_short"]] 263 strings = ["rev", hg_data["node_short"]]
263 try: 264 try:
264 if hg_data["modified"]: 265 if hg_data["modified"]:
265 strings.append(u"[M]") 266 strings.append("[M]")
266 except KeyError: 267 except KeyError:
267 pass 268 pass
268 try: 269 try:
269 strings.extend([u"({branch} {date})".format(**hg_data)]) 270 strings.extend(["({branch} {date})".format(**hg_data)])
270 except KeyError: 271 except KeyError:
271 pass 272 pass
272 try: 273 try:
273 strings.extend([u"+{distance}".format(**hg_data)]) 274 strings.extend(["+{distance}".format(**hg_data)])
274 except KeyError: 275 except KeyError:
275 pass 276 pass
276 repos_cache = u" ".join(strings) 277 repos_cache = " ".join(strings)
277 return repos_cache 278 return repos_cache
278 else: 279 else:
279 return hg_data 280 return hg_data