1. TortoiseHg
  2. TortoiseHg
  3. thg
  4. Issues
Issue #3542 resolved

When config.py is missing from hg clone demand import tries to use "random" package config.py

steve_barnes
created an issue

Running from source TortoiseHg Dialogues (version 2.10.1+182-d2d315e6fbf9), Mercurial (version 2.8.1). Depending on the content of PYHTONPATH and lib/site-packages when thg loads it attempts to import from tortoise.util.config - if this fails then demandimport will import any config module that it finds - in my case it is now importing config from wxPython 3.0.0 or from pyspread.

This seems to be because it effectively does from [.[.*]] import config.

I tried numerous PYTHONPATH values and it just changed which other package the wrong config.py was found in. Eventually I figured out that the tortoisehg hg repository doesn't contain config.py and does contain .hg/requies so that setup.py wasn't creating a config.py - once I 'manually' forced its creation the problem disappeared.

I do feel that, if from package import * is discouraged because of the lack of clarity due to name space removal, and because of the hard to diagnose problems that occur when you have name clashes, then code that effectively does if not found path.to.package from anwhere.recurse.package import ... is potentially even more perilous.
In my specific case if the exception output had been "can't load tortoisehg.util.config" I would probably have resolved the issue in a few minutes as it was I was getting "missing method mmmm in random.package.config" - this took days to isolate.

Classing as minor as this only occurs when running from source repository in the absence of config.py in util directory.

Comments (7)

  1. Yuya Nishihara

    import from tortoise.util.config - if this fails then demandimport will import any config module that it finds

    I'm curious why it happened. Can you test it without demandimport by deleting demandimport.enable() line in thg ?

    I've never experienced this problem by using the source install without config.py.

  2. steve_barnes reporter

    I tried deleting the config.py and .pyc plus commenting out the demandimport.enable() line in thg and got exactly the same result, then realised that I wasn't invoking ./thg so was getting the unmodified thg - tried ./thg and it worked with the commented out line.

  3. Yuya Nishihara

    Thanks for the info.

    Could you test the following change? This is more friendly style to Mercurial's demandimport.

    diff --git a/tortoisehg/util/paths.py b/tortoisehg/util/paths.py
    --- a/tortoisehg/util/paths.py
    +++ b/tortoisehg/util/paths.py
    @@ -6,7 +6,13 @@
     # GNU General Public License version 2, incorporated herein by reference.
    
     try:
    -    from config import icon_path, bin_path, license_path, locale_path
    +    # TODO: from tortoisehg.util import config (but I want to know whether or
    +    # not the problem was due to "from mod import var, ...")
    +    import config
    +    icon_path = config.icon_path
    +    bin_path = config.bin_path
    +    license_path = config.license_path
    +    locale_path = config.locale_path
     except ImportError:
         icon_path, bin_path, license_path, locale_path = None, None, None, None
    
  4. steve_barnes reporter

    Thanks Yaya - I tested and it made absolutely no difference.

    It looks like we are well in the hands of demand import before we get into path. Traceback on the modified code follows.

    Traceback (most recent call last):
      File "./thg", line 92, in <module>
        sys.exit(tortoisehg.hgqt.run.dispatch(argv))
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 102, in __getattribute__
        self._load()
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 74, in _load
        mod = _hgextimport(_import, head, globals, locals, None, level)
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 43, in _hgextimport
        return importfunc(name, globals, *args)
      File "/home/gadget/ToolBuild/tortoisehg/tortoisehg/hgqt/run.py", line 23, in <module>
        from tortoisehg.hgqt.i18n import agettext as _
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 130, in _demandimport
        mod = _hgextimport(_origimport, name, globals, locals)
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 43, in _hgextimport
        return importfunc(name, globals, *args)
      File "/home/gadget/ToolBuild/tortoisehg/tortoisehg/hgqt/i18n.py", line 8, in <module>
        from tortoisehg.util.i18n import _ as _gettext
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 130, in _demandimport
        mod = _hgextimport(_origimport, name, globals, locals)
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 43, in _hgextimport
        return importfunc(name, globals, *args)
      File "/home/gadget/ToolBuild/tortoisehg/tortoisehg/util/i18n.py", line 42, in <module>
        setlanguage()
      File "/home/gadget/ToolBuild/tortoisehg/tortoisehg/util/i18n.py", line 39, in setlanguage
        t = gettext.translation('tortoisehg', paths.get_locale_path(),
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 102, in __getattribute__
        self._load()
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 74, in _load
        mod = _hgextimport(_import, head, globals, locals, None, level)
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 43, in _hgextimport
        return importfunc(name, globals, *args)
      File "/home/gadget/ToolBuild/tortoisehg/tortoisehg/util/paths.py", line 13, in <module>
        icon_path = config.icon_path
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 102, in __getattribute__
        self._load()
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 74, in _load
        mod = _hgextimport(_import, head, globals, locals, None, level)
      File "/usr/local/lib/python2.7/dist-packages/mercurial/demandimport.py", line 43, in _hgextimport
        return importfunc(name, globals, *args)
      File "/home/gadget/ToolBuild/wxPython-3.0.0.0/wxPython/config.py", line 809, in <module>
        class MyUnixCCompiler(distutils.unixccompiler.UnixCCompiler):
    AttributeError: 'module' object has no attribute 'unixccompiler'
    
  5. Yuya Nishihara

    paths: import config in full spelling for demandimport.ignore (fixes #3542)

    tortoisehg.util.config is listed in demandimport.ignore, but "from config import" bypasses the list.

    I couldn't figure out the underlying problem of #3542, but it should be avoided by this change.

    → <<cset f6202e90874d>>

  6. Log in to comment