Repository: conan-io/conan
Pull request #17268 (2024-11-04 00:36:52)

refactor methods conans->conan
Changelog: Omit
Docs: Omit


Pure refactor


Patch:
diff --git a/conan/api/output.py b/conan/api/output.py
index d224498bd..a94e16cb5 100644
--- a/conan/api/output.py
+++ b/conan/api/output.py
@@ -4,6 +4,7 @@ import sys
 import time
 from threading import Lock
 
+import colorama
 from colorama import Fore, Style
 
 from conan.errors import ConanException
@@ -283,15 +284,15 @@ def cli_out_write(data, fg=None, bg=None, endline="\n", indentation=0):
     """
     Output to be used by formatters to dump information to stdout
     """
-
-    fg_ = fg or ''
-    bg_ = bg or ''
-    if (fg or bg) and _color_enabled(sys.stdout):
-        data = f"{' ' * indentation}{fg_}{bg_}{data}{Style.RESET_ALL}{endline}"
+    if (fg or bg) and _color_enabled(sys.stdout):  # need color
+        data = f"{' ' * indentation}{fg or ''}{bg or ''}{data}{Style.RESET_ALL}{endline}"
+        sys.stdout.write(data)
     else:
         data = f"{' ' * indentation}{data}{endline}"
-
-    sys.stdout.write(data)
+        # https://github.com/conan-io/conan/issues/17245 avoid colorama crash and overhead
+        colorama.deinit()
+        sys.stdout.write(data)
+        colorama.reinit()
 
 
 class TimedOutput:
diff --git a/conan/api/subapi/export.py b/conan/api/subapi/export.py
index 4eeb0201b..e6e62c4eb 100644
--- a/conan/api/subapi/export.py
+++ b/conan/api/subapi/export.py
@@ -1,7 +1,7 @@
 from conan.api.output import ConanOutput
 from conan.internal.conan_app import ConanApp
 from conan.internal.api.export import cmd_export
-from conans.client.conanfile.package import run_package_method
+from conan.internal.methods import run_package_method
 from conans.client.graph.graph import BINARY_BUILD, RECIPE_INCACHE
 from conans.model.package_ref import PkgReference
 from conans.util.files import mkdir
diff --git a/conan/api/subapi/local.py b/conan/api/subapi/local.py
index 7b252a6bd..1b4c1962a 100644
--- a/conan/api/subapi/local.py
+++ b/conan/api/subapi/local.py
@@ -3,10 +3,9 @@ import os
 from conan.cli import make_abs_path
 from conan.internal.conan_app import ConanApp
 from conan.internal.api.local.editable import EditablePackages
-from conans.client.conanfile.build import run_build_method
+from conan.internal.methods import run_build_method, run_source_method
 from conans.client.graph.graph import CONTEXT_HOST
 from conans.client.graph.profile_node_definer import initialize_conanfile_profile
-from conans.client.source import run_source_method
 from conan.internal.errors import conanfile_exception_formatter
 from conan.errors import ConanException
 from conans.model.recipe_ref import RecipeReference
