Repository: conan-io/conan
Pull request #16617 (2024-07-05 09:18:41)

Refactor/conans2conan
Changelog: Omit
Docs: Omit

Pure refactor conans -> conan


Patch:
diff --git a/conan/api/subapi/install.py b/conan/api/subapi/install.py
index 5a5b677f6..26bc0e202 100644
--- a/conan/api/subapi/install.py
+++ b/conan/api/subapi/install.py
@@ -1,8 +1,9 @@
 import os
 
+from conan.internal.api.install.generators import write_generators
 from conan.internal.conan_app import ConanApp
 from conan.internal.deploy import do_deploys
-from conans.client.generators import write_generators
+
 from conans.client.graph.install_graph import InstallGraph
 from conans.client.installer import BinaryInstaller
 from conans.errors import ConanInvalidConfiguration
diff --git a/conan/api/subapi/local.py b/conan/api/subapi/local.py
index 27ed46e00..224ef3dcd 100644
--- a/conan/api/subapi/local.py
+++ b/conan/api/subapi/local.py
@@ -1,9 +1,8 @@
 import os
 
-from conan.api.output import ConanOutput
 from conan.cli import make_abs_path
 from conan.internal.conan_app import ConanApp
-from conans.client.cache.editable import EditablePackages
+from conan.internal.api.local.editable import EditablePackages
 from conans.client.conanfile.build import run_build_method
 from conans.client.graph.graph import CONTEXT_HOST
 from conans.client.graph.profile_node_definer import initialize_conanfile_profile
diff --git a/conan/api/subapi/profiles.py b/conan/api/subapi/profiles.py
index 6184a60cc..62d50fd65 100644
--- a/conan/api/subapi/profiles.py
+++ b/conan/api/subapi/profiles.py
@@ -4,7 +4,7 @@ from conan.api.output import ConanOutput
 from conan.internal.cache.home_paths import HomePaths
 
 from conans.client.loader import load_python_file
-from conans.client.profile_loader import ProfileLoader
+from conan.internal.api.profile.profile_loader import ProfileLoader
 from conans.errors import ConanException, scoped_traceback
 from conans.model.profile import Profile
 
diff --git a/conan/api/subapi/remotes.py b/conan/api/subapi/remotes.py
index 1a54e61be..23b31a225 100644
--- a/conan/api/subapi/remotes.py
+++ b/conan/api/subapi/remotes.py
@@ -9,7 +9,7 @@ from conan.internal.cache.home_paths import HomePaths
 from conan.internal.conan_app import ConanApp
 from conans.client.rest_client_local_recipe_index import add_local_recipes_index_remote, \
     remove_local_recipes_index_remote
-from conans.client.store.localdb import LocalDB
+from conan.internal.api.remotes.localdb import LocalDB
 from conans.errors import ConanException
 from conans.util.files import save, load
 
diff --git a/conan/cli/commands/graph.py b/conan/cli/commands/graph.py
index 85d7cb510..8f4124744 100644
--- a/conan/cli/commands/graph.py
+++ b/conan/cli/commands/graph.py
@@ -8,6 +8,7 @@ from conan.cli.args import common_graph_args, validate_common_graph_args
 from conan.cli.command import conan_command, conan_subcommand
 from conan.cli.commands.list import prepare_pkglist_compact, print_serial
 from conan.cli.formatters.graph import format_graph_html, format_graph_json, format_graph_dot
+from conan.cli.formatters.graph.build_order_html import format_build_order_html
 from conan.cli.formatters.graph.graph_info_text import format_graph_info
 from conan.cli.printers.graph import print_graph_packages, print_graph_basic
 from conan.errors import ConanException
@@ -62,7 +63,8 @@ def json_build_order(build_order):
     cli_out_write(json.dumps(build_order, indent=4))
 
 
