Repository: conan-io/conan
Pull request #15382 (2024-01-03 16:56:11)

Add built in runtime deployer
Fix https://github.com/conan-io/conan/issues/15381

This PR is currently a draft, only tested manually on windows with:
```
conan install --requires=zlib/1.3 --requires=cmake/3.28.1 -of C:\Users\florian.degaulejac\tmp\zlib-cmake --deployer runtime_deploy.py -vtrace --deployer-folder C:\Users\florian.degaulejac\tmp\zlib-cmake\deploy -o "zlib/*:shared=True"
```

Remaining tasks that I won't have the time to complete:

- [ ]  write autotest instead of manual test
- [ ] test other env (linux, apple...)
- [ ] symbolic links
- [ ] test with deep hierarchy and check it is flatten

And a weird behavior I observed: dep.cpp_info.bindirs and dep.cpp_info.libdirs are populated with absolute paths instead of relative path like described in the documentation.

Docs: https://github.com/conan-io/docs/pull/XXXX

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [ ] I've followed the PEP8 style guides for Python code.
- [ ] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one.


CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/conan-io/conan?pullRequest=15382) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/conan-io/conan?pullRequest=15382) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/conan-io/conan?pullRequest=15382) it.</sub>
fdgStilla: > Do you think you could add some basic, simple test? Or do you want me to contribute it? No prob, I can help with that.

I am currently struggling to migrate all our projects to conan 2 and I won't have the time to do work more to this PR so any contribution is more than welcome!
memsharded: Started to add some tests and minor code changes
memsharded: Sorry for the delay, things have been a bit busy, and this was stuck in the backlog.

I have added some missing things:
- Components support
- Output scope
- Avoid unnecessary copies to speed up repeated deploys

Ready to move this for next 2.5

Patch:
diff --git a/conan/api/conan_api.py b/conan/api/conan_api.py
index 83760430c..0a922501f 100644
--- a/conan/api/conan_api.py
+++ b/conan/api/conan_api.py
@@ -22,7 +22,7 @@ from conans.client.migrations import ClientMigrator
 from conans.client.userio import init_colorama
 from conans.errors import ConanException
 from conans.model.version import Version
-from conans.paths import get_conan_user_home
+from conan.internal.paths import get_conan_user_home
 
 
 class ConanAPI(object):
diff --git a/conan/cli/commands/build.py b/conan/cli/commands/build.py
index 2212e5f79..bf1543a86 100644
--- a/conan/cli/commands/build.py
+++ b/conan/cli/commands/build.py
@@ -23,7 +23,8 @@ def build(conan_api, parser, *args):
     parser.add_argument("-of", "--output-folder",
                         help='The root output folder for generated and build files')
     parser.add_argument("-d", "--deployer", action="append",
-                        help='Deploy using the provided deployer to the output folder')
+                        help="Deploy using the provided deployer to the output folder. "
+                             "Built-in deployers: 'full_deploy', 'direct_deploy', 'runtime_deploy'")
     parser.add_argument("--deployer-folder",
                         help="Deployer output folder, base build folder by default if not set")
     parser.add_argument("--build-require", action='store_true', default=False,
diff --git a/conan/cli/commands/graph.py b/conan/cli/commands/graph.py
index c5fb5f168..85d7cb510 100644
--- a/conan/cli/commands/graph.py
+++ b/conan/cli/commands/graph.py
@@ -175,7 +175,10 @@ def graph_info(conan_api, parser, subparser, *args):
     subparser.add_argument("--package-filter", action="append",
                            help='Print information only for packages that match the patterns')
     subparser.add_argument("-d", "--deployer", action="append",
-                           help='Deploy using the provided deployer to the output folder')
+                           help="Deploy using the provided deployer to the output folder. "
+                                "Built-in deployers: 'full_deploy', 'direct_deploy'. Deployers "
+                                "will only deploy recipes, as 'conan graph info' do not retrieve "
+                                "binaries")
     subparser.add_argument("-df", "--deployer-folder",
                            help="Deployer output folder, base build folder by default if not set")
     subparser.add_argument("--build-require", action='store_true', default=False,
diff --git a/conan/cli/commands/install.py b/conan/cli/commands/install.py
index cad3168a5..703e022ea 100644
--- a/conan/cli/commands/install.py
+++ b/conan/cli/commands/install.py
@@ -30,7 +30,8 @@ def install(conan_api, parser, *args):
     parser.add_argument("-of", "--output-folder",
                         help='The root output folder for generated and build files')
     parser.add_argument("-d", "--deployer", action="append",
-                        help='Deploy using the provided deployer to the output folder')
+                        help="Deploy using the provided deployer to the output folder. "
+                             "Built-in deployers: 'full_deploy', 'direct_deploy', 'runtime_deploy'")
     parser.add_argument("--deployer-folder",
                         help="Deployer output folder, base build folder by default if not set")
     parser.add_argument("--deployer-package", action="append",
diff --git a/conan/internal/cache/conan_reference_layout.py b/conan/internal/cache/conan_reference_layout.py
index 3a4aab9b0..9933dcbbb 100644
--- a/conan/internal/cache/conan_reference_layout.py
+++ b/conan/internal/cache/conan_reference_layout.py
@@ -2,7 +2,7 @@ import os
 from contextlib import contextmanager
 
 from conans.model.manifest import FileTreeManifest
-from conans.paths import CONANFILE, DATA_YML
+from conan.internal.paths import CONANFILE, DATA_YML
 from conans.util.files import set_dirty, clean_dirty, is_dirty, rmdir
 
 
diff --git a/conan/internal/deploy.py b/conan/internal/deploy.py
index 9631645ff..d5f04693d 100644
--- a/conan/internal/deploy.py
+++ b/conan/internal/deploy.py
@@ -1,3 +1,4 @@
+import filecmp
 import os
 import shutil
 
@@ -31,7 +32,8 @@ def _find_deployer(d, cache_deploy_folder):
     if os.path.isfile(cache_path):
         return _load(cache_path)
     builtin_deploy = {"full_deploy.py": full_deploy,
-                      "direct_deploy.py": direct_deploy}.get(d)
+                      "direct_deploy.py": direct_deploy,
+                      "runtime_deploy.py": runtime_deploy}.get(d)
     if builtin_deploy is not None:
         return builtin_deploy
     raise ConanException(f"Cannot find deployer '{d}'")
