Conan: how to add requires from the same channel as current package?

Created on 18 Nov 2016  路  12Comments  路  Source: conan-io/conan

Hi,

sorry for may be stupid question, I've read docs and source code, but unfortunately I can't understand how can I add requires from the same channel as current package.

let me explain. for instance, I currently have OpenSSL package, which depends on two other packages - nasm_installer & ActivePerl_installer. so I have the following code:

self.requires.add("ActivePerl_installer/5.24.0.2400@sse4/testing", private=True)
self.requires.add("nasm_installer/2.12.02@sse4/testing", private=True)

I have many other packaging with complex dependency hierarchy. so, once I decide to make new channel for well-tested and stable packages, I will probably end-up with patching lots of my receipts like this:

self.requires.add("ActivePerl_installer/5.24.0.2400@sse4/stable", private=True)
self.requires.add("nasm_installer/2.12.02@sse4/stable", private=True)

which is pretty boring and annoying. same situation if my college wants to fork package hierarchy and change to his username. ideally, I would want to write something like these:

self.requires.add("ActivePerl_installer/5.24.0.2400@%s/%s" % (self.username, self.channel), private=True)
self.requires.add("nasm_installer/2.12.02@%s/%s" % (self.username, self.channel), private=True)

therefore all packages in hierarchy are from the same channel. is it somehow possibly to do something like that?
P.S. I've seen approach with environment variables, but it's external to conanfile, but I want to get information from the current file, which is much more transparent and less error prone.

Most helpful comment

@memsharded yes, requirements() method is perfect place to define requirements :) I'll try your proposal tomorrow and let you know how does it work.

All 12 comments

Hi @SSE4. I understand the question, and it's not stupid at all. I've the same doubt a couple of times, but not too needed for me. Actually I don't know if we can get the channel in the conanfile but I'm sure it would be easy to implement. Let me check it with @memsharded and will come back later.

Currently now that information is not available in the conanfiles, but I think it could be made available.
I am doing a quick check, might come with a proposal.

First issue. Lets suppose we have the following code:

from conans import ConanFile

class HelloConan(ConanFile):
    name = "Hello"
    version = "1.2"
    requires = "Say/0.1@%s/%s" % (self.username, self.channel)

This might work for packages. The problem comes when we are working, developing in the user space with an open package, which has typically not been exported yet into the local conan cache. In that case, the username/channel are not defined. They can't be defined, this is something that is done afterwards, when the user decides what to do with the project. Maybe did some things, and want to upload a "testing" package now.

We could come with the following solution:

  • If the package code is open under development, the username and channel have to be defined with environment variables, like those used typically in the test_package CONAN_USER_NAME, CONAN_CHANNEL.
  • If they are not defined and used with self.username, self.channel, that will raise an Error and stop execution until defined
  • For packages in the local cache, the internal usernames and channels will be assigned by conan, and then it will not check at all for the environment variables.

Feedback please! @lasote @SSE4

@memsharded not sure I understand the issue.
if I have started with new package development, I have to run "conan new' command first, isn't it?
and as I understand it already needs channel and username, e.g. from the "conan new -h":

positional arguments:
  name          Package name, e.g.: Poco/1.7.3@user/testing

so for me it looks like channel and username exist from the package's inception. they then can be changed (branches), e.g. if I run "conan copy" command.
do I misunderstand the workflow?

Not really. The username/channel are needed to define the test_package requirement and automate the export. Just a convenience for smooth following commands, but not required. Package recipes do not use the username/channel anywhere in the "static" model, as that would break the possibility to promote/copy/fork packages between usernames and channels. Note that test_package folder is not exported into packages.

As further clarification, the conan copy command does not change at all the recipes/packages, it copies them from one folder to another.

@memsharded roger that.
then I personally prefer explicit behaviour and no implicit defaults. so I vote for #2 - raising exception. if package maintainer needs implicit/default behaviour, he can write something like:

requires = "Say/0.1@%s/%s" % (self.username or default_username, self.channel or default_channel)

in my daily package development workflow, I personally always run "conan export" and only after that commands like "conan install" or "conan test_package"

I am not sure, agree about raising, but not sure how the defaults would be implemented, I guess that your conanfile recipe would be something like (not tested, just the idea):

from conans import ConanFile

def default_channel():
    channel = os.getenv("CONAN_CHANNEL")
    if channel:
         return channel
    raise Exception("Channel not defined")

def default_username():
    channel = os.getenv("CONAN_USERNAME")
    if channel:
         return channel
    raise Exception("Username not defined")

class HelloConan(ConanFile):
    name = "Hello"
    version = "1.2"
    requires = "Say/0.1@%s/%s" % (self.username or default_username(), self.channel or default_channel())

The above is necessary, otherwise, it wouldn't handle the information properly. I think it might be better to embed such default functions into the 麓麓self.usernameandself.channelproperties. How do you plan to define yourdefault_username/channel`` otherwise?

@memsharded yes, I would write something very similar to your snippet, if I wish to get defaults from environment variables. so your proposed solution satisfies my requirements anyway, let's stick on it.

Just a note about the pseudo-code I was proposing. It is not viable as is, as self doesn't exist at the class level. This is an advanced use of requires, and thus should be done inside the requirements() method. Sounds good? I am coding a proposal.

Proposal submitted here: https://github.com/conan-io/conan/pull/730/files in case @SSE4 wants to have a look or try it from my branch.

@memsharded yes, requirements() method is perfect place to define requirements :) I'll try your proposal tomorrow and let you know how does it work.

@memsharded I confirm your branch works as expected, thanks a lot for your effort!

Was this page helpful?
0 / 5 - 0 ratings