Skip to content

Commit

Permalink
Nicer DB rename method (#134)
Browse files Browse the repository at this point in the history
* remove feature flags

* nice rename api

* align name for list workspaces

* workspace create

* align list for branches

* cursor and next page methods

* prep release 1.0.0a3
  • Loading branch information
philkra authored Jul 7, 2023
1 parent da8891c commit 19075d7
Show file tree
Hide file tree
Showing 24 changed files with 254 additions and 40 deletions.
8 changes: 4 additions & 4 deletions codegen/api-rename-mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"name": "list"
},
"renameDatabase": {
"template": "endpoint",
"template": "database_rename",
"name": "rename"
}
},
Expand All @@ -60,10 +60,10 @@
"workspaces": {
"getWorkspacesList": {
"template": "endpoint",
"name": "get_workspaces"
"name": "list"
},
"createWorkspace": {
"template": "endpoint",
"template": "workspace_create",
"name": "create"
},
"getWorkspace": {
Expand Down Expand Up @@ -94,7 +94,7 @@
"branch": {
"getBranchList": {
"template": "endpoint",
"name": "get_branches"
"name": "list"
},
"getBranchDetails": {
"template": "endpoint",
Expand Down
34 changes: 34 additions & 0 deletions codegen/templates/database_rename.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

def ${operation_id}(self, db_name: str, new_name: str, workspace_id: str = None) -> ApiResponse:
"""
% for line in description :
${line}
% endfor

Path: ${path}
Method: ${http_method}
Response status codes:
% for rc in params['response_codes']:
- ${rc["code"]}: ${rc["description"]}
% endfor
% if len(params['response_content_types']) > 1 :
Responses:
% for rc in params['response_content_types']:
- ${rc["content_type"]}
% endfor
% elif len(params['response_content_types']) == 1 :
Response: ${params['response_content_types'][0]["content_type"]}
% endif

:param db_name: str Current database name
:param new_name: str New database name
:param workspace_id: str = None The workspace identifier. Default: workspace Id from the client.

:return Response
"""
if workspace_id is None:
workspace_id = self.client.get_workspace_id()
payload = {"newName": new_name}
url_path = f"${path}"
headers = {"content-type": "application/json"}
return self.request("${http_method}", url_path, headers, payload)
33 changes: 33 additions & 0 deletions codegen/templates/workspace_create.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

def ${operation_id}(self, name: str, slug: str = None) -> ApiResponse:
"""
% for line in description :
${line}
% endfor

Path: ${path}
Method: ${http_method}
Response status codes:
% for rc in params['response_codes']:
- ${rc["code"]}: ${rc["description"]}
% endfor
% if len(params['response_content_types']) > 1 :
Responses:
% for rc in params['response_content_types']:
- ${rc["content_type"]}
% endfor
% elif len(params['response_content_types']) == 1 :
Response: ${params['response_content_types'][0]["content_type"]}
% endif

:param name: str Workspace name
:param slug: str = None Slug to use

:return Response
"""
payload = {"name": name}
if slug:
payload["slug"] = slug
url_path = "${path}"
headers = {"content-type": "application/json"}
return self.request("${http_method}", url_path, headers, payload)
2 changes: 1 addition & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ Xata Client
.. autoclass:: Branch
:members:
.. autoclass:: Databases
:members:
:members:
6 changes: 3 additions & 3 deletions examples/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@
resp = xata.data().query("nba_teams", query)

# Print teams
for team in resp.json()["records"]:
for team in resp["records"]:
print("[%s] %s: %s, %s" % (team["conference"], team["state"], team["name"], team["city"]))

# Update controls
more = resp.json()["meta"]["page"].get("more", False) # has another page with results
cursor = resp.json()["meta"]["page"]["cursor"] # save next cursor for results
more = resp.has_more_results() # has another page with results
cursor = resp.get_cursor() # save next cursor for results

# Output:
# [west] California: LA Lakers, Los Angeles
Expand Down
12 changes: 6 additions & 6 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "xata"
version = "1.0.0a2"
version = "1.0.0a3"
description = "Python client for Xata.io"
authors = ["Xata <support@xata.io>"]
license = "Apache-2.0"
Expand Down
48 changes: 48 additions & 0 deletions tests/integration-tests/api_response_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,38 @@
# under the License.
#

import utils

from xata.client import XataClient


class TestApiResponse(object):
def setup_class(self):
self.db_name = utils.get_db_name()
self.client = XataClient(db_name=self.db_name)
assert self.client.databases().create(self.db_name).is_success()
assert self.client.table().create("Posts").is_success()
assert self.client.table().set_schema("Posts", utils.get_posts_schema()).is_success()

payload = {
"operations": [
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
{"insert": {"table": "Posts", "record": utils.get_post()}},
]
}
assert self.client.records().transaction(payload).is_success()

def teardown_class(self):
assert self.client.databases().delete(self.db_name).is_success()

def test_is_success_true(self):
user = XataClient().users().get()
assert user.is_success()
Expand All @@ -36,3 +64,23 @@ def test_direct_repr_and_json_are_the_same(self):
user = XataClient().users().get()
assert user.is_success()
assert user == user.json()

def test_get_cursor_and_has_more_results(self):
query = {
"columns": ["*"],
"page": {"size": 9, "after": None},
}
posts = self.client.data().query("Posts", query)
assert posts.is_success()
assert len(posts["records"]) == 9
assert posts.has_more_results()
assert posts.get_cursor() is not None

query = {
"columns": ["*"],
"page": {"size": 6, "after": posts.get_cursor()},
}
posts = self.client.data().query("Posts", query)
assert posts.is_success()
assert len(posts["records"]) == 1
assert not posts.has_more_results()
4 changes: 2 additions & 2 deletions tests/integration-tests/branch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def teardown_class(self):
assert r.is_success()

def test_get_branch_list(self):
r = self.client.branch().get_branches(self.db_name)
r = self.client.branch().list(self.db_name)
assert r.is_success()
assert "databaseName" in r
assert "branches" in r
Expand All @@ -63,7 +63,7 @@ def test_get_branch_list(self):
assert "createdAt" in r["branches"][0]
assert r["branches"][0]["name"] == "main"

r = self.client.branch().get_branches("NonExistingDatabase")
r = self.client.branch().list("NonExistingDatabase")
assert r.status_code == 404
assert not r.is_success()

Expand Down
23 changes: 22 additions & 1 deletion tests/integration-tests/databases_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def test_update_database_metadata(self):
self.client.databases().update_metadata(self.db_name, metadata, workspace_id="NonExistingWorkspaceId")
assert str(e.value)[0:23] == "code: 401, unauthorized"

# run last for cleanup
def test_delete_database(self):
r = self.client.databases().delete(self.db_name)
assert r.is_success()
Expand All @@ -103,6 +102,28 @@ def test_delete_database(self):
self.client.databases().delete(self.db_name, workspace_id="NonExistingWorkspaceId")
assert str(e.value)[0:23] == "code: 401, unauthorized"

def test_rename_database(self):
h = utils.get_random_string(6)
new_name = "rename_new-db-test-%s" % h
orig_name = "rename_orig-db-test-%s" % h
assert self.client.databases().create(orig_name).is_success()

r = self.client.databases().rename(orig_name, new_name)
assert r.is_success()
assert "name" in r
assert "region" in r
assert r["name"] == new_name
assert r["region"] == self.client.get_region()

assert not self.client.databases().rename("NonExistingDatabase", new_name).is_success()
assert not self.client.databases().rename("NonExistingDatabase", orig_name).is_success()

with pytest.raises(UnauthorizedError) as e:
self.client.databases().rename(new_name, orig_name, workspace_id="NonExistingWorkspaceId")
assert str(e.value)[0:23] == "code: 401, unauthorized"

assert self.client.databases().delete(new_name).is_success()

def test_get_available_regions(self):
r = self.client.databases().get_regions()
assert r.is_success()
Expand Down
1 change: 0 additions & 1 deletion tests/integration-tests/files_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def setup_class(self):
self.db_name = utils.get_db_name()
self.branch_name = "main"
self.client = XataClient(db_name=self.db_name, branch_name=self.branch_name)
self.client.set_header("X-Xata-Files", "true")
self.fake = utils.get_faker()

assert self.client.databases().create(self.db_name).is_success()
Expand Down
1 change: 0 additions & 1 deletion tests/integration-tests/files_multiple_files_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def setup_class(self):
self.db_name = utils.get_db_name()
self.branch_name = "main"
self.client = XataClient(db_name=self.db_name, branch_name=self.branch_name)
self.client.set_header("X-Xata-Files", "true")
self.fake = utils.get_faker()

assert self.client.databases().create(self.db_name).is_success()
Expand Down
1 change: 0 additions & 1 deletion tests/integration-tests/files_single_file_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def setup_class(self):
self.db_name = utils.get_db_name()
self.branch_name = "main"
self.client = XataClient(db_name=self.db_name, branch_name=self.branch_name)
self.client.set_header("X-Xata-Files", "true")
self.fake = Faker()

assert self.client.databases().create(self.db_name).is_success()
Expand Down
3 changes: 1 addition & 2 deletions tests/integration-tests/helpers_bulkprocessor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def setup_class(self):
assert r.is_success()

def teardown_class(self):
r = self.client.databases().delete(self.db_name)
assert r.is_success()
assert self.client.databases().delete(self.db_name).is_success()

@pytest.fixture
def record(self) -> dict:
Expand Down
20 changes: 20 additions & 0 deletions tests/integration-tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,23 @@ def get_file(file_name: str, public_url: bool = False, signed_url_timeout: int =
"enablePublicUrl": public_url,
"signedUrlTimeout": signed_url_timeout,
}


def get_post() -> dict:
return {
"title": get_faker().company(),
"labels": [get_faker().domain_word(), get_faker().domain_word()],
"slug": get_faker().catch_phrase(),
"content": get_faker().text(),
}


def get_posts_schema() -> dict:
return {
"columns": [
{"name": "title", "type": "string"},
{"name": "labels", "type": "multiple"},
{"name": "slug", "type": "string"},
{"name": "content", "type": "text"},
]
}
17 changes: 10 additions & 7 deletions tests/integration-tests/workspaces_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def setup_class(self):
self.workspace_name = "py-sdk-tests-%s" % utils.get_random_string(6)

def test_list_workspaces(self):
r = self.client.workspaces().get_workspaces()
r = self.client.workspaces().list()
assert r.is_success()
assert "workspaces" in r
assert len(r["workspaces"]) > 0
Expand All @@ -41,12 +41,7 @@ def test_list_workspaces(self):
assert "role" in r["workspaces"][0]

def test_create_new_workspace(self):
r = self.client.workspaces().create(
{
"name": self.workspace_name,
"slug": "sluginator",
}
)
r = self.client.workspaces().create(self.workspace_name, "sluginator")
assert r.is_success()
assert "id" in r
assert "name" in r
Expand All @@ -58,6 +53,14 @@ def test_create_new_workspace(self):

pytest.workspaces["workspace"] = r

def test_create_new_workspace_without_slug(self):
ws_id = "py-sdk-test-ws-without-slug-%s" % utils.get_random_string(4)
r = self.client.workspaces().create(ws_id)
assert r.is_success()
assert r["name"] == ws_id
assert r["slug"] == ws_id
assert self.client.workspaces().delete(r["id"]).is_success()

def test_get_workspace(self):
r = self.client.workspaces().get(workspace_id=pytest.workspaces["workspace"]["id"])
assert r.is_success()
Expand Down
Loading

0 comments on commit 19075d7

Please sign in to comment.