New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
python_require_extend_class method #6614
python_require_extend_class method #6614
Conversation
I've tried this, the test passes 😎 from conans import ConanFile
class PkgTest(ConanFile):
license = "MIT"
author = "frodo"
settings = "arch", # tuple!
python_requires = "base/1.1@user/testing"
python_requires_extend = "base.MyConanfileBase"
#@classmethod
#def python_require_extend_class(cls, c):
# cls.settings = c.settings + cls.settings
def __init__(self, *args, **kwargs):
self.settings = super(PkgTest, self).settings + self.settings
super(PkgTest, self).__init__(*args, **kwargs)
def build(self):
self.output.info("License! %s" % self.license)
self.output.info("Author! %s" % self.author)
self.output.info("os: %s arch: %s"
% (self.settings.get_safe("os"), self.settings.arch)) |
I'll try that, but it looks hacky. However, if it works, it could be the basis for implementation for your proposal with |
More hacky than a custom method magically invoked by Conan? The syntax might be a bit unknown for some users, but it is quite a pythonic idiom, isn't it? |
I wouldn't know - I'm a c++ developer 😸 . The part that bothers me (although it's probably because I'm not so much into python) is this: self.settings = super(PkgTest, self).settings + self.settings It looks like concatenation of Also, when does the change happen? Am I allowed to call With custom method magically invoked by Conan, at least I am confident that Conan will invoke it at the right moment and any further internal changes to conan will reduce the chance of breaking the expected behaviour. |
I see the point, let's have a second thought. |
I think this is something quite pythonic and I like it. However, it would be better to have all the attributes defined in the same place (all of them in the Nevertheless, I see the syntax makes sense and if people are using python_requires to do any kind of inheritance or pure python code reuse, I believe they should understand how python works for this matter. Additionally, we would have to clearly define the usage and provide meaningful examples in the documentation. |
That is the thing, that we are hiding the inheritance, making it lazy. So it is not evident where are you inheriting from. Otherwise, I'd agree that the solution is perfect. |
I've tried this: class MyPackage(ConanFile):
python_requires = 'MyBaseConanFile/1.0.0@company/stable'
python_requires_extend = "MyBaseConanFile.MyBaseConanFile"
options = {
'another_option': [True, False]
}
def __init__(self, *args, **kwargs):
super(MyPackage, self).__init__(*args, **kwargs)
self.options.update(super(MyPackage,self).options) and it appears to work. If you guys plan to keep this pattern stable for general usage, I'll be OK with using it. However, I am afraid that it will be a bit more complex to explain to my developers what is happening here. The issue is that it's not clear at which point does the class extending happens (obviously before invoking the constructor). Also, since now In general, if that would be the official pattern for inheriting options and settings from the base conanfile, please document it here (currently Also, one question: since the new |
Also, just out of curiosity, how did you plan to support multiple python requirements and multiple inheritances with the new model? I didn't need that so far, but in the old model it was theoretically achievable: the |
Yes, that is a good point. The |
Actually, we would need a syntax to tell multiple python requirements (i.e. I guess the same could be achieved also with hacked |
Another approach I'd really like more would be to use the from conans import ConanFile
class PkgTest(ConanFile):
license = "MIT"
author = "frodo"
settings = "arch", # tuple!
python_requires = "base/1.1@user/testing"
python_requires_extend = "base.MyConanfileBase"
def initialize(self, *args, **kwargs):
self.settings = self.python_requires['base'].module.MyConanfileBase.settings + self.settings
self.license = self.python_requires['base'].module.MyConanfileBase.license
self.author = self.python_requires['base'].module.MyConanfileBase.author
super(PkgTest, self).initialize(*args, **kwargs)
def build(self):
self.output.info("License! %s" % self.license)
self.output.info("Author! %s" % self.author)
self.output.info("os: %s arch: %s" % (self.settings.get_safe("os"), self.settings.arch)) This is just another approach to consider. |
Furthermore, we have full control, we could use another method, not a class one, and call it from conan, avoiding all |
Well, from my perspective, I am OK with both An additional benefit would be to be able to easily understand the process of extending so the training of developers would be easier. |
Also, accessing via But, @jgsogo, keep in mind how multiple inheritance would work. For accessing the base, the |
Please check the latest changes with a |
I prefer to call the function
I think that this test contains what you are looking for:
|
I agree with @jgsogo - I think the What about the original suggestion by @memsharded: |
IMO this |
Renamed it to I would document that explicitly for this purpose only, and we will see. The truth is that if it is useful for other things then later it is very ugly to be abusing a |
Need changlog and docs |
Changelog: Feature: Add a new
init()
method toconanfile.py
recipes that can be used to add extra logic when inheriting frompython_requires
classes.Docs: conan-io/docs#1622
Close #6612