-@conan_subcommand(formatters={"text": cli_build_order, "json": json_build_order})
+@conan_subcommand(formatters={"text": cli_build_order, "json": json_build_order,
+                              "html": format_build_order_html})
 def graph_build_order(conan_api, parser, subparser, *args):
     """
     Compute the build order of a dependency graph.
@@ -129,7 +131,8 @@ def graph_build_order(conan_api, parser, subparser, *args):
     return install_order_serialized
 
 
-@conan_subcommand(formatters={"text": cli_build_order, "json": json_build_order})
+@conan_subcommand(formatters={"text": cli_build_order, "json": json_build_order,
+                              "html": format_build_order_html})
 def graph_build_order_merge(conan_api, parser, subparser, *args):
     """
     Merge more than 1 build-order file.
diff --git a/conan/cli/formatters/graph/build_order_html.py b/conan/cli/formatters/graph/build_order_html.py
new file mode 100644
index 000000000..e785bb01b
--- /dev/null
+++ b/conan/cli/formatters/graph/build_order_html.py
@@ -0,0 +1,272 @@
+from jinja2 import select_autoescape, Template
+from conan.api.output import cli_out_write
+
+build_order_html = r"""
+<html lang="en">
+    <head>
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.30.0/cytoscape.min.js"
+        integrity="sha512-zHc90yHSbkgx0bvVpDK/nVgxANlE+yKN/jKy91tZ4P/vId8AL7HyjSpZqHmEujWDWNwxYXcfaLdYWjAULl35MQ=="
+        crossorigin="anonymous"
+        referrerpolicy="no-referrer"></script>
+    </head>
+
+    <body>
+        <style>
+            body {
+                font: 14px helvetica neue, helvetica, arial, sans-serif;
+                display: flex;
+                margin: 0;
+                padding: 0;
+                height: 100vh;
+            }
+
+            .sidebar {
+                background: #f9f9f9;
+                border-right: 1px solid #ccc;
+                padding: 20px;
+                box-sizing: border-box;
+                overflow-y: auto;
+                font-size: 14px;
+                width: 440px;
+            }
+
+            .content {
+                flex-grow: 1;
+                display: flex;
+                flex-direction: column;
+                overflow: hidden;
+            }
+
+            #cy {
+                flex-grow: 1;
+            }
+
+            #node-info {
+                margin-top: 20px;
+                background: #f9f9f9;
+                padding: 12px;
+                font-family: monospace;
+                white-space: pre-wrap;
+                font-size: 12px;
+                word-wrap: break-word;
+            }
+
+            .legend {
+                margin-top: 20px;
+                font-size: 14px;
+            }
+
+            .legend-item {
+                display: flex;
+                align-items: center;
+                margin-bottom: 5px;
+            }
+
+            .legend-color {
+                width: 20px;
+                height: 20px;
+                margin-right: 10px;
+            }
+        </style>
+
+        <div class="sidebar">
+            <div class="legend">
+                <div class="legend-item">
+                    <div class="legend-color" style="background-color: #ffff37;"></div>
+                    <span>All packages need to be built</span>
+                </div>
+                <div class="legend-item">
+                    <div class="legend-color" style="background-color: #ff9b28;"></div>
+                    <span>Some packages need to be built</span>
+                </div>
+                <div class="legend-item">
+                    <div class="legend-color" style="background-color: #70c7e6;"></div>
+                    <span>Cache</span>
+                </div>
+                <div class="legend-item">
+                    <div class="legend-color" style="background-color: #79eb8a;"></div>
+                    <span>Download</span>
+                </div>
+                <div class="legend-item">
+                    <div class="legend-color" style="border: 1px solid black; width: 20px; height: 20px;"></div>
+                    <span>Requirements in the <i>host</i> context</span>
+                </div>
+                <div class="legend-item">
+                    <div class="legend-color" style="border: 1px solid black; border-radius: 50%; width: 20px; height: 20px;"></div>
+                    <span>Requirements in the <i>build</i> context</span>
+                </div>
+            </div>
+            <div id="node-info">
+                <p>Click on a node to see details.</p>
+            </div>
+        </div>
+        <div class="content">
+            <div id="cy"></div>
+        </div>
+
+        <script type="text/javascript">
+            document.addEventListener("DOMContentLoaded", function() {
+                var buildOrderData = {{ build_order | tojson }};
+
+                var elements = [];
+                var edges = [];
+
+                var yOffset = 50;
+                var posX = 0;
+                var posY = 0;
+                var columns = 4;
+
+                buildOrderData.forEach((step, stepIndex) => {
+                    var stepId = 'step' + stepIndex;
+                    elements.push({
+                        data: { id: stepId, label: 'Step ' + (stepIndex + 1) },
+                        position: { x: posX, y: posY }
+                    });
+
+                    step.forEach((lib, libIndex) => {
+                        var libId = stepId + '_lib' + libIndex;
+                        var libLabel = lib.ref.split('#')[0];
+
+                        // Determine the type of the library
+                        var libData = Array.isArray(lib.packages) ? lib.packages[0][0] : lib;
+                        var libType = libData.binary || libData.build || libData.cache;
+
+                        var isAllBuild = true;
+                        var isSomeBuild = false;
+                        var shape = 'rectangle';
+                        var borderColor = '#00695C';
+
+                        if (Array.isArray(lib.packages)) {
+                            lib.packages.forEach(pkgArray => {
+                                pkgArray.forEach(pkg => {
+                                    if (pkg.binary === "Build") {
+                                        isSomeBuild = true;
+                                    } else {
+                                        isAllBuild = false;
+                                    }
+                                    if (pkg.context === "build") {
+                                        shape = 'ellipse';
+                                        borderColor = '#0000FF';  // Different border color for build context
+                                    }
+                                });
+                            });
+                        }
+
+                        var nodeColor;
+                        if (isAllBuild) {
+                            nodeColor = "#ffff37"; // Light orange for all build
+                        } else if (isSomeBuild) {
+                            nodeColor = "#ff9b28"; // Yellow for some build
+                        } else if (libType === "Cache") {
+                            nodeColor = "#70c7e6"; // Light green
+                        } else if (libType === "Download") {
+                            nodeColor = "#79eb8a"; // Light blue
+                        } else {
+                            nodeColor = "#FFFFFF"; // Default color
+                        }
+
+                        if (libIndex % columns === 0) {
+                            posX = 0;
+                            posY += yOffset; // move to the next row
+                        }
+
+                        elements.push({
+                            data: { id: libId, parent: stepId, label: libLabel, info: lib, color: nodeColor, shape: shape, borderColor: borderColor },
+                            position: { x: posX + libLabel.length / 2.0 * 12, y: posY }
+                        });
+                        posX += libLabel.length * 12;
+                    });
+
+                    if (stepIndex > 0) {
+                        var prevStepId = 'step' + (stepIndex - 1);
+                        edges.push({ data: { id: prevStepId + '_to_' + stepId, source: prevStepId, target: stepId } });
+                    }
+
+                    posY += yOffset * 2;
+                    posX = 0;
+                });
+
+                var cy = cytoscape({
+                    container: document.getElementById('cy'),
+                    boxSelectionEnabled: false,
+                    style: [
+                        {
+                            selector: 'node[color][shape][borderColor]',
+                            style: {
+                                'shape': 'data(shape)',
+                                'content': 'data(label)',
+                                'text-valign': 'center',
+                                'text-halign': 'center',
+                                'background-color': 'data(color)',
+                                'border-color': 'data(borderColor)',
+                                'border-width': 1,
+                                'width': function(ele) { return ele.data('label').length * 10.5; },
+                                'padding': '5px',
+                                'font-family': 'monospace',
+                                'font-size': '16px'
+                            }
+                        },
+                        {
+                            selector: ':parent',
+                            style: {
+                                'text-valign': 'top',
+                                'text-halign': 'center',
+                                'shape': 'round-rectangle',
+                                'background-opacity': 0.1,
+                                'border-color': '#004D40',
+                                'border-width': 2,
+                                'padding': 10,
+                                'font-family': 'monospace',
+                                'font-size': '16px'
+                            }
+                        },
+                        {
+                            selector: 'edge',
+                            style: {
+                                'curve-style': 'bezier',
+                                'target-arrow-shape': 'triangle',
+                                'line-color': '#004D40',
+                                'target-arrow-color': '#004D40',
+                                'width': 2
+                            }
+                        }
+                    ],
+                    elements: {
+                        nodes: elements,
+                        edges: edges
+                    },
+                    layout: {
+                        name: 'preset',
+                        padding: 5,
+                        fit: true
+                    }
+                });
+
+                // Add click event listener to nodes
+                cy.on('tap', 'node', function(evt){
+                    var node = evt.target;
+                    var info = node.data('info');
+                    var infoHtml = '';
+                    for (var key in info) {
+                        if (info.hasOwnProperty(key)) {
+                            infoHtml += '<p><strong>' + key + ':</strong> ' + JSON.stringify(info[key], null, 2) + '</p>';
+                        }
+                    }
+                    document.getElementById('node-info').innerHTML = infoHtml;
+                });
+            });
+        </script>
+    </body>
+</html>
+"""
+
+def _render_build_order(build_order, template):
+    from conans import __version__ as client_version
+    context = {'build_order': build_order, 'version': client_version, }
+    return template.render(context)
+
+
+def format_build_order_html(build_order):
+    build_order = build_order["order"] if isinstance(build_order, dict) else build_order
+    template = Template(build_order_html, autoescape=select_autoescape(['html', 'xml']))
+    cli_out_write(_render_build_order(build_order, template))
diff --git a/conans/client/cache/__init__.py b/conan/internal/api/install/__init__.py
similarity index 100%
rename from conans/client/cache/__init__.py
rename to conan/internal/api/install/__init__.py
diff --git a/conans/client/generators/__init__.py b/conan/internal/api/install/generators.py
similarity index 100%
rename from conans/client/generators/__init__.py
rename to conan/internal/api/install/generators.py
diff --git a/conans/client/store/__init__.py b/conan/internal/api/local/__init__.py
similarity index 100%
rename from conans/client/store/__init__.py
rename to conan/internal/api/local/__init__.py
diff --git a/conans/client/cache/editable.py b/conan/internal/api/local/editable.py
similarity index 100%
rename from conans/client/cache/editable.py
rename to conan/internal/api/local/editable.py
diff --git a/conan/internal/api/profile/__init__.py b/conan/internal/api/profile/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/conans/client/profile_loader.py b/conan/internal/api/profile/profile_loader.py
similarity index 99%
rename from conans/client/profile_loader.py
rename to conan/internal/api/profile/profile_loader.py
index ad4808177..6f6a83b81 100644
--- a/conans/client/profile_loader.py
+++ b/conan/internal/api/profile/profile_loader.py
@@ -335,7 +335,6 @@ class _ProfileValueParser(object):
         if runenv is not None:
             base_profile.runenv.update_profile_env(runenv)
 
