From 26269e7cfc198b4b0e7353e6796fc675db0094a7 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 10:35:42 +0200 Subject: [PATCH 01/13] update to require project_name as full name, issue warnings with other calls --- mergin/client.py | 25 ++++++++++++++++++++++--- mergin/test/test_client.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/mergin/client.py b/mergin/client.py index a00f8f07..5656a967 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -14,6 +14,7 @@ import ssl from enum import Enum, auto import re +import warnings from .common import ClientError, LoginError, InvalidProject from .merginproject import MerginProject @@ -434,23 +435,41 @@ def create_project(self, project_name, is_public=False, namespace=None): Create new project repository in user namespace on Mergin Maps server. Optionally initialized from given local directory. - :param project_name: Project name + :param project_name: Project's full name (/) :type project_name: String :param is_public: Flag for public/private project, defaults to False :type is_public: Boolean - :param namespace: Optional namespace for a new project. If empty username is used. + :param namespace: Deprecated. project_name should be full project name. Optional namespace for a new project. If empty username is used. :type namespace: String """ if not self._user_info: raise Exception("Authentication required") + if namespace and "/" not in project_name: + warnings.warn("The usage of `namespace` parameter in `create_project()` is deprecated." + "Specify `project_name` as full name (/)) instead.", + category=DeprecationWarning) + + if "/" in project_name: + if namespace: + warnings.warn("Parameter `namespace` specified with full project name (/)." + "The parameter will be ignored.") + + splitted = project_name.split("/") + project_name = splitted[1] + namespace = splitted[0] + elif namespace is None: + warnings.warn("The use of only project name in `create_project()` is deprecated." + "The `project_name` should be full name (/).", + category=DeprecationWarning) + params = {"name": project_name, "public": is_public} if namespace is None: namespace = self.username() try: - self.post("/v1/project/%s" % namespace, params, {"Content-Type": "application/json"}) + self.post(f"/v1/project/{namespace}", params, {"Content-Type": "application/json"}) except Exception as e: detail = f"Namespace: {namespace}, project name: {project_name}" raise ClientError(str(e), detail) diff --git a/mergin/test/test_client.py b/mergin/test/test_client.py index 891ab178..ee03fbaf 100644 --- a/mergin/test/test_client.py +++ b/mergin/test/test_client.py @@ -97,7 +97,7 @@ def test_login(mc): mc.login("foo", "bar") -def test_create_delete_project(mc): +def test_create_delete_project(mc: MerginClient): test_project = "test_create_delete" project = API_USER + "/" + test_project project_dir = os.path.join(TMP_DIR, test_project) @@ -122,6 +122,33 @@ def test_create_delete_project(mc): with pytest.raises(ClientError): mc.delete_project_now(API_USER + "/" + test_project) + # test that using namespace triggers deprecate warning, but creates project correctly + with pytest.deprecated_call(match=r"The usage of `namespace` parameter in `create_project\(\)` is deprecated."): + mc.create_project(test_project, namespace=API_USER) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == test_project and p["namespace"] == API_USER) + mc.delete_project_now(project) + + # test that using only project name triggers deprecate warning, but creates project correctly + with pytest.deprecated_call(match=r"The use of only project name in `create_project\(\)` is deprecated"): + mc.create_project(test_project) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == test_project and p["namespace"] == API_USER) + mc.delete_project_now(project) + + # test that even if project is specified with full name and namespace is specified a warning is raised, but still create project correctly + with pytest.warns(UserWarning, match="Parameter `namespace` specified with full project name"): + mc.create_project(project, namespace=API_USER) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == test_project and p["namespace"] == API_USER) + mc.delete_project_now(project) + + # test that create project with full name works + mc.create_project(project) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == test_project and p["namespace"] == API_USER) + mc.delete_project_now(project) + def test_create_remote_project_from_local(mc): test_project = "test_project" From 96212ef1ec5607139f46bfcf0d9c6bf9e10990b9 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 10:39:39 +0200 Subject: [PATCH 02/13] require cloned_project_name as full name, otherwise raise warnings --- mergin/client.py | 26 ++++++++++++++++++++++---- mergin/test/test_client.py | 30 +++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/mergin/client.py b/mergin/client.py index 5656a967..1d9f94d1 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -835,20 +835,38 @@ def clone_project(self, source_project_path, cloned_project_name, cloned_project Clone project on server. :param source_project_path: Project's full name (/) :type source_project_path: String - :param cloned_project_name: Cloned project's name + :param cloned_project_name: Cloned project's full name (/) :type cloned_project_name: String - :param cloned_project_namespace: Cloned project's namespace, username is used if not defined + :param cloned_project_namespace: Deprecated. cloned_project_name should be full project name. Cloned project's namespace, username is used if not defined :type cloned_project_namespace: String """ - path = "/v1/project/clone/%s" % source_project_path + + if cloned_project_namespace and "/" not in cloned_project_name: + warnings.warn("The usage of `cloned_project_namespace` parameter in `clone_project()` is deprecated." + "Speficy `cloned_project_name` as full name (/)) instead.", + category=DeprecationWarning) + + if "/" in cloned_project_name: + if cloned_project_namespace: + warnings.warn("Parameter `cloned_project_namespace` specified with full cloned project name (/)." + "The parameter will be ignored.") + + splitted = cloned_project_name.split("/") + cloned_project_name = splitted[1] + cloned_project_namespace = splitted[0] + elif cloned_project_namespace is None: + warnings.warn("The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." + "The `cloned_project_name` should be full name (/).", + category=DeprecationWarning) + + path = f"/v1/project/clone/{source_project_path}" url = urllib.parse.urljoin(self.url, urllib.parse.quote(path)) json_headers = {"Content-Type": "application/json", "Accept": "application/json"} data = { "namespace": cloned_project_namespace if cloned_project_namespace else self.username(), "project": cloned_project_name, } - request = urllib.request.Request(url, data=json.dumps(data).encode(), headers=json_headers, method="POST") self._do_request(request) diff --git a/mergin/test/test_client.py b/mergin/test/test_client.py index ee03fbaf..f02b88e9 100644 --- a/mergin/test/test_client.py +++ b/mergin/test/test_client.py @@ -586,7 +586,7 @@ def test_empty_file_in_subdir(mc): assert os.path.exists(os.path.join(project_dir_2, "subdir2", "empty2.txt")) -def test_clone_project(mc): +def test_clone_project(mc: MerginClient): test_project = "test_clone_project" test_project_fullname = API_USER + "/" + test_project @@ -600,14 +600,38 @@ def test_clone_project(mc): assert any(p for p in projects if p["name"] == test_project and p["namespace"] == API_USER) cloned_project_name = test_project + "_cloned" + test_cloned_project_fullname = API_USER + "/" + cloned_project_name + # cleanup cloned project cloned_project_dir = os.path.join(TMP_DIR, cloned_project_name) cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) - # clone project - mc.clone_project(test_project_fullname, cloned_project_name, API_USER) + # clone specifying cloned_project_namespace, does clone but raises deprecation warning + with pytest.deprecated_call(match=r"The usage of `cloned_project_namespace` parameter in `clone_project\(\)`"): + mc.clone_project(test_project_fullname, cloned_project_name, API_USER) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == cloned_project_name and p["namespace"] == API_USER) + cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) + + # clone without specifying cloned_project_namespace relies on workspace with user name, does clone but raises deprecation warning + with pytest.deprecated_call(match=r"The use of only project name as `cloned_project_name` in `clone_project\(\)`"): + mc.clone_project(test_project_fullname, cloned_project_name) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == cloned_project_name and p["namespace"] == API_USER) + cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) + + # clone project with full cloned project name with specification of `cloned_project_namespace` raises warning + with pytest.warns(match=r"Parameter `cloned_project_namespace` specified with full cloned project name"): + mc.clone_project(test_project_fullname, test_cloned_project_fullname, API_USER) projects = mc.projects_list(flag="created") assert any(p for p in projects if p["name"] == cloned_project_name and p["namespace"] == API_USER) + cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) + + # clone project using project full name + mc.clone_project(test_project_fullname, test_cloned_project_fullname) + projects = mc.projects_list(flag="created") + assert any(p for p in projects if p["name"] == cloned_project_name and p["namespace"] == API_USER) + cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) def test_set_read_write_access(mc): From 07ad3d06bcada8044eabdd0774b14cfc3482e261 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 10:40:20 +0200 Subject: [PATCH 03/13] mergin clone outputs messages about parameter deprecation, hides python warnings --- mergin/cli.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mergin/cli.py b/mergin/cli.py index ff1d027a..df05f70c 100755 --- a/mergin/cli.py +++ b/mergin/cli.py @@ -15,6 +15,7 @@ import sys import time import traceback +import warnings from mergin import ( ClientError, @@ -555,6 +556,15 @@ def clone(ctx, source_project_path, cloned_project_name, cloned_project_namespac if mc is None: return try: + if cloned_project_namespace: + click.secho("The usage of `cloned_project_namespace` parameter in `mergin clone` is deprecated." + "Speficy `cloned_project_name` as full name (/)) instead.", + fg="yellow") + if cloned_project_namespace is None and "/" not in cloned_project_name: + click.secho("The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." + "The `cloned_project_name` should be full name (/).", + fg="yellow") + warnings.filterwarnings("ignore") mc.clone_project(source_project_path, cloned_project_name, cloned_project_namespace) click.echo("Done") except ClientError as e: From 271fb6707486e5783230cbad114c97e94934138c Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 10:49:37 +0200 Subject: [PATCH 04/13] fix style --- mergin/cli.py | 16 ++++++++------ mergin/client.py | 44 ++++++++++++++++++++++++-------------- mergin/test/test_client.py | 4 ++-- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/mergin/cli.py b/mergin/cli.py index df05f70c..74d00945 100755 --- a/mergin/cli.py +++ b/mergin/cli.py @@ -557,13 +557,17 @@ def clone(ctx, source_project_path, cloned_project_name, cloned_project_namespac return try: if cloned_project_namespace: - click.secho("The usage of `cloned_project_namespace` parameter in `mergin clone` is deprecated." - "Speficy `cloned_project_name` as full name (/)) instead.", - fg="yellow") + click.secho( + "The usage of `cloned_project_namespace` parameter in `mergin clone` is deprecated." + "Speficy `cloned_project_name` as full name (/)) instead.", + fg="yellow", + ) if cloned_project_namespace is None and "/" not in cloned_project_name: - click.secho("The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." - "The `cloned_project_name` should be full name (/).", - fg="yellow") + click.secho( + "The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." + "The `cloned_project_name` should be full name (/).", + fg="yellow", + ) warnings.filterwarnings("ignore") mc.clone_project(source_project_path, cloned_project_name, cloned_project_namespace) click.echo("Done") diff --git a/mergin/client.py b/mergin/client.py index 1d9f94d1..bbaba231 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -448,22 +448,28 @@ def create_project(self, project_name, is_public=False, namespace=None): raise Exception("Authentication required") if namespace and "/" not in project_name: - warnings.warn("The usage of `namespace` parameter in `create_project()` is deprecated." - "Specify `project_name` as full name (/)) instead.", - category=DeprecationWarning) + warnings.warn( + "The usage of `namespace` parameter in `create_project()` is deprecated." + "Specify `project_name` as full name (/)) instead.", + category=DeprecationWarning, + ) if "/" in project_name: if namespace: - warnings.warn("Parameter `namespace` specified with full project name (/)." - "The parameter will be ignored.") + warnings.warn( + "Parameter `namespace` specified with full project name (/)." + "The parameter will be ignored." + ) splitted = project_name.split("/") project_name = splitted[1] namespace = splitted[0] elif namespace is None: - warnings.warn("The use of only project name in `create_project()` is deprecated." - "The `project_name` should be full name (/).", - category=DeprecationWarning) + warnings.warn( + "The use of only project name in `create_project()` is deprecated." + "The `project_name` should be full name (/).", + category=DeprecationWarning, + ) params = {"name": project_name, "public": is_public} if namespace is None: @@ -843,22 +849,28 @@ def clone_project(self, source_project_path, cloned_project_name, cloned_project """ if cloned_project_namespace and "/" not in cloned_project_name: - warnings.warn("The usage of `cloned_project_namespace` parameter in `clone_project()` is deprecated." - "Speficy `cloned_project_name` as full name (/)) instead.", - category=DeprecationWarning) + warnings.warn( + "The usage of `cloned_project_namespace` parameter in `clone_project()` is deprecated." + "Speficy `cloned_project_name` as full name (/)) instead.", + category=DeprecationWarning, + ) if "/" in cloned_project_name: if cloned_project_namespace: - warnings.warn("Parameter `cloned_project_namespace` specified with full cloned project name (/)." - "The parameter will be ignored.") + warnings.warn( + "Parameter `cloned_project_namespace` specified with full cloned project name (/)." + "The parameter will be ignored." + ) splitted = cloned_project_name.split("/") cloned_project_name = splitted[1] cloned_project_namespace = splitted[0] elif cloned_project_namespace is None: - warnings.warn("The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." - "The `cloned_project_name` should be full name (/).", - category=DeprecationWarning) + warnings.warn( + "The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." + "The `cloned_project_name` should be full name (/).", + category=DeprecationWarning, + ) path = f"/v1/project/clone/{source_project_path}" url = urllib.parse.urljoin(self.url, urllib.parse.quote(path)) diff --git a/mergin/test/test_client.py b/mergin/test/test_client.py index f02b88e9..410c0fd5 100644 --- a/mergin/test/test_client.py +++ b/mergin/test/test_client.py @@ -606,14 +606,14 @@ def test_clone_project(mc: MerginClient): cloned_project_dir = os.path.join(TMP_DIR, cloned_project_name) cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) - # clone specifying cloned_project_namespace, does clone but raises deprecation warning + # clone specifying cloned_project_namespace, does clone but raises deprecation warning with pytest.deprecated_call(match=r"The usage of `cloned_project_namespace` parameter in `clone_project\(\)`"): mc.clone_project(test_project_fullname, cloned_project_name, API_USER) projects = mc.projects_list(flag="created") assert any(p for p in projects if p["name"] == cloned_project_name and p["namespace"] == API_USER) cleanup(mc, API_USER + "/" + cloned_project_name, [cloned_project_dir]) - # clone without specifying cloned_project_namespace relies on workspace with user name, does clone but raises deprecation warning + # clone without specifying cloned_project_namespace relies on workspace with user name, does clone but raises deprecation warning with pytest.deprecated_call(match=r"The use of only project name as `cloned_project_name` in `clone_project\(\)`"): mc.clone_project(test_project_fullname, cloned_project_name) projects = mc.projects_list(flag="created") From aabfb8e34bed59589c6fb565c8845c5b24c6024c Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 15:21:51 +0200 Subject: [PATCH 05/13] fix typo Co-authored-by: Martin Dobias --- mergin/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mergin/cli.py b/mergin/cli.py index 74d00945..759237d3 100755 --- a/mergin/cli.py +++ b/mergin/cli.py @@ -559,7 +559,7 @@ def clone(ctx, source_project_path, cloned_project_name, cloned_project_namespac if cloned_project_namespace: click.secho( "The usage of `cloned_project_namespace` parameter in `mergin clone` is deprecated." - "Speficy `cloned_project_name` as full name (/)) instead.", + "Specify `cloned_project_name` as full name (/) instead.", fg="yellow", ) if cloned_project_namespace is None and "/" not in cloned_project_name: From 425c2f1e279e7b82c7788170bcb1cf5a02b1931a Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 15:24:02 +0200 Subject: [PATCH 06/13] fix typo Co-authored-by: Martin Dobias --- mergin/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mergin/client.py b/mergin/client.py index bbaba231..e0c62a63 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -851,7 +851,7 @@ def clone_project(self, source_project_path, cloned_project_name, cloned_project if cloned_project_namespace and "/" not in cloned_project_name: warnings.warn( "The usage of `cloned_project_namespace` parameter in `clone_project()` is deprecated." - "Speficy `cloned_project_name` as full name (/)) instead.", + "Specify `cloned_project_name` as full name (/) instead.", category=DeprecationWarning, ) From d6b45116a1010a08ce775a89a9430d3e5aa366b2 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 15:25:36 +0200 Subject: [PATCH 07/13] simplify splitting --- mergin/client.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mergin/client.py b/mergin/client.py index e0c62a63..a7c88f70 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -461,9 +461,8 @@ def create_project(self, project_name, is_public=False, namespace=None): "The parameter will be ignored." ) - splitted = project_name.split("/") - project_name = splitted[1] - namespace = splitted[0] + namespace, project_name = project_name.split("/") + elif namespace is None: warnings.warn( "The use of only project name in `create_project()` is deprecated." @@ -862,9 +861,8 @@ def clone_project(self, source_project_path, cloned_project_name, cloned_project "The parameter will be ignored." ) - splitted = cloned_project_name.split("/") - cloned_project_name = splitted[1] - cloned_project_namespace = splitted[0] + cloned_project_namespace, cloned_project_name = cloned_project_name.split("/") + elif cloned_project_namespace is None: warnings.warn( "The use of only project name as `cloned_project_name` in `clone_project()` is deprecated." From 27ea00ee0349e6d4f35423b9df4a894eafd04162 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 15:26:20 +0200 Subject: [PATCH 08/13] fix typo --- mergin/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mergin/client.py b/mergin/client.py index a7c88f70..e9f382d5 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -450,7 +450,7 @@ def create_project(self, project_name, is_public=False, namespace=None): if namespace and "/" not in project_name: warnings.warn( "The usage of `namespace` parameter in `create_project()` is deprecated." - "Specify `project_name` as full name (/)) instead.", + "Specify `project_name` as full name (/) instead.", category=DeprecationWarning, ) From 8ba3bd3c69e83e852716cf6065a4328cad2d3d07 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 15:40:36 +0200 Subject: [PATCH 09/13] clone using the preferred API call --- mergin/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mergin/cli.py b/mergin/cli.py index 759237d3..b36553e4 100755 --- a/mergin/cli.py +++ b/mergin/cli.py @@ -15,7 +15,6 @@ import sys import time import traceback -import warnings from mergin import ( ClientError, @@ -568,8 +567,9 @@ def clone(ctx, source_project_path, cloned_project_name, cloned_project_namespac "The `cloned_project_name` should be full name (/).", fg="yellow", ) - warnings.filterwarnings("ignore") - mc.clone_project(source_project_path, cloned_project_name, cloned_project_namespace) + if cloned_project_namespace and "/" not in cloned_project_name: + cloned_project_name = f"{cloned_project_namespace}/{cloned_project_name}" + mc.clone_project(source_project_path, cloned_project_name) click.echo("Done") except ClientError as e: click.secho("Error: " + str(e), fg="red") From dfc832d55f7d1a2f82c3f1ba11bbc5fe320ea99b Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 16:46:02 +0200 Subject: [PATCH 10/13] update create_project_and_push to use full project name --- mergin/client.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/mergin/client.py b/mergin/client.py index e9f382d5..f5062aca 100644 --- a/mergin/client.py +++ b/mergin/client.py @@ -482,20 +482,47 @@ def create_project(self, project_name, is_public=False, namespace=None): def create_project_and_push(self, project_name, directory, is_public=False, namespace=None): """ Convenience method to create project and push the initial version right after that. + + :param project_name: Project's full name (/) + :type project_name: String + + :param namespace: Deprecated. project_name should be full project name. Optional namespace for a new project. If empty username is used. + :type namespace: String """ if os.path.exists(os.path.join(directory, ".mergin")): raise ClientError("Directory is already assigned to a Mergin Maps project (contains .mergin sub-dir)") - if namespace is None: + if namespace and "/" not in project_name: + warnings.warn( + "The usage of `namespace` parameter in `create_project_and_push()` is deprecated." + "Specify `project_name` as full name (/) instead.", + category=DeprecationWarning, + ) + project_name = f"{namespace}/{project_name}" + + if "/" in project_name: + if namespace: + warnings.warn( + "Parameter `namespace` specified with full project name (/)." + "The parameter will be ignored." + ) + + elif namespace is None: + warnings.warn( + "The use of only project name in `create_project()` is deprecated." + "The `project_name` should be full name (/).", + category=DeprecationWarning, + ) namespace = self.username() - self.create_project(project_name, is_public, namespace) + project_name = f"{namespace}/{project_name}" + + self.create_project(project_name, is_public) if directory: - full_project_name = "{}/{}".format(namespace, project_name) - project_info = self.project_info(full_project_name) + project_info = self.project_info(project_name) MerginProject.write_metadata( directory, { - "name": full_project_name, + "name": project_name, "version": "v0", "files": [], "project_id": project_info["id"], From 24cd91d9cf4c0bcf2273523555aacf087d4ae408 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 12 Oct 2023 16:46:44 +0200 Subject: [PATCH 11/13] create_project_and_push use full name --- mergin/test/test_client.py | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/mergin/test/test_client.py b/mergin/test/test_client.py index 410c0fd5..febededf 100644 --- a/mergin/test/test_client.py +++ b/mergin/test/test_client.py @@ -161,7 +161,7 @@ def test_create_remote_project_from_local(mc): shutil.copytree(TEST_DATA_DIR, project_dir) # create remote project - mc.create_project_and_push(test_project, directory=project_dir) + mc.create_project_and_push(project, directory=project_dir) # verify we have correct metadata source_mp = MerginProject(project_dir) @@ -212,7 +212,7 @@ def test_push_pull_changes(mc): cleanup(mc, project, [project_dir, project_dir_2]) # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # make sure we have v1 also in concurrent project dir mc.download_project(project, project_dir_2) @@ -309,7 +309,7 @@ def test_cancel_push(mc): cleanup(mc, project, [project_dir, project_dir_2]) # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # modify the project (add, update) f_added = "new.txt" @@ -351,7 +351,7 @@ def test_ignore_files(mc): # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) shutil.copy(os.path.join(project_dir, "test.qgs"), os.path.join(project_dir, "test.qgs~")) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) project_info = mc.project_info(project) assert not next((f for f in project_info["files"] if f["path"] == "test.qgs~"), None) @@ -371,7 +371,7 @@ def test_sync_diff(mc): cleanup(mc, project, [project_dir, project_dir_2, project_dir_3]) # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # make sure we have v1 also in concurrent project dirs mc.download_project(project, project_dir_2) @@ -438,7 +438,7 @@ def test_list_of_push_changes(mc): cleanup(mc, project, [project_dir]) shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) f_updated = "base.gpkg" mp = MerginProject(project_dir) @@ -457,7 +457,7 @@ def test_token_renewal(mc): cleanup(mc, project, [project_dir]) shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) mc._auth_session["expire"] = datetime.now().replace(tzinfo=pytz.utc) - timedelta(days=1) pull_changes, push_changes, _ = mc.project_status(project_dir) @@ -473,7 +473,7 @@ def test_force_gpkg_update(mc): cleanup(mc, project, [project_dir]) # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # test push changes with force gpkg file upload: mp = MerginProject(project_dir) @@ -539,7 +539,7 @@ def test_missing_basefile_pull(mc): cleanup(mc, project, [project_dir, project_dir_2]) # create remote project shutil.copytree(test_data_dir, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # update our gpkg in a different directory mc.download_project(project, project_dir_2) @@ -570,7 +570,7 @@ def test_empty_file_in_subdir(mc): cleanup(mc, project, [project_dir, project_dir_2]) # create remote project shutil.copytree(test_data_dir, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # try to check out the project mc.download_project(project, project_dir_2) @@ -823,7 +823,7 @@ def test_download_versions(mc): cleanup(mc, project, [project_dir, project_dir_v1, project_dir_v2, project_dir_v3]) # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # create new version - v2 f_added = "new.txt" @@ -892,7 +892,7 @@ def test_missing_local_file_pull(mc): cleanup(mc, project, [project_dir, project_dir_2]) # create remote project shutil.copytree(test_data_dir, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # remove a file in a different directory mc.download_project(project, project_dir_2) @@ -935,7 +935,7 @@ def create_versioned_project(mc, project_name, project_dir, updated_file, remove # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(project_name, project_dir) + mc.create_project_and_push(project, project_dir) mp = MerginProject(project_dir) @@ -1083,7 +1083,7 @@ def test_modify_project_permissions(mc): shutil.copytree(TEST_DATA_DIR, project_dir) # create remote project - mc.create_project_and_push(test_project, directory=project_dir) + mc.create_project_and_push(project, directory=project_dir) # check basic metadata about created project project_info = mc.project_info(project) @@ -1219,7 +1219,7 @@ def test_push_gpkg_schema_change(mc): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) # shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) mp = MerginProject(project_dir) @@ -1298,7 +1298,7 @@ def test_rebase_local_schema_change(mc, extra_connection): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) _use_wal(test_gpkg) # make sure we use WAL, that's the more common and more difficult scenario - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) if extra_connection: # open a connection and keep it open (qgis does this with a pool of connections too) @@ -1364,7 +1364,7 @@ def test_rebase_remote_schema_change(mc, extra_connection): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) _use_wal(test_gpkg) # make sure we use WAL, that's the more common and more difficult scenario - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # Download project to the concurrent dir + change DB schema + push a new version mc.download_project(project, project_dir_2) @@ -1429,7 +1429,7 @@ def test_rebase_success(mc, extra_connection): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) _use_wal(test_gpkg) # make sure we use WAL, that's the more common and more difficult scenario - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # Download project to the concurrent dir + add a row + push a new version mc.download_project(project, project_dir_2) @@ -1590,7 +1590,7 @@ def test_unfinished_pull(mc): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) _use_wal(test_gpkg) # make sure we use WAL, that's the more common and more difficult scenario - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # Download project to the concurrent dir + change DB schema + push a new version mc.download_project(project, project_dir_2) @@ -1678,7 +1678,7 @@ def test_unfinished_pull_push(mc): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) _use_wal(test_gpkg) # make sure we use WAL, that's the more common and more difficult scenario - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # Download project to the concurrent dir + change DB schema + push a new version mc.download_project(project, project_dir_2) @@ -1882,7 +1882,7 @@ def test_report_failure(mc): os.makedirs(project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), test_gpkg) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "inserted_1_A.gpkg"), test_gpkg) mc.push_project(project_dir) @@ -1919,7 +1919,7 @@ def test_changesets_download(mc): os.makedirs(project_dir, exist_ok=True) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), file_path) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "inserted_1_A.gpkg"), file_path) mc.push_project(project_dir) @@ -1963,7 +1963,7 @@ def test_version_info(mc): os.makedirs(project_dir, exist_ok=True) shutil.copy(os.path.join(TEST_DATA_DIR, "base.gpkg"), file_path) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) shutil.copy(os.path.join(TEST_DATA_DIR, "inserted_1_A.gpkg"), file_path) mc.push_project(project_dir) @@ -1990,7 +1990,7 @@ def test_clean_diff_files(mc): cleanup(mc, project, [project_dir, project_dir_2]) # create remote project shutil.copytree(TEST_DATA_DIR, project_dir) - mc.create_project_and_push(test_project, project_dir) + mc.create_project_and_push(project, project_dir) # test push changes with diffs: mp = MerginProject(project_dir) From 5cc26f28eed3f37086ab015894df8ddbaeb82e9b Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 13 Oct 2023 08:30:31 +0200 Subject: [PATCH 12/13] create() uses project full name --- mergin/cli.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mergin/cli.py b/mergin/cli.py index b36553e4..6b1af55b 100755 --- a/mergin/cli.py +++ b/mergin/cli.py @@ -211,13 +211,14 @@ def create(ctx, project, public, from_dir): else: # namespace not specified, use current user namespace namespace = mc.username() + project_full_name = f"{namespace}/{project}" try: if from_dir is None: - mc.create_project(project, is_public=public, namespace=namespace) - click.echo("Created project " + project) + mc.create_project(project_full_name, is_public=public) + click.echo("Created project " + project_full_name) else: - mc.create_project_and_push(project, from_dir, is_public=public, namespace=namespace) - click.echo("Created project " + project + " and pushed content from directory " + from_dir) + mc.create_project_and_push(project_full_name, from_dir, is_public=public) + click.echo("Created project " + project_full_name + " and pushed content from directory " + from_dir) except ClientError as e: click.secho("Error: " + str(e), fg="red") return From 02d69bf175f5f9b44357aa2a5376b889facb74e8 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 13 Oct 2023 08:58:16 +0200 Subject: [PATCH 13/13] use project directly and let the MerginClient handle the issue of workspace --- mergin/cli.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/mergin/cli.py b/mergin/cli.py index 6b1af55b..7d5b5f95 100755 --- a/mergin/cli.py +++ b/mergin/cli.py @@ -200,25 +200,13 @@ def create(ctx, project, public, from_dir): mc = ctx.obj["client"] if mc is None: return - if "/" in project: - try: - namespace, project = project.split("/") - assert namespace, "No namespace given" - assert project, "No project name given" - except (ValueError, AssertionError) as e: - click.secho(f"Incorrect namespace/project format: {e}", fg="red") - return - else: - # namespace not specified, use current user namespace - namespace = mc.username() - project_full_name = f"{namespace}/{project}" try: if from_dir is None: - mc.create_project(project_full_name, is_public=public) - click.echo("Created project " + project_full_name) + mc.create_project(project, is_public=public) + click.echo("Created project " + project) else: - mc.create_project_and_push(project_full_name, from_dir, is_public=public) - click.echo("Created project " + project_full_name + " and pushed content from directory " + from_dir) + mc.create_project_and_push(project, from_dir, is_public=public) + click.echo("Created project " + project + " and pushed content from directory " + from_dir) except ClientError as e: click.secho("Error: " + str(e), fg="red") return