Skip to content

Commit

Permalink
merging develop to main (#66)
Browse files Browse the repository at this point in the history
* addd layer rest api (#43)

* added layer REST

* updated all pages

* param workspace added to get_all_layers

* added delete layer api

* addd layer rest api (#43)

* added layer REST

* updated all pages

* param workspace added to get_all_layers

* added delete layer api

* upgraded version in pyproject (#44)

* fixed all pydantic calls (#51)

* fixed all pydantic calls

* upgraded constraints file

* updated version of checkout and python in test.yml

* updated poetry version in contraints

* trying poetry installer

* updated poetry installation method in release.yml

* fixed few pydanticv2 issues (#53)

* fixed suggestions as per review (#54)

* Feature/create-stores (#46)

* added vector and raster store function

* added vector and raster store

* fixed test issue

* updated add vector layer to omit null

* updated good_layer_connection

* fixed suggestions as per review

* added vector and raster store function

* added vector and raster store

* fixed test issue

* updated add vector layer to omit null

* updated good_layer_connection

* fixed suggestions as per review

* added vector and raster store

* updated add vector layer to omit null

* Feature/layer-group (#52)

* added get layer group function

* fixed model names and lowercased function names in test

* added tests for LayerGroupsModel

* fixed as per pydanticv2 protocol (#55)

* fixed issues as per ruff (#57)

* using black isort and ruff in the test CI pipeline (#63)

* using black isort and ruff in the test CI pipeline

* removed duplicate installation

* testing with black and isort marketplace options

* testing black action

* testing with ruff

* fixed black .

* updated black and ruff version and run black again

* fixed as per isort

* added profile black to isort in CI

* testing if ruff gives error in CI

* fixed black but keeping error as per ruff

* fixed as per ruff

* updated readme (#59)

* updated readme

* using black isort and ruff in the test CI pipeline (#63)

* using black isort and ruff in the test CI pipeline

* removed duplicate installation

* testing with black and isort marketplace options

* testing black action

* testing with ruff

* fixed black .

* updated black and ruff version and run black again

* fixed as per isort

* added profile black to isort in CI

* testing if ruff gives error in CI

* fixed black but keeping error as per ruff

* fixed as per ruff

* Feature/get-geofence (#56)

* added base code to get geofence rules

* added header to geofence function

* added tests for geofence

* added single geofence rule

* adding new geofence rule

* added check_modules as per #58

* linting done

* added try: except in checl_module

* hotfix response schema to get geofence rule

* fixed as black

* hotfix - returning response in case of http error

* fixed remaining geofence functions

* added custom exception

* fixed as per black

* updated version to 0.0.4 (#64)

* updated version to 0.0.4

* updated description

* added readme config to toml

* update documents (#65)

* update docs

* updated requirements.txt

* updated flow for docs

* updating workflow file

* added site_url to mkdocs

* updated toml for mypu

* updated lock file

* fixed as per black
  • Loading branch information
krishnaglodha authored Nov 4, 2024
1 parent 4baa8cd commit 6434948
Show file tree
Hide file tree
Showing 74 changed files with 3,086 additions and 1,041 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/constraints.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pip==24.0
pip==24.2
poetry==1.8.3
virtualenv==20.26.0
virtualenv==20.26.3
11 changes: 9 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.5.1
- name: Install dependencies
run: poetry install --with docs
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v3
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install mkdocs-material
- run: mkdocs gh-deploy --force
- name: Deploy Documentation
run: |
poetry run mkdocs gh-deploy --force
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ jobs:
pip install --upgrade pip
pip --version
- name: Install Poetry
run: |
pip install poetry
poetry --version
uses: snok/install-poetry@v1
with:
version: 1.5.1
- name: Check if there is a parent commit
id: check-parent-commit
run: |
Expand Down
22 changes: 15 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ jobs:

steps:
- name: Check out the repository
uses: actions/checkout@v3.3.0
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v4.5.0
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}

Expand All @@ -44,15 +44,23 @@ jobs:
with open(os.environ["GITHUB_ENV"], mode="a") as io:
print(f"VIRTUALENV_PIP={pip.__version__}", file=io)
- name: Install Poetry
run: |
pip install poetry
poetry --version
uses: snok/install-poetry@v1
with:
version: 1.5.1
- name: Install dependencies
run: poetry install
- name: Run tests
run: poetry run pytest

- name: Run black
uses: psf/black@stable

- name: Run isort
uses: isort/isort-action@v1
with :
configuration : "--profile black"

- name : Ruff Check
uses: jpetrucciani/ruff-check@main
with:
black_args: "."
flags: '--fix'
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,21 @@ A GeoServer REST API client influenced by HTTPX

-----------

`geoserverx` allows `Sync` as well as `Async` Capabilities to talk to your geoserver REST APIs
`geoserverx` allows `Sync`, `Async` as well as `CLI` Capabilities to talk to your GeoServer REST APIs which makes it ideal to be used in software development project which relies on content of GeoServer.

Here is a simplistic view of how geoserverx works under the hood
![architecture](/docs/assets/images/arch.png "architecture")





## Contribution guide

### Feature/Bug request
Please open new issue if you want to report any bug or send feature request

### Running on local
`geoserverx` is built with [poetry](https://python-poetry.org/) and it uses following dependencies and dev-dependencies

![layout](/docs/assets/images/layout.png "layout")
Binary file added docs/assets/images/arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/layout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 20 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
---
hide:
- navigation
- toc

title : GeoServerX
description: modern python and CLI package for communicating with GeoServer
---
# Welcome to geoserverx

`geoserverx` is a modern Python package that provides an efficient and scalable way to interact with Geoserver REST APIs. It leverages the asynchronous capabilities of Python to offer a high-performance and reliable solution for managing Geoserver data and services.
Expand All @@ -24,13 +32,22 @@ pip install geoserverx

After which , It can be used in Python projects using <i>sync, async</i> methods or can ve used as Command Line tool

## Architecture

`geoserverx` is built on top of `httpx` and `pydantic` libraries. It uses `httpx` for making HTTP requests and `pydantic` for data validation. The package is designed to be modular and extensible, allowing for easy integration with other libraries and frameworks.

The package is structured into two main components: the `SyncGeoServerX` class and the `AsyncGeoServerX` class. The `SyncGeoServerX` class provides synchronous methods for interacting with Geoserver, while the `AsyncGeoServerX` class provides asynchronous methods using the `anyio` library

![layout](./assets/images/layout.png){ align=left }


## For testing purpose
If you don't have geoserver installed locally, feel free to use following command to quickly spin up Geoserver using [Docker](https://www.docker.com/)
If you don't have GeoServer installed locally, feel free to use following command to quickly spin up Geoserver using [Docker](https://www.docker.com/)

<div class="termy">
```console
docker run -e GEOSERVER_ADMIN_USER=admin -e GEOSERVER_ADMIN_PASSWORD=geoserver -e SAMPLE_DATA=true -p 8080:8080 kartoza/geoserver
docker run -e GEOSERVER_ADMIN_USER=admin -e GEOSERVER_ADMIN_PASSWORD=geoserver -e SAMPLE_DATA=true -p 8080:8080 kartoza/GeoServer
```
</div>

Please not that this will work on amd64 architecture machines.
Please note that this will work on amd64 architecture machines.
38 changes: 19 additions & 19 deletions docs/pages/async/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ Here, we'll have a look at implementation `geoserverx` asynchronous Class

## Setup Class instance

`AsyncGeoServerX` Class has default username, password, url which points to default geoserver settings.
`AsyncGeoServerX` Class has default username, password, url which points to default GeoServer settings.
```Python
# Import class from package
from geoserverx._async.gsx import AsyncGeoServerX
import asyncio
# Create class Instance with default paramaters
client = AsyncGeoServerX()
```
We'll assume connection to local geoserver with default credentials
We'll assume connection to local GeoServer with default credentials

## Get all workspaces

Expand All @@ -29,7 +29,7 @@ async def get_info_raster_workspaces(url, username, password):
print(await client.get_all_workspaces())

async def main():
await asyncio.gather(get_info_raster_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver'),get_info_raster_workspaces(url='http://89.233.108.250:8080/geoserver/rest',username='admin', password='myP'),get_info_raster_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver'))
await asyncio.gather(get_info_raster_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer'),get_info_raster_workspaces(url='http://locahost:8080/geoserver/rest',username='admin', password='myP'),get_info_raster_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer'))

asyncio.run(main())

Expand All @@ -53,7 +53,7 @@ async def get_info_raster_workspaces(url, username, password,workspace):
print(await client.get_workspace(workspace))

async def main():
await asyncio.gather(get_info_raster_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',workspace='cesium'))
await asyncio.gather(get_info_raster_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',workspace='cesium'))

asyncio.run(main())

Expand All @@ -80,13 +80,13 @@ async def create_single_workspaces(url, username, password,workspace,default,iso

async def main():
await asyncio.gather(create_single_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',
workspace='AsyncMyDefault',default=True,isolated= False),
create_single_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',
workspace='AsyncMyHidden',default=False,isolated= True),
create_single_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',
workspace='AsyncMySimple',default=False,isolated= False))

asyncio.run(main())
Expand Down Expand Up @@ -114,7 +114,7 @@ async def create_single_workspaces(url, username, password,workspace):

async def main():
await asyncio.gather(create_single_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',
workspace='cesium'))

asyncio.run(main())
Expand All @@ -138,7 +138,7 @@ async def get_info_vector_workspaces(url, username, password,workspace,store):

async def main():
await asyncio.gather(get_info_vector_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',
workspace='cesium',store='myshp'))

asyncio.run(main())
Expand All @@ -163,7 +163,7 @@ def add_vector_workspaces(url, username, password,workspace,store,file):
client = SyncGeoServerX(username, password,url)
return client.create_file_store(workspace, store, file, service_type='shapefile')
result = add_vector_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',
result = add_vector_workspaces(url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',
workspace='cesium',store='myshp', file='safe_users.zip' )
print(result.json())
Expand All @@ -188,7 +188,7 @@ async def get_all_raster_workspaces(url, username, password,workspace):

async def main():
await asyncio.gather(get_all_raster_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',workspace='cesium'))
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',workspace='cesium'))

asyncio.run(main())

Expand All @@ -211,7 +211,7 @@ async def get_info_raster_workspaces(url, username, password,workspace,store):

async def main():
await asyncio.gather(get_info_raster_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',workspace='cesium',store='dsm'))
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',workspace='cesium',store='dsm'))

asyncio.run(main())

Expand All @@ -221,7 +221,7 @@ coverageStore=CoveragesStoreModelDetail(name='dsm', description=None, enabled=Tr
'''
```

## Get all Styles in geoserver
## Get all Styles in GeoServer

```Python hl_lines="7"
from geoserverx._async.gsx import AsyncGeoServerX
Expand All @@ -230,21 +230,21 @@ import asyncio
async def get_info_raster_workspaces(url, username, password):
print("-------------start-----------------")
client = AsyncGeoServerX(username, password,url)
print(await client.get_allstyles())
print(await client.get_all_styles())

async def main():
await asyncio.gather(get_info_raster_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver'))
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer'))

asyncio.run(main())

''' Console
-------------start-----------------
styles=allStyleDict(style=[allStyleList(name='burg', href='http://localhost:8080/geoserver/rest/styles/burg.json'), allStyleList(name='capitals', href='http://localhost:8080/geoserver/rest/styles/capitals.json'), allStyleList(name='cite_lakes', href='http://localhost:8080/geoserver/rest/styles/cite_lakes.json'), allStyleList(name='dem', href='http://localhost:8080/geoserver/rest/styles/dem.json'), allStyleList(name='generic', href='http://localhost:8080/geoserver/rest/styles/generic.json'), allStyleList(name='giant_polygon', href='http://localhost:8080/geoserver/rest/styles/giant_polygon.json'), allStyleList(name='grass', href='http://localhost:8080/geoserver/rest/styles/grass.json'), allStyleList(name='green', href='http://localhost:8080/geoserver/rest/styles/green.json'), allStyleList(name='line', href='http://localhost:8080/geoserver/rest/styles/line.json'), allStyleList(name='poi', href='http://localhost:8080/geoserver/rest/styles/poi.json'), allStyleList(name='point', href='http://localhost:8080/geoserver/rest/styles/point.json'), allStyleList(name='poly_landmarks', href='http://localhost:8080/geoserver/rest/styles/poly_landmarks.json'), allStyleList(name='polygon', href='http://localhost:8080/geoserver/rest/styles/polygon.json'), allStyleList(name='pophatch', href='http://localhost:8080/geoserver/rest/styles/pophatch.json'), allStyleList(name='population', href='http://localhost:8080/geoserver/rest/styles/population.json'), allStyleList(name='rain', href='http://localhost:8080/geoserver/rest/styles/rain.json'), allStyleList(name='raster', href='http://localhost:8080/geoserver/rest/styles/raster.json'), allStyleList(name='restricted', href='http://localhost:8080/geoserver/rest/styles/restricted.json'), allStyleList(name='simple_roads', href='http://localhost:8080/geoserver/rest/styles/simple_roads.json'), allStyleList(name='simple_streams', href='http://localhost:8080/geoserver/rest/styles/simple_streams.json'), allStyleList(name='tiger_roads', href='http://localhost:8080/geoserver/rest/styles/tiger_roads.json')])
styles=allStyle(style=[allStyleList(name='burg', href='http://localhost:8080/geoserver/rest/styles/burg.json'), allStyleList(name='capitals', href='http://localhost:8080/geoserver/rest/styles/capitals.json'), allStyleList(name='cite_lakes', href='http://localhost:8080/geoserver/rest/styles/cite_lakes.json'), allStyleList(name='dem', href='http://localhost:8080/geoserver/rest/styles/dem.json'), allStyleList(name='generic', href='http://localhost:8080/geoserver/rest/styles/generic.json'), allStyleList(name='giant_polygon', href='http://localhost:8080/geoserver/rest/styles/giant_polygon.json'), allStyleList(name='grass', href='http://localhost:8080/geoserver/rest/styles/grass.json'), allStyleList(name='green', href='http://localhost:8080/geoserver/rest/styles/green.json'), allStyleList(name='line', href='http://localhost:8080/geoserver/rest/styles/line.json'), allStyleList(name='poi', href='http://localhost:8080/geoserver/rest/styles/poi.json'), allStyleList(name='point', href='http://localhost:8080/geoserver/rest/styles/point.json'), allStyleList(name='poly_landmarks', href='http://localhost:8080/geoserver/rest/styles/poly_landmarks.json'), allStyleList(name='polygon', href='http://localhost:8080/geoserver/rest/styles/polygon.json'), allStyleList(name='pophatch', href='http://localhost:8080/geoserver/rest/styles/pophatch.json'), allStyleList(name='population', href='http://localhost:8080/geoserver/rest/styles/population.json'), allStyleList(name='rain', href='http://localhost:8080/geoserver/rest/styles/rain.json'), allStyleList(name='raster', href='http://localhost:8080/geoserver/rest/styles/raster.json'), allStyleList(name='restricted', href='http://localhost:8080/geoserver/rest/styles/restricted.json'), allStyleList(name='simple_roads', href='http://localhost:8080/geoserver/rest/styles/simple_roads.json'), allStyleList(name='simple_streams', href='http://localhost:8080/geoserver/rest/styles/simple_streams.json'), allStyleList(name='tiger_roads', href='http://localhost:8080/geoserver/rest/styles/tiger_roads.json')])
'''
```

## Get Single Style in geoserver
## Get Single Style in GeoServer

```Python hl_lines="7"
from geoserverx._async.gsx import AsyncGeoServerX
Expand All @@ -257,11 +257,11 @@ async def get_info_raster_workspaces(url, username, password,style):

async def main():
await asyncio.gather(get_info_raster_workspaces(
url='http://localhost:8080/geoserver/rest/',username='admin', password='geoserver',style='poi'))
url='http://localhost:8080/geoserver/rest/',username='admin', password='GeoServer',style='poi'))

asyncio.run(main())
''' Console
-------------start-----------------
style=SingleStyleDict(name='poi', format='sld', languageVersion=langVersion(version='1.0.0'), filename='poi.sld')
style=SingleStyle(name='poi', format='sld', languageVersion=langVersion(version='1.0.0'), filename='poi.sld')
'''
```
2 changes: 1 addition & 1 deletion docs/pages/async/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

## Setup Class instance

`AsyncGeoServerX` Class has default username, password, url which points to default geoserver settings.
`AsyncGeoServerX` Class has default username, password, url which points to default GeoServer settings.
```Python
# Import class from package
from geoserverx._async.gsx import AsyncGeoServerX
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/async/raster-store.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Raster Stores

`geoserverx` allows users to access all/one raster stores from geoserver
`geoserverx` allows users to access all/one raster stores from GeoServer


## Get all raster stores
This command fetches all Vector store available in given workspace from geoserver.
This command fetches all Vector store available in given workspace from GeoServer.

```py
# Get all raster stores available in `cite` workspace
Expand All @@ -14,7 +14,7 @@ await client.get_raster_stores_in_workspaces('cite')

## Get single raster store

This command fetches all Information about raster store available in given workspace from geoserver.
This command fetches all Information about raster store available in given workspace from GeoServer.

```Python
# Get all information about `image` raster stores available in `cite` workspace
Expand Down
10 changes: 5 additions & 5 deletions docs/pages/async/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@

## Get all Styles

This command fetches all Styles available in geoserver.
This command fetches all Styles available in GeoServer.

```Python
# Get all styles available in geoserver
await client.get_allstyles()
# Get all styles available in GeoServer
await client.get_all_styles()
```


## Get single Style

This command fetches information about particular Style from geoserver.
This command fetches information about particular Style from GeoServer.

```py
# Get information about `population` style from geoserver
# Get information about `population` style from GeoServer
await client.get_style('population')
```
22 changes: 19 additions & 3 deletions docs/pages/async/vector-store.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Vector Stores

`geoserverx` allows users to access all/one vector stores from geoserver. As of now, `geoserverx` also supports new vector store creation for `shapefile` and `gpkg` data
`geoserverx` allows users to access all/one vector stores from GeoServer. As of now, `geoserverx` also supports new vector store creation for `shapefile` and `gpkg` data

## Get all Vector stores
This command fetches all Vector store available in given workspace from geoserver.
This command fetches all Vector store available in given workspace from GeoServer.

```Python
# Get all vector stores available in `cite` workspace
Expand All @@ -13,7 +13,7 @@ await client.get_vector_stores_in_workspaces('cite')


## Get single Vector store
This command fetches all Information about Vector store available in given workspace from geoserver.
This command fetches all Information about Vector store available in given workspace from GeoServer.

```Python
# Get all information about `shape` vector stores available in `cite` workspace
Expand Down Expand Up @@ -52,4 +52,20 @@ await client.create_pg_store(
username="XXXXXXXX",
password="XXXXXXXX",
database="test")
```

## Get all Vector layers
This command fetches all Vector layers available in given workspace from GeoServer.

```Python
# Get all vector layers available in `cite` workspace
await client.get_all_layers(workspace='cite')
```

## Get single Vector layer
This command fetches all Information about Vector layer available in given workspace from GeoServer.

```Python
# Get all information about `roads` vector layers available in `cite` workspace
await client.get_vector_layer(workspace='cite', store='shape', layer='roads')
```
Loading

0 comments on commit 6434948

Please sign in to comment.