-
         runner = _ProfileValueParser._parse_key_value(doc.runner) if doc.runner else {}
         base_profile.runner.update(runner)
         return base_profile
diff --git a/conan/internal/api/remotes/__init__.py b/conan/internal/api/remotes/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/conans/util/encrypt.py b/conan/internal/api/remotes/encrypt.py
similarity index 100%
rename from conans/util/encrypt.py
rename to conan/internal/api/remotes/encrypt.py
diff --git a/conans/client/store/localdb.py b/conan/internal/api/remotes/localdb.py
similarity index 97%
rename from conans/client/store/localdb.py
rename to conan/internal/api/remotes/localdb.py
index 9b95d8701..d6df369e2 100644
--- a/conans/client/store/localdb.py
+++ b/conan/internal/api/remotes/localdb.py
@@ -3,8 +3,8 @@ import sqlite3
 from contextlib import contextmanager
 from sqlite3 import OperationalError
 
-from conans.errors import ConanException
-from conans.util import encrypt
+from conan.errors import ConanException
+from conan.internal.api.remotes import encrypt
 
 REMOTES_USER_TABLE = "users_remotes"
 LOCALDB = ".conan.db"
diff --git a/conan/internal/conan_app.py b/conan/internal/conan_app.py
index 0f92e3eb2..28de3d94c 100644
--- a/conan/internal/conan_app.py
+++ b/conan/internal/conan_app.py
@@ -12,7 +12,7 @@ from conans.client.remote_manager import RemoteManager
 from conans.client.rest.auth_manager import ConanApiAuthManager
 from conans.client.rest.conan_requester import ConanRequester
 from conans.client.rest.rest_client import RestApiClientFactory