diff --git a/conan/internal/methods.py b/conan/internal/methods.py
new file mode 100644
index 000000000..c8405bf55
--- /dev/null
+++ b/conan/internal/methods.py
@@ -0,0 +1,159 @@
+import os
+
+from conan.api.output import ConanOutput
+from conan.errors import ConanException
+from conan.internal.errors import conanfile_exception_formatter, conanfile_remove_attr
+from conan.internal.paths import CONANINFO
+from conans.model.manifest import FileTreeManifest
+from conans.model.package_ref import PkgReference
+from conans.model.pkg_type import PackageType
+from conans.model.requires import BuildRequirements, TestRequirements, ToolRequirements
+from conans.util.files import mkdir, chdir, save
+
+
+def run_source_method(conanfile, hook_manager):
+    mkdir(conanfile.source_folder)
+    with chdir(conanfile.source_folder):
+        hook_manager.execute("pre_source", conanfile=conanfile)
+        if hasattr(conanfile, "source"):
+            conanfile.output.highlight("Calling source() in {}".format(conanfile.source_folder))
+            with conanfile_exception_formatter(conanfile, "source"):
+                with conanfile_remove_attr(conanfile, ['info', 'settings', "options"], "source"):
+                    conanfile.source()
+        hook_manager.execute("post_source", conanfile=conanfile)
+
+
+def run_build_method(conanfile, hook_manager):
+    mkdir(conanfile.build_folder)
+    mkdir(conanfile.package_metadata_folder)
+    with chdir(conanfile.build_folder):
+        hook_manager.execute("pre_build", conanfile=conanfile)
+        if hasattr(conanfile, "build"):
+            conanfile.output.highlight("Calling build()")
+            with conanfile_exception_formatter(conanfile, "build"):
+                try:
+                    conanfile.build()
+                except Exception:
+                    hook_manager.execute("post_build_fail", conanfile=conanfile)
+                    raise
+        hook_manager.execute("post_build", conanfile=conanfile)
+
+
+def run_package_method(conanfile, package_id, hook_manager, ref):
+    """ calls the recipe "package()" method
+    - Assigns folders to conanfile.package_folder, source_folder, install_folder, build_folder
+    - Calls pre-post package hook
+    """
+
+    if conanfile.package_folder == conanfile.build_folder:
+        raise ConanException("Cannot 'conan package' to the build folder. "
+                             "--build-folder and package folder can't be the same")
+
+    mkdir(conanfile.package_folder)
+    scoped_output = conanfile.output
+    # Make the copy of all the patterns
+    scoped_output.info("Generating the package")
+    scoped_output.info("Packaging in folder %s" % conanfile.package_folder)
+
+    hook_manager.execute("pre_package", conanfile=conanfile)
+    if hasattr(conanfile, "package"):
+        scoped_output.highlight("Calling package()")
+        with conanfile_exception_formatter(conanfile, "package"):
+            with chdir(conanfile.build_folder):
+                with conanfile_remove_attr(conanfile, ['info'], "package"):
+                    conanfile.package()
+    hook_manager.execute("post_package", conanfile=conanfile)
+
+    save(os.path.join(conanfile.package_folder, CONANINFO), conanfile.info.dumps())
+    manifest = FileTreeManifest.create(conanfile.package_folder)
+    manifest.save(conanfile.package_folder)
+    package_output = ConanOutput(scope="%s: package()" % scoped_output.scope)
+    manifest.report_summary(package_output, "Packaged")
+
+    prev = manifest.summary_hash
+    scoped_output.info("Created package revision %s" % prev)
+    pref = PkgReference(ref, package_id)
+    pref.revision = prev
+    scoped_output.success("Package '%s' created" % package_id)
+    scoped_output.success("Full package reference: {}".format(pref.repr_notime()))
+    return prev
+
+
+def run_configure_method(conanfile, down_options, profile_options, ref):
+    """ Run all the config-related functions for the given conanfile object """
+
+    initial_requires_count = len(conanfile.requires)
+
+    if hasattr(conanfile, "config_options"):
+        with conanfile_exception_formatter(conanfile, "config_options"):
+            conanfile.config_options()
+    elif "auto_shared_fpic" in conanfile.implements:
+        auto_shared_fpic_config_options(conanfile)
+
+    auto_language(conanfile)  # default implementation removes `compiler.cstd`
+
+    # Assign only the current package options values, but none of the dependencies
+    is_consumer = conanfile._conan_is_consumer
+    conanfile.options.apply_downstream(down_options, profile_options, ref, is_consumer)
+
+    if hasattr(conanfile, "configure"):
+        with conanfile_exception_formatter(conanfile, "configure"):
+            conanfile.configure()
+    elif "auto_shared_fpic" in conanfile.implements:
+        auto_shared_fpic_configure(conanfile)
+
+    if initial_requires_count != len(conanfile.requires):
+        conanfile.output.warning("Requirements should only be added in the requirements()/"
+                                 "build_requirements() methods, not configure()/config_options(), "
+                                 "which might raise errors in the future.", warn_tag="deprecated")
+
+    result = conanfile.options.get_upstream_options(down_options, ref, is_consumer)
+    self_options, up_options, private_up_options = result
+    # self_options are the minimum to reproduce state, as defined from downstream (not profile)
+    conanfile.self_options = self_options
+    # up_options are the minimal options that should be propagated to dependencies
+    conanfile.up_options = up_options
+    conanfile.private_up_options = private_up_options
+
+    PackageType.compute_package_type(conanfile)
+
+    conanfile.build_requires = BuildRequirements(conanfile.requires)
+    conanfile.test_requires = TestRequirements(conanfile.requires)
+    conanfile.tool_requires = ToolRequirements(conanfile.requires)
+
+    if hasattr(conanfile, "requirements"):
+        with conanfile_exception_formatter(conanfile, "requirements"):
+            conanfile.requirements()
+
+    if hasattr(conanfile, "build_requirements"):
+        with conanfile_exception_formatter(conanfile, "build_requirements"):
+            conanfile.build_requirements()
+
+
+def auto_shared_fpic_config_options(conanfile):
+    if conanfile.settings.get_safe("os") == "Windows":
+        conanfile.options.rm_safe("fPIC")
+
+
+def auto_shared_fpic_configure(conanfile):
+    if conanfile.options.get_safe("header_only"):
+        conanfile.options.rm_safe("fPIC")
+        conanfile.options.rm_safe("shared")
+    elif conanfile.options.get_safe("shared"):
+        conanfile.options.rm_safe("fPIC")
+
+
+def auto_header_only_package_id(conanfile):
+    if conanfile.options.get_safe("header_only") or conanfile.package_type is PackageType.HEADER:
+        conanfile.info.clear()
+
+
+def auto_language(conanfile):
+    if not conanfile.languages:
+        conanfile.settings.rm_safe("compiler.cstd")
+        return
+    if "C" not in conanfile.languages:
+        conanfile.settings.rm_safe("compiler.cstd")
+    if "C++" not in conanfile.languages:
+        conanfile.settings.rm_safe("compiler.cppstd")
+        conanfile.settings.rm_safe("compiler.libcxx")
diff --git a/conan/tools/meson/toolchain.py b/conan/tools/meson/toolchain.py
index 743d38cbb..363861b8e 100644
--- a/conan/tools/meson/toolchain.py
+++ b/conan/tools/meson/toolchain.py
@@ -16,7 +16,7 @@ from conan.tools.microsoft import VCVars, msvc_runtime_flag
 from conans.util.files import save
 
 
