comparison mercurial/extensions.py @ 50920:c642c03969ff

dynamic-import: use sysstr for importing extension and others This logic is used by extensions, and python hooks and merge-tools. All this logic eventually deals with native string (unicode in Python 3). This patch makes it handle `str` directly instead of relying on some pycompat low lever layer to do the conversion at the last minutes. We adjust the Python version filtering of a test as the output seems to be present with Python 3.7 too.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 31 Aug 2023 02:41:33 +0200
parents 0e6cea0c3113
children d718eddf01d9
comparison
equal deleted inserted replaced
50919:0e6cea0c3113 50920:c642c03969ff
82 raise KeyError(name) 82 raise KeyError(name)
83 return mod 83 return mod
84 84
85 85
86 def loadpath(path, module_name): 86 def loadpath(path, module_name):
87 module_name = module_name.replace(b'.', b'_') 87 module_name = module_name.replace('.', '_')
88 path = util.normpath(util.expandpath(path)) 88 path = util.normpath(util.expandpath(path))
89 module_name = pycompat.fsdecode(module_name)
90 path = pycompat.fsdecode(path) 89 path = pycompat.fsdecode(path)
91 if os.path.isdir(path): 90 if os.path.isdir(path):
92 # module/__init__.py style 91 # module/__init__.py style
93 init_py_path = os.path.join(path, '__init__.py') 92 init_py_path = os.path.join(path, '__init__.py')
94 if not os.path.exists(init_py_path): 93 if not os.path.exists(init_py_path):
104 return module 103 return module
105 104
106 105
107 def _importh(name): 106 def _importh(name):
108 """import and return the <name> module""" 107 """import and return the <name> module"""
109 mod = __import__(pycompat.sysstr(name)) 108 mod = __import__(name)
110 components = name.split(b'.') 109 components = name.split('.')
111 for comp in components[1:]: 110 for comp in components[1:]:
112 mod = getattr(mod, comp) 111 mod = getattr(mod, comp)
113 return mod 112 return mod
114 113
115 114
116 def _importext(name, path=None, reportfunc=None): 115 def _importext(name, path=None, reportfunc=None):
116 name = pycompat.fsdecode(name)
117 if path: 117 if path:
118 # the module will be loaded in sys.modules 118 # the module will be loaded in sys.modules
119 # choose an unique name so that it doesn't 119 # choose an unique name so that it doesn't
120 # conflicts with other modules 120 # conflicts with other modules
121 mod = loadpath(path, b'hgext.%s' % name) 121 mod = loadpath(path, 'hgext.%s' % name)
122 else: 122 else:
123 try: 123 try:
124 mod = _importh(b"hgext.%s" % name) 124 mod = _importh("hgext.%s" % name)
125 except ImportError as err: 125 except ImportError as err:
126 if reportfunc: 126 if reportfunc:
127 reportfunc(err, b"hgext.%s" % name, b"hgext3rd.%s" % name) 127 reportfunc(err, "hgext.%s" % name, "hgext3rd.%s" % name)
128 try: 128 try:
129 mod = _importh(b"hgext3rd.%s" % name) 129 mod = _importh("hgext3rd.%s" % name)
130 except ImportError as err: 130 except ImportError as err:
131 if reportfunc: 131 if reportfunc:
132 reportfunc(err, b"hgext3rd.%s" % name, name) 132 reportfunc(err, "hgext3rd.%s" % name, name)
133 mod = _importh(name) 133 mod = _importh(name)
134 return mod 134 return mod
135 135
136 136
137 def _reportimporterror(ui, err, failed, next): 137 def _reportimporterror(ui, err, failed, next):
138 # note: this ui.log happens before --debug is processed, 138 # note: this ui.log happens before --debug is processed,
139 # Use --config ui.debug=1 to see them. 139 # Use --config ui.debug=1 to see them.
140 ui.log( 140 ui.log(
141 b'extension', 141 b'extension',
142 b' - could not import %s (%s): trying %s\n', 142 b' - could not import %s (%s): trying %s\n',
143 failed, 143 stringutil.forcebytestr(failed),
144 stringutil.forcebytestr(err), 144 stringutil.forcebytestr(err),
145 next, 145 stringutil.forcebytestr(next),
146 ) 146 )
147 if ui.debugflag and ui.configbool(b'devel', b'debug.extensions'): 147 if ui.debugflag and ui.configbool(b'devel', b'debug.extensions'):
148 ui.traceback() 148 ui.traceback()
149 149
150 150