-from conans.client.store.localdb import LocalDB
+from conan.internal.api.remotes.localdb import LocalDB
 
 
 class CmdWrapper:
diff --git a/conan/internal/runner/ssh.py b/conan/internal/runner/ssh.py
index b47f01247..66aca5bd0 100644
--- a/conan/internal/runner/ssh.py
+++ b/conan/internal/runner/ssh.py
@@ -1,10 +1,9 @@
 from pathlib import Path
 import pathlib
 import tempfile
-from conan.api.conan_api import ConfigAPI
+
 from conan.api.output import Color, ConanOutput
 from conans.errors import ConanException
-from conans.client.profile_loader import ProfileLoader
 
 import os
 from io import BytesIO
@@ -41,7 +40,7 @@ class SSHRunner:
         if host_profile.runner.get('use_ssh_config', False):
             ssh_config_file = Path.home() / ".ssh" / "config"
             ssh_config = SSHConfig.from_file(open(ssh_config_file))
-        
+
         hostname = host_profile.runner.get("host") # TODO: this one is required
         if ssh_config and ssh_config.lookup(hostname):
             hostname = ssh_config.lookup(hostname)['hostname']
@@ -66,7 +65,7 @@ class SSHRunner:
         command = f"{self.remote_conan} create {raw_args} --format json > {remote_json_output}"
 
         ssh_info(f"Remote command: {command}")
