Skip to content

Commit

Permalink
Merge branch 'develop2' into gh-actions-linux
Browse files Browse the repository at this point in the history
  • Loading branch information
czoido authored Oct 25, 2024
2 parents 47fd058 + 6e1f44c commit 7d40e59
Show file tree
Hide file tree
Showing 43 changed files with 479 additions and 188 deletions.
2 changes: 1 addition & 1 deletion conan/api/conan_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys

from conan.api.output import init_colorama
from conan.api.subapi.cache import CacheAPI
from conan.api.subapi.command import CommandAPI
from conan.api.subapi.local import LocalAPI
Expand All @@ -18,7 +19,6 @@
from conan.api.subapi.search import SearchAPI
from conan.api.subapi.upload import UploadAPI
from conans.client.migrations import ClientMigrator
from conans.client.userio import init_colorama
from conan.errors import ConanException
from conans.model.version import Version
from conan.internal.paths import get_conan_user_home
Expand Down
44 changes: 3 additions & 41 deletions conans/client/userio.py → conan/api/input.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,10 @@
import getpass
import os
import sys

from conan.errors import ConanException


def is_terminal(stream):
return hasattr(stream, "isatty") and stream.isatty()


def color_enabled(stream):
"""
NO_COLOR: No colors
https://no-color.org/
Command-line software which adds ANSI color to its output by default should check for the
presence of a NO_COLOR environment variable that, when present (**regardless of its value**),
prevents the addition of ANSI color.
CLICOLOR_FORCE: Force color
https://bixense.com/clicolors/
"""

if os.getenv("CLICOLOR_FORCE", "0") != "0":
# CLICOLOR_FORCE != 0, ANSI colors should be enabled no matter what.
return True

if os.getenv("NO_COLOR") is not None:
return False
return is_terminal(stream)


def init_colorama(stream):
import colorama
if color_enabled(stream):
if os.getenv("CLICOLOR_FORCE", "0") != "0":
# Otherwise it is not really forced if colorama doesn't feel it
colorama.init(strip=False, convert=False)
else:
colorama.init()


class UserInput(object):
class UserInput:
"""Class to interact with the user, used to show messages and ask for information"""

def __init__(self, non_interactive):
Expand Down Expand Up @@ -75,7 +36,8 @@ def request_login(self, remote_name, username=None):
self._out.write("Remote '%s' username: " % remote_name)
username = self.get_username()

self._out.write('Please enter a password for "%s" account: ' % username)
self._out.write("Please enter a password for user '%s' on remote '%s': "
% (username, remote_name))
try:
pwd = self.get_password()
except ConanException:
Expand Down
39 changes: 36 additions & 3 deletions conan/api/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from colorama import Fore, Style

from conans.client.userio import color_enabled
from conan.errors import ConanException

LEVEL_QUIET = 80 # -q
Expand Down Expand Up @@ -50,6 +49,40 @@ class Color(object):
Color.BRIGHT_GREEN = Fore.GREEN


def init_colorama(stream):
import colorama
if _color_enabled(stream):
if os.getenv("CLICOLOR_FORCE", "0") != "0":
# Otherwise it is not really forced if colorama doesn't feel it
colorama.init(strip=False, convert=False)
else:
colorama.init()


def _color_enabled(stream):
"""
NO_COLOR: No colors
https://no-color.org/
Command-line software which adds ANSI color to its output by default should check for the
presence of a NO_COLOR environment variable that, when present (**regardless of its value**),
prevents the addition of ANSI color.
CLICOLOR_FORCE: Force color
https://bixense.com/clicolors/
"""

if os.getenv("CLICOLOR_FORCE", "0") != "0":
# CLICOLOR_FORCE != 0, ANSI colors should be enabled no matter what.
return True

if os.getenv("NO_COLOR") is not None:
return False
return hasattr(stream, "isatty") and stream.isatty()


class ConanOutput:
# Singleton
_conan_output_level = LEVEL_STATUS
Expand All @@ -62,7 +95,7 @@ def __init__(self, scope=""):
self._scope = scope
# FIXME: This is needed because in testing we are redirecting the sys.stderr to a buffer
# stream to capture it, so colorama is not there to strip the color bytes
self._color = color_enabled(self.stream)
self._color = _color_enabled(self.stream)

@classmethod
def define_silence_warnings(cls, warnings):
Expand Down Expand Up @@ -253,7 +286,7 @@ def cli_out_write(data, fg=None, bg=None, endline="\n", indentation=0):

fg_ = fg or ''
bg_ = bg or ''
if (fg or bg) and color_enabled(sys.stdout):
if (fg or bg) and _color_enabled(sys.stdout):
data = f"{' ' * indentation}{fg_}{bg_}{data}{Style.RESET_ALL}{endline}"
else:
data = f"{' ' * indentation}{data}{endline}"
Expand Down
40 changes: 32 additions & 8 deletions conan/api/subapi/new.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fnmatch
import os

