mercurial/extensions.py
changeset 50816 3ccef7902070
parent 50798 ee1617c04858
parent 50754 19108906abaf
child 50891 f75fd677cc05
equal deleted inserted replaced
50807:5c3d07950bac 50816:3ccef7902070
     7 
     7 
     8 
     8 
     9 import ast
     9 import ast
    10 import collections
    10 import collections
    11 import functools
    11 import functools
    12 import imp
    12 import importlib
    13 import inspect
    13 import inspect
    14 import os
    14 import os
       
    15 import sys
    15 
    16 
    16 from .i18n import (
    17 from .i18n import (
    17     _,
    18     _,
    18     gettext,
    19     gettext,
    19 )
    20 )
    87     path = util.normpath(util.expandpath(path))
    88     path = util.normpath(util.expandpath(path))
    88     module_name = pycompat.fsdecode(module_name)
    89     module_name = pycompat.fsdecode(module_name)
    89     path = pycompat.fsdecode(path)
    90     path = pycompat.fsdecode(path)
    90     if os.path.isdir(path):
    91     if os.path.isdir(path):
    91         # module/__init__.py style
    92         # module/__init__.py style
    92         d, f = os.path.split(path)
    93         init_py_path = os.path.join(path, '__init__.py')
    93         fd, fpath, desc = imp.find_module(f, [d])
    94         if not os.path.exists(init_py_path):
    94         # When https://github.com/python/typeshed/issues/3466 is fixed
    95             raise ImportError("No module named '%s'" % os.path.basename(path))
    95         # and in a pytype release we can drop this disable.
    96         path = init_py_path
    96         return imp.load_module(
    97 
    97             module_name, fd, fpath, desc  # pytype: disable=wrong-arg-types
    98     loader = importlib.machinery.SourceFileLoader(module_name, path)
    98         )
    99     spec = importlib.util.spec_from_file_location(module_name, loader=loader)
    99     else:
   100     assert spec is not None  # help Pytype
   100         try:
   101     module = importlib.util.module_from_spec(spec)
   101             return imp.load_source(module_name, path)
   102     sys.modules[module_name] = module
   102         except IOError as exc:
   103     spec.loader.exec_module(module)
   103             if not exc.filename:
   104     return module
   104                 exc.filename = path  # python does not fill this
       
   105             raise
       
   106 
   105 
   107 
   106 
   108 def _importh(name):
   107 def _importh(name):
   109     """import and return the <name> module"""
   108     """import and return the <name> module"""
   110     mod = __import__(pycompat.sysstr(name))
   109     mod = __import__(pycompat.sysstr(name))
   892     This may raise IOError or SyntaxError.
   891     This may raise IOError or SyntaxError.
   893     """
   892     """
   894     with open(path, b'rb') as src:
   893     with open(path, b'rb') as src:
   895         root = ast.parse(src.read(), path)
   894         root = ast.parse(src.read(), path)
   896     cmdtable = {}
   895     cmdtable = {}
       
   896 
       
   897     # Python 3.12 started removing Bytes and Str and deprecate harder
       
   898     use_constant = 'Bytes' not in vars(ast)
       
   899 
   897     for node in _walkcommand(root):
   900     for node in _walkcommand(root):
   898         if not node.args:
   901         if not node.args:
   899             continue
   902             continue
   900         a = node.args[0]
   903         a = node.args[0]
   901         if isinstance(a, ast.Str):
   904         if use_constant:  # Valid since Python 3.8
   902             name = pycompat.sysbytes(a.s)
   905             if isinstance(a, ast.Constant):
   903         elif isinstance(a, ast.Bytes):
   906                 if isinstance(a.value, str):
   904             name = a.s
   907                     name = pycompat.sysbytes(a.value)
   905         else:
   908                 elif isinstance(a.value, bytes):
   906             continue
   909                     name = a.value
       
   910                 else:
       
   911                     continue
       
   912             else:
       
   913                 continue
       
   914         else:  # Valid until 3.11
       
   915             if isinstance(a, ast.Str):
       
   916                 name = pycompat.sysbytes(a.s)
       
   917             elif isinstance(a, ast.Bytes):
       
   918                 name = a.s
       
   919             else:
       
   920                 continue
   907         cmdtable[name] = (None, [], b'')
   921         cmdtable[name] = (None, [], b'')
   908     return cmdtable
   922     return cmdtable
   909 
   923 
   910 
   924 
   911 def _finddisabledcmd(ui, cmd, name, path, strict):
   925 def _finddisabledcmd(ui, cmd, name, path, strict):