@@ -87,6 +89,75 @@ def full_deploy(graph, output_folder):
         _deploy_single(dep, conanfile, output_folder, folder_name)
 
 
+def runtime_deploy(graph, output_folder):
+    """
+    Deploy all the shared libraries and the executables of the dependencies in a flat directory.
+    """
+    conanfile = graph.root.conanfile
+    output = ConanOutput(scope="runtime_deploy")
+    output.info(f"Deploying dependencies runtime to folder: {output_folder}")
+    output.warning("This deployer is experimental and subject to change. "
+                   "Please give feedback at https://github.com/conan-io/conan/issues")
+    mkdir(output_folder)
+    symlinks = conanfile.conf.get("tools.deployer:symlinks", check_type=bool, default=True)
+    for _, dep in conanfile.dependencies.host.items():
+        if dep.package_folder is None:
+            output.warning(f"{dep.ref} does not have any package folder, skipping binary")
+            continue
+        count = 0
+        cpp_info = dep.cpp_info.aggregated_components()
+        for bindir in cpp_info.bindirs:
+            if not os.path.isdir(bindir):
+                output.warning(f"{dep.ref} {bindir} does not exist")
+                continue
+            count += _flatten_directory(dep, bindir, output_folder, symlinks)
+
+        for libdir in cpp_info.libdirs:
+            if not os.path.isdir(libdir):
+                output.warning(f"{dep.ref} {libdir} does not exist")
+                continue
+            count += _flatten_directory(dep, libdir, output_folder, symlinks, [".dylib", ".so"])
+
+        output.info(f"Copied {count} files from {dep.ref}")
+    conanfile.output.success(f"Runtime deployed to folder: {output_folder}")
+
+
+def _flatten_directory(dep, src_dir, output_dir, symlinks, extension_filter=None):
+    """
+    Copy all the files from the source directory in a flat output directory.
+    An optional string, named extension_filter, can be set to copy only the files with
+    the listed extensions.
+    """
+    file_count = 0
+
+    output = ConanOutput(scope="runtime_deploy")
+    for src_dirpath, _, src_filenames in os.walk(src_dir, followlinks=symlinks):
+        for src_filename in src_filenames:
+            if extension_filter and not any(src_filename.endswith(ext) for ext in extension_filter):
+                continue
+
+            src_filepath = os.path.join(src_dirpath, src_filename)
+            dest_filepath = os.path.join(output_dir, src_filename)
+            if os.path.exists(dest_filepath):
+                if filecmp.cmp(src_filepath, dest_filepath):  # Be efficient, do not copy
+                    output.verbose(f"{dest_filepath} exists with same contents, skipping copy")
+                    continue
+                else:
+                    output.warning(f"{dest_filepath} exists and will be overwritten")
+
+            try:
+                file_count += 1
+                shutil.copy2(src_filepath, dest_filepath, follow_symlinks=symlinks)
+                output.verbose(f"Copied {src_filepath} into {output_dir}")
+            except Exception as e:
+                if "WinError 1314" in str(e):
+                    ConanOutput().error("runtime_deploy: Windows symlinks require admin privileges "
+                                        "or 'Developer mode = ON'", error_type="exception")
+                raise ConanException(f"runtime_deploy: Copy of '{dep}' files failed: {e}.\nYou can "
+                                     f"use 'tools.deployer:symlinks' conf to disable symlinks")
+    return file_count
+
+
 def _deploy_single(dep, conanfile, output_folder, folder_name):
     new_folder = os.path.join(output_folder, folder_name)
     rmdir(new_folder)