-    
+
         stdout, _ = self._run_command(command)
         first_line = True
         while not stdout.channel.exit_status_ready():
@@ -127,15 +126,15 @@ class SSHRunner:
             _, _stdout, _stderr = self.client.exec_command(f"""{python_command} -c "import os; os.makedirs('{folder}', exist_ok=True)""")
             if _stdout.channel.recv_exit_status() != 0:
                 ssh_info(f"Error creating remote folder: {_stderr.read().decode()}")
-                raise ConanException(f"Unable to create remote workfolder at {folder}") 
-            
+                raise ConanException(f"Unable to create remote workfolder at {folder}")
+
         conan_venv = remote_folder + "/venv"
         if is_windows:
             conan_cmd = remote_folder + "/venv/Scripts/conan.exe"
         else:
             conan_cmd = remote_folder + "/venv/bin/conan"
 
-        ssh_info(f"Expected remote conan home: {remote_conan_home}")      
+        ssh_info(f"Expected remote conan home: {remote_conan_home}")
         ssh_info(f"Expected remote conan command: {conan_cmd}")
 
         # Check if remote Conan executable exists, otherwise invoke pip inside venv
@@ -246,11 +245,11 @@ class SSHRunner:
             channel.get_pty(width=width, height=height)
 
         channel.exec_command(command)
-        
+
         stdout = channel.makefile("r")
         stderr = channel.makefile("r")
         return stdout, stderr
-        
+
     def update_local_cache(self, json_result):
         # ('conan list --graph=create.json --graph-binaries=build --format=json > pkglist.json'
         _Path = pathlib.PureWindowsPath if self.remote_is_windows else pathlib.PurePath
@@ -259,13 +258,13 @@ class SSHRunner:
         _, stdout, _ = self.client.exec_command(pkg_list_command)
         if stdout.channel.recv_exit_status() != 0:
             raise ConanException("Unable to generate remote package list")
