diff --git a/docs/pages/async/workspace.md b/docs/pages/async/workspace.md index 463feae..4b7347b 100644 --- a/docs/pages/async/workspace.md +++ b/docs/pages/async/workspace.md @@ -1,9 +1,9 @@ -# Workspaces +# Workspaces -`geoserverx` allows users to access all/one workspace from GeoServer, along with ability to do CRUD operations on workspaces. +`geoserverx` allows users to access all/one workspace from GeoServer, along with ability to do CRUD operations on workspaces. !!! get "Get started" - To start using `geoserverx` in Sync mode, create a new instance of `AsyncGeoServerX` Class, ream more about it [here](https://geobeyond.github.io/geoserverx/pages/async/) +To start using `geoserverx` in Sync mode, create a new instance of `AsyncGeoServerX` Class, read more about it [here](https://geobeyond.github.io/geoserverx/pages/async/) ## Get all workspaces @@ -16,7 +16,7 @@ await client.get_all_workspaces() ## Get single workspace -This command fetches workspace with parameter as name of it from GeoServer. +Fetches workspace details. ```Python # Get workspace with name `cite` @@ -25,15 +25,15 @@ await client.get_workspace('cite') ## Create workspace -This command allows user to create new workspace. +This command allows user to create new workspace. Creating new workspace requires following parameters -| Parameter | Required | Default value | Data type | Description | -| ----------- | ----------- | ----------- |---- | ------------------------------------ | -| Name | :white_check_mark: | | `str` | To define Name of the workspace | -| default | :negative_squared_cross_mark: | `False` | `bool` | To define whether to keep workspace as default or not | -| isolated | :negative_squared_cross_mark: | `False` |`bool` | To define whether to keep workspace as Isolated or not | - +| Parameter | Required | Default value | Data type | Description | +| --------- | ----------------------------- | ------------- | --------- | ------------------------------------------------------ | +| Name | :white_check_mark: | | `str` | To define Name of the workspace | +| default | :negative_squared_cross_mark: | `False` | `bool` | To define whether to keep workspace as default or not | +| isolated | :negative_squared_cross_mark: | `False` | `bool` | To define whether to keep workspace as Isolated or not | + ```Python #Create new workspace with name `my_wrkspc` , make it Default and Isolated await client.create_workspace(name='my_wrkspc',default=True,Isolated=True) @@ -41,12 +41,12 @@ await client.create_workspace(name='my_wrkspc',default=True,Isolated=True) ## Delete workspace -This command allows user to delete workspace. +This command allows user to delete workspace. -| Parameter | Required | Default value | Data type | Description | -| ----------- | ----------- | ----------- | -- | ------------------------------------ | -| workspace | :white_check_mark: | | `str` | Name of the workspace | -| recurse | :negative_squared_cross_mark: | `False` | `bool` | This parameter recursively deletes all layers referenced by the specified workspace, including data stores, coverage stores, feature types, and so on | +| Parameter | Required | Default value | Data type | Description | +| --------- | ----------------------------- | ------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| workspace | :white_check_mark: | | `str` | Name of the workspace | +| recurse | :negative_squared_cross_mark: | `False` | `bool` | This parameter recursively deletes all layers referenced by the specified workspace, including data stores, coverage stores, feature types, and so on | ```Python #Delete workspace with name `my_wrkspc`. @@ -55,14 +55,14 @@ await client.delete_workspace(workspace='my_wrkspc',recurse=True) ## Update workspace -This command allows user to update existing workspace. +This command allows user to update existing workspace. Updating workspace requires following parameters -| Parameter | Required | Data type | Description | -| ----------- | ----------- | ----------- | ------------------------------------ | -| name | :white_check_mark: | `str` | Name of the workspace to be updated | -| update | :white_check_mark: | [`UpdateWorkspaceInfo`](https://github.com/geobeyond/geoserverx/blob/b7757c9f0130864b06c40c2faa17afc841fc705f/src/geoserverx/models/workspace.py#L42) | To define body of the update request | - +| Parameter | Required | Data type | Description | +| --------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| name | :white_check_mark: | `str` | Name of the workspace to be updated | +| update | :white_check_mark: | [`UpdateWorkspaceInfo`](https://github.com/geobeyond/geoserverx/blob/b7757c9f0130864b06c40c2faa17afc841fc705f/src/geoserverx/models/workspace.py#L42) | To define body of the update request | + ```Python #Updating workspace with name `my_wrkspc` , make is Isolated and rename it to `my_new_wrkspc` from geoserverx.models.workspace import UpdateWorkspaceInfo diff --git a/docs/pages/sync/workspace.md b/docs/pages/sync/workspace.md index 08cff4c..e2b6568 100644 --- a/docs/pages/sync/workspace.md +++ b/docs/pages/sync/workspace.md @@ -1,12 +1,12 @@ -# Workspaces +# Workspaces -`geoserverx` allows users to access all/one workspace from GeoServer, along with ability to do CRUD operations on workspaces. +`geoserverx` allows users to access all/one workspace from GeoServer, along with ability to do CRUD operations on workspaces. !!! get "Get started" - To start using `geoserverx` in Sync mode, create a new instance of `SyncGeoServerX` Class, ream more about it [here](https://geobeyond.github.io/geoserverx/pages/sync/) - +To start using `geoserverx` in Sync mode, create a new instance of `SyncGeoServerX` Class, read more about it [here](https://geobeyond.github.io/geoserverx/pages/sync/) ## Get all workspaces + This command fetches all workspaces available in GeoServer. No paramters are required to be passed. ```Python @@ -15,37 +15,37 @@ client.get_all_workspaces() ``` ## Get single workspace + This command fetches workspace with parameter as name of it from GeoServer. + ```Python # Get workspace with name `cite` client.get_workspace('cite') ``` ## Create workspace -This command allows user to create new workspace. - -| Parameter | Required | Default value | Data type | Description | -| ----------- | ----------- | ----------- |---- | ------------------------------------ | -| Name | :white_check_mark: | | `str` | workspace name | -| default | :negative_squared_cross_mark: | `False` | `bool` | whether to keep workspace as default | -| isolated | :negative_squared_cross_mark: | `False` |`bool` | set workspace as being isolated | - + +This command allows user to create new workspace. + +| Parameter | Required | Default value | Data type | Description | +| --------- | ----------------------------- | ------------- | --------- | ----------------------------------------------------- | +| Name | :white_check_mark: | | `str` | To define Name of the workspace | +| default | :negative_squared_cross_mark: | `False` | `bool` | To define whether to keep workspace as default or not | +| isolated | :negative_squared_cross_mark: | `False` | `bool` | To define whether to keep workspace as default or not | + ```Python #Create new workspace with name `my_wrkspc` , make it Default and Isolated client.create_workspace(name='my_wrkspc',default=True,Isolated=True) ``` ## Delete workspace -This command allows user to delete workspace. - - - -| Parameter | Required | Default value | Data type | Description | -| ----------- | ----------- | ----------- | -- | ------------------------------------ | -| workspace | :white_check_mark: | | `str` | Name of the workspace | -| recurse | :negative_squared_cross_mark: | `False` | `bool` | This parameter recursively deletes all layers referenced by the specified workspace, including data stores, coverage stores, feature types, and so on | +This command allows user to delete workspace. +| Parameter | Required | Default value | Data type | Description | +| --------- | ----------------------------- | ------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| workspace | :white_check_mark: | | `str` | Name of the workspace | +| recurse | :negative_squared_cross_mark: | `False` | `bool` | This parameter recursively deletes all layers referenced by the specified workspace, including data stores, coverage stores, feature types, and so on | ```Python #Delete workspace with name `my_wrkspc`. @@ -53,16 +53,17 @@ client.delete_workspace(workspace='my_wrkspc',recurse=True) ``` ## Update workspace -This command allows user to update existing workspace. -| Parameter | Required | Data type | Description | -| ----------- | ----------- | ----------- | ------------------------------------ | -| name | :white_check_mark: | `str` | Name of the workspace to be updated | -| update | :white_check_mark: | [`UpdateWorkspaceInfo`](https://github.com/geobeyond/geoserverx/blob/b7757c9f0130864b06c40c2faa17afc841fc705f/src/geoserverx/models/workspace.py#L42) | To define body of the update request | - +This command allows user to update existing workspace. + +| Parameter | Required | Data type | Description | +| --------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| name | :white_check_mark: | `str` | Name of the workspace to be updated | +| update | :white_check_mark: | [`UpdateWorkspaceInfo`](https://github.com/geobeyond/geoserverx/blob/b7757c9f0130864b06c40c2faa17afc841fc705f/src/geoserverx/models/workspace.py#L42) | To define body of the update request | + ```Python #Updating workspace with name `my_wrkspc` , make is Isolated and rename it to `my_new_wrkspc` from geoserverx.models.workspace import UpdateWorkspaceInfo client.update_workspace(name='my_wrkspc',update=UpdateWorkspaceInfo(name='my_new_wrkspc',isolated=True)) -``` \ No newline at end of file +``` diff --git a/src/geoserverx/cli/cli.py b/src/geoserverx/cli/cli.py index 1539dd2..17a7211 100644 --- a/src/geoserverx/cli/cli.py +++ b/src/geoserverx/cli/cli.py @@ -1,4 +1,3 @@ -import json from enum import Enum from pathlib import Path from typing import Optional @@ -15,6 +14,11 @@ console = Console() +class OutputFormats(str, Enum): + json = "json" + table = "table" + + @app.callback() def callback(): """ @@ -43,7 +47,7 @@ def workspaces( ), password: str = typer.Option("geoserver", help="Geoserver Password"), username: str = typer.Option("admin", help="Geoserver username"), - output: str = typer.Option("table", help="Output format - 'json' or 'table'"), + output: OutputFormats = typer.Option(OutputFormats.table), ): """ Get all workspaces in the Geoserver @@ -53,10 +57,10 @@ def workspaces( client = SyncGeoServerX(username, password, url) result = client.get_all_workspaces() if "code" in result: - typer.secho(result, fg=typer.colors.RED) + print(result) else: if output == "json": - print(json.dumps(result.model_dump(), indent=2)) + print(result.model_dump_json(indent=2)) else: try: table = Table("Name", "Link") @@ -64,9 +68,9 @@ def workspaces( table.add_row(workspace.name, workspace.href) console.print(table) except AttributeError: - typer.secho(result.response, fg=typer.colors.RED) + print(result.response) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -79,7 +83,7 @@ def workspace( ), password: str = typer.Option("geoserver", help="Geoserver Password"), username: str = typer.Option("admin", help="Geoserver username"), - output: str = typer.Option("table", help="Output format - 'json' or 'table'"), + output: OutputFormats = typer.Option(OutputFormats.table), ): """ Get workspace in the Geoserver @@ -89,10 +93,10 @@ def workspace( client = SyncGeoServerX(username, password, url) result = client.get_workspace(workspace) if "code" in result: - typer.secho(result, fg=typer.colors.RED) + print(result) else: if output == "json": - print(json.dumps(result.model_dump(), indent=2)) + print(result.model_dump_json(indent=2)) else: try: table = Table("Column", "Value") @@ -105,9 +109,9 @@ def workspace( table.add_row("wmtsStores", result.workspace.wmtsStores) console.print(table) except AttributeError: - typer.secho(result.response, fg=typer.colors.RED) + print(result.response) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -131,7 +135,7 @@ def delete_workspace( result = client.delete_workspace(workspace, recurse) print(result.response) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -157,7 +161,7 @@ def create_workspace( print(result.response) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -186,7 +190,7 @@ def update_workspace( print(result.response) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -206,12 +210,9 @@ def vector_st_wp( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_vector_stores_in_workspaces(workspace).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -231,12 +232,9 @@ def raster_st_wp( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_raster_stores_in_workspaces(workspace).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -257,12 +255,9 @@ def vector_store( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_vector_store(workspace, store).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -283,12 +278,9 @@ def raster_store( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_raster_store(workspace, store).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -307,12 +299,9 @@ def styles( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_all_styles().model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -332,12 +321,9 @@ def style( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_style(style).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -364,14 +350,11 @@ def create_file( result = client.create_file_store( workspace, store, files.read(), service_type ) - if result.code == 201: - typer.secho(result, fg=typer.colors.GREEN) - else: - typer.secho(result, fg=typer.colors.RED) + print(result) except Exception: - typer.secho("File path is incorrect", fg=typer.colors.YELLOW) + print("File path is incorrect") else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -405,12 +388,9 @@ def create_pg_store( password=dbpwd, database=dbname, ) - if result.code == 201: - typer.secho(result, fg=typer.colors.GREEN) - else: - typer.secho(result, fg=typer.colors.RED) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -430,12 +410,9 @@ def layers( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_all_layers(workspace).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -457,12 +434,9 @@ def layer( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_layer(workspace, layer, detail).model_dump_json() - if "code" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -482,12 +456,9 @@ def layer_groups( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_all_layer_groups(workspace).json() - if "layerGroups" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -506,12 +477,9 @@ def geofence_rules( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_all_geofence_rules().model_dump_json() - if "rules" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") @SyncGeoServerX.exception_handler @@ -531,9 +499,6 @@ def geofence_rule( if request.value == "sync": client = SyncGeoServerX(username, password, url) result = client.get_geofence_rule(id).model_dump_json() - if "rule" in result: - typer.secho(result, fg=typer.colors.RED) - else: - print(result) + print(result) else: - typer.echo("Async support will be shortly") + print("Async support will be shortly") diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index c858656..ac21f3a 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -1,5 +1,3 @@ -from typing import Any, Dict - import httpx import pytest from typer.testing import CliRunner @@ -9,38 +7,38 @@ runner = CliRunner() baseUrl = "http://127.0.0.1:8080/geoserver/rest/" -# Test data -WORKSPACE_TEST_CASES = [ - {"name": "aa", "href": "http://127.0.0.1:8080/geoserver/rest/workspaces/aa.json"}, - { - "name": "aaba", - "href": "http://127.0.0.1:8080/geoserver/rest/workspaces/aaba.json", - }, -] - - -@pytest.fixture -def workspace_response() -> Dict[str, Any]: - return {"workspaces": {"workspace": WORKSPACE_TEST_CASES}} -def test_get_all_workspaces_success(workspace_response, respx_mock): +# Test - workspaces +def test_get_all_workspaces_success(respx_mock): """Test getting all workspaces""" + # Test data + workspace_response = { + "workspaces": { + "workspace": [ + { + "name": "aa", + "href": "http://127.0.0.1:8080/geoserver/rest/workspaces/aa.json", + }, + { + "name": "aaba", + "href": "http://127.0.0.1:8080/geoserver/rest/workspaces/aaba.json", + }, + ] + } + } + # Mock the response respx_mock.get(f"{baseUrl}workspaces").mock( return_value=httpx.Response(200, json=workspace_response) ) + # Invoke the command result = runner.invoke(app, ["workspaces", "--output", "json"]) + # Assertions assert result.exit_code == 0 - for workspace in WORKSPACE_TEST_CASES: + for workspace in workspace_response["workspaces"]["workspace"]: assert workspace["name"] in result.output -def test_get_all_workspaces_NetworkError(respx_mock): - respx_mock.get(f"{baseUrl}workspaces").mock(side_effect=httpx.ConnectError) - result = runner.invoke(app, ["workspaces"]) - assert "Error in connecting to Geoserver" in result.stdout - - # Test - get_workspace @pytest.mark.parametrize( "workspace_name,status_code,response_data,expected_response",