diff --git a/conans/client/cmd/export.py b/conans/client/cmd/export.py
index 93ae8bc26..b503ac474 100644
--- a/conans/client/cmd/export.py
+++ b/conans/client/cmd/export.py
@@ -7,7 +7,7 @@ from conan.tools.scm import Git
 from conans.errors import ConanException, conanfile_exception_formatter
 from conans.model.manifest import FileTreeManifest
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import DATA_YML
+from conan.internal.paths import DATA_YML
 from conans.util.files import is_dirty, rmdir, set_dirty, mkdir, clean_dirty, chdir
 
 
diff --git a/conans/client/cmd/uploader.py b/conans/client/cmd/uploader.py
index 424e100ff..cff1385a9 100644
--- a/conans/client/cmd/uploader.py
+++ b/conans/client/cmd/uploader.py
@@ -6,7 +6,7 @@ from conan.internal.conan_app import ConanApp
 from conan.api.output import ConanOutput
 from conans.client.source import retrieve_exports_sources
 from conans.errors import ConanException, NotFoundException
-from conans.paths import (CONAN_MANIFEST, CONANFILE, EXPORT_SOURCES_TGZ_NAME,
+from conan.internal.paths import (CONAN_MANIFEST, CONANFILE, EXPORT_SOURCES_TGZ_NAME,
                           EXPORT_TGZ_NAME, PACKAGE_TGZ_NAME, CONANINFO)
 from conans.util.files import (clean_dirty, is_dirty, gather_files,
                                gzopen_without_timestamps, set_dirty_context_manager, mkdir,
diff --git a/conans/client/conanfile/package.py b/conans/client/conanfile/package.py
index 3ee44ab39..12745e6bd 100644
--- a/conans/client/conanfile/package.py
+++ b/conans/client/conanfile/package.py
@@ -4,7 +4,7 @@ from conan.api.output import ConanOutput
 from conans.errors import ConanException, conanfile_exception_formatter, conanfile_remove_attr
 from conans.model.manifest import FileTreeManifest
 from conans.model.package_ref import PkgReference
-from conans.paths import CONANINFO
+from conan.internal.paths import CONANINFO
 from conans.util.files import save, mkdir, chdir
 
 
diff --git a/conans/client/installer.py b/conans/client/installer.py
index ce4755728..20198cc03 100644
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -13,7 +13,7 @@ from conans.client.source import retrieve_exports_sources, config_source
 from conans.errors import (ConanException, conanfile_exception_formatter, conanfile_remove_attr)
 from conans.model.build_info import CppInfo, MockInfoProperty
 from conans.model.package_ref import PkgReference
-from conans.paths import CONANINFO
+from conan.internal.paths import CONANINFO
 from conans.util.files import clean_dirty, is_dirty, mkdir, rmdir, save, set_dirty, chdir
 
 
diff --git a/conans/client/loader.py b/conans/client/loader.py
index 65f0c61bd..3eae33874 100644
--- a/conans/client/loader.py
+++ b/conans/client/loader.py
@@ -20,7 +20,7 @@ from conans.errors import ConanException, NotFoundException, conanfile_exception
 from conans.model.conan_file import ConanFile
 from conans.model.options import Options
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import DATA_YML
+from conan.internal.paths import DATA_YML
 from conans.util.files import load, chdir, load_user_encoded
 
 
diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py
index 51ce2e2d1..9aea240a6 100644
--- a/conans/client/remote_manager.py
+++ b/conans/client/remote_manager.py
@@ -16,7 +16,7 @@ from conans.model.info import load_binary_info
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
 from conans.util.files import rmdir, human_size
-from conans.paths import EXPORT_SOURCES_TGZ_NAME, EXPORT_TGZ_NAME, PACKAGE_TGZ_NAME
+from conan.internal.paths import EXPORT_SOURCES_TGZ_NAME, EXPORT_TGZ_NAME, PACKAGE_TGZ_NAME
 from conans.util.files import mkdir, tar_extract
 
 
diff --git a/conans/client/rest/rest_client_v2.py b/conans/client/rest/rest_client_v2.py
index cc05c3038..2e46de8de 100644
--- a/conans/client/rest/rest_client_v2.py
+++ b/conans/client/rest/rest_client_v2.py
@@ -11,7 +11,7 @@ from conans.client.rest.rest_client_common import RestCommonMethods, get_excepti
 from conans.errors import ConanException, NotFoundException, PackageNotFoundException, \
     RecipeNotFoundException, AuthenticationException, ForbiddenException
 from conans.model.package_ref import PkgReference
-from conans.paths import EXPORT_SOURCES_TGZ_NAME
+from conan.internal.paths import EXPORT_SOURCES_TGZ_NAME
 from conans.util.dates import from_iso8601_to_timestamp
 from conans.util.thread import ExceptionThread
 
diff --git a/conans/model/manifest.py b/conans/model/manifest.py
index c3c10737f..06ec8daa5 100644
--- a/conans/model/manifest.py
+++ b/conans/model/manifest.py
@@ -1,7 +1,7 @@
 import os
 from collections import defaultdict
 
-from conans.paths import CONAN_MANIFEST, EXPORT_SOURCES_TGZ_NAME, EXPORT_TGZ_NAME, PACKAGE_TGZ_NAME
+from conan.internal.paths import CONAN_MANIFEST, EXPORT_SOURCES_TGZ_NAME, EXPORT_TGZ_NAME, PACKAGE_TGZ_NAME
 from conans.util.dates import timestamp_now, timestamp_to_str
 from conans.util.files import load, md5, md5sum, save, gather_files
 
diff --git a/conans/search/search.py b/conans/search/search.py
index aae814937..c0adea1e7 100644
--- a/conans/search/search.py
+++ b/conans/search/search.py
@@ -8,7 +8,7 @@ from conans.errors import ConanException
 from conans.model.info import load_binary_info
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANINFO
+from conan.internal.paths import CONANINFO
 from conans.search.query_parse import evaluate_postfix, infix_to_postfix
 from conans.util.files import load
 
diff --git a/conans/server/conf/__init__.py b/conans/server/conf/__init__.py
index 348ee124d..a1247e10a 100644
--- a/conans/server/conf/__init__.py
+++ b/conans/server/conf/__init__.py
@@ -9,7 +9,7 @@ from datetime import timedelta
 from configparser import ConfigParser, NoSectionError
 
 from conans.errors import ConanException
-from conans.paths import conan_expand_user
+from conan.internal.paths import conan_expand_user
 from conans.server.conf.default_server_conf import default_server_conf
 from conans.server.store.disk_adapter import ServerDiskAdapter
 from conans.server.store.server_store import ServerStore
diff --git a/conans/server/launcher.py b/conans/server/launcher.py
index 7fde4d390..85247ad83 100644
--- a/conans/server/launcher.py
+++ b/conans/server/launcher.py
@@ -3,7 +3,7 @@ import os
 import sys
 
 from conans import REVISIONS
-from conans.paths import conan_expand_user
+from conan.internal.paths import conan_expand_user
 from conans.server import SERVER_CAPABILITIES
 from conans.server.conf import get_server_store
 
diff --git a/conans/server/service/v2/search.py b/conans/server/service/v2/search.py
index 0a02134de..66ec092ff 100644
--- a/conans/server/service/v2/search.py
+++ b/conans/server/service/v2/search.py
@@ -6,7 +6,7 @@ from fnmatch import translate
 from conans.errors import ForbiddenException, RecipeNotFoundException
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANINFO
+from conan.internal.paths import CONANINFO
 from conans.search.search import _partial_match
 from conans.server.utils.files import list_folder_subdirs
 from conans.util.files import load
diff --git a/conans/server/service/v2/service_v2.py b/conans/server/service/v2/service_v2.py
index 021c2c402..be37b5d68 100644
--- a/conans/server/service/v2/service_v2.py
+++ b/conans/server/service/v2/service_v2.py
@@ -4,7 +4,7 @@ import os
 from bottle import FileUpload, static_file
 
 from conans.errors import RecipeNotFoundException, PackageNotFoundException, NotFoundException
-from conans.paths import CONAN_MANIFEST
+from conan.internal.paths import CONAN_MANIFEST
 from conans.model.package_ref import PkgReference
 from conans.server.service.mime import get_mime_type
 from conans.server.store.server_store import ServerStore
diff --git a/conans/server/store/server_store.py b/conans/server/store/server_store.py
index f103ba2a3..e79e956a3 100644
--- a/conans/server/store/server_store.py
+++ b/conans/server/store/server_store.py
@@ -2,7 +2,7 @@ import os
 from os.path import join, normpath, relpath
 
 from conans.errors import ConanException, PackageNotFoundException, RecipeNotFoundException
-from conans.paths import CONAN_MANIFEST
+from conan.internal.paths import CONAN_MANIFEST
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
 from conans.server.revision_list import RevisionList


Test patch:
diff --git a/conans/paths/__init__.py b/conan/internal/paths.py
similarity index 100%
rename from conans/paths/__init__.py
rename to conan/internal/paths.py
diff --git a/conan/test/utils/test_files.py b/conan/test/utils/test_files.py
index c35f556ed..fa88b3bf2 100644
--- a/conan/test/utils/test_files.py
+++ b/conan/test/utils/test_files.py
@@ -11,7 +11,7 @@ from io import BytesIO
 from conan.tools.files.files import untargz
 from conans.client.subsystems import get_cased_path
 from conans.errors import ConanException
-from conans.paths import PACKAGE_TGZ_NAME
+from conan.internal.paths import PACKAGE_TGZ_NAME
 from conans.util.files import gzopen_without_timestamps
 
 
diff --git a/test/functional/command/config_install_test.py b/test/functional/command/config_install_test.py
index 073baa852..5e5d668c5 100644
--- a/test/functional/command/config_install_test.py
+++ b/test/functional/command/config_install_test.py
@@ -10,7 +10,7 @@ from mock import patch
 from conan.api.model import Remote
 from conans.client.conf.config_installer import _hide_password
 from conans.client.downloaders.file_downloader import FileDownloader
-from conans.paths import DEFAULT_CONAN_HOME
+from conan.internal.paths import DEFAULT_CONAN_HOME
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.file_server import TestFileServer
 from conan.test.utils.test_files import scan_folder, temp_folder, tgz_with_contents
diff --git a/test/functional/command/test_install_deploy.py b/test/functional/command/test_install_deploy.py
index 24bb1bd63..1967e4b48 100644
--- a/test/functional/command/test_install_deploy.py
+++ b/test/functional/command/test_install_deploy.py
@@ -435,3 +435,57 @@ def test_not_deploy_absolute_paths():
 
     env = c.load("conanbuildenv-release-x86_64.sh")
     assert f'export MYPATH="{some_abs_path}/mypath"' in env
+
+
+class TestRuntimeDeployer:
+    def test_runtime_deploy(self):
+        c = TestClient()
+        conanfile = textwrap.dedent("""
+           from conan import ConanFile
+           from conan.tools.files import copy
+           class Pkg(ConanFile):
+               def package(self):
+                   copy(self, "*.so", src=self.build_folder, dst=self.package_folder)
+                   copy(self, "*.dll", src=self.build_folder, dst=self.package_folder)
+           """)
+        c.save({"pkga/conanfile.py": conanfile,
+                "pkga/lib/pkga.so": "",
+                "pkga/bin/pkga.dll": "",
+                "pkgb/conanfile.py": conanfile,
+                "pkgb/lib/pkgb.so": ""})
+        c.run("export-pkg pkga --name=pkga --version=1.0")
+        c.run("export-pkg pkgb --name=pkgb --version=1.0")
+        c.run("install --requires=pkga/1.0 --requires=pkgb/1.0 --deployer=runtime_deploy "
+              "--deployer-folder=myruntime -vvv")
+
+        expected = sorted(["pkga.so", "pkgb.so", "pkga.dll"])
+        assert sorted(os.listdir(os.path.join(c.current_folder, "myruntime"))) == expected
+
+    def test_runtime_deploy_components(self):
+        c = TestClient()
+        conanfile = textwrap.dedent("""
+            import os
+            from conan import ConanFile
+            from conan.tools.files import copy
+            class Pkg(ConanFile):
+               def package(self):
+                   copy(self, "*.so", src=self.build_folder,
+                        dst=os.path.join(self.package_folder, "a"))
+                   copy(self, "*.dll", src=self.build_folder,
+                        dst=os.path.join(self.package_folder, "b"))
+               def package_info(self):
+                   self.cpp_info.components["a"].libdirs = ["a"]
+                   self.cpp_info.components["b"].bindirs = ["b"]
+           """)
+        c.save({"pkga/conanfile.py": conanfile,
+                "pkga/lib/pkga.so": "",
+                "pkga/bin/pkga.dll": "",
+                "pkgb/conanfile.py": conanfile,
+                "pkgb/lib/pkgb.so": ""})
+        c.run("export-pkg pkga --name=pkga --version=1.0")
+        c.run("export-pkg pkgb --name=pkgb --version=1.0")
+        c.run("install --requires=pkga/1.0 --requires=pkgb/1.0 --deployer=runtime_deploy "
+              "--deployer-folder=myruntime -vvv")
+
+        expected = sorted(["pkga.so", "pkgb.so", "pkga.dll"])
+        assert sorted(os.listdir(os.path.join(c.current_folder, "myruntime"))) == expected
diff --git a/test/integration/build_requires/profile_build_requires_test.py b/test/integration/build_requires/profile_build_requires_test.py
index cda554a1e..1d7c9c4a3 100644
--- a/test/integration/build_requires/profile_build_requires_test.py
+++ b/test/integration/build_requires/profile_build_requires_test.py
@@ -3,7 +3,7 @@ import platform
 import textwrap
 import unittest
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.utils.tools import TestClient, GenConanfile
 
 
diff --git a/test/integration/command/export/export_test.py b/test/integration/command/export/export_test.py
index 33f6ff3d1..ea2485ac1 100644
--- a/test/integration/command/export/export_test.py
+++ b/test/integration/command/export/export_test.py
@@ -10,7 +10,7 @@ from parameterized import parameterized
 
 from conans.model.manifest import FileTreeManifest
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE, CONAN_MANIFEST
+from conan.internal.paths import CONANFILE, CONAN_MANIFEST
 from conan.test.utils.tools import TestClient, GenConanfile
 from conans.util.files import load, save
 
diff --git a/test/integration/command/export_pkg_test.py b/test/integration/command/export_pkg_test.py
index bb6f4cb13..6ed19891b 100644
--- a/test/integration/command/export_pkg_test.py
+++ b/test/integration/command/export_pkg_test.py
@@ -6,7 +6,7 @@ import textwrap
 import unittest
 from textwrap import dedent
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.utils.tools import TestClient, GenConanfile
 from conans.util.files import load
 
diff --git a/test/integration/command/info/test_info_folders.py b/test/integration/command/info/test_info_folders.py
index d29b3f56c..464a02e65 100644
--- a/test/integration/command/info/test_info_folders.py
+++ b/test/integration/command/info/test_info_folders.py
@@ -3,7 +3,7 @@ import textwrap
 import json
 import pytest
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.utils.tools import TestClient
 from conan.internal.cache.conan_reference_layout import EXPORT_FOLDER
 
diff --git a/test/integration/command/install/test_install_transitive.py b/test/integration/command/install/test_install_transitive.py
index 3f82cdb0a..017ce6c57 100644
--- a/test/integration/command/install/test_install_transitive.py
+++ b/test/integration/command/install/test_install_transitive.py
@@ -4,7 +4,7 @@ import pytest
 
 from conans.model.info import load_binary_info
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE_TXT, CONANINFO
+from conan.internal.paths import CONANFILE_TXT, CONANINFO
 from conan.test.utils.tools import TestClient,  GenConanfile
 from conans.util.files import save, load
 
diff --git a/test/integration/command/source_test.py b/test/integration/command/source_test.py
index d04bf0074..c856d4627 100644
--- a/test/integration/command/source_test.py
+++ b/test/integration/command/source_test.py
@@ -6,7 +6,7 @@ from collections import OrderedDict
 
 import pytest
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.tools import TestClient, TestServer
 from conans.util.files import save
diff --git a/test/integration/command/test_package_test.py b/test/integration/command/test_package_test.py
index 6b8cc8f21..727fa9872 100644
--- a/test/integration/command/test_package_test.py
+++ b/test/integration/command/test_package_test.py
@@ -4,7 +4,7 @@ import textwrap
 import unittest
 
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, GenConanfile
 from conans.util.files import load
 
diff --git a/test/integration/command/upload/syncronize_test.py b/test/integration/command/upload/syncronize_test.py
index ddeede375..27dd539e1 100644
--- a/test/integration/command/upload/syncronize_test.py
+++ b/test/integration/command/upload/syncronize_test.py
@@ -4,7 +4,7 @@ import unittest
 from conan.tools.files.files import untargz  # FIXME: DO not import from tools
 from conans.model.manifest import FileTreeManifest
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import EXPORT_TGZ_NAME
+from conan.internal.paths import EXPORT_TGZ_NAME
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.test_files import temp_folder
 from conan.test.utils.tools import TestClient, TestServer
diff --git a/test/integration/command/upload/upload_complete_test.py b/test/integration/command/upload/upload_complete_test.py
index 79b23a579..becb690db 100644
--- a/test/integration/command/upload/upload_complete_test.py
+++ b/test/integration/command/upload/upload_complete_test.py
@@ -3,7 +3,7 @@ import unittest
 
 from requests import ConnectionError
 
-from conans.paths import CONAN_MANIFEST
+from conan.internal.paths import CONAN_MANIFEST
 from conan.test.utils.tools import (TestClient, TestRequester, TestServer,
                                      GenConanfile)
 from conans.util.env import environment_update
diff --git a/test/integration/command/upload/upload_test.py b/test/integration/command/upload/upload_test.py
index d77ed839b..1e344ae45 100644
--- a/test/integration/command/upload/upload_test.py
+++ b/test/integration/command/upload/upload_test.py
@@ -13,7 +13,7 @@ from requests import Response
 from conans.errors import ConanException
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import EXPORT_SOURCES_TGZ_NAME, PACKAGE_TGZ_NAME
+from conan.internal.paths import EXPORT_SOURCES_TGZ_NAME, PACKAGE_TGZ_NAME
 from conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, TestServer, \
     TurboTestClient, GenConanfile, TestRequester, TestingResponse
 from conans.util.files import gzopen_without_timestamps, is_dirty, save, set_dirty
diff --git a/test/integration/configuration/default_profile_test.py b/test/integration/configuration/default_profile_test.py
index 4b39c8e45..d8a98eab8 100644
--- a/test/integration/configuration/default_profile_test.py
+++ b/test/integration/configuration/default_profile_test.py
@@ -2,7 +2,7 @@ import os
 import textwrap
 import unittest
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.test_files import temp_folder
 from conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient
diff --git a/test/integration/configuration/profile_test.py b/test/integration/configuration/profile_test.py
index d47dba871..c121cdf4c 100644
--- a/test/integration/configuration/profile_test.py
+++ b/test/integration/configuration/profile_test.py
@@ -9,7 +9,7 @@ from textwrap import dedent
 import pytest
 from parameterized import parameterized
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.profiles import create_profile as _create_profile
 from conan.test.utils.test_files import temp_folder
diff --git a/test/integration/remote/auth_test.py b/test/integration/remote/auth_test.py
index d5cdd2333..e95969854 100644
--- a/test/integration/remote/auth_test.py
+++ b/test/integration/remote/auth_test.py
@@ -8,7 +8,7 @@ from requests.models import Response
 from conans.client.store.localdb import LocalDB
 from conans.errors import AuthenticationException
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.test_files import temp_folder
 from conan.test.utils.tools import TestClient
diff --git a/test/integration/remote/download_retries_test.py b/test/integration/remote/download_retries_test.py
index 6b5e5cadf..c22176357 100644
--- a/test/integration/remote/download_retries_test.py
+++ b/test/integration/remote/download_retries_test.py
@@ -1,6 +1,6 @@
 import unittest
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.tools import TestClient, TestServer, TestRequester
 
diff --git a/test/integration/remote/multi_remote_test.py b/test/integration/remote/multi_remote_test.py
index 91c21c53d..3ab4d074d 100644
--- a/test/integration/remote/multi_remote_test.py
+++ b/test/integration/remote/multi_remote_test.py
@@ -3,7 +3,7 @@ from collections import OrderedDict
 from time import sleep
 
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.tools import TestClient, TestServer
 
diff --git a/test/integration/remote/rest_api_test.py b/test/integration/remote/rest_api_test.py
index 9d9e81ae5..736e48d28 100644
--- a/test/integration/remote/rest_api_test.py
+++ b/test/integration/remote/rest_api_test.py
@@ -15,7 +15,7 @@ from conans.client.userio import UserInput
 from conans.model.manifest import FileTreeManifest
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE, CONANINFO, CONAN_MANIFEST
+from conan.internal.paths import CONANFILE, CONANINFO, CONAN_MANIFEST
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.mocks import LocalDBMock
 from conan.test.utils.server_launcher import TestServerLauncher
diff --git a/test/integration/settings/settings_override_test.py b/test/integration/settings/settings_override_test.py
index c5c26f1c5..e1959a2bf 100644
--- a/test/integration/settings/settings_override_test.py
+++ b/test/integration/settings/settings_override_test.py
@@ -3,7 +3,7 @@ import os
 import pytest
 
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANINFO
+from conan.internal.paths import CONANINFO
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.tools import TestClient
 from conans.util.files import load
diff --git a/test/integration/symlinks/symlinks_test.py b/test/integration/symlinks/symlinks_test.py
index 407f4c572..2ceb7bd8b 100644
--- a/test/integration/symlinks/symlinks_test.py
+++ b/test/integration/symlinks/symlinks_test.py
@@ -5,7 +5,7 @@ import textwrap
 import pytest
 
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import PACKAGE_TGZ_NAME
+from conan.internal.paths import PACKAGE_TGZ_NAME
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.test_files import temp_folder
 from conan.test.utils.tools import TestClient, TestServer, TurboTestClient
diff --git a/test/integration/tgz_macos_dot_files_test.py b/test/integration/tgz_macos_dot_files_test.py
index 082a0ed84..8da10dae7 100644
--- a/test/integration/tgz_macos_dot_files_test.py
+++ b/test/integration/tgz_macos_dot_files_test.py
@@ -10,7 +10,7 @@ import pytest
 
 from conans.client.remote_manager import uncompress_file
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import EXPORT_SOURCES_TGZ_NAME
+from conan.internal.paths import EXPORT_SOURCES_TGZ_NAME
 from conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID
 
 
diff --git a/test/integration/ui/exit_with_code_test.py b/test/integration/ui/exit_with_code_test.py
index a75297c90..5613ccb22 100644
--- a/test/integration/ui/exit_with_code_test.py
+++ b/test/integration/ui/exit_with_code_test.py
@@ -1,6 +1,6 @@
 import unittest
 
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.utils.tools import TestClient
 from conans.util.files import save
 
diff --git a/test/unittests/client/remote_manager_test.py b/test/unittests/client/remote_manager_test.py
index 966b0e608..e0438bcd8 100644
--- a/test/unittests/client/remote_manager_test.py
+++ b/test/unittests/client/remote_manager_test.py
@@ -2,7 +2,7 @@ import os
 import unittest
 
 from conans.client.cmd.uploader import compress_files
-from conans.paths import PACKAGE_TGZ_NAME
+from conan.internal.paths import PACKAGE_TGZ_NAME
 from conan.test.utils.test_files import temp_folder
 from conans.util.files import save
 
diff --git a/test/unittests/model/other_settings_test.py b/test/unittests/model/other_settings_test.py
index bbd309c98..5c04a50bd 100644
--- a/test/unittests/model/other_settings_test.py
+++ b/test/unittests/model/other_settings_test.py
@@ -4,7 +4,7 @@ import unittest
 
 from conans.model.info import load_binary_info
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANFILE
+from conan.internal.paths import CONANFILE
 from conan.test.utils.tools import TestClient
 from conans.util.files import load, save
 
diff --git a/test/unittests/paths/user_home_test.py b/test/unittests/paths/user_home_test.py
index 61b28eddf..50f2b800e 100644
--- a/test/unittests/paths/user_home_test.py
+++ b/test/unittests/paths/user_home_test.py
@@ -2,7 +2,7 @@ import os
 import platform
 from pathlib import Path
 
-from conans.paths import get_conan_user_home, DEFAULT_CONAN_HOME
+from conan.internal.paths import get_conan_user_home, DEFAULT_CONAN_HOME
 from conan.test.utils.test_files import temp_folder
 from conans.util.files import chdir
 
diff --git a/test/unittests/server/conf_test.py b/test/unittests/server/conf_test.py
index d2d1f91a3..54b274c1c 100644
--- a/test/unittests/server/conf_test.py
+++ b/test/unittests/server/conf_test.py
@@ -3,7 +3,7 @@ import unittest
 from datetime import timedelta
 
 from conans.errors import ConanException
-from conans.paths import conan_expand_user
+from conan.internal.paths import conan_expand_user
 from conans.server.conf import ConanServerConfigParser
 from conan.test.utils.test_files import temp_folder
 from conans.util.config_parser import ConfigParser
diff --git a/test/unittests/server/service/service_test.py b/test/unittests/server/service/service_test.py
index fbdcbe8cb..80c50943f 100644
--- a/test/unittests/server/service/service_test.py
+++ b/test/unittests/server/service/service_test.py
@@ -6,7 +6,7 @@ from conans.errors import NotFoundException
 from conans.model.manifest import FileTreeManifest
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
-from conans.paths import CONANINFO, CONAN_MANIFEST
+from conan.internal.paths import CONANINFO, CONAN_MANIFEST
 from conans.server.service.authorize import BasicAuthorizer
 from conans.server.service.v2.search import SearchService
 from conans.server.service.v2.service_v2 import ConanServiceV2