Conan: [bug] Inconsistent type of self.version in conanfile methods with different commands

Created on 1 Apr 2020  路  5Comments  路  Source: conan-io/conan

Some commands translate the conanfile version into a conans.model.version.Version object before it is accessible to the method (conan create and conan export_pkg). A few commands return it as a str (conan install). Others return it as a Version if conan.lock file is present and a str otherwise (conan source, conan graph lock, conan build, conan package, conan import).

This inconsistency leads to recipes that work in a conan create workflow, but fail if the build process is split over multiple steps. (I found this while working on a script to localize all of the sources so that they could be security scanned before building them.)

from conans import ConanFile

class VersionTest(ConanFile):
    version = "1.1.1"
    name = 'VersionTest'

    def source(self):
       minor = self.version.minor()

This is used successfully in conan create, but fails during conan source with:

ERROR: Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/conans/errors.py", line 34, in conanfile_exception_formatter
    yield
  File "/usr/local/lib/python3.6/site-packages/conans/client/source.py", line 143, in _run_source
    conanfile.source()
  File "/home/rdesmond/Desktop/output/version_test/exception/conanfile.py", line 8, in source
    minor = self.version.minor()
AttributeError: 'str' object has no attribute 'minor'

NOTE: If a conan.lock file is present (such as if conan install is run) conan source will succeed.

Environment Details (include every applicable attribute)

  • Operating System+version: Centos 7.7.1908
  • Compiler+version: n/a
  • Conan version: 1.23.0
  • Python version: 2.7.5

Attachments

version_test.tar.gz contains the above and a recipe that invokes has method (except the new set_*) and prints the type of self.version. I used it to test.

low low queue bug

Most helpful comment

Makes sense. Thanks for all the hard work. Conan continues to make everything in the c++ stack so much easier.

All 5 comments

Hi @rddesmond and thanks a lot for the report.

Yes, I can confirm this is happening and it should be fixed. The conanfile.version filed should be always a string for the user interface inside recipes and conans.model.version.Version should not be used as it is an internal implementation.

I'd recommend you to use the public interface class tools.Version instead: https://docs.conan.io/en/latest/reference/tools.html#tools-version that has a similar interface.

Thanks for the triage! It's probably reasonable to expect that self.version can be evaluated as a string, but could be varying types, though yeah, didn't expect that to change conditionally as it did. Good call-out to the tool. I needed to learn that model.version.Version.minor != tools.Version.minor (given a version 1.2.0, minor() returns 1.2 and 2 for the different classes, respectively), but it's useful and the right answer.

The thing is that self.version is intended to be always a string.
At some point in one of the latest unrelated changed, we internally assigned a Version object. This will be changed, it is not documented anywhere, self.version.minor is not part of the public api.

We will revert that change so self.version is always a string. If you want to do some version processing, you will be able wrapping it like Version(self.version), being Version the documented helper, not the internal one.

Makes sense. Thanks for all the hard work. Conan continues to make everything in the c++ stack so much easier.

Hi @rddesmond

We have proposed a fix in https://github.com/conan-io/conan/pull/6782, but then realized that this change has a potential to break other users, and we certainly don't want to do this, so it will need to wait until Conan 2.0.

So at the moment, I would recommend you the following:

  • Assume that self.version is always a string.
  • When you want to do comparisons and access members, do a Version(self.version) first.
  • This should work in all methods and scenarios, even when self.version is already the internal Version object, because that can be processed too.
  • Make sure that that Version is conans.tools.Version (documented in https://docs.conan.io/en/latest/reference/tools.html?tools-version#tools-version) and not the internal one.

Thanks!

Was this page helpful?
0 / 5 - 0 ratings