equal
deleted
inserted
replaced
170 |
170 |
171 def _validatecmdtable(ui, cmdtable): |
171 def _validatecmdtable(ui, cmdtable): |
172 """Check if extension commands have required attributes""" |
172 """Check if extension commands have required attributes""" |
173 for c, e in cmdtable.items(): |
173 for c, e in cmdtable.items(): |
174 f = e[0] |
174 f = e[0] |
175 missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)] |
175 missing = [a for a in _cmdfuncattrs if not hasattr(f, a)] |
176 if not missing: |
176 if not missing: |
177 continue |
177 continue |
178 msg = b'missing attributes: %s' |
178 msg = b'missing attributes: %s' |
179 msg %= b', '.join([stringutil.forcebytestr(m) for m in missing]) |
179 msg %= b', '.join([stringutil.forcebytestr(m) for m in missing]) |
180 hint = b"use @command decorator to register '%s'" % c |
180 hint = b"use @command decorator to register '%s'" % c |
740 |
740 |
741 exts = {} |
741 exts = {} |
742 |
742 |
743 # The hgext might not have a __file__ attribute (e.g. in PyOxidizer) and |
743 # The hgext might not have a __file__ attribute (e.g. in PyOxidizer) and |
744 # it might not be on a filesystem even if it does. |
744 # it might not be on a filesystem even if it does. |
745 if util.safehasattr(hgext, '__file__'): |
745 if hasattr(hgext, '__file__'): |
746 extpath = os.path.dirname( |
746 extpath = os.path.dirname( |
747 util.abspath(pycompat.fsencode(hgext.__file__)) |
747 util.abspath(pycompat.fsencode(hgext.__file__)) |
748 ) |
748 ) |
749 try: |
749 try: |
750 files = os.listdir(extpath) |
750 files = os.listdir(extpath) |
855 import hgext |
855 import hgext |
856 from hgext import __index__ # pytype: disable=import-error |
856 from hgext import __index__ # pytype: disable=import-error |
857 |
857 |
858 # The extensions are filesystem based, so either an error occurred |
858 # The extensions are filesystem based, so either an error occurred |
859 # or all are enabled. |
859 # or all are enabled. |
860 if util.safehasattr(hgext, '__file__'): |
860 if hasattr(hgext, '__file__'): |
861 return |
861 return |
862 |
862 |
863 if name in _order: # enabled |
863 if name in _order: # enabled |
864 return |
864 return |
865 else: |
865 else: |
985 return [name for name, mod in _extensions.items() if mod is None] |
985 return [name for name, mod in _extensions.items() if mod is None] |
986 |
986 |
987 |
987 |
988 def moduleversion(module): |
988 def moduleversion(module): |
989 '''return version information from given module as a string''' |
989 '''return version information from given module as a string''' |
990 if util.safehasattr(module, 'getversion') and callable(module.getversion): |
990 if hasattr(module, 'getversion') and callable(module.getversion): |
991 try: |
991 try: |
992 version = module.getversion() |
992 version = module.getversion() |
993 except Exception: |
993 except Exception: |
994 version = b'unknown' |
994 version = b'unknown' |
995 |
995 |
996 elif util.safehasattr(module, '__version__'): |
996 elif hasattr(module, '__version__'): |
997 version = module.__version__ |
997 version = module.__version__ |
998 else: |
998 else: |
999 version = b'' |
999 version = b'' |
1000 if isinstance(version, (list, tuple)): |
1000 if isinstance(version, (list, tuple)): |
1001 version = b'.'.join(pycompat.bytestr(o) for o in version) |
1001 version = b'.'.join(pycompat.bytestr(o) for o in version) |