Conan: [python_requires] imports inside python_required modules

Created on 29 Oct 2018  路  3Comments  路  Source: conan-io/conan

Title: [python_requires] imports inside python_required modules

  • [x] I've read the CONTRIBUTING guide.
  • [x] I've specified the Conan version, operating system version and any tool that can be relevant.
  • [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

Conan 1.8.2
Python 3.6.5
Windows 7

according to the official Conan documentation for python_requires, we created a base class package with helper functions in a separate python file (helper.py) which is imported from the base class with a regular Python import statement like described in the documentation.

This worked perfectly for us as long as we had only one version of the base package. The problem occured after we created version 2.0 of the base package with one module using version 2.0 and another module still using version 1.0. The helper.py import statement inside the base package cannot distinguish from which version of the base package it is called and therefore always helper.py from the first version mentioned in a Conan file is used.

Here are the steps to reproduce this problem. I hope it gets a little bit more clear then:

base/conanfile.py
```python
from conans import ConanFile
import helper
class Base(ConanFile):
exports = "*.py"


**base/helper.py**
```python
def getVersion():
    return "1.0"

Conan command: conan export . Base/1.0@user/channel
This exports Base/1.0@user/channel correctly.

module1/conanfile.py

from conans import ConanFile, python_requires
base = python_requires("Base/1.0@user/channel")
class Module1(ConanFile):
    name = "module1"
    version = base.helper.getVersion()

Conan command: conan export . user/channel.
This exports module1/1.0@user/channel correctly.

module2/conanfile.py

from conans import ConanFile, python_requires
base = python_requires("Base/1.0@user/channel")
module1 = python_requires("module1/1.0@user/channel")
class MyPackage(ConanFile):
    name = "module2"
    version = base.helper.getVersion()

Conan command: conan export . user/channel.
This exports module2/1.0@user/channel correctly.

So far everthing works well. Now we create a new version 2.0 of the Base package. In the new version we rename the helper.py method getVersion() to getVersionInADifferentWay():

base/helper.py

def getVersionInADifferentWay():
    return "2.0"

Conan command: conan export . Base/2.0@user/channel
This exports Base/2.0@user/channel correctly.

Now module2 should use the new Base package 2.0 whereas module1 should still use the old version Base/1.0:

module2/conanfile.py

from conans import ConanFile, python_requires
base = python_requires("Base/2.0@user/channel")
module1 = python_requires("module1/1.0@user/channel")
class MyPackage(ConanFile):
    name = "module2"
    version = base.helper.getVersionInADifferentWay()

Conan command: conan export . user/channel.
This leads to the following error:

ERROR: Unable to load conanfile in module2/V2.0/conanfile.py
KeyError: 'module1/1.0@user/channel'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Python3/lib/site-packages/conans/client/loader.py", line 235, in _parse_file
    loaded = imp.load_source(filename, conan_file_path)
  File "Python3/lib/imp.py", line 172, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 684, in _load
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "module2/V2.0/conanfile.py", line 3, in <module>
    module1 = python_requires("module1/1.0@user/channel")
  File "Python3/lib/site-packages/conans/client/graph/python_requires.py", line 41, in __call__
    module = imp.load_source(str(r).replace(".", "*"), path)
  File "Python3/lib/imp.py", line 172, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 684, in _load
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File ".conan/data/module1/1.0/user/channel/export/conanfile.py", line 3, in <module>
    class Module1(ConanFile):
  File ".conan/data/module1/1.0/user/channel/export/conanfile.py", line 5, in Module1
    version = base.helper.getVersion()
AttributeError: module 'helper' has no attribute 'getVersion'

Could you please give us a hint or suggestions how we could solve this problem with Conan

Thank You!

bug

Most helpful comment

Wow thanks, already solved. That was fast. Did you even sleep last night?

All 3 comments

Hi! I think that this issue may have been already resolved by this PR (https://github.com/conan-io/conan/pull/3854). Version v1.9 will be released as soon as possible, we need to check this issue against it. We'll keep you updated.

(I'm labeling it as bug and tagging it to 1.10, in order to be aware of it)

No, it has not been resolved, I have been able to reproduce it. Indeed a bug.

Wow thanks, already solved. That was fast. Did you even sleep last night?

Was this page helpful?
0 / 5 - 0 ratings