[bug] `python_requires_extend` in base class should extend base class but extends sub class
See original GitHub issueI stumbled upon a little quirk in the implementation of python_requires_extend
. I am not sure whether it is worthy to be called a bug, but I think it is unintuitive at the least.
Let’s say that we have a ConanFile
subclass ProjectBaseConanFile
which serves as the base class for some project variants with their classes VariantAConanFile
, VariantBConanFile
, VariantCConanFile
.
Instances of these VariantXConanFile
classes have the following inheritance hierarchy (packages ommitted):
<object>
<class 'ConanFile'>
<class 'ProjectBaseConanFile'>
<class 'VariantXConanFile'>
Now, let’s say that we have a new company-wide Conan base class CompanyConanFile
and we want to use python_requires
and python_requires_extend
in all of our ConanFile
implementations (including ProjectBaseConanFile
) to inject CompanyConanFile
as their respective base class.
Issue description
When we now set python_requires_extend = "companyconan.CompanyConanFile"
in ProjectBaseConanFile
, then Conan currently injects CompanyConanFile
as the base class of self.__class__
, so at this position:
<object>
<class 'ConanFile'>
<class 'ProjectBaseConanFile'>
<class 'CompanyConanFile'> <-- injected here
<class 'VariantXConanFile'> <-- self
But that means that the custom implementations of ProjectBaseConanFile
would be overridden by the default implementations of CompanyConanFile
when in fact it should be the other way around.
Expected behavior / workaround
You could work around this and inject the base class at the expected location by adding the following to the ProjectBaseConanFile
class:
class ProjectBaseConanFile(ConanFile):
python_requires = "companyconan/0.1@Company/stable"
# Intentionally commented-out, injection done manually in init()
# python_requires_extend = "companyconan.CompanyConanFile"
def init(self):
CompanyConanFile = self.python_requires["companyConan"].module.CompanyConanFile
ProjectBaseConanFile.__bases__ = (CompanyConanFile,) + ProjectBaseConanFile.__bases__
(Workaround deduced from here) https://github.com/conan-io/conan/blob/ebed0370c439a8274c2992ee41e424438eebd455/conans/client/graph/python_requires.py#L103
This injects CompanyConanFile
at the correct position:
<object>
<ConanFile>
<CompanyConanFile> <-- injected here
<ProjectBaseConanFile>
<VariantXConanFile> <-- self
Environment Details
- Operating System+version: macOS Catalina 10.15.7
- Compiler+version: Apple clang version 12.0.0 (clang-1200.0.32.29)
- Conan version: 1.43.0
- Python version: 3.9.9
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (4 by maintainers)
Cool! I consider this issue closed then.
Closed by https://github.com/conan-io/docs/pull/2393