-        
+
         conan_cache_tgz = _Path(self.remote_create_dir).joinpath("cache.tgz").as_posix()
         cache_save_command = f"{self.remote_conan} cache save --list {pkg_list_json} --file {conan_cache_tgz}"
         _, stdout, _ = self.client.exec_command(cache_save_command)
         if stdout.channel.recv_exit_status() != 0:
             raise ConanException("Unable to save remote conan cache state")
-        
+
         sftp = self.client.open_sftp()
         with tempfile.TemporaryDirectory() as tmp:
             local_cache_tgz = os.path.join(tmp, 'cache.tgz')
diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py
index 315e2cf30..2aa6bf514 100644
--- a/conan/tools/cmake/cmakedeps/templates/target_data.py
+++ b/conan/tools/cmake/cmakedeps/templates/target_data.py
@@ -5,7 +5,7 @@ from conan.tools.cmake.cmakedeps import FIND_MODE_NONE, FIND_MODE_CONFIG, FIND_M
     FIND_MODE_BOTH
 from conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate
 from conan.errors import ConanException
-from conans.client.generators import relativize_path
+from conan.internal.api.install.generators import relativize_path
 
 """
 
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index 1f4509cb0..0d6585718 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -16,7 +16,7 @@ from conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME
 from conan.tools.cmake.utils import is_multi_configuration
 from conan.tools.intel import IntelCC
 from conan.tools.microsoft.visual import msvc_version_to_toolset_version
-from conans.client.generators import relativize_path
+from conan.internal.api.install.generators import relativize_path
 from conans.client.subsystems import deduce_subsystem, WINDOWS
 from conan.errors import ConanException
 from conans.model.version import Version
diff --git a/conan/tools/env/environment.py b/conan/tools/env/environment.py
index ca5d98685..59a9660f5 100644
--- a/conan/tools/env/environment.py
+++ b/conan/tools/env/environment.py
@@ -3,7 +3,7 @@ import textwrap
 from collections import OrderedDict
 from contextlib import contextmanager
 
-from conans.client.generators import relativize_paths
+from conan.internal.api.install.generators import relativize_paths
 from conans.client.subsystems import deduce_subsystem, WINDOWS, subsystem_path
 from conan.errors import ConanException
 from conans.model.recipe_ref import ref_matches
diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py
index 3b4a2b79c..a747c1c1c 100644
--- a/conan/tools/microsoft/msbuilddeps.py
+++ b/conan/tools/microsoft/msbuilddeps.py
@@ -8,7 +8,7 @@ from jinja2 import Template
 
 from conan.internal import check_duplicated_generator
 from conan.errors import ConanException
-from conans.client.generators import relativize_path
+from conan.internal.api.install.generators import relativize_path
 from conans.model.dependencies import get_transitive_requires
 from conans.util.files import load, save
 
diff --git a/conans/client/installer.py b/conans/client/installer.py
index 20198cc03..ea679f44e 100644
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -5,7 +5,7 @@ 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 conans.client.generators import write_generators
+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
 from conans.client.graph.install_graph import InstallGraph
diff --git a/conans/client/migrations.py b/conans/client/migrations.py
index 74267a5b3..ddde216ac 100644
--- a/conans/client/migrations.py
+++ b/conans/client/migrations.py
@@ -50,7 +50,7 @@ class ClientMigrator(Migrator):
         from conans.client.graph.compatibility import migrate_compatibility_files
         migrate_compatibility_files(self.cache_folder)
         # Update profile plugin
-        from conans.client.profile_loader import migrate_profile_plugin
+        from conan.internal.api.profile.profile_loader import migrate_profile_plugin
         migrate_profile_plugin(self.cache_folder)
 
         if old_version and old_version < "2.0.14-":


Test patch:
diff --git a/.ci/jenkins/testsv2.jenkins b/.ci/jenkins/testsv2.jenkins
index 08ba87fff..f443a2a7e 100644
--- a/.ci/jenkins/testsv2.jenkins
+++ b/.ci/jenkins/testsv2.jenkins
@@ -21,9 +21,9 @@ List<Map> getConfigurations(String moduleName, String branchName, String jobName
         configs.add([node: "Linux", pyvers: ["PY312"]])
     }
     if (branchName =~ /(^PR-.*)/) {
-        configs.add([node: "Linux", pyvers: ["PY36"]])
-        configs.add([node: "Windows", pyvers: ["PY36"]])
-        configs.add([node: "M2Macos", pyvers: ["PY36"]])
+        configs.add([node: "Linux", pyvers: ["PY38"]])
+        configs.add([node: "Windows", pyvers: ["PY38"]])
+        configs.add([node: "M2Macos", pyvers: ["PY38"]])
     }
     else if (jobName == "ConanNightlyv2" || branchName =~ /^release.*/) {
         configs.add([node: "Linux", pyvers: ["PY36", "PY38"]])
diff --git a/test/integration/command/user_test.py b/test/integration/command/user_test.py
index e071415ec..b5e4857a1 100644
--- a/test/integration/command/user_test.py
+++ b/test/integration/command/user_test.py
@@ -5,7 +5,7 @@ import unittest
 from collections import OrderedDict
 from datetime import timedelta
 
-from conans.client.store.localdb import LocalDB
+from conan.internal.api.remotes.localdb import LocalDB
 from conan.test.utils.tools import TestClient, TestServer
 from conans.util.env import environment_update
 
diff --git a/test/integration/command_v2/test_info_build_order.py b/test/integration/command_v2/test_info_build_order.py
index cf95afb54..b735920e1 100644
--- a/test/integration/command_v2/test_info_build_order.py
+++ b/test/integration/command_v2/test_info_build_order.py
@@ -73,6 +73,14 @@ def test_info_build_order():
     assert bo_json["order_by"] == "recipe"
     assert bo_json["order"] == result
 
+    # test html format
+    c.run("graph build-order consumer --build=missing --format=html")
+    assert "<body>" in c.stdout
+    c.run("graph build-order consumer --order-by=recipe --format=html")
+    assert "<body>" in c.stdout
+    c.run("graph build-order consumer --order-by=configuration --format=html")
+    assert "<body>" in c.stdout
+
 
 def test_info_build_order_configuration():
     c = TestClient()
@@ -332,6 +340,11 @@ def test_info_build_order_merge_multi_product():
 
     assert bo_json == result
 
+    # test that html format for build-order-merge generates something
+    c.run("graph build-order-merge --file=bo1.json --file=bo2.json --format=html")
+    assert "<body>" in c.stdout
+
+
 
 def test_info_build_order_merge_multi_product_configurations():
     c = TestClient()
diff --git a/test/integration/remote/auth_test.py b/test/integration/remote/auth_test.py
index e95969854..80213394c 100644
--- a/test/integration/remote/auth_test.py
+++ b/test/integration/remote/auth_test.py
@@ -5,7 +5,7 @@ import unittest
 
 from requests.models import Response
 
-from conans.client.store.localdb import LocalDB
+from conan.internal.api.remotes.localdb import LocalDB
 from conans.errors import AuthenticationException
 from conans.model.recipe_ref import RecipeReference
 from conan.internal.paths import CONANFILE
diff --git a/test/integration/test_package_vendor.py b/test/integration/test_package_vendor.py
index 562ae4cd3..08c3e4c35 100644
--- a/test/integration/test_package_vendor.py
+++ b/test/integration/test_package_vendor.py
@@ -138,3 +138,42 @@ def test_vendor_dont_propagate_options():
     c.run("install consumer_shared --build=app/* -c tools.graph:vendor=build")
     c.assert_listed_binary({"pkga/0.1": ("55c609fe8808aa5308134cb5989d23d3caffccf2", "Cache"),
                             "app/0.1": ("da39a3ee5e6b4b0d3255bfef95601890afd80709", "Build")})
+
+
+def test_package_vendor_export_pkg():
+    c = TestClient()
+    app = textwrap.dedent("""
+        import os
+        from conan import ConanFile
+        from conan.tools.files import copy, save
+
+        class App(ConanFile):
+            name = "app"
+            version = "0.1"
+            package_type = "application"
+            vendor = True
+            requires = "pkga/0.1"
+            def package(self):
+                copy(self, "*", src=self.dependencies["pkga"].package_folder,
+                     dst=self.package_folder)
+                save(self, os.path.join(self.package_folder, "app.exe"), "app")
+            """)
+
+    c.save({"pkga/conanfile.py": GenConanfile("pkga", "0.1").with_package_type("shared-library")
+                                                            .with_package_file("pkga.dll", "dll"),
+            "app/conanfile.py": app
+            })
+    c.run("create pkga")
+    c.run("build app")  # -c tools.graph:vendor=build will be automatic
+    c.run("export-pkg app")
+    assert "pkga/0.1" in c.out  # In the export-pkg process, dependencies are still needed
+    assert "conanfile.py (app/0.1): package(): Packaged 1 '.dll' file: pkga.dll" in c.out
+
+    # we can safely remove pkga, once the package is created, it can work without deps
+    c.run("remove pkg* -c")
+    c.run("list app:*")
+    assert "pkga" not in c.out  # The binary doesn't depend on pkga
+    c.run("install --requires=app/0.1 --deployer=full_deploy")
+    assert "pkga" not in c.out
+    assert c.load("full_deploy/host/app/0.1/app.exe") == "app"
+    assert c.load("full_deploy/host/app/0.1/pkga.dll") == "dll"
diff --git a/test/unittests/client/profile_loader/compiler_cppstd_test.py b/test/unittests/client/profile_loader/compiler_cppstd_test.py
index 2046afafb..baaaa33e0 100644
--- a/test/unittests/client/profile_loader/compiler_cppstd_test.py
+++ b/test/unittests/client/profile_loader/compiler_cppstd_test.py
@@ -8,7 +8,7 @@ from jinja2 import Template
 from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
 from conans.client.conf import default_settings_yml
-from conans.client.profile_loader import ProfileLoader
+from conan.internal.api.profile.profile_loader import ProfileLoader
 from conans.errors import ConanException
 from conans.model.conf import ConfDefinition
 from conans.model.settings import Settings
diff --git a/test/unittests/client/profile_loader/profile_loader_test.py b/test/unittests/client/profile_loader/profile_loader_test.py
index 3b2cc7504..b62722b80 100644
--- a/test/unittests/client/profile_loader/profile_loader_test.py
+++ b/test/unittests/client/profile_loader/profile_loader_test.py
@@ -3,7 +3,7 @@ import textwrap
 
 import pytest
 
-from conans.client.profile_loader import _ProfileParser, ProfileLoader
+from conan.internal.api.profile.profile_loader import _ProfileParser, ProfileLoader
 from conans.errors import ConanException
 from conans.model.recipe_ref import RecipeReference
 from conan.test.utils.mocks import ConanFileMock, MockSettings
diff --git a/test/unittests/util/local_db_test.py b/test/unittests/util/local_db_test.py
index fd1ff261f..4f35601f1 100644
--- a/test/unittests/util/local_db_test.py
+++ b/test/unittests/util/local_db_test.py
@@ -1,7 +1,7 @@
 import os
 import unittest
 
-from conans.client.store.localdb import LocalDB
+from conan.internal.api.remotes.localdb import LocalDB
 from conan.test.utils.test_files import temp_folder
 
 
diff --git a/test/unittests/util/test_encrypt.py b/test/unittests/util/test_encrypt.py
index 749a81bd3..f48293762 100644
--- a/test/unittests/util/test_encrypt.py
+++ b/test/unittests/util/test_encrypt.py
@@ -2,7 +2,7 @@ import uuid
 
 import pytest
 
-from conans.util import encrypt
+from conan.internal.api.remotes import encrypt
 
 
 def test_encryp_basic():