-class MesonToolchain(object):
+class MesonToolchain:
     """
     MesonToolchain generator
     """
@@ -156,7 +156,7 @@ class MesonToolchain(object):
         self._conanfile = conanfile
         self._native = native
         self._is_apple_system = is_apple_os(self._conanfile)
-        is_cross_building = cross_building(conanfile, skip_x64_x86=True)
+        is_cross_building = cross_building(conanfile)  # x86_64->x86 is considered cross-building
         if not is_cross_building and native:
             raise ConanException("You can only pass native=True if you're cross-building, "
                                  "otherwise, it could cause unexpected results.")
@@ -164,8 +164,8 @@ class MesonToolchain(object):
         # Values are kept as Python built-ins so users can modify them more easily, and they are
         # only converted to Meson file syntax for rendering
         # priority: first user conf, then recipe, last one is default "ninja"
-        self._backend = conanfile.conf.get("tools.meson.mesontoolchain:backend",
-                                           default=backend or 'ninja')
+        self._backend = self._conanfile_conf.get("tools.meson.mesontoolchain:backend",
+                                                 default=backend or 'ninja')
         build_type = self._conanfile.settings.get_safe("build_type")
         self._buildtype = {"Debug": "debug",  # Note, it is not "'debug'"
                            "Release": "release",
@@ -424,13 +424,13 @@ class MesonToolchain(object):
         exelinkflags = self._conanfile_conf.get("tools.build:exelinkflags", default=[], check_type=list)
         linker_scripts = self._conanfile_conf.get("tools.build:linker_scripts", default=[], check_type=list)
         linker_script_flags = ['-T"' + linker_script + '"' for linker_script in linker_scripts]
-        defines = self._conanfile.conf.get("tools.build:defines", default=[], check_type=list)
+        defines = self._conanfile_conf.get("tools.build:defines", default=[], check_type=list)
         sys_root = [f"--sysroot={self._sys_root}"] if self._sys_root else [""]
+        ld = sharedlinkflags + exelinkflags + linker_script_flags + sys_root + self.extra_ldflags
         return {
             "cxxflags": cxxflags + sys_root + self.extra_cxxflags,
             "cflags": cflags + sys_root + self.extra_cflags,
-            "ldflags": sharedlinkflags + exelinkflags + linker_script_flags
-                       + sys_root + self.extra_ldflags,
+            "ldflags": ld,
             "defines": [f"-D{d}" for d in (defines + self.extra_defines)]
         }
 
@@ -447,11 +447,12 @@ class MesonToolchain(object):
     def _sanitize_env_format(value):
         if value is None or isinstance(value, list):
             return value
+        if not isinstance(value, str):
+            raise ConanException(f"MesonToolchain: Value '{value}' should be a string")
         ret = [x.strip() for x in value.split() if x]
         return ret[0] if len(ret) == 1 else ret
 
     def _context(self):
-
         apple_flags = self.apple_isysroot_flag + self.apple_arch_flag + self.apple_min_version_flag
         extra_flags = self._get_extra_flags()
 
@@ -474,10 +475,11 @@ class MesonToolchain(object):
 
         subproject_options = {}
         for subproject, listkeypair in self.subproject_options.items():
-            if listkeypair is not None and listkeypair is not []:
-                subproject_options[subproject] = []
-                for keypair in listkeypair:
-                    subproject_options[subproject].append({k: to_meson_value(v) for k, v in keypair.items()})
+            if listkeypair:
+                if not isinstance(listkeypair, list):
+                    raise ConanException("MesonToolchain.subproject_options must be a list of dicts")
+                subproject_options[subproject] = [{k: to_meson_value(v) for k, v in keypair.items()}
+                                                  for keypair in listkeypair]
 
         return {
             # https://mesonbuild.com/Machine-files.html#properties
@@ -555,6 +557,7 @@ class MesonToolchain(object):
         If Windows OS, it will be created a ``conanvcvars.bat`` as well.
         """
         check_duplicated_generator(self, self._conanfile)
+        self._conanfile.output.info(f"MesonToolchain generated: {self._filename}")
         save(self._filename, self._content)
         # FIXME: Should we check the OS and compiler to call VCVars?
         VCVars(self._conanfile).generate()
diff --git a/conan/tools/ros/rosenv.py b/conan/tools/ros/rosenv.py
index 1ddc3341a..fabe6866a 100644
--- a/conan/tools/ros/rosenv.py
+++ b/conan/tools/ros/rosenv.py
@@ -28,7 +28,7 @@ class ROSEnv:
         """
         cmake_toolchain_path = os.path.join(self._conanfile.generators_folder,
                                             "conan_toolchain.cmake")
-        self.variables["CMAKE_TOOLCHAIN_FILE"] = f"\"{cmake_toolchain_path}\""
+        self.variables["CMAKE_TOOLCHAIN_FILE"] = cmake_toolchain_path
         build_type = self._conanfile.settings.get_safe("build_type")
         if build_type:
             self.variables["CMAKE_BUILD_TYPE"] = build_type
diff --git a/conans/client/conanfile/__init__.py b/conans/client/conanfile/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/conans/client/conanfile/build.py b/conans/client/conanfile/build.py
deleted file mode 100644
index 743be2885..000000000
--- a/conans/client/conanfile/build.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from conan.internal.errors import conanfile_exception_formatter
-from conans.util.files import chdir, mkdir
-
-
-def run_build_method(conanfile, hook_manager):
-    mkdir(conanfile.build_folder)
-    mkdir(conanfile.package_metadata_folder)
-    with chdir(conanfile.build_folder):
-        hook_manager.execute("pre_build", conanfile=conanfile)
-        if hasattr(conanfile, "build"):
-            conanfile.output.highlight("Calling build()")
-            with conanfile_exception_formatter(conanfile, "build"):
-                try:
-                    conanfile.build()
-                except Exception:
-                    hook_manager.execute("post_build_fail", conanfile=conanfile)
-                    raise
-        hook_manager.execute("post_build", conanfile=conanfile)
diff --git a/conans/client/conanfile/configure.py b/conans/client/conanfile/configure.py
deleted file mode 100644
index bf99cb0e7..000000000
--- a/conans/client/conanfile/configure.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from conan.internal.errors import conanfile_exception_formatter
-from conans.model.pkg_type import PackageType
-from conans.model.requires import BuildRequirements, TestRequirements, ToolRequirements
-from conans.client.conanfile.implementations import auto_shared_fpic_config_options, \
-    auto_shared_fpic_configure, auto_language
-
-
-def run_configure_method(conanfile, down_options, profile_options, ref):
-    """ Run all the config-related functions for the given conanfile object """
-
-    initial_requires_count = len(conanfile.requires)
-
-    if hasattr(conanfile, "config_options"):
-        with conanfile_exception_formatter(conanfile, "config_options"):
-            conanfile.config_options()
-    elif "auto_shared_fpic" in conanfile.implements:
-        auto_shared_fpic_config_options(conanfile)
-
-    auto_language(conanfile)  # default implementation removes `compiler.cstd`
-
-    # Assign only the current package options values, but none of the dependencies
-    is_consumer = conanfile._conan_is_consumer
-    conanfile.options.apply_downstream(down_options, profile_options, ref, is_consumer)
-
-    if hasattr(conanfile, "configure"):
-        with conanfile_exception_formatter(conanfile, "configure"):
-            conanfile.configure()
-    elif "auto_shared_fpic" in conanfile.implements:
-        auto_shared_fpic_configure(conanfile)
-
-    if initial_requires_count != len(conanfile.requires):
-        conanfile.output.warning("Requirements should only be added in the requirements()/build_requirements() methods, not configure()/config_options(), which might raise errors in the future.", warn_tag="deprecated")
-
-    result = conanfile.options.get_upstream_options(down_options, ref, is_consumer)
-    self_options, up_options, private_up_options = result
-    # self_options are the minimum to reproduce state, as defined from downstream (not profile)
-    conanfile.self_options = self_options
-    # up_options are the minimal options that should be propagated to dependencies
-    conanfile.up_options = up_options
-    conanfile.private_up_options = private_up_options
-
-    PackageType.compute_package_type(conanfile)
-
-    conanfile.build_requires = BuildRequirements(conanfile.requires)
-    conanfile.test_requires = TestRequirements(conanfile.requires)
-    conanfile.tool_requires = ToolRequirements(conanfile.requires)
-
-    if hasattr(conanfile, "requirements"):
-        with conanfile_exception_formatter(conanfile, "requirements"):
-            conanfile.requirements()
-
-    if hasattr(conanfile, "build_requirements"):
-        with conanfile_exception_formatter(conanfile, "build_requirements"):
-            conanfile.build_requirements()
diff --git a/conans/client/conanfile/implementations.py b/conans/client/conanfile/implementations.py
deleted file mode 100644
index 14cabc760..000000000
--- a/conans/client/conanfile/implementations.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from conans.model.pkg_type import PackageType
-
-
-def auto_shared_fpic_config_options(conanfile):
-    if conanfile.settings.get_safe("os") == "Windows":
-        conanfile.options.rm_safe("fPIC")
-
-
-def auto_shared_fpic_configure(conanfile):
-    if conanfile.options.get_safe("header_only"):
-        conanfile.options.rm_safe("fPIC")
-        conanfile.options.rm_safe("shared")
-    elif conanfile.options.get_safe("shared"):
-        conanfile.options.rm_safe("fPIC")
-
-
-def auto_header_only_package_id(conanfile):
-    if conanfile.options.get_safe("header_only") or conanfile.package_type is PackageType.HEADER:
-        conanfile.info.clear()
-
-
-def auto_language(conanfile):
-    if not conanfile.languages:
-        conanfile.settings.rm_safe("compiler.cstd")
-        return
-    if "C" not in conanfile.languages:
-        conanfile.settings.rm_safe("compiler.cstd")
-    if "C++" not in conanfile.languages:
-        conanfile.settings.rm_safe("compiler.cppstd")
-        conanfile.settings.rm_safe("compiler.libcxx")
diff --git a/conans/client/conanfile/package.py b/conans/client/conanfile/package.py
deleted file mode 100644
index dd90d3138..000000000
--- a/conans/client/conanfile/package.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import os
-
-from conan.api.output import ConanOutput
-from conan.internal.errors import conanfile_remove_attr, conanfile_exception_formatter
-from conan.errors import ConanException
-from conans.model.manifest import FileTreeManifest
-from conans.model.package_ref import PkgReference
-from conan.internal.paths import CONANINFO
-from conans.util.files import save, mkdir, chdir
-
-
-def run_package_method(conanfile, package_id, hook_manager, ref):
-    """ calls the recipe "package()" method
-    - Assigns folders to conanfile.package_folder, source_folder, install_folder, build_folder
-    - Calls pre-post package hook
-    """
-
-    if conanfile.package_folder == conanfile.build_folder:
-        raise ConanException("Cannot 'conan package' to the build folder. "
-                             "--build-folder and package folder can't be the same")
-
-    mkdir(conanfile.package_folder)
-    scoped_output = conanfile.output
-    # Make the copy of all the patterns
-    scoped_output.info("Generating the package")
-    scoped_output.info("Packaging in folder %s" % conanfile.package_folder)
-
-    hook_manager.execute("pre_package", conanfile=conanfile)
-    if hasattr(conanfile, "package"):
-        scoped_output.highlight("Calling package()")
-        with conanfile_exception_formatter(conanfile, "package"):
-            with chdir(conanfile.build_folder):
-                with conanfile_remove_attr(conanfile, ['info'], "package"):
-                    conanfile.package()
-    hook_manager.execute("post_package", conanfile=conanfile)
-
-    save(os.path.join(conanfile.package_folder, CONANINFO), conanfile.info.dumps())
-    manifest = FileTreeManifest.create(conanfile.package_folder)
-    manifest.save(conanfile.package_folder)
-    package_output = ConanOutput(scope="%s: package()" % scoped_output.scope)
-    manifest.report_summary(package_output, "Packaged")
-
-    prev = manifest.summary_hash
-    scoped_output.info("Created package revision %s" % prev)
-    pref = PkgReference(ref, package_id)
-    pref.revision = prev
-    scoped_output.success("Package '%s' created" % package_id)
-    scoped_output.success("Full package reference: {}".format(pref.repr_notime()))
-    return prev
-
-
diff --git a/conans/client/graph/compute_pid.py b/conans/client/graph/compute_pid.py
index 9aa690bb9..5852b9387 100644
--- a/conans/client/graph/compute_pid.py
+++ b/conans/client/graph/compute_pid.py
@@ -2,8 +2,8 @@ from collections import OrderedDict
 
 from conan.internal.errors import conanfile_remove_attr, conanfile_exception_formatter
 from conan.errors import ConanException, ConanInvalidConfiguration
+from conan.internal.methods import auto_header_only_package_id
 from conans.model.info import ConanInfo, RequirementsInfo, RequirementInfo, PythonRequiresInfo
-from conans.client.conanfile.implementations import auto_header_only_package_id
 
 
 def compute_package_id(node, modes, config_version):
diff --git a/conans/client/graph/graph_builder.py b/conans/client/graph/graph_builder.py
index 7a5999fea..8745f8f07 100644
--- a/conans/client/graph/graph_builder.py
+++ b/conans/client/graph/graph_builder.py
@@ -3,7 +3,7 @@ import copy
 from collections import deque
 
 from conan.internal.cache.conan_reference_layout import BasicLayout
-from conans.client.conanfile.configure import run_configure_method
+from conan.internal.methods import run_configure_method
 from conans.client.graph.graph import DepsGraph, Node, CONTEXT_HOST, \
     CONTEXT_BUILD, TransitiveRequirement, RECIPE_VIRTUAL, RECIPE_EDITABLE
 from conans.client.graph.graph import RECIPE_PLATFORM
diff --git a/conans/client/installer.py b/conans/client/installer.py
index bdeb24efe..b9bb03d7f 100644
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -3,8 +3,7 @@ import shutil
 from multiprocessing.pool import ThreadPool
 
 from conan.api.output import ConanOutput
-from conans.client.conanfile.build import run_build_method
-from conans.client.conanfile.package import run_package_method
+from conan.internal.methods import run_build_method, run_package_method
 from conan.internal.api.install.generators import write_generators
 from conans.client.graph.graph import BINARY_BUILD, BINARY_CACHE, BINARY_DOWNLOAD, BINARY_EDITABLE, \
     BINARY_UPDATE, BINARY_EDITABLE_BUILD, BINARY_SKIP
diff --git a/conans/client/source.py b/conans/client/source.py
index 9b0aee5b0..053de6bdb 100644
--- a/conans/client/source.py
+++ b/conans/client/source.py
@@ -1,11 +1,12 @@
 import os
 
 from conan.api.output import ConanOutput
+from conan.internal.methods import run_source_method
 from conan.tools.env import VirtualBuildEnv
-from conan.internal.errors import conanfile_remove_attr, conanfile_exception_formatter, NotFoundException
+from conan.internal.errors import NotFoundException
 from conan.errors import ConanException
 from conans.util.files import (is_dirty, mkdir, rmdir, set_dirty_context_manager,
-                               merge_directories, clean_dirty, chdir)
+                               merge_directories, clean_dirty)
 
 
 def _try_get_sources(ref, remote_manager, recipe_layout, remote):
@@ -73,15 +74,3 @@ def config_source(export_source_folder, conanfile, hook_manager):
                     run_source_method(conanfile, hook_manager)
             else:
                 run_source_method(conanfile, hook_manager)
-
-
-def run_source_method(conanfile, hook_manager):
-    mkdir(conanfile.source_folder)
-    with chdir(conanfile.source_folder):
-        hook_manager.execute("pre_source", conanfile=conanfile)
-        if hasattr(conanfile, "source"):
-            conanfile.output.highlight("Calling source() in {}".format(conanfile.source_folder))
-            with conanfile_exception_formatter(conanfile, "source"):
-                with conanfile_remove_attr(conanfile, ['info', 'settings', "options"], "source"):
-                    conanfile.source()
-        hook_manager.execute("post_source", conanfile=conanfile)


Test patch:
diff --git a/test/integration/toolchains/meson/test_mesontoolchain.py b/test/integration/toolchains/meson/test_mesontoolchain.py
index d9ca23ea9..a9075c667 100644
--- a/test/integration/toolchains/meson/test_mesontoolchain.py
+++ b/test/integration/toolchains/meson/test_mesontoolchain.py
@@ -7,7 +7,6 @@ import pytest
 
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.tools import TestClient
-from conan.tools.files import load
 from conan.tools.meson import MesonToolchain
 
 
@@ -540,8 +539,8 @@ def test_native_attribute():
                  "build": build,
                  "conanfile.py": conanfile})
     client.run("install . -pr:h host -pr:b build")
