Merge pull request #1 from joshuasundance-swca/connor
Browse files- .github/workflows/docker-hub.yml +4 -3
- Dockerfile +11 -4
- README.md +12 -12
- dev-requirements.txt +2 -0
- docker-compose.yml +18 -16
- {geospatial_data_converter β geospatial-data-converter}/.streamlit/config.toml +0 -0
- {geospatial_data_converter β geospatial-data-converter}/app.py +1 -4
- {geospatial_data_converter β geospatial-data-converter}/kml_tricks.py +0 -0
- {geospatial_data_converter β geospatial-data-converter}/utils.py +1 -4
- geospatial_data_converter/__init__.py +0 -0
- kubernetes/resources.yaml +10 -10
- bumpver.toml β pyproject.toml +9 -4
- requirements.txt +0 -1
- tests/__init__.py +0 -0
- tests/test_conversions.py +1 -1
.github/workflows/docker-hub.yml
CHANGED
@@ -23,9 +23,10 @@ jobs:
|
|
23 |
- name: Build Docker image
|
24 |
run: |
|
25 |
docker build \
|
26 |
-
|
27 |
-
-t joshuasundance/
|
|
|
28 |
.
|
29 |
|
30 |
- name: Push to Docker Hub
|
31 |
-
run: docker push -a joshuasundance/
|
|
|
23 |
- name: Build Docker image
|
24 |
run: |
|
25 |
docker build \
|
26 |
+
--target runtime \
|
27 |
+
-t joshuasundance/geospatial-data-converter:${{ github.ref_name }} \
|
28 |
+
-t joshuasundance/geospatial-data-converter:latest \
|
29 |
.
|
30 |
|
31 |
- name: Push to Docker Hub
|
32 |
+
run: docker push -a joshuasundance/geospatial-data-converter
|
Dockerfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
FROM python:3.11-slim-bookworm
|
2 |
|
3 |
RUN adduser --uid 1000 --disabled-password --gecos '' appuser
|
4 |
USER 1000
|
@@ -10,11 +10,18 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
10 |
RUN pip install --user --no-cache-dir --upgrade pip
|
11 |
COPY ./requirements.txt /home/appuser/requirements.txt
|
12 |
RUN pip install --user --no-cache-dir --upgrade -r /home/appuser/requirements.txt
|
|
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
WORKDIR /workspace
|
18 |
EXPOSE 7860
|
19 |
|
20 |
-
CMD ["streamlit", "run", "/home/appuser/
|
|
|
1 |
+
FROM python:3.11-slim-bookworm AS base
|
2 |
|
3 |
RUN adduser --uid 1000 --disabled-password --gecos '' appuser
|
4 |
USER 1000
|
|
|
10 |
RUN pip install --user --no-cache-dir --upgrade pip
|
11 |
COPY ./requirements.txt /home/appuser/requirements.txt
|
12 |
RUN pip install --user --no-cache-dir --upgrade -r /home/appuser/requirements.txt
|
13 |
+
COPY geospatial-data-converter/ /home/appuser/geospatial-data-converter/
|
14 |
|
15 |
+
|
16 |
+
FROM base AS test
|
17 |
+
|
18 |
+
COPY dev-requirements.txt /home/appuser/dev-requirements.txt
|
19 |
+
RUN pip install --user --no-cache-dir --upgrade -r /home/appuser/dev-requirements.txt
|
20 |
+
|
21 |
+
|
22 |
+
FROM base AS runtime
|
23 |
|
24 |
WORKDIR /workspace
|
25 |
EXPOSE 7860
|
26 |
|
27 |
+
CMD ["streamlit", "run", "/home/appuser/geospatial-data-converter/app.py", "--server.port", "7860", "--server.address", "0.0.0.0", "--server.enableXsrfProtection=false"]
|
README.md
CHANGED
@@ -13,17 +13,17 @@ tags: [geospatial, streamlit, docker]
|
|
13 |
|
14 |
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
15 |
[![python](https://img.shields.io/badge/Python-3.11-3776AB.svg?style=flat&logo=python&logoColor=white)](https://www.python.org)
|
16 |
-
![GitHub tag (with filter)](https://img.shields.io/github/v/tag/joshuasundance-swca/
|
17 |
|
18 |
-
[![Push to Docker Hub](https://github.com/joshuasundance-swca/
|
19 |
-
[![Docker Image Size (tag)](https://img.shields.io/docker/image-size/joshuasundance/
|
20 |
|
21 |
-
[![Push to HuggingFace Space](https://github.com/joshuasundance-swca/
|
22 |
-
[![Open HuggingFace Space](https://huggingface.co/datasets/huggingface/badges/raw/main/open-in-hf-spaces-sm.svg)](https://huggingface.co/spaces/joshuasundance/
|
23 |
|
24 |
-
![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/joshuasundance-swca/
|
25 |
-
![Code Climate issues](https://img.shields.io/codeclimate/issues/joshuasundance-swca/
|
26 |
-
![Code Climate technical debt](https://img.shields.io/codeclimate/tech-debt/joshuasundance-swca/
|
27 |
|
28 |
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
|
29 |
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)
|
@@ -31,7 +31,7 @@ tags: [geospatial, streamlit, docker]
|
|
31 |
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
32 |
|
33 |
[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
|
34 |
-
![Known Vulnerabilities](https://snyk.io/test/github/joshuasundance-swca/
|
35 |
|
36 |
This project showcases a simple geospatial data converter using [Streamlit](https://streamlit.io) and [GeoPandas](https://geopandas.org/).
|
37 |
|
@@ -45,11 +45,11 @@ This project showcases a simple geospatial data converter using [Streamlit](http
|
|
45 |
- Download button for the converted data
|
46 |
|
47 |
# Deployment
|
48 |
-
`
|
49 |
|
50 |
## With Docker (pull from Docker Hub)
|
51 |
1. Run in terminal:
|
52 |
-
`docker run -p 7860:7860 <your-dockerhub-username>/
|
53 |
2. Open http://localhost:8501 in your browser
|
54 |
|
55 |
## Docker Compose (build locally)
|
@@ -63,7 +63,7 @@ This project showcases a simple geospatial data converter using [Streamlit](http
|
|
63 |
## Kubernetes
|
64 |
1. Clone the repo. Navigate to cloned repo directory
|
65 |
2. Run bash script: `/bin/bash ./kubernetes/deploy.sh`
|
66 |
-
3. Get the IP address for your new service: `kubectl get service
|
67 |
|
68 |
# Links
|
69 |
- [Streamlit](https://streamlit.io)
|
|
|
13 |
|
14 |
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
15 |
[![python](https://img.shields.io/badge/Python-3.11-3776AB.svg?style=flat&logo=python&logoColor=white)](https://www.python.org)
|
16 |
+
![GitHub tag (with filter)](https://img.shields.io/github/v/tag/joshuasundance-swca/geospatial-data-converter)
|
17 |
|
18 |
+
[![Push to Docker Hub](https://github.com/joshuasundance-swca/geospatial-data-converter/actions/workflows/docker-hub.yml/badge.svg)](https://github.com/joshuasundance-swca/geospatial-data-converter/actions/workflows/docker-hub.yml)
|
19 |
+
[![Docker Image Size (tag)](https://img.shields.io/docker/image-size/joshuasundance/geospatial-data-converter/latest)](https://hub.docker.com/r/joshuasundance/geospatial-data-converter)
|
20 |
|
21 |
+
[![Push to HuggingFace Space](https://github.com/joshuasundance-swca/geospatial-data-converter/actions/workflows/hf-space.yml/badge.svg)](https://github.com/joshuasundance-swca/geospatial-data-converter/actions/workflows/hf-space.yml)
|
22 |
+
[![Open HuggingFace Space](https://huggingface.co/datasets/huggingface/badges/raw/main/open-in-hf-spaces-sm.svg)](https://huggingface.co/spaces/joshuasundance/geospatial-data-converter)
|
23 |
|
24 |
+
![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/joshuasundance-swca/geospatial-data-converter)
|
25 |
+
![Code Climate issues](https://img.shields.io/codeclimate/issues/joshuasundance-swca/geospatial-data-converter)
|
26 |
+
![Code Climate technical debt](https://img.shields.io/codeclimate/tech-debt/joshuasundance-swca/geospatial-data-converter)
|
27 |
|
28 |
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
|
29 |
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)
|
|
|
31 |
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
32 |
|
33 |
[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
|
34 |
+
![Known Vulnerabilities](https://snyk.io/test/github/joshuasundance-swca/geospatial-data-converter/badge.svg)
|
35 |
|
36 |
This project showcases a simple geospatial data converter using [Streamlit](https://streamlit.io) and [GeoPandas](https://geopandas.org/).
|
37 |
|
|
|
45 |
- Download button for the converted data
|
46 |
|
47 |
# Deployment
|
48 |
+
`geospatial-data-converter` is deployed as a [Docker image](https://hub.docker.com/r/<your-dockerhub-username>/geospatial-data-converter) based on the `python:3.11-slim-bookworm` image.
|
49 |
|
50 |
## With Docker (pull from Docker Hub)
|
51 |
1. Run in terminal:
|
52 |
+
`docker run -p 7860:7860 <your-dockerhub-username>/geospatial-data-converter:latest`
|
53 |
2. Open http://localhost:8501 in your browser
|
54 |
|
55 |
## Docker Compose (build locally)
|
|
|
63 |
## Kubernetes
|
64 |
1. Clone the repo. Navigate to cloned repo directory
|
65 |
2. Run bash script: `/bin/bash ./kubernetes/deploy.sh`
|
66 |
+
3. Get the IP address for your new service: `kubectl get service geospatial-data-converter`
|
67 |
|
68 |
# Links
|
69 |
- [Streamlit](https://streamlit.io)
|
dev-requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
pytest==7.4.3
|
2 |
+
pytest-cov==4.1.0
|
docker-compose.yml
CHANGED
@@ -1,21 +1,23 @@
|
|
1 |
version: '3.8'
|
2 |
|
3 |
services:
|
4 |
-
geospatial_data_converter:
|
5 |
-
image: geospatial_data_converter:latest
|
6 |
-
build: .
|
7 |
-
ports:
|
8 |
-
- "${APP_PORT:-7860}:${APP_PORT:-7860}"
|
9 |
-
working_dir: /workspace
|
10 |
-
command: [
|
11 |
-
"streamlit", "run",
|
12 |
-
"/home/appuser/geospatial_data_converter/app.py",
|
13 |
-
"--server.port", "${APP_PORT:-7860}",
|
14 |
-
"--server.address", "0.0.0.0",
|
15 |
-
"--server.enableXsrfProtection=false"
|
16 |
-
]
|
17 |
test:
|
18 |
-
|
19 |
-
build:
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
working_dir: /home/appuser
|
21 |
-
command: ["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
version: '3.8'
|
2 |
|
3 |
services:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
test:
|
5 |
+
container_name: geospatial-data-converter-test
|
6 |
+
build:
|
7 |
+
context: .
|
8 |
+
dockerfile: Dockerfile
|
9 |
+
target: test
|
10 |
+
volumes:
|
11 |
+
- ./tests/:/home/appuser/tests/
|
12 |
+
- ./pyproject.toml:/home/appuser/pyproject.toml
|
13 |
working_dir: /home/appuser
|
14 |
+
command: ["pytest"]
|
15 |
+
|
16 |
+
geospatial-data-converter:
|
17 |
+
container_name: geospatial-data-converter
|
18 |
+
build:
|
19 |
+
context: .
|
20 |
+
dockerfile: Dockerfile
|
21 |
+
target: runtime
|
22 |
+
ports:
|
23 |
+
- "${APP_PORT:-7860}:${APP_PORT:-7860}"
|
{geospatial_data_converter β geospatial-data-converter}/.streamlit/config.toml
RENAMED
File without changes
|
{geospatial_data_converter β geospatial-data-converter}/app.py
RENAMED
@@ -6,10 +6,7 @@ import streamlit as st
|
|
6 |
from aiohttp import ClientSession
|
7 |
from restgdf import FeatureLayer
|
8 |
|
9 |
-
|
10 |
-
from utils import read_file, convert, output_format_dict
|
11 |
-
except ImportError:
|
12 |
-
from .utils import read_file, convert, output_format_dict
|
13 |
|
14 |
__version__ = "0.2.1"
|
15 |
|
|
|
6 |
from aiohttp import ClientSession
|
7 |
from restgdf import FeatureLayer
|
8 |
|
9 |
+
from utils import read_file, convert, output_format_dict
|
|
|
|
|
|
|
10 |
|
11 |
__version__ = "0.2.1"
|
12 |
|
{geospatial_data_converter β geospatial-data-converter}/kml_tricks.py
RENAMED
File without changes
|
{geospatial_data_converter β geospatial-data-converter}/utils.py
RENAMED
@@ -5,10 +5,7 @@ from tempfile import TemporaryDirectory
|
|
5 |
from typing import BinaryIO
|
6 |
import geopandas as gpd
|
7 |
|
8 |
-
|
9 |
-
from kml_tricks import load_ge_data
|
10 |
-
except ImportError:
|
11 |
-
from .kml_tricks import load_ge_data
|
12 |
|
13 |
output_format_dict = {
|
14 |
"ESRI Shapefile": ("shp", "zip", "application/zip"), # must be zipped
|
|
|
5 |
from typing import BinaryIO
|
6 |
import geopandas as gpd
|
7 |
|
8 |
+
from kml_tricks import load_ge_data
|
|
|
|
|
|
|
9 |
|
10 |
output_format_dict = {
|
11 |
"ESRI Shapefile": ("shp", "zip", "application/zip"), # must be zipped
|
geospatial_data_converter/__init__.py
DELETED
File without changes
|
kubernetes/resources.yaml
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
apiVersion: apps/v1
|
2 |
kind: Deployment
|
3 |
metadata:
|
4 |
-
name:
|
5 |
spec:
|
6 |
replicas: 1
|
7 |
selector:
|
8 |
matchLabels:
|
9 |
-
app:
|
10 |
template:
|
11 |
metadata:
|
12 |
labels:
|
13 |
-
app:
|
14 |
spec:
|
15 |
containers:
|
16 |
-
- name:
|
17 |
-
image: joshuasundance/
|
18 |
imagePullPolicy: Always
|
19 |
resources:
|
20 |
requests:
|
@@ -29,15 +29,15 @@ spec:
|
|
29 |
apiVersion: v1
|
30 |
kind: Service
|
31 |
metadata:
|
32 |
-
name:
|
33 |
# configure on Azure and uncomment below to use a vnet
|
34 |
# annotations:
|
35 |
# service.beta.kubernetes.io/azure-load-balancer-internal: "true"
|
36 |
# service.beta.kubernetes.io/azure-load-balancer-ipv4: vnet.ip.goes.here
|
37 |
-
# service.beta.kubernetes.io/azure-dns-label-name: "
|
38 |
spec:
|
39 |
selector:
|
40 |
-
app:
|
41 |
ports:
|
42 |
- protocol: TCP
|
43 |
port: 80
|
@@ -47,11 +47,11 @@ spec:
|
|
47 |
apiVersion: networking.k8s.io/v1
|
48 |
kind: NetworkPolicy
|
49 |
metadata:
|
50 |
-
name:
|
51 |
spec:
|
52 |
podSelector:
|
53 |
matchLabels:
|
54 |
-
app:
|
55 |
policyTypes:
|
56 |
- Ingress
|
57 |
ingress:
|
|
|
1 |
apiVersion: apps/v1
|
2 |
kind: Deployment
|
3 |
metadata:
|
4 |
+
name: geospatial-data-converter-deployment
|
5 |
spec:
|
6 |
replicas: 1
|
7 |
selector:
|
8 |
matchLabels:
|
9 |
+
app: geospatial-data-converter
|
10 |
template:
|
11 |
metadata:
|
12 |
labels:
|
13 |
+
app: geospatial-data-converter
|
14 |
spec:
|
15 |
containers:
|
16 |
+
- name: geospatial-data-converter
|
17 |
+
image: joshuasundance/geospatial-data-converter:0.1.1
|
18 |
imagePullPolicy: Always
|
19 |
resources:
|
20 |
requests:
|
|
|
29 |
apiVersion: v1
|
30 |
kind: Service
|
31 |
metadata:
|
32 |
+
name: geospatial-data-converter-service
|
33 |
# configure on Azure and uncomment below to use a vnet
|
34 |
# annotations:
|
35 |
# service.beta.kubernetes.io/azure-load-balancer-internal: "true"
|
36 |
# service.beta.kubernetes.io/azure-load-balancer-ipv4: vnet.ip.goes.here
|
37 |
+
# service.beta.kubernetes.io/azure-dns-label-name: "geospatial-data-converter"
|
38 |
spec:
|
39 |
selector:
|
40 |
+
app: geospatial-data-converter
|
41 |
ports:
|
42 |
- protocol: TCP
|
43 |
port: 80
|
|
|
47 |
apiVersion: networking.k8s.io/v1
|
48 |
kind: NetworkPolicy
|
49 |
metadata:
|
50 |
+
name: geospatial-data-converter-network-policy
|
51 |
spec:
|
52 |
podSelector:
|
53 |
matchLabels:
|
54 |
+
app: geospatial-data-converter
|
55 |
policyTypes:
|
56 |
- Ingress
|
57 |
ingress:
|
bumpver.toml β pyproject.toml
RENAMED
@@ -1,4 +1,9 @@
|
|
1 |
-
[
|
|
|
|
|
|
|
|
|
|
|
2 |
current_version = "0.2.1"
|
3 |
version_pattern = "MAJOR.MINOR.PATCH"
|
4 |
commit_message = "bump version {old_version} -> {new_version}"
|
@@ -10,9 +15,9 @@ commit = true
|
|
10 |
tag = true
|
11 |
push = true
|
12 |
|
13 |
-
[bumpver.file_patterns]
|
14 |
"bumpver.toml" = [
|
15 |
'current_version = "{version}"',
|
16 |
]
|
17 |
-
"
|
18 |
-
"kubernetes/resources.yaml" = [' image: joshuasundance/
|
|
|
1 |
+
[tool.pytest.ini_options]
|
2 |
+
pythonpath = ["geospatial-data-converter"]
|
3 |
+
testpaths = ["tests"]
|
4 |
+
addopts = "--cov=geospatial-data-converter"
|
5 |
+
|
6 |
+
[tool.bumpver]
|
7 |
current_version = "0.2.1"
|
8 |
version_pattern = "MAJOR.MINOR.PATCH"
|
9 |
commit_message = "bump version {old_version} -> {new_version}"
|
|
|
15 |
tag = true
|
16 |
push = true
|
17 |
|
18 |
+
[tool.bumpver.file_patterns]
|
19 |
"bumpver.toml" = [
|
20 |
'current_version = "{version}"',
|
21 |
]
|
22 |
+
"geospatial-data-converter/app.py" = ['__version__ = "{version}"']
|
23 |
+
"kubernetes/resources.yaml" = [' image: joshuasundance/geospatial-data-converter:{version}']
|
requirements.txt
CHANGED
@@ -3,6 +3,5 @@ beautifulsoup4==4.12.2
|
|
3 |
geopandas==0.14.1
|
4 |
lxml==4.9.3
|
5 |
pyogrio==0.7.2
|
6 |
-
pytest
|
7 |
restgdf==0.9.7
|
8 |
streamlit==1.29.0
|
|
|
3 |
geopandas==0.14.1
|
4 |
lxml==4.9.3
|
5 |
pyogrio==0.7.2
|
|
|
6 |
restgdf==0.9.7
|
7 |
streamlit==1.29.0
|
tests/__init__.py
DELETED
File without changes
|
tests/test_conversions.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import os
|
2 |
import pytest
|
3 |
-
from
|
4 |
|
5 |
input_exts = ["kml", "kmz", "geojson", "zip"]
|
6 |
output_exts = ["KML", "ESRI Shapefile", "GeoJSON", "CSV", "OpenFileGDB"]
|
|
|
1 |
import os
|
2 |
import pytest
|
3 |
+
from utils import convert, read_file
|
4 |
|
5 |
input_exts = ["kml", "kmz", "geojson", "zip"]
|
6 |
output_exts = ["KML", "ESRI Shapefile", "GeoJSON", "CSV", "OpenFileGDB"]
|