from jinja2 import Template, StrictUndefined
from jinja2 import Template, StrictUndefined, UndefinedError, Environment, meta

from conan.errors import ConanException
from conans.util.files import load
Expand Down Expand Up @@ -118,11 +118,35 @@ def as_name(ref):
definitions["package_name"] = as_package_name(name)
definitions["as_name"] = as_name
definitions["names"] = lambda x: ", ".join(r.split("/", 1)[0] for r in x)
for k, v in template_files.items():
k = Template(k, keep_trailing_newline=True, undefined=StrictUndefined).render(
**definitions)
v = Template(v, keep_trailing_newline=True, undefined=StrictUndefined).render(
**definitions)
if v:
result[k] = v
if "name" not in definitions:
definitions["name"] = "mypkg"
if "version" not in definitions:
definitions["version"] = "0.1"
version = definitions.get("version")
if isinstance(version, list):
raise ConanException(f"version argument can't be multiple: {version}")

try:
for k, v in template_files.items():
k = Template(k, keep_trailing_newline=True, undefined=StrictUndefined).render(
**definitions)
v = Template(v, keep_trailing_newline=True, undefined=StrictUndefined).render(
**definitions)
if v:
result[k] = v
except UndefinedError:
template_vars = []
for templ_str in template_files.values():
env = Environment()
ast = env.parse(templ_str)
template_vars.extend(meta.find_undeclared_variables(ast))

injected_vars = {"conan_version", "package_name", "as_name"}
optional_vars = {"requires", "tool_requires", "output_root_dir"}
template_vars = list(set(template_vars) - injected_vars - optional_vars)
template_vars.sort()

raise ConanException("Missing definitions for the template. "
"Required definitions are: {}"
.format(", ".join("'{}'".format(var) for var in template_vars)))
return result
5 changes: 5 additions & 0 deletions conan/api/subapi/profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ def _get_profile(self, profiles, settings, options, conf, cwd, cache_settings,
f"Use '&:{k}={v}' to refer to the current package.\n"
f"Use '*:{k}={v}' or other pattern if the intent was to apply to "
f"dependencies", warn_tag="legacy")
if profile.conf.get("tools.graph:skip_test", check_type=bool):
ConanOutput().warning("Usage of 'tools.graph:skip_test'", warn_tag="experimental")
if not profile.conf.get("tools.build:skip_test", check_type=bool):
ConanOutput().warning("tools.graph:skip_test set, but tools.build:skip_test is not, "
"probably you need to define it too")
return profile

def get_path(self, profile, cwd=None, exists=True):
Expand Down
22 changes: 1 addition & 21 deletions conan/cli/commands/new.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import os
import shutil

from jinja2 import Environment, meta, exceptions

from conan.api.output import ConanOutput
from conan.cli.command import conan_command
from conan.errors import ConanException
Expand Down Expand Up @@ -57,25 +55,7 @@ def new(conan_api, parser, *args):
if not template_files and not non_template_files:
raise ConanException("Template doesn't exist or not a folder: {}".format(args.template))

try:
template_files = conan_api.new.render(template_files, definitions)
except exceptions.UndefinedError:
def get_template_vars():
template_vars = []
for _, templ_str in template_files.items():
env = Environment()
ast = env.parse(templ_str)
template_vars.extend(meta.find_undeclared_variables(ast))

injected_vars = {"conan_version", "package_name", "as_name"}
optional_vars = {"requires", "tool_requires", "output_root_dir"}
template_vars = list(set(template_vars) - injected_vars - optional_vars)
template_vars.sort()
return template_vars

raise ConanException("Missing definitions for the template. "
"Required definitions are: {}"
.format(", ".join("'{}'".format(var) for var in get_template_vars())))
template_files = conan_api.new.render(template_files, definitions)

# Saving the resulting files
output = ConanOutput()
Expand Down
2 changes: 1 addition & 1 deletion conan/cli/commands/remove.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from conan.api.conan_api import ConanAPI
from conan.api.model import ListPattern, MultiPackagesList
from conan.api.output import cli_out_write, ConanOutput
from conan.api.input import UserInput
from conan.cli import make_abs_path
from conan.cli.command import conan_command, OnceArgument
from conan.cli.commands.list import print_list_json, print_serial
from conans.client.userio import UserInput
from conan.errors import ConanException


Expand Down
2 changes: 1 addition & 1 deletion conan/cli/commands/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from conan.cli import make_abs_path
from conan.cli.command import conan_command, OnceArgument
from conan.cli.commands.list import print_list_json, print_serial
from conans.client.userio import UserInput
from conan.api.input import UserInput
from conan.errors import ConanException


