Skip to content

Commit 7ff8768

Browse files
authored
Fix awkward syntax of create_project, create_project_and_push, clone_project (#187)
Also fixes CLI to use the full project names (<workspace>/<name>) rather than having workspace separately
1 parent 5aa0b3c commit 7ff8768

3 files changed

Lines changed: 182 additions & 54 deletions

File tree

mergin/cli.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -200,23 +200,12 @@ def create(ctx, project, public, from_dir):
200200
mc = ctx.obj["client"]
201201
if mc is None:
202202
return
203-
if "/" in project:
204-
try:
205-
namespace, project = project.split("/")
206-
assert namespace, "No namespace given"
207-
assert project, "No project name given"
208-
except (ValueError, AssertionError) as e:
209-
click.secho(f"Incorrect namespace/project format: {e}", fg="red")
210-
return
211-
else:
212-
# namespace not specified, use current user namespace
213-
namespace = mc.username()
214203
try:
215204
if from_dir is None:
216-
mc.create_project(project, is_public=public, namespace=namespace)
205+
mc.create_project(project, is_public=public)
217206
click.echo("Created project " + project)
218207
else:
219-
mc.create_project_and_push(project, from_dir, is_public=public, namespace=namespace)
208+
mc.create_project_and_push(project, from_dir, is_public=public)
220209
click.echo("Created project " + project + " and pushed content from directory " + from_dir)
221210
except ClientError as e:
222211
click.secho("Error: " + str(e), fg="red")
@@ -555,7 +544,21 @@ def clone(ctx, source_project_path, cloned_project_name, cloned_project_namespac
555544
if mc is None:
556545
return
557546
try:
558-
mc.clone_project(source_project_path, cloned_project_name, cloned_project_namespace)
547+
if cloned_project_namespace:
548+
click.secho(
549+
"The usage of `cloned_project_namespace` parameter in `mergin clone` is deprecated."
550+
"Specify `cloned_project_name` as full name (<namespace>/<name>) instead.",
551+
fg="yellow",
552+
)
553+
if cloned_project_namespace is None and "/" not in cloned_project_name:
554+
click.secho(
555+
"The use of only project name as `cloned_project_name` in `clone_project()` is deprecated."
556+
"The `cloned_project_name` should be full name (<namespace>/<name>).",
557+
fg="yellow",
558+
)
559+
if cloned_project_namespace and "/" not in cloned_project_name:
560+
cloned_project_name = f"{cloned_project_namespace}/{cloned_project_name}"
561+
mc.clone_project(source_project_path, cloned_project_name)
559562
click.echo("Done")
560563
except ClientError as e:
561564
click.secho("Error: " + str(e), fg="red")

mergin/client.py

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import ssl
1515
from enum import Enum, auto
1616
import re
17+
import warnings
1718

1819
from .common import ClientError, LoginError, InvalidProject
1920
from .merginproject import MerginProject
@@ -434,44 +435,94 @@ def create_project(self, project_name, is_public=False, namespace=None):
434435
Create new project repository in user namespace on Mergin Maps server.
435436
Optionally initialized from given local directory.
436437
437-
:param project_name: Project name
438+
:param project_name: Project's full name (<namespace>/<name>)
438439
:type project_name: String
439440
440441
:param is_public: Flag for public/private project, defaults to False
441442
:type is_public: Boolean
442443
443-
:param namespace: Optional namespace for a new project. If empty username is used.
444+
:param namespace: Deprecated. project_name should be full project name. Optional namespace for a new project. If empty username is used.
444445
:type namespace: String
445446
"""
446447
if not self._user_info:
447448
raise Exception("Authentication required")
448449

450+
if namespace and "/" not in project_name:
451+
warnings.warn(
452+
"The usage of `namespace` parameter in `create_project()` is deprecated."
453+
"Specify `project_name` as full name (<namespace>/<name>) instead.",
454+
category=DeprecationWarning,
455+
)
456+
457+
if "/" in project_name:
458+
if namespace:
459+
warnings.warn(
460+
"Parameter `namespace` specified with full project name (<namespace>/<name>)."
461+
"The parameter will be ignored."
462+
)
463+
464+
namespace, project_name = project_name.split("/")
465+
466+
elif namespace is None:
467+
warnings.warn(
468+
"The use of only project name in `create_project()` is deprecated."
469+
"The `project_name` should be full name (<namespace>/<name>).",
470+
category=DeprecationWarning,
471+
)
472+
449473
params = {"name": project_name, "public": is_public}
450474
if namespace is None:
451475
namespace = self.username()
452476
try:
453-
self.post("/v1/project/%s" % namespace, params, {"Content-Type": "application/json"})
477+
self.post(f"/v1/project/{namespace}", params, {"Content-Type": "application/json"})
454478
except Exception as e:
455479
detail = f"Namespace: {namespace}, project name: {project_name}"
456480
raise ClientError(str(e), detail)
457481

458482
def create_project_and_push(self, project_name, directory, is_public=False, namespace=None):
459483
"""
460484
Convenience method to create project and push the initial version right after that.
485+
486+
:param project_name: Project's full name (<namespace>/<name>)
487+
:type project_name: String
488+
489+
:param namespace: Deprecated. project_name should be full project name. Optional namespace for a new project. If empty username is used.
490+
:type namespace: String
461491
"""
462492
if os.path.exists(os.path.join(directory, ".mergin")):
463493
raise ClientError("Directory is already assigned to a Mergin Maps project (contains .mergin sub-dir)")
464494

465-
if namespace is None:
495+
if namespace and "/" not in project_name:
496+
warnings.warn(
497+
"The usage of `namespace` parameter in `create_project_and_push()` is deprecated."
498+
"Specify `project_name` as full name (<namespace>/<name>) instead.",
499+
category=DeprecationWarning,
500+
)
501+
project_name = f"{namespace}/{project_name}"
502+
503+
if "/" in project_name:
504+
if namespace:
505+
warnings.warn(
506+
"Parameter `namespace` specified with full project name (<namespace>/<name>)."
507+
"The parameter will be ignored."
508+
)
509+
510+
elif namespace is None:
511+
warnings.warn(
512+
"The use of only project name in `create_project()` is deprecated."
513+
"The `project_name` should be full name (<namespace>/<name>).",
514+
category=DeprecationWarning,
515+
)
466516
namespace = self.username()
467-
self.create_project(project_name, is_public, namespace)
517+
project_name = f"{namespace}/{project_name}"
518+
519+
self.create_project(project_name, is_public)
468520
if directory:
469-
full_project_name = "{}/{}".format(namespace, project_name)
470-
project_info = self.project_info(full_project_name)
521+
project_info = self.project_info(project_name)
471522
MerginProject.write_metadata(
472523
directory,
473524
{
474-
"name": full_project_name,
525+
"name": project_name,
475526
"version": "v0",
476527
"files": [],
477528
"project_id": project_info["id"],
@@ -816,20 +867,43 @@ def clone_project(self, source_project_path, cloned_project_name, cloned_project
816867
Clone project on server.
817868
:param source_project_path: Project's full name (<namespace>/<name>)
818869
:type source_project_path: String
819-
:param cloned_project_name: Cloned project's name
870+
:param cloned_project_name: Cloned project's full name (<namespace>/<name>)
820871
:type cloned_project_name: String
821-
:param cloned_project_namespace: Cloned project's namespace, username is used if not defined
872+
:param cloned_project_namespace: Deprecated. cloned_project_name should be full project name. Cloned project's namespace, username is used if not defined
822873
:type cloned_project_namespace: String
823874
824875
"""
825-
path = "/v1/project/clone/%s" % source_project_path
876+
877+
if cloned_project_namespace and "/" not in cloned_project_name:
878+
warnings.warn(
879+
"The usage of `cloned_project_namespace` parameter in `clone_project()` is deprecated."
880+
"Specify `cloned_project_name` as full name (<namespace>/<name>) instead.",
881+
category=DeprecationWarning,
882+
)
883+
884+
if "/" in cloned_project_name:
885+
if cloned_project_namespace:
886+
warnings.warn(
887+
"Parameter `cloned_project_namespace` specified with full cloned project name (<namespace>/<name>)."
888+
"The parameter will be ignored."
889+
)
890+
891+
cloned_project_namespace, cloned_project_name = cloned_project_name.split("/")
892+
893+
elif cloned_project_namespace is None:
894+
warnings.warn(
895+
"The use of only project name as `cloned_project_name` in `clone_project()` is deprecated."
896+
"The `cloned_project_name` should be full name (<namespace>/<name>).",
897+
category=DeprecationWarning,
898+
)
899+
900+
path = f"/v1/project/clone/{source_project_path}"
826901
url = urllib.parse.urljoin(self.url, urllib.parse.quote(path))
827902
json_headers = {"Content-Type": "application/json", "Accept": "application/json"}
828903
data = {
829904
"namespace": cloned_project_namespace if cloned_project_namespace else self.username(),
830905
"project": cloned_project_name,
831906
}
832-
833907
request = urllib.request.Request(url, data=json.dumps(data).encode(), headers=json_headers, method="POST")
834908
self._do_request(request)
835909

0 commit comments

Comments
 (0)