Skip to content

Commit 6654f46

Browse files
committed
Add linting (ruff) and type checking (mypy)
1 parent 7cb2df6 commit 6654f46

15 files changed

Lines changed: 138 additions & 78 deletions

.github/workflows/lint.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Felt Python Linting And Formatting
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: astral-sh/ruff-action@v3
15+
run: ruff check --fix
16+
run: ruff format --diff
17+
with:
18+
python-version: '3.12'
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Felt Python Type Checking
2+
3+
4+
on:
5+
push:
6+
branches: [ main ]
7+
pull_request:
8+
branches: [ main ]
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Python ${{ matrix.python-version }}
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: '3.12'
21+
22+
- name: Install Dependencies
23+
run: pip install mypy
24+
25+
- name: Run mypy
26+
run: mypy .

felt_python/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"create_embed_token",
9393
"add_source_layer",
9494
"duplicate_map",
95+
"get_map",
9596
# Layers
9697
"list_layers",
9798
"upload_file",
@@ -120,6 +121,7 @@
120121
# Elements
121122
"list_elements",
122123
"list_element_groups",
124+
"get_element_group",
123125
"upsert_elements",
124126
"delete_element",
125127
"upsert_element_groups",

felt_python/api.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
def make_request(
2424
url: str,
2525
method: typing.Literal["GET", "POST", "PATCH", "DELETE"],
26-
json: dict | None = None,
26+
json: dict | list | None = None,
2727
api_token: str | None = None,
2828
) -> http.client.HTTPResponse:
2929
"""Basic wrapper for requests that adds auth"""
@@ -40,10 +40,13 @@ def make_request(
4040
except PackageNotFoundError:
4141
package_version = "local"
4242

43-
data, headers = None, {
44-
"Authorization": f"Bearer {api_token}",
45-
"User-Agent": f"felt-python/{package_version}",
46-
}
43+
data, headers = (
44+
None,
45+
{
46+
"Authorization": f"Bearer {api_token}",
47+
"User-Agent": f"felt-python/{package_version}",
48+
},
49+
)
4750
if json is not None:
4851
data = json_.dumps(json).encode("utf8")
4952
headers["Content-Type"] = "application/json"

felt_python/elements.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ def upsert_elements(
102102
"""
103103
if isinstance(geojson_feature_collection, str):
104104
geojson_feature_collection = json.loads(geojson_feature_collection)
105+
assert isinstance(
106+
geojson_feature_collection, dict
107+
), "geojson_feature_collection must be a valid GeoJSON"
105108
response = make_request(
106109
url=ELEMENTS.format(map_id=map_id),
107110
method="POST",
@@ -132,12 +135,17 @@ def post_element_group(
132135
json_element: dict | str,
133136
api_token: str | None = None,
134137
):
135-
upsert_element_groups(map_id, json_element, api_token)
138+
if isinstance(json_element, str):
139+
json_element = json.loads(json_element)
140+
assert isinstance(
141+
json_element, dict
142+
), "json_element must be a valid JSON object"
143+
upsert_element_groups(map_id, [json_element], api_token)
136144

137145

138146
def upsert_element_groups(
139147
map_id: str,
140-
element_groups: list[dict[str, str]],
148+
element_groups: list[dict],
141149
api_token: str | None = None,
142150
):
143151
"""Post multiple element groups

felt_python/layer_groups.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ def delete_layer_group(
103103
def update_layer_group(
104104
map_id: str,
105105
layer_group_id: str,
106-
name: str = None,
107-
caption: str = None,
108-
ordering_key: int = None,
109-
visibility_interaction: str = None,
106+
name: str | None = None,
107+
caption: str | None = None,
108+
ordering_key: int | None = None,
109+
visibility_interaction: str | None = None,
110110
api_token: str | None = None,
111111
):
112112
"""Update a single layer group
@@ -124,7 +124,7 @@ def update_layer_group(
124124
Returns:
125125
The updated layer group
126126
"""
127-
json_payload = {}
127+
json_payload: dict = {}
128128

129129
if name is not None:
130130
json_payload["name"] = name
@@ -147,7 +147,7 @@ def update_layer_group(
147147
def publish_layer_group(
148148
map_id: str,
149149
layer_group_id: str,
150-
name: str = None,
150+
name: str | None = None,
151151
api_token: str | None = None,
152152
):
153153
"""Publish a layer group to the Felt library

felt_python/layers.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import typing
88
import urllib.request
99
import uuid
10-
import typing
1110

1211
from urllib.parse import urljoin
1312

@@ -43,11 +42,11 @@ def upload_file(
4342
map_id: str,
4443
file_name: str,
4544
layer_name: str,
46-
metadata: dict[str, str] = None,
47-
hints: list[dict[str, str]] = None,
48-
lat: float = None,
49-
lng: float = None,
50-
zoom: float = None,
45+
metadata: dict[str, str] | None = None,
46+
hints: list[dict[str, str]] | None = None,
47+
lat: float | None = None,
48+
lng: float | None = None,
49+
zoom: float | None = None,
5150
api_token: str | None = None,
5251
):
5352
"""Upload a file to a Felt map
@@ -66,7 +65,7 @@ def upload_file(
6665
Returns:
6766
The upload response including layer ID and presigned upload details
6867
"""
69-
json_payload = {"name": layer_name}
68+
json_payload: dict = {"name": layer_name}
7069

7170
if metadata is not None:
7271
json_payload["metadata"] = metadata
@@ -91,10 +90,10 @@ def upload_file(
9190

9291
def upload_dataframe(
9392
map_id: str,
94-
dataframe: "pd.DataFrame",
93+
dataframe: "pandas.DataFrame", # type: ignore[name-defined] # noqa: F821
9594
layer_name: str,
96-
metadata: dict[str, str] = None,
97-
hints: list[dict[str, str]] = None,
95+
metadata: dict[str, str] | None = None,
96+
hints: list[dict[str, str]] | None = None,
9897
api_token: str | None = None,
9998
):
10099
"""Upload a Pandas DataFrame to a Felt map"""
@@ -113,10 +112,10 @@ def upload_dataframe(
113112

114113
def upload_geodataframe(
115114
map_id: str,
116-
geodataframe: "gpd.GeoDataFrame",
115+
geodataframe: "geopandas.GeoDataFrame", # type: ignore[name-defined] # noqa: F821
117116
layer_name: str,
118-
metadata: dict[str, str] = None,
119-
hints: list[dict[str, str]] = None,
117+
metadata: dict[str, str] | None = None,
118+
hints: list[dict[str, str]] | None = None,
120119
api_token: str | None = None,
121120
):
122121
"""Upload a GeoPandas GeoDataFrame to a Felt map"""
@@ -159,8 +158,8 @@ def upload_url(
159158
map_id: str,
160159
layer_url: str,
161160
layer_name: str,
162-
metadata: dict[str, str] = None,
163-
hints: list[dict[str, str]] = None,
161+
metadata: dict[str, str] | None = None,
162+
hints: list[dict[str, str]] | None = None,
164163
api_token: str | None = None,
165164
):
166165
"""Upload a URL to a Felt map
@@ -176,7 +175,7 @@ def upload_url(
176175
Returns:
177176
The upload response
178177
"""
179-
json_payload = {
178+
json_payload: dict = {
180179
"import_url": layer_url,
181180
"name": layer_name,
182181
}
@@ -209,8 +208,8 @@ def refresh_url_layer(map_id: str, layer_id: str, api_token: str | None = None):
209208

210209

211210
@deprecated(reason="Please use `get_layer` instead")
212-
def get_layer_details(map_id: str, api_token: str | None = None):
213-
get_layer(map_id, api_token)
211+
def get_layer_details(map_id: str, layer_id: str, api_token: str | None = None):
212+
get_layer(map_id, layer_id, api_token)
214213

215214

216215
def get_layer(
@@ -331,7 +330,7 @@ def delete_layer(
331330
def publish_layer(
332331
map_id: str,
333332
layer_id: str,
334-
name: str = None,
333+
name: str | None = None,
335334
api_token: str | None = None,
336335
):
337336
"""Publish a layer to the Felt library
@@ -345,7 +344,7 @@ def publish_layer(
345344
Returns:
346345
The published layer
347346
"""
348-
json_payload = {}
347+
json_payload: dict = {}
349348
if name is not None:
350349
json_payload["name"] = name
351350

@@ -362,7 +361,7 @@ def create_custom_export(
362361
map_id: str,
363362
layer_id: str,
364363
output_format: str,
365-
filters: list = None,
364+
filters: list | None = None,
366365
email_on_completion: bool = True,
367366
api_token: str | None = None,
368367
):
@@ -381,7 +380,7 @@ def create_custom_export(
381380
Returns:
382381
Export request details including ID and polling endpoint
383382
"""
384-
json_payload = {
383+
json_payload: dict = {
385384
"output_format": output_format,
386385
"email_on_completion": email_on_completion,
387386
}

felt_python/maps.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@
1818

1919

2020
def create_map(
21-
title: str = None,
22-
description: str = None,
23-
public_access: str = None,
24-
basemap: str = None,
25-
lat: float = None,
26-
lon: float = None,
27-
zoom: float = None,
28-
layer_urls: list[str] = None,
29-
workspace_id: str = None,
30-
api_token: str = None,
21+
title: str | None = None,
22+
description: str | None = None,
23+
public_access: str | None = None,
24+
basemap: str | None = None,
25+
lat: float | None = None,
26+
lon: float | None = None,
27+
zoom: float | None = None,
28+
layer_urls: list[str] | None = None,
29+
workspace_id: str | None = None,
30+
api_token: str | None = None,
3131
):
3232
"""Create a new Felt map
3333
@@ -56,7 +56,7 @@ def create_map(
5656
Returns:
5757
The created map
5858
"""
59-
json_args = {}
59+
json_args: dict = {}
6060

6161
if title is not None:
6262
json_args["title"] = title
@@ -112,10 +112,10 @@ def get_map_details(map_id: str, api_token: str | None = None):
112112

113113
def update_map(
114114
map_id: str,
115-
title: str = None,
116-
description: str = None,
117-
public_access: str = None,
118-
api_token: str = None,
115+
title: str | None = None,
116+
description: str | None = None,
117+
public_access: str | None = None,
118+
api_token: str | None = None,
119119
):
120120
"""Update a map's details
121121
@@ -124,8 +124,8 @@ def update_map(
124124
title: Optional new title for the map
125125
description: Optional new description for the map
126126
public_access: Optional new public access setting
127-
Options are "private", "view_only", "view_and_comment",
128-
or "view_comment_and_edit"
127+
Options are "private", "view_only", "view_and_comment",
128+
or "view_comment_and_edit"
129129
api_token: Optional API token
130130
131131
Returns:
@@ -149,7 +149,10 @@ def update_map(
149149

150150

151151
def move_map(
152-
map_id: str, project_id: str = None, folder_id: str = None, api_token: str = None
152+
map_id: str,
153+
project_id: str | None = None,
154+
folder_id: str | None = None,
155+
api_token: str | None = None,
153156
):
154157
"""Move a map to a different project or folder
155158
@@ -182,7 +185,9 @@ def move_map(
182185
return json.load(response)
183186

184187

185-
def create_embed_token(map_id: str, user_email: str = None, api_token: str = None):
188+
def create_embed_token(
189+
map_id: str, user_email: str | None = None, api_token: str | None = None
190+
):
186191
"""Create an embed token for a map
187192
188193
Args:
@@ -208,7 +213,7 @@ def create_embed_token(map_id: str, user_email: str = None, api_token: str = Non
208213

209214

210215
def add_source_layer(
211-
map_id: str, source_layer_params: dict[str, str], api_token: str = None
216+
map_id: str, source_layer_params: dict[str, str], api_token: str | None = None
212217
):
213218
"""Add a layer from a source to a map
214219
@@ -235,10 +240,10 @@ def add_source_layer(
235240

236241
def duplicate_map(
237242
map_id: str,
238-
title: str = None,
239-
project_id: str = None,
240-
folder_id: str = None,
241-
api_token: str = None,
243+
title: str | None = None,
244+
project_id: str | None = None,
245+
folder_id: str | None = None,
246+
api_token: str | None = None,
242247
):
243248
"""Duplicate a map
244249
@@ -257,7 +262,7 @@ def duplicate_map(
257262
if project_id is not None and folder_id is not None:
258263
raise ValueError("Cannot specify both project_id and folder_id")
259264

260-
json_args = {}
265+
json_args: dict = {}
261266
if title is not None:
262267
json_args["title"] = title
263268

0 commit comments

Comments
 (0)