Expand Down
21 changes: 19 additions & 2 deletions conan/internal/api/install/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def load_cache_generators(path):
def write_generators(conanfile, app, envs_generation=None):
new_gen_folder = conanfile.generators_folder
_receive_conf(conanfile)
_receive_generators(conanfile)

hook_manager = app.hook_manager
# TODO: Optimize this, so the global generators are not loaded every call to write_generators
Expand All @@ -92,8 +93,12 @@ def write_generators(conanfile, app, envs_generation=None):
conanfile.generators = []
try:
for generator_name in old_generators:
global_generator = global_generators.get(generator_name)
generator_class = global_generator or _get_generator_class(generator_name)
if isinstance(generator_name, str):
global_generator = global_generators.get(generator_name)
generator_class = global_generator or _get_generator_class(generator_name)
else:
generator_class = generator_name
generator_name = generator_class.__name__
if generator_class:
try:
generator = generator_class(conanfile)
Expand Down Expand Up @@ -152,6 +157,18 @@ def _receive_conf(conanfile):
conanfile.conf.compose_conf(build_require.conf_info)


def _receive_generators(conanfile):
""" Collect generators_info from the immediate build_requires"""
for build_req in conanfile.dependencies.direct_build.values():
if build_req.generator_info:
if not isinstance(build_req.generator_info, list):
raise ConanException(f"{build_req} 'generator_info' must be a list")
names = [c.__name__ if not isinstance(c, str) else c for c in build_req.generator_info]
conanfile.output.warning(f"Tool-require {build_req} adding generators: {names}",
warn_tag="experimental")
conanfile.generators = build_req.generator_info + conanfile.generators


def _generate_aggregated_env(conanfile):

def deactivates(filenames):
Expand Down
68 changes: 16 additions & 52 deletions conan/internal/api/profile/profile_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,71 +43,35 @@ def profile_plugin(profile):
def _check_correct_cppstd(settings):
from conan.tools.scm import Version
def _error(compiler, cppstd, min_version, version):
from conan.errors import ConanException
raise ConanException(f"The provided compiler.cppstd={cppstd} requires at least {compiler}"
f">={min_version} but version {version} provided")
cppstd = settings.get("compiler.cppstd")
version = settings.get("compiler.version")
if cppstd and version:
cppstd = cppstd.replace("gnu", "")
version = Version(version)
mver = None
compiler = settings.get("compiler")
if compiler == "gcc":
mver = {"20": "8",
"17": "5",
"14": "4.8",
"11": "4.3"}.get(cppstd)
elif compiler == "clang":
mver = {"20": "6",
"17": "3.5",
"14": "3.4",
"11": "2.1"}.get(cppstd)
elif compiler == "apple-clang":
mver = {"20": "10",
"17": "6.1",
"14": "5.1",
"11": "4.5"}.get(cppstd)
elif compiler == "msvc":
mver = {"23": "193",
"20": "192",
"17": "191",
"14": "190"}.get(cppstd)
if mver and version < mver:
_error(compiler, cppstd, mver, version)
from conan.tools.build.cppstd import supported_cppstd
supported = supported_cppstd(None, compiler, version)
# supported is None when we don't have information about the compiler
# but an empty list when no flags are supported for this version
if supported is not None and cppstd not in supported:
from conan.errors import ConanException
raise ConanException(f"The provided compiler.cppstd={cppstd} is not supported by {compiler} {version}. "
f"Supported values are: {supported}")
def _check_correct_cstd(settings):
from conan.tools.scm import Version
def _error(compiler, cstd, min_version, version):
from conan.errors import ConanException
raise ConanException(f"The provided compiler.cstd={cstd} requires at least {compiler}"
f">={min_version} but version {version} provided")
cstd = settings.get("compiler.cstd")
version = settings.get("compiler.version")
if cstd and version:
cstd = cstd.replace("gnu", "")
version = Version(version)
mver = None
compiler = settings.get("compiler")
if compiler == "gcc":
# TODO: right versions
mver = {}.get(cstd)
elif compiler == "clang":
# TODO: right versions
mver = {}.get(cstd)
elif compiler == "apple-clang":
# TODO: Right versions
mver = {}.get(cstd)
elif compiler == "msvc":
mver = {"17": "192",
"11": "192"}.get(cstd)
if mver and version < mver:
_error(compiler, cstd, mver, version)
from conan.tools.build.cstd import supported_cstd
supported = supported_cstd(None, compiler, version)
# supported is None when we don't have information about the compiler
# but an empty list when no flags are supported for this version
if supported is not None and cstd not in supported:
from conan.errors import ConanException
raise ConanException(f"The provided compiler.cstd={cstd} is not supported by {compiler} {version}. "
f"Supported values are: {supported}")
"""


Expand Down
Loading

0 comments on commit 7d40e59

Please sign in to comment.