-    native_content = load(None, os.path.join(client.current_folder, MesonToolchain.native_filename))
-    cross_content = load(None, os.path.join(client.current_folder, MesonToolchain.cross_filename))
+    native_content = client.load(MesonToolchain.native_filename)
+    cross_content = client.load(MesonToolchain.cross_filename)
     expected_native = textwrap.dedent("""
     [binaries]
     c = 'clang'
@@ -640,9 +639,23 @@ def test_meson_sysroot_app():
                  "host": profile})
     client.run("install . -pr:h host -pr:b build")
     # Check the meson configuration file
-    conan_meson = client.load(os.path.join(client.current_folder, "conan_meson_cross.ini"))
+    conan_meson = client.load("conan_meson_cross.ini")
     assert f"sys_root = '{sysroot}'\n" in conan_meson
     assert re.search(r"c_args =.+--sysroot={}.+".format(sysroot), conan_meson)
     assert re.search(r"c_link_args =.+--sysroot={}.+".format(sysroot), conan_meson)
     assert re.search(r"cpp_args =.+--sysroot={}.+".format(sysroot), conan_meson)
     assert re.search(r"cpp_link_args =.+--sysroot={}.+".format(sysroot), conan_meson)
+
+
+def test_cross_x86_64_to_x86():
+    """
+    https://github.com/conan-io/conan/issues/17261
+    """
+
+    c = TestClient()
+    c.save({"conanfile.py": GenConanfile().with_settings("os", "compiler", "arch", "build_type")})
+    c.run("install . -g MesonToolchain -s arch=x86 -s:b arch=x86_64")
+    assert not os.path.exists(os.path.join(c.current_folder, MesonToolchain.native_filename))
+    cross = c.load(MesonToolchain.cross_filename)
+    assert "cpu = 'x86_64'" in cross  # This is the build machine
+    assert "cpu = 'x86'" in cross  # This is the host machine
diff --git a/test/integration/tools/ros/test_rosenv.py b/test/integration/tools/ros/test_rosenv.py
index 2865fb6c4..987558edc 100644
--- a/test/integration/tools/ros/test_rosenv.py
+++ b/test/integration/tools/ros/test_rosenv.py
@@ -32,9 +32,12 @@ def test_rosenv():
     assert os.path.exists(conanrosenv_path)
     conanrosenvbuild_path = os.path.join(install_folder, "conanrosenv-build.sh")
     assert os.path.exists(conanrosenvbuild_path)
-    client.run_command(f". \"{conanrosenv_path}\" && env")
     toolchain_path = os.path.join(client.current_folder, "install", "conan", "conan_toolchain.cmake")
-    assert f"CMAKE_TOOLCHAIN_FILE=\"{toolchain_path}\"" in client.out
+    content = client.load(conanrosenvbuild_path)
+    assert f'CMAKE_TOOLCHAIN_FILE="{toolchain_path}"' in content
+    assert 'CMAKE_BUILD_TYPE="Release"' in content
+    client.run_command(f'. "{conanrosenv_path}" && env')
+    assert f"CMAKE_TOOLCHAIN_FILE={toolchain_path}" in client.out
     assert "CMAKE_BUILD_TYPE=Release" in client.out