From 9129dd8a90fc435618ea9be45014bdd1c1ac4613 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Wed, 11 Nov 2020 15:33:04 +0100 Subject: [PATCH 01/10] pass settings to the remote_manager --- conans/client/cmd/uploader.py | 3 +- conans/client/graph/graph_binaries.py | 13 +++++--- conans/client/remote_manager.py | 31 ++++++++++++------- conans/client/rest/rest_client.py | 4 +-- conans/client/rest/rest_client_common.py | 18 ++++++----- conans/client/rest/rest_client_v1.py | 2 +- conans/client/rest/rest_client_v2.py | 4 +-- .../remote/test_package_id_raw_data.py | 0 8 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 conans/test/functional/remote/test_package_id_raw_data.py diff --git a/conans/client/cmd/uploader.py b/conans/client/cmd/uploader.py index 5278786b659..dd7d6c3d326 100644 --- a/conans/client/cmd/uploader.py +++ b/conans/client/cmd/uploader.py @@ -507,7 +507,8 @@ def _package_files_to_upload(self, pref, policy, the_files, remote): if remote_snapshot and policy != UPLOAD_POLICY_FORCE: if not is_package_snapshot_complete(remote_snapshot): return the_files, set() - remote_manifest, _ = self._remote_manager.get_package_manifest(pref, remote) + remote_manifest, _ = self._remote_manager.get_package_manifest(pref, remote, + settings=None) local_manifest = FileTreeManifest.loads(load(the_files["conanmanifest.txt"])) if remote_manifest == local_manifest: return None, None diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 033067b313a..54b4d578118 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -72,7 +72,8 @@ def _evaluate_cache_pkg(self, node, package_layout, pref, metadata, remote, remo output = node.conanfile.output if remote: try: - tmp = self._remote_manager.get_package_manifest(pref, remote) + settings = node.conanfile.info.full_settings.as_list() + tmp = self._remote_manager.get_package_manifest(pref, remote, settings=settings) upstream_manifest, pref = tmp except NotFoundException: output.warn("Can't update, no package in remote") @@ -93,11 +94,15 @@ def _evaluate_cache_pkg(self, node, package_layout, pref, metadata, remote, remo node.prev = metadata.packages[pref.id].revision assert node.prev, "PREV for %s is None: %s" % (str(pref), metadata.dumps()) + def _get_package_info(self, node, pref, remote): + settings = node.conanfile.info.full_settings.as_list() + return self._remote_manager.get_package_info(pref, remote, settings=settings) + def _evaluate_remote_pkg(self, node, pref, remote, remotes): remote_info = None if remote: try: - remote_info, pref = self._remote_manager.get_package_info(pref, remote) + remote_info, pref = self._get_package_info(node, pref, remote) except NotFoundException: pass except Exception: @@ -109,7 +114,7 @@ def _evaluate_remote_pkg(self, node, pref, remote, remotes): if not remote or (not remote_info and self._cache.config.revisions_enabled): for r in remotes.values(): try: - remote_info, pref = self._remote_manager.get_package_info(pref, r) + remote_info, pref = self._get_package_info(node, pref, r) except NotFoundException: pass else: @@ -236,7 +241,7 @@ def _process_node(self, node, pref, build_mode, update, remotes): if build_mode.outdated: if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE): if node.binary == BINARY_UPDATE: - info, pref = self._remote_manager.get_package_info(pref, remote) + info, pref = self._get_package_info(node, pref, remote) recipe_hash = info.recipe_hash elif node.binary == BINARY_CACHE: package_folder = package_layout.package(pref) diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index 6df71cd4dbc..0bcf164c1a6 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -38,7 +38,7 @@ def get_recipe_snapshot(self, ref, remote): return self._call_remote(remote, "get_recipe_snapshot", ref) def get_package_snapshot(self, pref, remote): - assert pref.ref.revision, "upload_package requires RREV" + assert pref.ref.revision, "get_package_snapshot requires RREV" assert pref.revision, "get_package_snapshot requires PREV" return self._call_remote(remote, "get_package_snapshot", pref) @@ -57,14 +57,14 @@ def get_recipe_manifest(self, ref, remote): ref = self._resolve_latest_ref(ref, remote) return self._call_remote(remote, "get_recipe_manifest", ref), ref - def get_package_manifest(self, pref, remote): - pref = self._resolve_latest_pref(pref, remote) + def get_package_manifest(self, pref, remote, settings=None): + pref = self._resolve_latest_pref(pref, remote, settings=settings) return self._call_remote(remote, "get_package_manifest", pref), pref - def get_package_info(self, pref, remote): + def get_package_info(self, pref, remote, settings=None): """ Read a package ConanInfo from remote """ - pref = self._resolve_latest_pref(pref, remote) + pref = self._resolve_latest_pref(pref, remote, settings=settings) return self._call_remote(remote, "get_package_info", pref), pref def get_recipe(self, ref, remote): @@ -140,16 +140,19 @@ def get_package(self, conanfile, pref, layout, remote, output, recorder): output.info("Retrieving package %s from remote '%s' " % (pref.id, remote.name)) layout.package_remove(pref) # Remove first the destination folder with layout.set_dirty_context_manager(pref): - self._get_package(layout, pref, remote, output, recorder) + settings = None + if hasattr(conanfile, 'info'): + settings = conanfile.info.full_settings.as_list() + self._get_package(layout, pref, remote, output, recorder, settings=settings) self._hook_manager.execute("post_download_package", conanfile_path=conanfile_path, reference=pref.ref, package_id=pref.id, remote=remote, conanfile=conanfile) - def _get_package(self, layout, pref, remote, output, recorder): + def _get_package(self, layout, pref, remote, output, recorder, settings): t1 = time.time() try: - pref = self._resolve_latest_pref(pref, remote) + pref = self._resolve_latest_pref(pref, remote, settings=settings) snapshot = self._call_remote(remote, "get_package_snapshot", pref) if not is_package_snapshot_complete(snapshot): raise PackageNotFoundException(pref) @@ -230,8 +233,8 @@ def get_latest_recipe_revision(self, ref, remote): revision = self._call_remote(remote, "get_latest_recipe_revision", ref) return revision - def get_latest_package_revision(self, pref, remote): - revision = self._call_remote(remote, "get_latest_package_revision", pref) + def get_latest_package_revision(self, pref, remote, headers): + revision = self._call_remote(remote, "get_latest_package_revision", pref, headers=headers) return revision def _resolve_latest_ref(self, ref, remote): @@ -242,10 +245,14 @@ def _resolve_latest_ref(self, ref, remote): ref = ref.copy_with_rev(DEFAULT_REVISION_V1) return ref - def _resolve_latest_pref(self, pref, remote): + def _resolve_latest_pref(self, pref, remote, settings): if pref.revision is None: try: - pref = self.get_latest_package_revision(pref, remote) + headers = None + if settings: + settings = ['{}={}'.format(*it) for it in settings] + headers = {'Conan-PkgID-Settings': ';'.join(settings), } + pref = self.get_latest_package_revision(pref, remote, headers=headers) except NoRestV2Available: pref = pref.copy_with_revs(pref.ref.revision, DEFAULT_REVISION_V1) return pref diff --git a/conans/client/rest/rest_client.py b/conans/client/rest/rest_client.py index b3b6dc7ef29..6948e0943d5 100644 --- a/conans/client/rest/rest_client.py +++ b/conans/client/rest/rest_client.py @@ -161,5 +161,5 @@ def get_package_revisions(self, pref): def get_latest_recipe_revision(self, ref): return self._get_api().get_latest_recipe_revision(ref) - def get_latest_package_revision(self, pref): - return self._get_api().get_latest_package_revision(pref) + def get_latest_package_revision(self, pref, headers): + return self._get_api().get_latest_package_revision(pref, headers=headers) diff --git a/conans/client/rest/rest_client_common.py b/conans/client/rest/rest_client_common.py index 769759e8050..18405e2cdf4 100644 --- a/conans/client/rest/rest_client_common.py +++ b/conans/client/rest/rest_client_common.py @@ -13,6 +13,7 @@ class JWTAuth(AuthBase): """Attaches JWT Authentication to the given Request object.""" + def __init__(self, token): self.token = token @@ -42,6 +43,7 @@ def handle_return_deserializer(deserializer=None): Map exceptions and http return codes and deserialize if needed. deserializer: Function for deserialize values""" + def handle_return(method): def inner(*argc, **argv): ret = method(*argc, **argv) @@ -50,7 +52,9 @@ def inner(*argc, **argv): text = ret.text if ret.status_code != 404 else "404 Not found" raise get_exception_from_error(ret.status_code)(text) return deserializer(ret.content) if deserializer else decode_text(ret.content) + return inner + return handle_return @@ -169,19 +173,20 @@ def server_capabilities(self, user=None, password=None): return [cap.strip() for cap in server_capabilities.split(",") if cap] - def get_json(self, url, data=None): - headers = self.custom_headers + def get_json(self, url, data=None, headers=None): + req_headers = self.custom_headers.copy() + req_headers.update(headers or {}) if data: # POST request - headers.update({'Content-type': 'application/json', - 'Accept': 'application/json'}) + req_headers.update({'Content-type': 'application/json', + 'Accept': 'application/json'}) logger.debug("REST: post: %s" % url) - response = self.requester.post(url, auth=self.auth, headers=headers, + response = self.requester.post(url, auth=self.auth, headers=req_headers, verify=self.verify_ssl, stream=True, data=json.dumps(data)) else: logger.debug("REST: get: %s" % url) - response = self.requester.get(url, auth=self.auth, headers=headers, + response = self.requester.get(url, auth=self.auth, headers=req_headers, verify=self.verify_ssl, stream=True) @@ -244,4 +249,3 @@ def search_packages(self, ref, query): url = self.router.search_packages(ref, query) package_infos = self.get_json(url) return package_infos - diff --git a/conans/client/rest/rest_client_v1.py b/conans/client/rest/rest_client_v1.py index 96fdbd43c84..328db5bb10f 100644 --- a/conans/client/rest/rest_client_v1.py +++ b/conans/client/rest/rest_client_v1.py @@ -340,7 +340,7 @@ def get_package_revisions(self, pref): def get_latest_recipe_revision(self, ref): raise NoRestV2Available("The remote doesn't support revisions") - def get_latest_package_revision(self, pref): + def get_latest_package_revision(self, pref, headers): raise NoRestV2Available("The remote doesn't support revisions") def _post_json(self, url, payload): diff --git a/conans/client/rest/rest_client_v2.py b/conans/client/rest/rest_client_v2.py index dd53f7b209f..22842d1d78c 100644 --- a/conans/client/rest/rest_client_v2.py +++ b/conans/client/rest/rest_client_v2.py @@ -329,9 +329,9 @@ def get_latest_recipe_revision(self, ref): # Ignored data["time"] return ref.copy_with_rev(rev) - def get_latest_package_revision(self, pref): + def get_latest_package_revision(self, pref, headers): url = self.router.package_latest(pref) - data = self.get_json(url) + data = self.get_json(url, headers=headers) prev = data["revision"] # Ignored data["time"] return pref.copy_with_revs(pref.ref.revision, prev) diff --git a/conans/test/functional/remote/test_package_id_raw_data.py b/conans/test/functional/remote/test_package_id_raw_data.py new file mode 100644 index 00000000000..e69de29bb2d From 67e091690194870facbefcab333054686f7f4278 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Wed, 11 Nov 2020 17:02:59 +0100 Subject: [PATCH 02/10] basic implementation --- conans/client/remote_manager.py | 27 ++-- conans/client/rest/rest_client.py | 4 +- conans/client/rest/rest_client_v1.py | 8 +- conans/client/rest/rest_client_v2.py | 8 +- .../remote/test_package_id_raw_data.py | 0 .../functional/remote/test_settings_header.py | 116 ++++++++++++++++++ 6 files changed, 143 insertions(+), 20 deletions(-) delete mode 100644 conans/test/functional/remote/test_package_id_raw_data.py create mode 100644 conans/test/functional/remote/test_settings_header.py diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index 0bcf164c1a6..69f70fbb4a5 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -20,6 +20,15 @@ log_recipe_download, log_recipe_sources_download, log_uncompressed_file) +CONAN_REQUEST_HEADER_SETTINGS = 'Conan-PkgID-Settings' + + +def _headers_for_settings(settings): + if settings: + settings = ['{}={}'.format(*it) for it in settings] + return {CONAN_REQUEST_HEADER_SETTINGS: ';'.join(settings), } + return None + class RemoteManager(object): """ Will handle the remotes to get recipes, packages etc """ @@ -64,8 +73,9 @@ def get_package_manifest(self, pref, remote, settings=None): def get_package_info(self, pref, remote, settings=None): """ Read a package ConanInfo from remote """ - pref = self._resolve_latest_pref(pref, remote, settings=settings) - return self._call_remote(remote, "get_package_info", pref), pref + headers = _headers_for_settings(settings) + pref = self._resolve_latest_pref(pref, remote, headers=headers) + return self._call_remote(remote, "get_package_info", pref, headers=headers), pref def get_recipe(self, ref, remote): """ @@ -152,7 +162,8 @@ def get_package(self, conanfile, pref, layout, remote, output, recorder): def _get_package(self, layout, pref, remote, output, recorder, settings): t1 = time.time() try: - pref = self._resolve_latest_pref(pref, remote, settings=settings) + headers = _headers_for_settings(settings) + pref = self._resolve_latest_pref(pref, remote, headers=headers) snapshot = self._call_remote(remote, "get_package_snapshot", pref) if not is_package_snapshot_complete(snapshot): raise PackageNotFoundException(pref) @@ -245,20 +256,16 @@ def _resolve_latest_ref(self, ref, remote): ref = ref.copy_with_rev(DEFAULT_REVISION_V1) return ref - def _resolve_latest_pref(self, pref, remote, settings): + def _resolve_latest_pref(self, pref, remote, headers): if pref.revision is None: try: - headers = None - if settings: - settings = ['{}={}'.format(*it) for it in settings] - headers = {'Conan-PkgID-Settings': ';'.join(settings), } pref = self.get_latest_package_revision(pref, remote, headers=headers) except NoRestV2Available: pref = pref.copy_with_revs(pref.ref.revision, DEFAULT_REVISION_V1) return pref def _call_remote(self, remote, method, *args, **kwargs): - assert(isinstance(remote, Remote)) + assert (isinstance(remote, Remote)) try: return self._auth_manager.call_rest_api_method(remote, method, *args, **kwargs) except ConnectionError as exc: @@ -301,7 +308,7 @@ def uncompress_file(src_path, dest_folder, output): t1 = time.time() try: with progress_bar.open_binary(src_path, output, "Decompressing %s" % os.path.basename( - src_path)) as file_handler: + src_path)) as file_handler: tar_extract(file_handler, dest_folder) except Exception as e: error_msg = "Error while downloading/extracting files to %s\n%s\n" % (dest_folder, str(e)) diff --git a/conans/client/rest/rest_client.py b/conans/client/rest/rest_client.py index 6948e0943d5..4ee532047a7 100644 --- a/conans/client/rest/rest_client.py +++ b/conans/client/rest/rest_client.py @@ -79,8 +79,8 @@ def get_recipe_manifest(self, ref): def get_package_manifest(self, pref): return self._get_api().get_package_manifest(pref) - def get_package_info(self, pref): - return self._get_api().get_package_info(pref) + def get_package_info(self, pref, headers): + return self._get_api().get_package_info(pref, headers=headers) def get_recipe(self, ref, dest_folder): return self._get_api().get_recipe(ref, dest_folder) diff --git a/conans/client/rest/rest_client_v1.py b/conans/client/rest/rest_client_v1.py index 328db5bb10f..ed6e34a384f 100644 --- a/conans/client/rest/rest_client_v1.py +++ b/conans/client/rest/rest_client_v1.py @@ -106,11 +106,11 @@ def get_package_manifest(self, pref): logger.error(traceback.format_exc()) raise ConanException(msg) - def get_package_info(self, pref): + def get_package_info(self, pref, headers): """Gets a ConanInfo file from a package""" pref = pref.copy_with_revs(None, None) url = self.router.package_download_urls(pref) - urls = self._get_file_to_url_dict(url) + urls = self._get_file_to_url_dict(url, headers=headers) if not urls: raise PackageNotFoundException(pref) @@ -124,10 +124,10 @@ def get_package_info(self, pref): contents = {key: decode_text(value) for key, value in dict(contents).items()} return ConanInfo.loads(contents[CONANINFO]) - def _get_file_to_url_dict(self, url, data=None): + def _get_file_to_url_dict(self, url, data=None, headers=None): """Call to url and decode the json returning a dict of {filepath: url} dict converting the url to a complete url when needed""" - urls = self.get_json(url, data=data) + urls = self.get_json(url, data=data, headers=headers) return {filepath: complete_url(self.remote_url, url) for filepath, url in urls.items()} def _upload_recipe(self, ref, files_to_upload, retry, retry_wait): diff --git a/conans/client/rest/rest_client_v2.py b/conans/client/rest/rest_client_v2.py index 22842d1d78c..cf1ba2b3de3 100644 --- a/conans/client/rest/rest_client_v2.py +++ b/conans/client/rest/rest_client_v2.py @@ -39,12 +39,12 @@ def _get_file_list_json(self, url): data["files"] = list(data["files"].keys()) return data - def _get_remote_file_contents(self, url, use_cache): + def _get_remote_file_contents(self, url, use_cache, headers): # We don't want traces in output of these downloads, they are ugly in output downloader = FileDownloader(self.requester, None, self.verify_ssl, self._config) if use_cache and self._config.download_cache: downloader = CachedFileDownloader(self._config.download_cache, downloader) - contents = downloader.download(url, auth=self.auth) + contents = downloader.download(url, auth=self.auth, headers=headers) return contents def _get_snapshot(self, url): @@ -77,10 +77,10 @@ def get_package_manifest(self, pref): logger.error(traceback.format_exc()) raise ConanException(msg) - def get_package_info(self, pref): + def get_package_info(self, pref, headers): url = self.router.package_info(pref) cache = (pref.revision != DEFAULT_REVISION_V1) - content = self._get_remote_file_contents(url, use_cache=cache) + content = self._get_remote_file_contents(url, use_cache=cache, headers=headers) return ConanInfo.loads(decode_text(content)) def get_recipe(self, ref, dest_folder): diff --git a/conans/test/functional/remote/test_package_id_raw_data.py b/conans/test/functional/remote/test_package_id_raw_data.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/conans/test/functional/remote/test_settings_header.py b/conans/test/functional/remote/test_settings_header.py new file mode 100644 index 00000000000..cd0839abeeb --- /dev/null +++ b/conans/test/functional/remote/test_settings_header.py @@ -0,0 +1,116 @@ +import textwrap +import unittest + +from conans.client.remote_manager import CONAN_REQUEST_HEADER_SETTINGS +from conans.test.assets.genconanfile import GenConanfile +from conans.test.utils.tools import TestClient, TestServer, TestRequester + + +class RequesterClass(TestRequester): + requests = None + + def __init__(self, *args, **kwargs): + self.requests = [] + super(RequesterClass, self).__init__(*args, **kwargs) + + def get(self, url, headers=None, **kwargs): + self.requests.append((url, headers)) + return super(RequesterClass, self).get(url, headers=headers, **kwargs) + + +class RequestSettingsHeaderTestCase(unittest.TestCase): + """ Send all the information together with the request when searching for package IDs """ + + profile = textwrap.dedent(""" + [settings] + os=Macos + arch=x86_64 + compiler=apple-clang + compiler.version=11.0 + compiler.libcxx=libc++ + """) + + def setUp(self): + test_server = TestServer(users={"user": "mypass"}) + self.servers = {"default": test_server} + t = TestClient(servers=self.servers, users={"default": [("user", "mypass")]}) + t.save({'conanfile.py': GenConanfile().with_settings('os', 'arch', 'compiler'), + 'profile': self.profile}) + t.run('create conanfile.py name/version@user/channel --profile:host=profile') + t.run('upload name/version@user/channel --all') + + @staticmethod + def _get_settings_headers(requester): + settings = None + for url, headers in requester.requests: + if CONAN_REQUEST_HEADER_SETTINGS in headers: + assert not settings + settings = headers.get(CONAN_REQUEST_HEADER_SETTINGS) + return settings + + def _assert_settings_headers(self, settings_header, compiler_version='11.0'): + # It takes only the values that are relevant to the recipe + self.assertListEqual( + sorted(['os', 'arch', 'compiler', 'compiler.version', 'compiler.libcxx']), + sorted([it.split('=', 1)[0] for it in settings_header.split(';')])) + self.assertIn('os=Macos', settings_header) + self.assertIn('arch=x86_64', settings_header) + self.assertIn('compiler=apple-clang', settings_header) + self.assertIn('compiler.libcxx=libc++', settings_header) + self.assertIn('compiler.version={}'.format(compiler_version), settings_header) + self.assertNotIn('build_type', settings_header) + + def test_install_recipe_mismatch(self): + t = TestClient(requester_class=RequesterClass, servers=self.servers, + users={"default": [("user", "mypass")]}) + t.save({'profile': self.profile}) + t.run('install failing/version@user/channel --profile=profile', assert_error=True) + self.assertIsNone(self._get_settings_headers(t.api.http_requester)) + + def test_install_package_match(self): + t = TestClient(requester_class=RequesterClass, servers=self.servers, + users={"default": [("user", "mypass")]}) + t.save({'profile': self.profile}) + + # Package match + t.run('install name/version@user/channel --profile=profile -s build_type=Release') + settings_header = self._get_settings_headers(t.api.http_requester) + self._assert_settings_headers(settings_header) + + # Package mismatch + t.run('install name/version@user/channel --profile=profile -s compiler.version=12.0', + assert_error=True) + settings_header = self._get_settings_headers(t.api.http_requester) + self._assert_settings_headers(settings_header, compiler_version='12.0') + + def test_info_package_match(self): + t = TestClient(requester_class=RequesterClass, servers=self.servers, + users={"default": [("user", "mypass")]}) + t.save({'profile': self.profile}) + + # Package match + t.run('info name/version@user/channel --profile=profile -s build_type=Release') + settings_header = self._get_settings_headers(t.api.http_requester) + self._assert_settings_headers(settings_header) + + # Package mismatch + t.run('info name/version@user/channel --profile=profile -s compiler.version=12.0') + settings_header = self._get_settings_headers(t.api.http_requester) + self._assert_settings_headers(settings_header, compiler_version='12.0') + + def test_install_as_requirement(self): + t = TestClient(requester_class=RequesterClass, servers=self.servers, + users={"default": [("user", "mypass")]}) + t.save({'conanfile.py': GenConanfile().with_requires('name/version@user/channel'), + 'profile': self.profile}) + + # Requirement is found + t.run('install . consumer/version@ --profile=profile -s compiler.version=11.0') + settings_header = self._get_settings_headers(t.api.http_requester) + self._assert_settings_headers(settings_header) + + # Requirement is not found + t.run('install . consumer/version@ --profile=profile -s compiler.version=12.0', + assert_error=True) + settings_header = self._get_settings_headers(t.api.http_requester) + self._assert_settings_headers(settings_header, compiler_version='12.0') From ca9de88456580eb6e9e76e9b4fdb1a7650e13938 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Wed, 11 Nov 2020 17:29:57 +0100 Subject: [PATCH 03/10] add tests --- conans/client/cmd/uploader.py | 3 +- conans/client/graph/graph_binaries.py | 5 +-- conans/client/remote_manager.py | 4 +- conans/client/rest/rest_client_v2.py | 2 +- .../functional/remote/test_settings_header.py | 38 +++++++++++-------- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/conans/client/cmd/uploader.py b/conans/client/cmd/uploader.py index dd7d6c3d326..5278786b659 100644 --- a/conans/client/cmd/uploader.py +++ b/conans/client/cmd/uploader.py @@ -507,8 +507,7 @@ def _package_files_to_upload(self, pref, policy, the_files, remote): if remote_snapshot and policy != UPLOAD_POLICY_FORCE: if not is_package_snapshot_complete(remote_snapshot): return the_files, set() - remote_manifest, _ = self._remote_manager.get_package_manifest(pref, remote, - settings=None) + remote_manifest, _ = self._remote_manager.get_package_manifest(pref, remote) local_manifest = FileTreeManifest.loads(load(the_files["conanmanifest.txt"])) if remote_manifest == local_manifest: return None, None diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 54b4d578118..035ef81bd34 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -72,8 +72,7 @@ def _evaluate_cache_pkg(self, node, package_layout, pref, metadata, remote, remo output = node.conanfile.output if remote: try: - settings = node.conanfile.info.full_settings.as_list() - tmp = self._remote_manager.get_package_manifest(pref, remote, settings=settings) + tmp = self._remote_manager.get_package_manifest(pref, remote) upstream_manifest, pref = tmp except NotFoundException: output.warn("Can't update, no package in remote") @@ -112,7 +111,7 @@ def _evaluate_remote_pkg(self, node, pref, remote, remotes): # If the "remote" came from the registry but the user didn't specified the -r, with # revisions iterate all remotes if not remote or (not remote_info and self._cache.config.revisions_enabled): - for r in remotes.values(): + for r in remotes.values(): # FIXME: Here we hit the same remote as before try: remote_info, pref = self._get_package_info(node, pref, r) except NotFoundException: diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index 69f70fbb4a5..e7829cd8946 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -66,8 +66,8 @@ def get_recipe_manifest(self, ref, remote): ref = self._resolve_latest_ref(ref, remote) return self._call_remote(remote, "get_recipe_manifest", ref), ref - def get_package_manifest(self, pref, remote, settings=None): - pref = self._resolve_latest_pref(pref, remote, settings=settings) + def get_package_manifest(self, pref, remote): + pref = self._resolve_latest_pref(pref, remote, headers=None) return self._call_remote(remote, "get_package_manifest", pref), pref def get_package_info(self, pref, remote, settings=None): diff --git a/conans/client/rest/rest_client_v2.py b/conans/client/rest/rest_client_v2.py index cf1ba2b3de3..8f49198e2ef 100644 --- a/conans/client/rest/rest_client_v2.py +++ b/conans/client/rest/rest_client_v2.py @@ -39,7 +39,7 @@ def _get_file_list_json(self, url): data["files"] = list(data["files"].keys()) return data - def _get_remote_file_contents(self, url, use_cache, headers): + def _get_remote_file_contents(self, url, use_cache, headers=None): # We don't want traces in output of these downloads, they are ugly in output downloader = FileDownloader(self.requester, None, self.verify_ssl, self._config) if use_cache and self._config.download_cache: diff --git a/conans/test/functional/remote/test_settings_header.py b/conans/test/functional/remote/test_settings_header.py index cd0839abeeb..b6110f069ba 100644 --- a/conans/test/functional/remote/test_settings_header.py +++ b/conans/test/functional/remote/test_settings_header.py @@ -1,6 +1,8 @@ import textwrap import unittest +from parameterized.parameterized import parameterized_class + from conans.client.remote_manager import CONAN_REQUEST_HEADER_SETTINGS from conans.test.assets.genconanfile import GenConanfile from conans.test.utils.tools import TestClient, TestServer, TestRequester @@ -18,8 +20,9 @@ def get(self, url, headers=None, **kwargs): return super(RequesterClass, self).get(url, headers=headers, **kwargs) +@parameterized_class([{"revs_enabled": True}, {"revs_enabled": False}, ]) class RequestSettingsHeaderTestCase(unittest.TestCase): - """ Send all the information together with the request when searching for package IDs """ + """ Conan adds a header with the settings used to compute the package ID """ profile = textwrap.dedent(""" [settings] @@ -39,14 +42,16 @@ def setUp(self): t.run('create conanfile.py name/version@user/channel --profile:host=profile') t.run('upload name/version@user/channel --all') - @staticmethod - def _get_settings_headers(requester): - settings = None + def _get_settings_headers(self, requester): + hits = sum([CONAN_REQUEST_HEADER_SETTINGS in headers for _, headers in requester.requests]) + self.assertEquals(hits, 2 if self.revs_enabled else 1) for url, headers in requester.requests: if CONAN_REQUEST_HEADER_SETTINGS in headers: - assert not settings - settings = headers.get(CONAN_REQUEST_HEADER_SETTINGS) - return settings + if self.revs_enabled: + self.assertTrue(url.endswith('/latest'), msg=url) + else: + self.assertTrue(url.endswith('/download_urls'), msg=url) + return headers.get(CONAN_REQUEST_HEADER_SETTINGS) def _assert_settings_headers(self, settings_header, compiler_version='11.0'): # It takes only the values that are relevant to the recipe @@ -60,16 +65,21 @@ def _assert_settings_headers(self, settings_header, compiler_version='11.0'): self.assertIn('compiler.version={}'.format(compiler_version), settings_header) self.assertNotIn('build_type', settings_header) - def test_install_recipe_mismatch(self): + def _get_test_client(self): t = TestClient(requester_class=RequesterClass, servers=self.servers, users={"default": [("user", "mypass")]}) + t.run('config set general.revisions_enabled={}'.format('1' if self.revs_enabled else '0')) + return t + + def test_install_recipe_mismatch(self): + t = self._get_test_client() t.save({'profile': self.profile}) t.run('install failing/version@user/channel --profile=profile', assert_error=True) - self.assertIsNone(self._get_settings_headers(t.api.http_requester)) + self.assertFalse(any([CONAN_REQUEST_HEADER_SETTINGS in headers for _, headers in + t.api.http_requester.requests])) def test_install_package_match(self): - t = TestClient(requester_class=RequesterClass, servers=self.servers, - users={"default": [("user", "mypass")]}) + t = self._get_test_client() t.save({'profile': self.profile}) # Package match @@ -84,8 +94,7 @@ def test_install_package_match(self): self._assert_settings_headers(settings_header, compiler_version='12.0') def test_info_package_match(self): - t = TestClient(requester_class=RequesterClass, servers=self.servers, - users={"default": [("user", "mypass")]}) + t = self._get_test_client() t.save({'profile': self.profile}) # Package match @@ -99,8 +108,7 @@ def test_info_package_match(self): self._assert_settings_headers(settings_header, compiler_version='12.0') def test_install_as_requirement(self): - t = TestClient(requester_class=RequesterClass, servers=self.servers, - users={"default": [("user", "mypass")]}) + t = self._get_test_client() t.save({'conanfile.py': GenConanfile().with_requires('name/version@user/channel'), 'profile': self.profile}) From 2e215c75fd4e083e202c24a092467a7de98f3151 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Wed, 11 Nov 2020 17:47:03 +0100 Subject: [PATCH 04/10] add comments --- conans/client/graph/graph_binaries.py | 2 +- conans/client/remote_manager.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 035ef81bd34..286eb84f95d 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -111,7 +111,7 @@ def _evaluate_remote_pkg(self, node, pref, remote, remotes): # If the "remote" came from the registry but the user didn't specified the -r, with # revisions iterate all remotes if not remote or (not remote_info and self._cache.config.revisions_enabled): - for r in remotes.values(): # FIXME: Here we hit the same remote as before + for r in remotes.values(): # FIXME: Here we hit the same remote we did before try: remote_info, pref = self._get_package_info(node, pref, r) except NotFoundException: diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index e7829cd8946..1c7400cf76a 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -75,6 +75,7 @@ def get_package_info(self, pref, remote, settings=None): """ headers = _headers_for_settings(settings) pref = self._resolve_latest_pref(pref, remote, headers=headers) + # FIXME Conan 2.0: With revisions, it is not needed to pass headers to this second function return self._call_remote(remote, "get_package_info", pref, headers=headers), pref def get_recipe(self, ref, remote): From e0ffccea608c58fe11dbbda99c082e62ceccd131 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Wed, 11 Nov 2020 18:10:44 +0100 Subject: [PATCH 05/10] call function from test requires argument --- conans/test/functional/remote/rest_api_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conans/test/functional/remote/rest_api_test.py b/conans/test/functional/remote/rest_api_test.py index 3fdd01e09b0..fd09f407a38 100644 --- a/conans/test/functional/remote/rest_api_test.py +++ b/conans/test/functional/remote/rest_api_test.py @@ -159,7 +159,7 @@ def test_get_package_info(self): self._upload_package(pref, {CONANINFO: conan_info}) # Get the package info - info = self.api.get_package_info(pref) + info = self.api.get_package_info(pref, headers=None) self.assertIsInstance(info, ConanInfo) self.assertEqual(info, ConanInfo.loads(conan_info)) From 1aa16e0e2db155930f12c11643e824f6f3b96c40 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Thu, 12 Nov 2020 10:19:59 +0100 Subject: [PATCH 06/10] add parameter to None --- conans/client/conan_api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py index 798fbe3ef35..69da5ae8dad 100644 --- a/conans/client/conan_api.py +++ b/conans/client/conan_api.py @@ -1133,7 +1133,8 @@ def get_path(self, reference, package_id=None, path=None, remote_name=None): if package_id: pref = PackageReference(ref, package_id) if self.app.config.revisions_enabled and not pref.revision: - pref = self.app.remote_manager.get_latest_package_revision(pref, remote) + pref = self.app.remote_manager.get_latest_package_revision(pref, remote, + headers=None) return self.app.remote_manager.get_package_path(pref, path, remote), path else: return self.app.remote_manager.get_recipe_path(ref, path, remote), path From 1363dfe2d5b9f41bf646a80d9342f9400dfc6548 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Thu, 12 Nov 2020 17:43:24 +0100 Subject: [PATCH 07/10] list options too in headers too --- conans/client/graph/graph_binaries.py | 4 +- conans/client/remote_manager.py | 32 +++++--- ...ings_header.py => test_request_headers.py} | 74 ++++++++++++++----- 3 files changed, 78 insertions(+), 32 deletions(-) rename conans/test/functional/remote/{test_settings_header.py => test_request_headers.py} (57%) diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 286eb84f95d..02430e9f45f 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -94,8 +94,8 @@ def _evaluate_cache_pkg(self, node, package_layout, pref, metadata, remote, remo assert node.prev, "PREV for %s is None: %s" % (str(pref), metadata.dumps()) def _get_package_info(self, node, pref, remote): - settings = node.conanfile.info.full_settings.as_list() - return self._remote_manager.get_package_info(pref, remote, settings=settings) + info = getattr(node.conanfile, 'info') + return self._remote_manager.get_package_info(pref, remote, info=info) def _evaluate_remote_pkg(self, node, pref, remote, remotes): remote_info = None diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index 1c7400cf76a..f80b93c4ea0 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -21,13 +21,25 @@ log_uncompressed_file) CONAN_REQUEST_HEADER_SETTINGS = 'Conan-PkgID-Settings' +CONAN_REQUEST_HEADER_OPTIONS = 'Conan-PkgID-Options' -def _headers_for_settings(settings): +def _headers_for_info(info): + if not info: + return None + + r = {} + settings = info.full_settings.as_list() if settings: settings = ['{}={}'.format(*it) for it in settings] - return {CONAN_REQUEST_HEADER_SETTINGS: ';'.join(settings), } - return None + r.update({CONAN_REQUEST_HEADER_SETTINGS: ';'.join(settings)}) + + options = info.options.as_list() + if options: + options = filter(lambda u: u[0] in ['shared', 'fPIC', 'header_only'], options) + options = ['{}={}'.format(*it) for it in options] + r.update({CONAN_REQUEST_HEADER_OPTIONS: ';'.join(options)}) + return r class RemoteManager(object): @@ -70,10 +82,10 @@ def get_package_manifest(self, pref, remote): pref = self._resolve_latest_pref(pref, remote, headers=None) return self._call_remote(remote, "get_package_manifest", pref), pref - def get_package_info(self, pref, remote, settings=None): + def get_package_info(self, pref, remote, info=None): """ Read a package ConanInfo from remote """ - headers = _headers_for_settings(settings) + headers = _headers_for_info(info) pref = self._resolve_latest_pref(pref, remote, headers=headers) # FIXME Conan 2.0: With revisions, it is not needed to pass headers to this second function return self._call_remote(remote, "get_package_info", pref, headers=headers), pref @@ -151,19 +163,17 @@ def get_package(self, conanfile, pref, layout, remote, output, recorder): output.info("Retrieving package %s from remote '%s' " % (pref.id, remote.name)) layout.package_remove(pref) # Remove first the destination folder with layout.set_dirty_context_manager(pref): - settings = None - if hasattr(conanfile, 'info'): - settings = conanfile.info.full_settings.as_list() - self._get_package(layout, pref, remote, output, recorder, settings=settings) + info = getattr(conanfile, 'info') + self._get_package(layout, pref, remote, output, recorder, info=info) self._hook_manager.execute("post_download_package", conanfile_path=conanfile_path, reference=pref.ref, package_id=pref.id, remote=remote, conanfile=conanfile) - def _get_package(self, layout, pref, remote, output, recorder, settings): + def _get_package(self, layout, pref, remote, output, recorder, info): t1 = time.time() try: - headers = _headers_for_settings(settings) + headers = _headers_for_info(info) pref = self._resolve_latest_pref(pref, remote, headers=headers) snapshot = self._call_remote(remote, "get_package_snapshot", pref) if not is_package_snapshot_complete(snapshot): diff --git a/conans/test/functional/remote/test_settings_header.py b/conans/test/functional/remote/test_request_headers.py similarity index 57% rename from conans/test/functional/remote/test_settings_header.py rename to conans/test/functional/remote/test_request_headers.py index b6110f069ba..e1cedf3b5ed 100644 --- a/conans/test/functional/remote/test_settings_header.py +++ b/conans/test/functional/remote/test_request_headers.py @@ -3,7 +3,7 @@ from parameterized.parameterized import parameterized_class -from conans.client.remote_manager import CONAN_REQUEST_HEADER_SETTINGS +from conans.client.remote_manager import CONAN_REQUEST_HEADER_SETTINGS, CONAN_REQUEST_HEADER_OPTIONS from conans.test.assets.genconanfile import GenConanfile from conans.test.utils.tools import TestClient, TestServer, TestRequester @@ -21,7 +21,7 @@ def get(self, url, headers=None, **kwargs): @parameterized_class([{"revs_enabled": True}, {"revs_enabled": False}, ]) -class RequestSettingsHeaderTestCase(unittest.TestCase): +class RequestHeadersTestCase(unittest.TestCase): """ Conan adds a header with the settings used to compute the package ID """ profile = textwrap.dedent(""" @@ -31,27 +31,34 @@ class RequestSettingsHeaderTestCase(unittest.TestCase): compiler=apple-clang compiler.version=11.0 compiler.libcxx=libc++ + build_type=Release """) + conanfile = GenConanfile().with_settings('os', 'arch', 'compiler') \ + .with_option('opt1', [True, False]) \ + .with_option('shared', [True, False]) \ + .with_default_option('opt1', True) \ + .with_default_option('shared', False) + def setUp(self): test_server = TestServer(users={"user": "mypass"}) self.servers = {"default": test_server} t = TestClient(servers=self.servers, users={"default": [("user", "mypass")]}) - t.save({'conanfile.py': GenConanfile().with_settings('os', 'arch', 'compiler'), + t.save({'conanfile.py': self.conanfile, 'profile': self.profile}) t.run('create conanfile.py name/version@user/channel --profile:host=profile') t.run('upload name/version@user/channel --all') - def _get_settings_headers(self, requester): - hits = sum([CONAN_REQUEST_HEADER_SETTINGS in headers for _, headers in requester.requests]) + def _get_header(self, requester, header_name): + hits = sum([header_name in headers for _, headers in requester.requests]) self.assertEquals(hits, 2 if self.revs_enabled else 1) for url, headers in requester.requests: - if CONAN_REQUEST_HEADER_SETTINGS in headers: + if header_name in headers: if self.revs_enabled: self.assertTrue(url.endswith('/latest'), msg=url) else: self.assertTrue(url.endswith('/download_urls'), msg=url) - return headers.get(CONAN_REQUEST_HEADER_SETTINGS) + return headers.get(header_name) def _assert_settings_headers(self, settings_header, compiler_version='11.0'): # It takes only the values that are relevant to the recipe @@ -65,6 +72,10 @@ def _assert_settings_headers(self, settings_header, compiler_version='11.0'): self.assertIn('compiler.version={}'.format(compiler_version), settings_header) self.assertNotIn('build_type', settings_header) + def _assert_options_headers(self, options_header, shared_value='False'): + self.assertListEqual(['shared'], [it.split('=', 1)[0] for it in options_header.split(';')]) + self.assertIn('shared={}'.format(shared_value), options_header) + def _get_test_client(self): t = TestClient(requester_class=RequesterClass, servers=self.servers, users={"default": [("user", "mypass")]}) @@ -77,48 +88,73 @@ def test_install_recipe_mismatch(self): t.run('install failing/version@user/channel --profile=profile', assert_error=True) self.assertFalse(any([CONAN_REQUEST_HEADER_SETTINGS in headers for _, headers in t.api.http_requester.requests])) + self.assertFalse(any([CONAN_REQUEST_HEADER_OPTIONS in headers for _, headers in + t.api.http_requester.requests])) def test_install_package_match(self): t = self._get_test_client() t.save({'profile': self.profile}) # Package match - t.run('install name/version@user/channel --profile=profile -s build_type=Release') - settings_header = self._get_settings_headers(t.api.http_requester) + t.run('install name/version@user/channel --profile=profile') + settings_header = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_SETTINGS) self._assert_settings_headers(settings_header) + options_headers = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_OPTIONS) + self._assert_options_headers(options_headers) - # Package mismatch + # Package mismatch (settings) t.run('install name/version@user/channel --profile=profile -s compiler.version=12.0', assert_error=True) - settings_header = self._get_settings_headers(t.api.http_requester) + settings_header = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_SETTINGS) self._assert_settings_headers(settings_header, compiler_version='12.0') + # Package mismatch (options) + t.run('install name/version@user/channel --profile=profile -o shared=True', + assert_error=True) + options_headers = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_OPTIONS) + self._assert_options_headers(options_headers, shared_value='True') + def test_info_package_match(self): t = self._get_test_client() t.save({'profile': self.profile}) # Package match - t.run('info name/version@user/channel --profile=profile -s build_type=Release') - settings_header = self._get_settings_headers(t.api.http_requester) + t.run('info name/version@user/channel --profile=profile') + settings_header = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_SETTINGS) self._assert_settings_headers(settings_header) + options_headers = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_OPTIONS) + self._assert_options_headers(options_headers) - # Package mismatch + # Package mismatch (settings) t.run('info name/version@user/channel --profile=profile -s compiler.version=12.0') - settings_header = self._get_settings_headers(t.api.http_requester) + settings_header = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_SETTINGS) self._assert_settings_headers(settings_header, compiler_version='12.0') + # Package mismatch (options) + t.run('install name/version@user/channel --profile=profile -o shared=True', + assert_error=True) + options_headers = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_OPTIONS) + self._assert_options_headers(options_headers, shared_value='True') + def test_install_as_requirement(self): t = self._get_test_client() t.save({'conanfile.py': GenConanfile().with_requires('name/version@user/channel'), 'profile': self.profile}) # Requirement is found - t.run('install . consumer/version@ --profile=profile -s compiler.version=11.0') - settings_header = self._get_settings_headers(t.api.http_requester) + t.run('install . consumer/version@ --profile=profile') + settings_header = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_SETTINGS) self._assert_settings_headers(settings_header) + options_headers = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_OPTIONS) + self._assert_options_headers(options_headers) - # Requirement is not found + # Requirement is not found (settings) t.run('install . consumer/version@ --profile=profile -s compiler.version=12.0', assert_error=True) - settings_header = self._get_settings_headers(t.api.http_requester) + settings_header = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_SETTINGS) self._assert_settings_headers(settings_header, compiler_version='12.0') + + # Requirement is not found (options) + t.run('install . consumer/version@ --profile=profile -o name:shared=True', assert_error=True) + options_headers = self._get_header(t.api.http_requester, CONAN_REQUEST_HEADER_OPTIONS) + self._assert_options_headers(options_headers, shared_value='True') From ed667e69b58294867d192551418d8105065868c8 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Thu, 12 Nov 2020 18:16:28 +0100 Subject: [PATCH 08/10] handle info variable with care --- conans/client/graph/graph_binaries.py | 3 +-- conans/client/remote_manager.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index 02430e9f45f..ee81dd4aab6 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -94,8 +94,7 @@ def _evaluate_cache_pkg(self, node, package_layout, pref, metadata, remote, remo assert node.prev, "PREV for %s is None: %s" % (str(pref), metadata.dumps()) def _get_package_info(self, node, pref, remote): - info = getattr(node.conanfile, 'info') - return self._remote_manager.get_package_info(pref, remote, info=info) + return self._remote_manager.get_package_info(pref, remote, info=node.conanfile.info) def _evaluate_remote_pkg(self, node, pref, remote, remotes): remote_info = None diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index f80b93c4ea0..8c72ed459a8 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -163,7 +163,7 @@ def get_package(self, conanfile, pref, layout, remote, output, recorder): output.info("Retrieving package %s from remote '%s' " % (pref.id, remote.name)) layout.package_remove(pref) # Remove first the destination folder with layout.set_dirty_context_manager(pref): - info = getattr(conanfile, 'info') + info = getattr(conanfile, 'info', None) self._get_package(layout, pref, remote, output, recorder, info=info) self._hook_manager.execute("post_download_package", conanfile_path=conanfile_path, From 8faf2b46c644b64a3bcb181b477fafe9cf74fbbc Mon Sep 17 00:00:00 2001 From: jgsogo Date: Fri, 13 Nov 2020 14:54:31 +0100 Subject: [PATCH 09/10] get the value from the one assigned by the test environment --- conans/test/functional/remote/test_request_headers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conans/test/functional/remote/test_request_headers.py b/conans/test/functional/remote/test_request_headers.py index e1cedf3b5ed..15dc1cbdbc9 100644 --- a/conans/test/functional/remote/test_request_headers.py +++ b/conans/test/functional/remote/test_request_headers.py @@ -6,6 +6,7 @@ from conans.client.remote_manager import CONAN_REQUEST_HEADER_SETTINGS, CONAN_REQUEST_HEADER_OPTIONS from conans.test.assets.genconanfile import GenConanfile from conans.test.utils.tools import TestClient, TestServer, TestRequester +from conans.util.env_reader import get_env class RequesterClass(TestRequester): @@ -20,9 +21,9 @@ def get(self, url, headers=None, **kwargs): return super(RequesterClass, self).get(url, headers=headers, **kwargs) -@parameterized_class([{"revs_enabled": True}, {"revs_enabled": False}, ]) class RequestHeadersTestCase(unittest.TestCase): """ Conan adds a header with the settings used to compute the package ID """ + revs_enabled = get_env("TESTING_REVISIONS_ENABLED", False) profile = textwrap.dedent(""" [settings] From b69a00bd5dc7fa6cd2ddfdcf25f09600081036b1 Mon Sep 17 00:00:00 2001 From: jgsogo Date: Fri, 13 Nov 2020 14:54:43 +0100 Subject: [PATCH 10/10] add default argument --- conans/client/conan_api.py | 3 +-- conans/client/remote_manager.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/conans/client/conan_api.py b/conans/client/conan_api.py index 69da5ae8dad..798fbe3ef35 100644 --- a/conans/client/conan_api.py +++ b/conans/client/conan_api.py @@ -1133,8 +1133,7 @@ def get_path(self, reference, package_id=None, path=None, remote_name=None): if package_id: pref = PackageReference(ref, package_id) if self.app.config.revisions_enabled and not pref.revision: - pref = self.app.remote_manager.get_latest_package_revision(pref, remote, - headers=None) + pref = self.app.remote_manager.get_latest_package_revision(pref, remote) return self.app.remote_manager.get_package_path(pref, path, remote), path else: return self.app.remote_manager.get_recipe_path(ref, path, remote), path diff --git a/conans/client/remote_manager.py b/conans/client/remote_manager.py index 8c72ed459a8..677e143d7d4 100644 --- a/conans/client/remote_manager.py +++ b/conans/client/remote_manager.py @@ -255,7 +255,7 @@ def get_latest_recipe_revision(self, ref, remote): revision = self._call_remote(remote, "get_latest_recipe_revision", ref) return revision - def get_latest_package_revision(self, pref, remote, headers): + def get_latest_package_revision(self, pref, remote, headers=None): revision = self._call_remote(remote, "get_latest_package_revision", pref, headers=headers) return revision