comparison mercurial/extensions.py @ 43077:687b865b95ad

formatting: byteify all mercurial/ and hgext/ string literals Done with python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py') black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**') # skip-blame mass-reformatting only Differential Revision: https://phab.mercurial-scm.org/D6972
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:48:39 -0400
parents 2372284d9457
children eef9a2d67051
comparison
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
32 _extensions = {} 32 _extensions = {}
33 _disabledextensions = {} 33 _disabledextensions = {}
34 _aftercallbacks = {} 34 _aftercallbacks = {}
35 _order = [] 35 _order = []
36 _builtin = { 36 _builtin = {
37 'hbisect', 37 b'hbisect',
38 'bookmarks', 38 b'bookmarks',
39 'color', 39 b'color',
40 'parentrevspec', 40 b'parentrevspec',
41 'progress', 41 b'progress',
42 'interhg', 42 b'interhg',
43 'inotify', 43 b'inotify',
44 'hgcia', 44 b'hgcia',
45 'shelve', 45 b'shelve',
46 } 46 }
47 47
48 48
49 def extensions(ui=None): 49 def extensions(ui=None):
50 if ui: 50 if ui:
51 51
52 def enabled(name): 52 def enabled(name):
53 for format in ['%s', 'hgext.%s']: 53 for format in [b'%s', b'hgext.%s']:
54 conf = ui.config('extensions', format % name) 54 conf = ui.config(b'extensions', format % name)
55 if conf is not None and not conf.startswith('!'): 55 if conf is not None and not conf.startswith(b'!'):
56 return True 56 return True
57 57
58 else: 58 else:
59 enabled = lambda name: True 59 enabled = lambda name: True
60 for name in _order: 60 for name in _order:
68 mod = None 68 mod = None
69 try: 69 try:
70 mod = _extensions[name] 70 mod = _extensions[name]
71 except KeyError: 71 except KeyError:
72 for k, v in _extensions.iteritems(): 72 for k, v in _extensions.iteritems():
73 if k.endswith('.' + name) or k.endswith('/' + name): 73 if k.endswith(b'.' + name) or k.endswith(b'/' + name):
74 mod = v 74 mod = v
75 break 75 break
76 if not mod: 76 if not mod:
77 raise KeyError(name) 77 raise KeyError(name)
78 return mod 78 return mod
79 79
80 80
81 def loadpath(path, module_name): 81 def loadpath(path, module_name):
82 module_name = module_name.replace('.', '_') 82 module_name = module_name.replace(b'.', b'_')
83 path = util.normpath(util.expandpath(path)) 83 path = util.normpath(util.expandpath(path))
84 module_name = pycompat.fsdecode(module_name) 84 module_name = pycompat.fsdecode(module_name)
85 path = pycompat.fsdecode(path) 85 path = pycompat.fsdecode(path)
86 if os.path.isdir(path): 86 if os.path.isdir(path):
87 # module/__init__.py style 87 # module/__init__.py style
98 98
99 99
100 def _importh(name): 100 def _importh(name):
101 """import and return the <name> module""" 101 """import and return the <name> module"""
102 mod = __import__(pycompat.sysstr(name)) 102 mod = __import__(pycompat.sysstr(name))
103 components = name.split('.') 103 components = name.split(b'.')
104 for comp in components[1:]: 104 for comp in components[1:]:
105 mod = getattr(mod, comp) 105 mod = getattr(mod, comp)
106 return mod 106 return mod
107 107
108 108
109 def _importext(name, path=None, reportfunc=None): 109 def _importext(name, path=None, reportfunc=None):
110 if path: 110 if path:
111 # the module will be loaded in sys.modules 111 # the module will be loaded in sys.modules
112 # choose an unique name so that it doesn't 112 # choose an unique name so that it doesn't
113 # conflicts with other modules 113 # conflicts with other modules
114 mod = loadpath(path, 'hgext.%s' % name) 114 mod = loadpath(path, b'hgext.%s' % name)
115 else: 115 else:
116 try: 116 try:
117 mod = _importh("hgext.%s" % name) 117 mod = _importh(b"hgext.%s" % name)
118 except ImportError as err: 118 except ImportError as err:
119 if reportfunc: 119 if reportfunc:
120 reportfunc(err, "hgext.%s" % name, "hgext3rd.%s" % name) 120 reportfunc(err, b"hgext.%s" % name, b"hgext3rd.%s" % name)
121 try: 121 try:
122 mod = _importh("hgext3rd.%s" % name) 122 mod = _importh(b"hgext3rd.%s" % name)
123 except ImportError as err: 123 except ImportError as err:
124 if reportfunc: 124 if reportfunc:
125 reportfunc(err, "hgext3rd.%s" % name, name) 125 reportfunc(err, b"hgext3rd.%s" % name, name)
126 mod = _importh(name) 126 mod = _importh(name)
127 return mod 127 return mod
128 128
129 129
130 def _reportimporterror(ui, err, failed, next): 130 def _reportimporterror(ui, err, failed, next):
135 b' - could not import %s (%s): trying %s\n', 135 b' - could not import %s (%s): trying %s\n',
136 failed, 136 failed,
137 stringutil.forcebytestr(err), 137 stringutil.forcebytestr(err),
138 next, 138 next,
139 ) 139 )
140 if ui.debugflag and ui.configbool('devel', 'debug.extensions'): 140 if ui.debugflag and ui.configbool(b'devel', b'debug.extensions'):
141 ui.traceback() 141 ui.traceback()
142 142
143 143
144 def _rejectunicode(name, xs): 144 def _rejectunicode(name, xs):
145 if isinstance(xs, (list, set, tuple)): 145 if isinstance(xs, (list, set, tuple)):
150 _rejectunicode(name, k) 150 _rejectunicode(name, k)
151 _rejectunicode(b'%s.%s' % (name, stringutil.forcebytestr(k)), v) 151 _rejectunicode(b'%s.%s' % (name, stringutil.forcebytestr(k)), v)
152 elif isinstance(xs, type(u'')): 152 elif isinstance(xs, type(u'')):
153 raise error.ProgrammingError( 153 raise error.ProgrammingError(
154 b"unicode %r found in %s" % (xs, name), 154 b"unicode %r found in %s" % (xs, name),
155 hint="use b'' to make it byte string", 155 hint=b"use b'' to make it byte string",
156 ) 156 )
157 157
158 158
159 # attributes set by registrar.command 159 # attributes set by registrar.command
160 _cmdfuncattrs = ('norepo', 'optionalrepo', 'inferrepo') 160 _cmdfuncattrs = (b'norepo', b'optionalrepo', b'inferrepo')
161 161
162 162
163 def _validatecmdtable(ui, cmdtable): 163 def _validatecmdtable(ui, cmdtable):
164 """Check if extension commands have required attributes""" 164 """Check if extension commands have required attributes"""
165 for c, e in cmdtable.iteritems(): 165 for c, e in cmdtable.iteritems():
166 f = e[0] 166 f = e[0]
167 missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)] 167 missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)]
168 if not missing: 168 if not missing:
169 continue 169 continue
170 raise error.ProgrammingError( 170 raise error.ProgrammingError(
171 'missing attributes: %s' % ', '.join(missing), 171 b'missing attributes: %s' % b', '.join(missing),
172 hint="use @command decorator to register '%s'" % c, 172 hint=b"use @command decorator to register '%s'" % c,
173 ) 173 )
174 174
175 175
176 def _validatetables(ui, mod): 176 def _validatetables(ui, mod):
177 """Sanity check for loadable tables provided by extension module""" 177 """Sanity check for loadable tables provided by extension module"""
178 for t in ['cmdtable', 'colortable', 'configtable']: 178 for t in [b'cmdtable', b'colortable', b'configtable']:
179 _rejectunicode(t, getattr(mod, t, {})) 179 _rejectunicode(t, getattr(mod, t, {}))
180 for t in [ 180 for t in [
181 'filesetpredicate', 181 b'filesetpredicate',
182 'internalmerge', 182 b'internalmerge',
183 'revsetpredicate', 183 b'revsetpredicate',
184 'templatefilter', 184 b'templatefilter',
185 'templatefunc', 185 b'templatefunc',
186 'templatekeyword', 186 b'templatekeyword',
187 ]: 187 ]:
188 o = getattr(mod, t, None) 188 o = getattr(mod, t, None)
189 if o: 189 if o:
190 _rejectunicode(t, o._table) 190 _rejectunicode(t, o._table)
191 _validatecmdtable(ui, getattr(mod, 'cmdtable', {})) 191 _validatecmdtable(ui, getattr(mod, 'cmdtable', {}))
192 192
193 193
194 def load(ui, name, path, loadingtime=None): 194 def load(ui, name, path, loadingtime=None):
195 if name.startswith('hgext.') or name.startswith('hgext/'): 195 if name.startswith(b'hgext.') or name.startswith(b'hgext/'):
196 shortname = name[6:] 196 shortname = name[6:]
197 else: 197 else:
198 shortname = name 198 shortname = name
199 if shortname in _builtin: 199 if shortname in _builtin:
200 return None 200 return None
201 if shortname in _extensions: 201 if shortname in _extensions:
202 return _extensions[shortname] 202 return _extensions[shortname]
203 ui.log(b'extension', b' - loading extension: %s\n', shortname) 203 ui.log(b'extension', b' - loading extension: %s\n', shortname)
204 _extensions[shortname] = None 204 _extensions[shortname] = None
205 with util.timedcm('load extension %s', shortname) as stats: 205 with util.timedcm(b'load extension %s', shortname) as stats:
206 mod = _importext(name, path, bind(_reportimporterror, ui)) 206 mod = _importext(name, path, bind(_reportimporterror, ui))
207 ui.log(b'extension', b' > %s extension loaded in %s\n', shortname, stats) 207 ui.log(b'extension', b' > %s extension loaded in %s\n', shortname, stats)
208 if loadingtime is not None: 208 if loadingtime is not None:
209 loadingtime[shortname] += stats.elapsed 209 loadingtime[shortname] += stats.elapsed
210 210
213 # extensions short circuit when loaded with a known incompatible version 213 # extensions short circuit when loaded with a known incompatible version
214 # of Mercurial. 214 # of Mercurial.
215 minver = getattr(mod, 'minimumhgversion', None) 215 minver = getattr(mod, 'minimumhgversion', None)
216 if minver and util.versiontuple(minver, 2) > util.versiontuple(n=2): 216 if minver and util.versiontuple(minver, 2) > util.versiontuple(n=2):
217 msg = _( 217 msg = _(
218 '(third party extension %s requires version %s or newer ' 218 b'(third party extension %s requires version %s or newer '
219 'of Mercurial (current: %s); disabling)\n' 219 b'of Mercurial (current: %s); disabling)\n'
220 ) 220 )
221 ui.warn(msg % (shortname, minver, util.version())) 221 ui.warn(msg % (shortname, minver, util.version()))
222 return 222 return
223 ui.log(b'extension', b' - validating extension tables: %s\n', shortname) 223 ui.log(b'extension', b' - validating extension tables: %s\n', shortname)
224 _validatetables(ui, mod) 224 _validatetables(ui, mod)
226 _extensions[shortname] = mod 226 _extensions[shortname] = mod
227 _order.append(shortname) 227 _order.append(shortname)
228 ui.log( 228 ui.log(
229 b'extension', b' - invoking registered callbacks: %s\n', shortname 229 b'extension', b' - invoking registered callbacks: %s\n', shortname
230 ) 230 )
231 with util.timedcm('callbacks extension %s', shortname) as stats: 231 with util.timedcm(b'callbacks extension %s', shortname) as stats:
232 for fn in _aftercallbacks.get(shortname, []): 232 for fn in _aftercallbacks.get(shortname, []):
233 fn(loaded=True) 233 fn(loaded=True)
234 ui.log(b'extension', b' > callbacks completed in %s\n', stats) 234 ui.log(b'extension', b' > callbacks completed in %s\n', stats)
235 return mod 235 return mod
236 236
241 try: 241 try:
242 uisetup(ui) 242 uisetup(ui)
243 except Exception as inst: 243 except Exception as inst:
244 ui.traceback(force=True) 244 ui.traceback(force=True)
245 msg = stringutil.forcebytestr(inst) 245 msg = stringutil.forcebytestr(inst)
246 ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg)) 246 ui.warn(_(b"*** failed to set up extension %s: %s\n") % (name, msg))
247 return False 247 return False
248 return True 248 return True
249 249
250 250
251 def _runextsetup(name, ui): 251 def _runextsetup(name, ui):
254 try: 254 try:
255 extsetup(ui) 255 extsetup(ui)
256 except Exception as inst: 256 except Exception as inst:
257 ui.traceback(force=True) 257 ui.traceback(force=True)
258 msg = stringutil.forcebytestr(inst) 258 msg = stringutil.forcebytestr(inst)
259 ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg)) 259 ui.warn(_(b"*** failed to set up extension %s: %s\n") % (name, msg))
260 return False 260 return False
261 return True 261 return True
262 262
263 263
264 def loadall(ui, whitelist=None): 264 def loadall(ui, whitelist=None):
265 loadingtime = collections.defaultdict(int) 265 loadingtime = collections.defaultdict(int)
266 result = ui.configitems("extensions") 266 result = ui.configitems(b"extensions")
267 if whitelist is not None: 267 if whitelist is not None:
268 result = [(k, v) for (k, v) in result if k in whitelist] 268 result = [(k, v) for (k, v) in result if k in whitelist]
269 newindex = len(_order) 269 newindex = len(_order)
270 ui.log( 270 ui.log(
271 b'extension', 271 b'extension',
272 b'loading %sextensions\n', 272 b'loading %sextensions\n',
273 'additional ' if newindex else '', 273 b'additional ' if newindex else b'',
274 ) 274 )
275 ui.log(b'extension', b'- processing %d entries\n', len(result)) 275 ui.log(b'extension', b'- processing %d entries\n', len(result))
276 with util.timedcm('load all extensions') as stats: 276 with util.timedcm(b'load all extensions') as stats:
277 for (name, path) in result: 277 for (name, path) in result:
278 if path: 278 if path:
279 if path[0:1] == '!': 279 if path[0:1] == b'!':
280 if name not in _disabledextensions: 280 if name not in _disabledextensions:
281 ui.log( 281 ui.log(
282 b'extension', 282 b'extension',
283 b' - skipping disabled extension: %s\n', 283 b' - skipping disabled extension: %s\n',
284 name, 284 name,
289 load(ui, name, path, loadingtime) 289 load(ui, name, path, loadingtime)
290 except Exception as inst: 290 except Exception as inst:
291 msg = stringutil.forcebytestr(inst) 291 msg = stringutil.forcebytestr(inst)
292 if path: 292 if path:
293 ui.warn( 293 ui.warn(
294 _("*** failed to import extension %s from %s: %s\n") 294 _(b"*** failed to import extension %s from %s: %s\n")
295 % (name, path, msg) 295 % (name, path, msg)
296 ) 296 )
297 else: 297 else:
298 ui.warn( 298 ui.warn(
299 _("*** failed to import extension %s: %s\n") 299 _(b"*** failed to import extension %s: %s\n")
300 % (name, msg) 300 % (name, msg)
301 ) 301 )
302 if isinstance(inst, error.Hint) and inst.hint: 302 if isinstance(inst, error.Hint) and inst.hint:
303 ui.warn(_("*** (%s)\n") % inst.hint) 303 ui.warn(_(b"*** (%s)\n") % inst.hint)
304 ui.traceback() 304 ui.traceback()
305 305
306 ui.log( 306 ui.log(
307 b'extension', 307 b'extension',
308 b'> loaded %d extensions, total time %s\n', 308 b'> loaded %d extensions, total time %s\n',
316 # - loadername is the name of the function, 316 # - loadername is the name of the function,
317 # which takes (ui, extensionname, extraobj) arguments 317 # which takes (ui, extensionname, extraobj) arguments
318 # 318 #
319 # This one is for the list of item that must be run before running any setup 319 # This one is for the list of item that must be run before running any setup
320 earlyextraloaders = [ 320 earlyextraloaders = [
321 ('configtable', configitems, 'loadconfigtable'), 321 (b'configtable', configitems, b'loadconfigtable'),
322 ] 322 ]
323 323
324 ui.log(b'extension', b'- loading configtable attributes\n') 324 ui.log(b'extension', b'- loading configtable attributes\n')
325 _loadextra(ui, newindex, earlyextraloaders) 325 _loadextra(ui, newindex, earlyextraloaders)
326 326
327 broken = set() 327 broken = set()
328 ui.log(b'extension', b'- executing uisetup hooks\n') 328 ui.log(b'extension', b'- executing uisetup hooks\n')
329 with util.timedcm('all uisetup') as alluisetupstats: 329 with util.timedcm(b'all uisetup') as alluisetupstats:
330 for name in _order[newindex:]: 330 for name in _order[newindex:]:
331 ui.log(b'extension', b' - running uisetup for %s\n', name) 331 ui.log(b'extension', b' - running uisetup for %s\n', name)
332 with util.timedcm('uisetup %s', name) as stats: 332 with util.timedcm(b'uisetup %s', name) as stats:
333 if not _runuisetup(name, ui): 333 if not _runuisetup(name, ui):
334 ui.log( 334 ui.log(
335 b'extension', 335 b'extension',
336 b' - the %s extension uisetup failed\n', 336 b' - the %s extension uisetup failed\n',
337 name, 337 name,
340 ui.log(b'extension', b' > uisetup for %s took %s\n', name, stats) 340 ui.log(b'extension', b' > uisetup for %s took %s\n', name, stats)
341 loadingtime[name] += stats.elapsed 341 loadingtime[name] += stats.elapsed
342 ui.log(b'extension', b'> all uisetup took %s\n', alluisetupstats) 342 ui.log(b'extension', b'> all uisetup took %s\n', alluisetupstats)
343 343
344 ui.log(b'extension', b'- executing extsetup hooks\n') 344 ui.log(b'extension', b'- executing extsetup hooks\n')
345 with util.timedcm('all extsetup') as allextetupstats: 345 with util.timedcm(b'all extsetup') as allextetupstats:
346 for name in _order[newindex:]: 346 for name in _order[newindex:]:
347 if name in broken: 347 if name in broken:
348 continue 348 continue
349 ui.log(b'extension', b' - running extsetup for %s\n', name) 349 ui.log(b'extension', b' - running extsetup for %s\n', name)
350 with util.timedcm('extsetup %s', name) as stats: 350 with util.timedcm(b'extsetup %s', name) as stats:
351 if not _runextsetup(name, ui): 351 if not _runextsetup(name, ui):
352 ui.log( 352 ui.log(
353 b'extension', 353 b'extension',
354 b' - the %s extension extsetup failed\n', 354 b' - the %s extension extsetup failed\n',
355 name, 355 name,
363 ui.log(b'extension', b' - disabling broken %s extension\n', name) 363 ui.log(b'extension', b' - disabling broken %s extension\n', name)
364 _extensions[name] = None 364 _extensions[name] = None
365 365
366 # Call aftercallbacks that were never met. 366 # Call aftercallbacks that were never met.
367 ui.log(b'extension', b'- executing remaining aftercallbacks\n') 367 ui.log(b'extension', b'- executing remaining aftercallbacks\n')
368 with util.timedcm('aftercallbacks') as stats: 368 with util.timedcm(b'aftercallbacks') as stats:
369 for shortname in _aftercallbacks: 369 for shortname in _aftercallbacks:
370 if shortname in _extensions: 370 if shortname in _extensions:
371 continue 371 continue
372 372
373 for fn in _aftercallbacks[shortname]: 373 for fn in _aftercallbacks[shortname]:
401 # - loadermod is the module where loader is placed 401 # - loadermod is the module where loader is placed
402 # - loadername is the name of the function, 402 # - loadername is the name of the function,
403 # which takes (ui, extensionname, extraobj) arguments 403 # which takes (ui, extensionname, extraobj) arguments
404 ui.log(b'extension', b'- loading extension registration objects\n') 404 ui.log(b'extension', b'- loading extension registration objects\n')
405 extraloaders = [ 405 extraloaders = [
406 ('cmdtable', commands, 'loadcmdtable'), 406 (b'cmdtable', commands, b'loadcmdtable'),
407 ('colortable', color, 'loadcolortable'), 407 (b'colortable', color, b'loadcolortable'),
408 ('filesetpredicate', fileset, 'loadpredicate'), 408 (b'filesetpredicate', fileset, b'loadpredicate'),
409 ('internalmerge', filemerge, 'loadinternalmerge'), 409 (b'internalmerge', filemerge, b'loadinternalmerge'),
410 ('revsetpredicate', revset, 'loadpredicate'), 410 (b'revsetpredicate', revset, b'loadpredicate'),
411 ('templatefilter', templatefilters, 'loadfilter'), 411 (b'templatefilter', templatefilters, b'loadfilter'),
412 ('templatefunc', templatefuncs, 'loadfunction'), 412 (b'templatefunc', templatefuncs, b'loadfunction'),
413 ('templatekeyword', templatekw, 'loadkeyword'), 413 (b'templatekeyword', templatekw, b'loadkeyword'),
414 ] 414 ]
415 with util.timedcm('load registration objects') as stats: 415 with util.timedcm(b'load registration objects') as stats:
416 _loadextra(ui, newindex, extraloaders) 416 _loadextra(ui, newindex, extraloaders)
417 ui.log( 417 ui.log(
418 b'extension', 418 b'extension',
419 b'> extension registration object loading took %s\n', 419 b'> extension registration object loading took %s\n',
420 stats, 420 stats,
480 try: 480 try:
481 hook(ui) 481 hook(ui)
482 except Exception as inst: 482 except Exception as inst:
483 ui.traceback(force=True) 483 ui.traceback(force=True)
484 ui.warn( 484 ui.warn(
485 _('*** failed to populate ui by extension %s: %s\n') 485 _(b'*** failed to populate ui by extension %s: %s\n')
486 % (name, stringutil.forcebytestr(inst)) 486 % (name, stringutil.forcebytestr(inst))
487 ) 487 )
488 488
489 489
490 def bind(func, *args): 490 def bind(func, *args):
707 except OSError: 707 except OSError:
708 return {} 708 return {}
709 709
710 exts = {} 710 exts = {}
711 for e in files: 711 for e in files:
712 if e.endswith('.py'): 712 if e.endswith(b'.py'):
713 name = e.rsplit('.', 1)[0] 713 name = e.rsplit(b'.', 1)[0]
714 path = os.path.join(extpath, e) 714 path = os.path.join(extpath, e)
715 else: 715 else:
716 name = e 716 name = e
717 path = os.path.join(extpath, e, '__init__.py') 717 path = os.path.join(extpath, e, b'__init__.py')
718 if not os.path.exists(path): 718 if not os.path.exists(path):
719 continue 719 continue
720 if name in exts or name in _order or name == '__init__': 720 if name in exts or name in _order or name == b'__init__':
721 continue 721 continue
722 exts[name] = path 722 exts[name] = path
723 for name, path in _disabledextensions.iteritems(): 723 for name, path in _disabledextensions.iteritems():
724 # If no path was provided for a disabled extension (e.g. "color=!"), 724 # If no path was provided for a disabled extension (e.g. "color=!"),
725 # don't replace the path we already found by the scan above. 725 # don't replace the path we already found by the scan above.
735 handle triple quotes and to return the whole text instead of just 735 handle triple quotes and to return the whole text instead of just
736 the synopsis''' 736 the synopsis'''
737 result = [] 737 result = []
738 738
739 line = file.readline() 739 line = file.readline()
740 while line[:1] == '#' or not line.strip(): 740 while line[:1] == b'#' or not line.strip():
741 line = file.readline() 741 line = file.readline()
742 if not line: 742 if not line:
743 break 743 break
744 744
745 start = line[:3] 745 start = line[:3]
746 if start == '"""' or start == "'''": 746 if start == b'"""' or start == b"'''":
747 line = line[3:] 747 line = line[3:]
748 while line: 748 while line:
749 if line.rstrip().endswith(start): 749 if line.rstrip().endswith(start):
750 line = line.split(start)[0] 750 line = line.split(start)[0]
751 if line: 751 if line:
756 result.append(line) 756 result.append(line)
757 line = file.readline() 757 line = file.readline()
758 else: 758 else:
759 return None 759 return None
760 760
761 return ''.join(result) 761 return b''.join(result)
762 762
763 763
764 def _disabledhelp(path): 764 def _disabledhelp(path):
765 '''retrieve help synopsis of a disabled extension (without importing)''' 765 '''retrieve help synopsis of a disabled extension (without importing)'''
766 try: 766 try:
767 with open(path, 'rb') as src: 767 with open(path, b'rb') as src:
768 doc = _moduledoc(src) 768 doc = _moduledoc(src)
769 except IOError: 769 except IOError:
770 return 770 return
771 771
772 if doc: # extracting localized synopsis 772 if doc: # extracting localized synopsis
773 return gettext(doc) 773 return gettext(doc)
774 else: 774 else:
775 return _('(no help text available)') 775 return _(b'(no help text available)')
776 776
777 777
778 def disabled(): 778 def disabled():
779 '''find disabled extensions from hgext. returns a dict of {name: desc}''' 779 '''find disabled extensions from hgext. returns a dict of {name: desc}'''
780 try: 780 try:
839 def _disabledcmdtable(path): 839 def _disabledcmdtable(path):
840 """Construct a dummy command table without loading the extension module 840 """Construct a dummy command table without loading the extension module
841 841
842 This may raise IOError or SyntaxError. 842 This may raise IOError or SyntaxError.
843 """ 843 """
844 with open(path, 'rb') as src: 844 with open(path, b'rb') as src:
845 root = ast.parse(src.read(), path) 845 root = ast.parse(src.read(), path)
846 cmdtable = {} 846 cmdtable = {}
847 for node in _walkcommand(root): 847 for node in _walkcommand(root):
848 if not node.args: 848 if not node.args:
849 continue 849 continue
904 904
905 def enabled(shortname=True): 905 def enabled(shortname=True):
906 '''return a dict of {name: desc} of extensions''' 906 '''return a dict of {name: desc} of extensions'''
907 exts = {} 907 exts = {}
908 for ename, ext in extensions(): 908 for ename, ext in extensions():
909 doc = gettext(ext.__doc__) or _('(no help text available)') 909 doc = gettext(ext.__doc__) or _(b'(no help text available)')
910 if shortname: 910 if shortname:
911 ename = ename.split('.')[-1] 911 ename = ename.split(b'.')[-1]
912 exts[ename] = doc.splitlines()[0].strip() 912 exts[ename] = doc.splitlines()[0].strip()
913 913
914 return exts 914 return exts
915 915
916 916
919 return [name for name, mod in _extensions.iteritems() if mod is None] 919 return [name for name, mod in _extensions.iteritems() if mod is None]
920 920
921 921
922 def moduleversion(module): 922 def moduleversion(module):
923 '''return version information from given module as a string''' 923 '''return version information from given module as a string'''
924 if util.safehasattr(module, 'getversion') and callable(module.getversion): 924 if util.safehasattr(module, b'getversion') and callable(module.getversion):
925 version = module.getversion() 925 version = module.getversion()
926 elif util.safehasattr(module, '__version__'): 926 elif util.safehasattr(module, b'__version__'):
927 version = module.__version__ 927 version = module.__version__
928 else: 928 else:
929 version = '' 929 version = b''
930 if isinstance(version, (list, tuple)): 930 if isinstance(version, (list, tuple)):
931 version = '.'.join(pycompat.bytestr(o) for o in version) 931 version = b'.'.join(pycompat.bytestr(o) for o in version)
932 return version 932 return version
933 933
934 934
935 def ismoduleinternal(module): 935 def ismoduleinternal(module):
936 exttestedwith = getattr(module, 'testedwith', None) 936 exttestedwith = getattr(module, 'testedwith', None)
937 return exttestedwith == "ships-with-hg-core" 937 return exttestedwith == b"ships-with-hg-core"