From 6654f46cf2ffa0baf39de4264bcbbd18621a71a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:09:17 +0200 Subject: [PATCH 1/7] Add linting (ruff) and type checking (mypy) --- .github/workflows/lint.yml | 18 ++++++++++ .github/workflows/type_checking.yml | 26 ++++++++++++++ felt_python/__init__.py | 2 ++ felt_python/api.py | 13 ++++--- felt_python/elements.py | 12 +++++-- felt_python/layer_groups.py | 12 +++---- felt_python/layers.py | 43 +++++++++++----------- felt_python/maps.py | 55 ++++++++++++++++------------- felt_python/sources.py | 4 +-- tests/delete_test.py | 5 ++- tests/elements_test.py | 2 +- tests/layer_groups_test.py | 11 ++++-- tests/maps_test.py | 8 ++--- tests/projects_test.py | 3 +- tests/sources_test.py | 2 -- 15 files changed, 138 insertions(+), 78 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/type_checking.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..50283a6 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,18 @@ +name: Felt Python Linting And Formatting + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: astral-sh/ruff-action@v3 + run: ruff check --fix + run: ruff format --diff + with: + python-version: '3.12' diff --git a/.github/workflows/type_checking.yml b/.github/workflows/type_checking.yml new file mode 100644 index 0000000..d09cfba --- /dev/null +++ b/.github/workflows/type_checking.yml @@ -0,0 +1,26 @@ +name: Felt Python Type Checking + + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install Dependencies + run: pip install mypy + + - name: Run mypy + run: mypy . diff --git a/felt_python/__init__.py b/felt_python/__init__.py index a76dd91..d7e3ca9 100644 --- a/felt_python/__init__.py +++ b/felt_python/__init__.py @@ -92,6 +92,7 @@ "create_embed_token", "add_source_layer", "duplicate_map", + "get_map", # Layers "list_layers", "upload_file", @@ -120,6 +121,7 @@ # Elements "list_elements", "list_element_groups", + "get_element_group", "upsert_elements", "delete_element", "upsert_element_groups", diff --git a/felt_python/api.py b/felt_python/api.py index b9123c4..68c91d1 100644 --- a/felt_python/api.py +++ b/felt_python/api.py @@ -23,7 +23,7 @@ def make_request( url: str, method: typing.Literal["GET", "POST", "PATCH", "DELETE"], - json: dict | None = None, + json: dict | list | None = None, api_token: str | None = None, ) -> http.client.HTTPResponse: """Basic wrapper for requests that adds auth""" @@ -40,10 +40,13 @@ def make_request( except PackageNotFoundError: package_version = "local" - data, headers = None, { - "Authorization": f"Bearer {api_token}", - "User-Agent": f"felt-python/{package_version}", - } + data, headers = ( + None, + { + "Authorization": f"Bearer {api_token}", + "User-Agent": f"felt-python/{package_version}", + }, + ) if json is not None: data = json_.dumps(json).encode("utf8") headers["Content-Type"] = "application/json" diff --git a/felt_python/elements.py b/felt_python/elements.py index cd92c68..295a71a 100644 --- a/felt_python/elements.py +++ b/felt_python/elements.py @@ -102,6 +102,9 @@ def upsert_elements( """ if isinstance(geojson_feature_collection, str): geojson_feature_collection = json.loads(geojson_feature_collection) + assert isinstance( + geojson_feature_collection, dict + ), "geojson_feature_collection must be a valid GeoJSON" response = make_request( url=ELEMENTS.format(map_id=map_id), method="POST", @@ -132,12 +135,17 @@ def post_element_group( json_element: dict | str, api_token: str | None = None, ): - upsert_element_groups(map_id, json_element, api_token) + if isinstance(json_element, str): + json_element = json.loads(json_element) + assert isinstance( + json_element, dict + ), "json_element must be a valid JSON object" + upsert_element_groups(map_id, [json_element], api_token) def upsert_element_groups( map_id: str, - element_groups: list[dict[str, str]], + element_groups: list[dict], api_token: str | None = None, ): """Post multiple element groups diff --git a/felt_python/layer_groups.py b/felt_python/layer_groups.py index 483a330..5ada895 100644 --- a/felt_python/layer_groups.py +++ b/felt_python/layer_groups.py @@ -103,10 +103,10 @@ def delete_layer_group( def update_layer_group( map_id: str, layer_group_id: str, - name: str = None, - caption: str = None, - ordering_key: int = None, - visibility_interaction: str = None, + name: str | None = None, + caption: str | None = None, + ordering_key: int | None = None, + visibility_interaction: str | None = None, api_token: str | None = None, ): """Update a single layer group @@ -124,7 +124,7 @@ def update_layer_group( Returns: The updated layer group """ - json_payload = {} + json_payload: dict = {} if name is not None: json_payload["name"] = name @@ -147,7 +147,7 @@ def update_layer_group( def publish_layer_group( map_id: str, layer_group_id: str, - name: str = None, + name: str | None = None, api_token: str | None = None, ): """Publish a layer group to the Felt library diff --git a/felt_python/layers.py b/felt_python/layers.py index bd52692..228d7fc 100644 --- a/felt_python/layers.py +++ b/felt_python/layers.py @@ -7,7 +7,6 @@ import typing import urllib.request import uuid -import typing from urllib.parse import urljoin @@ -43,11 +42,11 @@ def upload_file( map_id: str, file_name: str, layer_name: str, - metadata: dict[str, str] = None, - hints: list[dict[str, str]] = None, - lat: float = None, - lng: float = None, - zoom: float = None, + metadata: dict[str, str] | None = None, + hints: list[dict[str, str]] | None = None, + lat: float | None = None, + lng: float | None = None, + zoom: float | None = None, api_token: str | None = None, ): """Upload a file to a Felt map @@ -66,7 +65,7 @@ def upload_file( Returns: The upload response including layer ID and presigned upload details """ - json_payload = {"name": layer_name} + json_payload: dict = {"name": layer_name} if metadata is not None: json_payload["metadata"] = metadata @@ -91,10 +90,10 @@ def upload_file( def upload_dataframe( map_id: str, - dataframe: "pd.DataFrame", + dataframe: "pandas.DataFrame", # type: ignore[name-defined] # noqa: F821 layer_name: str, - metadata: dict[str, str] = None, - hints: list[dict[str, str]] = None, + metadata: dict[str, str] | None = None, + hints: list[dict[str, str]] | None = None, api_token: str | None = None, ): """Upload a Pandas DataFrame to a Felt map""" @@ -113,10 +112,10 @@ def upload_dataframe( def upload_geodataframe( map_id: str, - geodataframe: "gpd.GeoDataFrame", + geodataframe: "geopandas.GeoDataFrame", # type: ignore[name-defined] # noqa: F821 layer_name: str, - metadata: dict[str, str] = None, - hints: list[dict[str, str]] = None, + metadata: dict[str, str] | None = None, + hints: list[dict[str, str]] | None = None, api_token: str | None = None, ): """Upload a GeoPandas GeoDataFrame to a Felt map""" @@ -159,8 +158,8 @@ def upload_url( map_id: str, layer_url: str, layer_name: str, - metadata: dict[str, str] = None, - hints: list[dict[str, str]] = None, + metadata: dict[str, str] | None = None, + hints: list[dict[str, str]] | None = None, api_token: str | None = None, ): """Upload a URL to a Felt map @@ -176,7 +175,7 @@ def upload_url( Returns: The upload response """ - json_payload = { + json_payload: dict = { "import_url": layer_url, "name": layer_name, } @@ -209,8 +208,8 @@ def refresh_url_layer(map_id: str, layer_id: str, api_token: str | None = None): @deprecated(reason="Please use `get_layer` instead") -def get_layer_details(map_id: str, api_token: str | None = None): - get_layer(map_id, api_token) +def get_layer_details(map_id: str, layer_id: str, api_token: str | None = None): + get_layer(map_id, layer_id, api_token) def get_layer( @@ -331,7 +330,7 @@ def delete_layer( def publish_layer( map_id: str, layer_id: str, - name: str = None, + name: str | None = None, api_token: str | None = None, ): """Publish a layer to the Felt library @@ -345,7 +344,7 @@ def publish_layer( Returns: The published layer """ - json_payload = {} + json_payload: dict = {} if name is not None: json_payload["name"] = name @@ -362,7 +361,7 @@ def create_custom_export( map_id: str, layer_id: str, output_format: str, - filters: list = None, + filters: list | None = None, email_on_completion: bool = True, api_token: str | None = None, ): @@ -381,7 +380,7 @@ def create_custom_export( Returns: Export request details including ID and polling endpoint """ - json_payload = { + json_payload: dict = { "output_format": output_format, "email_on_completion": email_on_completion, } diff --git a/felt_python/maps.py b/felt_python/maps.py index 3827e92..c532521 100644 --- a/felt_python/maps.py +++ b/felt_python/maps.py @@ -18,16 +18,16 @@ def create_map( - title: str = None, - description: str = None, - public_access: str = None, - basemap: str = None, - lat: float = None, - lon: float = None, - zoom: float = None, - layer_urls: list[str] = None, - workspace_id: str = None, - api_token: str = None, + title: str | None = None, + description: str | None = None, + public_access: str | None = None, + basemap: str | None = None, + lat: float | None = None, + lon: float | None = None, + zoom: float | None = None, + layer_urls: list[str] | None = None, + workspace_id: str | None = None, + api_token: str | None = None, ): """Create a new Felt map @@ -56,7 +56,7 @@ def create_map( Returns: The created map """ - json_args = {} + json_args: dict = {} if title is not None: json_args["title"] = title @@ -112,10 +112,10 @@ def get_map_details(map_id: str, api_token: str | None = None): def update_map( map_id: str, - title: str = None, - description: str = None, - public_access: str = None, - api_token: str = None, + title: str | None = None, + description: str | None = None, + public_access: str | None = None, + api_token: str | None = None, ): """Update a map's details @@ -124,8 +124,8 @@ def update_map( title: Optional new title for the map description: Optional new description for the map public_access: Optional new public access setting - Options are "private", "view_only", "view_and_comment", - or "view_comment_and_edit" + Options are "private", "view_only", "view_and_comment", + or "view_comment_and_edit" api_token: Optional API token Returns: @@ -149,7 +149,10 @@ def update_map( def move_map( - map_id: str, project_id: str = None, folder_id: str = None, api_token: str = None + map_id: str, + project_id: str | None = None, + folder_id: str | None = None, + api_token: str | None = None, ): """Move a map to a different project or folder @@ -182,7 +185,9 @@ def move_map( return json.load(response) -def create_embed_token(map_id: str, user_email: str = None, api_token: str = None): +def create_embed_token( + map_id: str, user_email: str | None = None, api_token: str | None = None +): """Create an embed token for a map Args: @@ -208,7 +213,7 @@ def create_embed_token(map_id: str, user_email: str = None, api_token: str = Non def add_source_layer( - map_id: str, source_layer_params: dict[str, str], api_token: str = None + map_id: str, source_layer_params: dict[str, str], api_token: str | None = None ): """Add a layer from a source to a map @@ -235,10 +240,10 @@ def add_source_layer( def duplicate_map( map_id: str, - title: str = None, - project_id: str = None, - folder_id: str = None, - api_token: str = None, + title: str | None = None, + project_id: str | None = None, + folder_id: str | None = None, + api_token: str | None = None, ): """Duplicate a map @@ -257,7 +262,7 @@ def duplicate_map( if project_id is not None and folder_id is not None: raise ValueError("Cannot specify both project_id and folder_id") - json_args = {} + json_args: dict = {} if title is not None: json_args["title"] = title diff --git a/felt_python/sources.py b/felt_python/sources.py index c811153..1317b7e 100644 --- a/felt_python/sources.py +++ b/felt_python/sources.py @@ -29,7 +29,7 @@ def list_sources(workspace_id: str | None = None, api_token: str | None = None): def create_source( name: str, connection: dict[str, str], - permissions: dict[str, str] = None, + permissions: dict[str, str] | None = None, api_token: str | None = None, ): """Create a new source @@ -85,7 +85,7 @@ def update_source( Returns: The updated source reference """ - json_payload = {} + json_payload: dict = {} if name is not None: json_payload["name"] = name if connection is not None: diff --git a/tests/delete_test.py b/tests/delete_test.py index 17a574d..f2565de 100644 --- a/tests/delete_test.py +++ b/tests/delete_test.py @@ -19,7 +19,6 @@ list_elements, upsert_elements, delete_element, - list_element_groups, upsert_element_groups, # Layers get_layer, @@ -230,9 +229,9 @@ def test_resource_deletion(self): # Verify layer deletion by attempting to get it try: - deleted_layer = get_layer(map_id, layer_id) + get_layer(map_id, layer_id) self.fail("Layer should have been deleted but was still accessible") - except Exception as e: + except Exception: print("Layer deleted successfully") # Delete the map diff --git a/tests/elements_test.py b/tests/elements_test.py index e0c4a48..5fe9f11 100644 --- a/tests/elements_test.py +++ b/tests/elements_test.py @@ -90,7 +90,7 @@ def test_elements_workflow(self): barcelona_element = next( el for el in elements["features"] if el["properties"]["name"] == "Barcelona" ) - barcelona_element_id = barcelona_element["properties"]["felt:id"] + barcelona_element["properties"]["felt:id"] barcelona_element["properties"]["felt:color"] = "#0000FF" barcelona_feature_collection = { diff --git a/tests/layer_groups_test.py b/tests/layer_groups_test.py index 1ca83e2..e06e71e 100644 --- a/tests/layer_groups_test.py +++ b/tests/layer_groups_test.py @@ -201,12 +201,17 @@ def test_layer_groups_workflow(self): name="Vector Data (Individual Update)", caption="Updated via individual update function", ordering_key=10, - visibility_interaction="slider" + visibility_interaction="slider", ) self.assertIsNotNone(individual_update_result) - self.assertEqual(individual_update_result["name"], "Vector Data (Individual Update)") - self.assertEqual(individual_update_result["caption"], "Updated via individual update function") + self.assertEqual( + individual_update_result["name"], "Vector Data (Individual Update)" + ) + self.assertEqual( + individual_update_result["caption"], + "Updated via individual update function", + ) self.assertEqual(individual_update_result["ordering_key"], 10) self.assertEqual(individual_update_result["visibility_interaction"], "slider") diff --git a/tests/maps_test.py b/tests/maps_test.py index bf90831..869d215 100644 --- a/tests/maps_test.py +++ b/tests/maps_test.py @@ -6,7 +6,6 @@ import os import sys import unittest -import time import datetime sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) @@ -128,7 +127,7 @@ def test_map_workflow(self): print("Creating embed token...") token_data = create_embed_token( - map_id=map_id, user_email=f"test.user@example.com" + map_id=map_id, user_email="test.user@example.com" ) self.assertIsNotNone(token_data) @@ -140,10 +139,7 @@ def test_map_workflow(self): print("Duplicating map...") duplicated_map_name = f"Duplicated Map ({self.timestamp})" - duplicated_map = duplicate_map( - map_id=map_id, - title=duplicated_map_name - ) + duplicated_map = duplicate_map(map_id=map_id, title=duplicated_map_name) self.assertIsNotNone(duplicated_map) self.assertIn("id", duplicated_map) diff --git a/tests/projects_test.py b/tests/projects_test.py index c8e5373..49be0bf 100644 --- a/tests/projects_test.py +++ b/tests/projects_test.py @@ -45,7 +45,8 @@ def test_projects_workflow(self): print(f"Creating project: {project_name}...") project = create_project( - name=project_name, visibility="private" # Options: "workspace" or "private" + name=project_name, + visibility="private", # Options: "workspace" or "private" ) self.assertIsNotNone(project) diff --git a/tests/sources_test.py b/tests/sources_test.py index 7a8db85..5a001b0 100644 --- a/tests/sources_test.py +++ b/tests/sources_test.py @@ -123,14 +123,12 @@ def test_sources_workflow(self): print("Waiting for source synchronization...") max_wait_time = 60 # seconds start_time = time.time() - sync_completed = False while time.time() - start_time < max_wait_time: current_source = get_source(source_id) sync_status = current_source.get("sync_status") if sync_status == "completed": - sync_completed = True print( f"Source sync completed in {time.time() - start_time:.1f} seconds" ) From 24a29cffd97369836df5555d66c8d19e07a04af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:13:30 +0200 Subject: [PATCH 2/7] update dependencies in mypy action --- .github/workflows/lint.yml | 5 ++--- .github/workflows/type_checking.yml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50283a6..3b47dc5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,8 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: astral-sh/ruff-action@v3 + - name: Lint and format using Ruff + uses: astral-sh/ruff-action@v3 run: ruff check --fix run: ruff format --diff - with: - python-version: '3.12' diff --git a/.github/workflows/type_checking.yml b/.github/workflows/type_checking.yml index d09cfba..c33d7e0 100644 --- a/.github/workflows/type_checking.yml +++ b/.github/workflows/type_checking.yml @@ -20,7 +20,7 @@ jobs: python-version: '3.12' - name: Install Dependencies - run: pip install mypy + run: pip install mypy certifi - name: Run mypy run: mypy . From 069404f171a6639c29dfdc98274746e3a6214171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:17:36 +0200 Subject: [PATCH 3/7] single action for linting and type checking --- .github/workflows/lint.yml | 17 ----------------- .../{type_checking.yml => lint_type_check.yml} | 13 +++++++++++-- 2 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 .github/workflows/lint.yml rename .github/workflows/{type_checking.yml => lint_type_check.yml} (63%) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 3b47dc5..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Felt Python Linting And Formatting - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - name: Lint and format using Ruff - uses: astral-sh/ruff-action@v3 - run: ruff check --fix - run: ruff format --diff diff --git a/.github/workflows/type_checking.yml b/.github/workflows/lint_type_check.yml similarity index 63% rename from .github/workflows/type_checking.yml rename to .github/workflows/lint_type_check.yml index c33d7e0..0beccb3 100644 --- a/.github/workflows/type_checking.yml +++ b/.github/workflows/lint_type_check.yml @@ -1,4 +1,4 @@ -name: Felt Python Type Checking +name: Linting And Type Checking on: @@ -8,7 +8,7 @@ on: branches: [ main ] jobs: - test: + type_check: runs-on: ubuntu-latest steps: @@ -24,3 +24,12 @@ jobs: - name: Run mypy run: mypy . + + lint: + runs-on: ubuntu-latest + + steps: + - name: Lint and format using Ruff + uses: astral-sh/ruff-action@v3 + run: ruff check --fix + run: ruff format --diff From d4747dfb888566f6d3e4f7d708a5c2c08cf36322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:20:23 +0200 Subject: [PATCH 4/7] fix linting action --- .github/workflows/lint_type_check.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint_type_check.yml b/.github/workflows/lint_type_check.yml index 0beccb3..2a82541 100644 --- a/.github/workflows/lint_type_check.yml +++ b/.github/workflows/lint_type_check.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' @@ -29,7 +29,6 @@ jobs: runs-on: ubuntu-latest steps: - - name: Lint and format using Ruff - uses: astral-sh/ruff-action@v3 - run: ruff check --fix - run: ruff format --diff + - uses: astral-sh/ruff-action@v3 + - run: ruff check --fix + - run: ruff format From 2826d9a2eb7a8a34738a500e4c7dc2cac497013b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:27:03 +0200 Subject: [PATCH 5/7] actually unify lint/type check actions --- .github/workflows/lint_type_check.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint_type_check.yml b/.github/workflows/lint_type_check.yml index 2a82541..ecfdd48 100644 --- a/.github/workflows/lint_type_check.yml +++ b/.github/workflows/lint_type_check.yml @@ -8,7 +8,7 @@ on: branches: [ main ] jobs: - type_check: + lint_type_check: runs-on: ubuntu-latest steps: @@ -20,15 +20,13 @@ jobs: python-version: '3.12' - name: Install Dependencies - run: pip install mypy certifi + run: pip install mypy certifi ruff - name: Run mypy run: mypy . - - lint: - runs-on: ubuntu-latest - - steps: - - uses: astral-sh/ruff-action@v3 - - run: ruff check --fix - - run: ruff format + + - name: Lint + run: ruff check --fix + + - name: Format + run: ruff format --diff From 9814d35d5197b440fd330e81f080201953bf17e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:29:05 +0200 Subject: [PATCH 6/7] ignore notebooks --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index afe2e22..f766d9d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,3 +24,6 @@ classifiers = [ Homepage = "https://github.com/felt/felt-python" Issues = "https://github.com/felt/felt-python/issues" Documentation = "https://developers.felt.com" + +[tool.ruff] +extend-exclude = ["*.ipynb"] From 7f8d659a129f4b8b8706e5826eb6091dde0986c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arredondo?= Date: Mon, 23 Jun 2025 13:31:41 +0200 Subject: [PATCH 7/7] some more linting --- .github/workflows/lint_type_check.yml | 2 +- felt_python/elements.py | 12 ++++++------ tests/layers_test.py | 2 +- tests/library_test.py | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint_type_check.yml b/.github/workflows/lint_type_check.yml index ecfdd48..347e270 100644 --- a/.github/workflows/lint_type_check.yml +++ b/.github/workflows/lint_type_check.yml @@ -26,7 +26,7 @@ jobs: run: mypy . - name: Lint - run: ruff check --fix + run: ruff check - name: Format run: ruff format --diff diff --git a/felt_python/elements.py b/felt_python/elements.py index 295a71a..fcd86dd 100644 --- a/felt_python/elements.py +++ b/felt_python/elements.py @@ -102,9 +102,9 @@ def upsert_elements( """ if isinstance(geojson_feature_collection, str): geojson_feature_collection = json.loads(geojson_feature_collection) - assert isinstance( - geojson_feature_collection, dict - ), "geojson_feature_collection must be a valid GeoJSON" + assert isinstance(geojson_feature_collection, dict), ( + "geojson_feature_collection must be a valid GeoJSON" + ) response = make_request( url=ELEMENTS.format(map_id=map_id), method="POST", @@ -137,9 +137,9 @@ def post_element_group( ): if isinstance(json_element, str): json_element = json.loads(json_element) - assert isinstance( - json_element, dict - ), "json_element must be a valid JSON object" + assert isinstance(json_element, dict), ( + "json_element must be a valid JSON object" + ) upsert_element_groups(map_id, [json_element], api_token) diff --git a/tests/layers_test.py b/tests/layers_test.py index 30c4d89..62b55b5 100644 --- a/tests/layers_test.py +++ b/tests/layers_test.py @@ -231,7 +231,7 @@ def test_layers_workflow(self): # Poll for export status (try a few times) max_polls = 3 for i in range(max_polls): - print(f"Checking export status (attempt {i+1}/{max_polls})...") + print(f"Checking export status (attempt {i + 1}/{max_polls})...") export_status = get_custom_export_status( map_id=map_id, layer_id=layer_id, export_id=export_id diff --git a/tests/library_test.py b/tests/library_test.py index c406894..dd4e8e0 100644 --- a/tests/library_test.py +++ b/tests/library_test.py @@ -48,7 +48,7 @@ def test_library_workflow(self): # Show first few layers if any for i, layer in enumerate(workspace_library["layers"][:3]): - print(f"Layer {i+1}: {layer['name']} (ID: {layer['id']})") + print(f"Layer {i + 1}: {layer['name']} (ID: {layer['id']})") # Step 2: List layers in the Felt data library print("\nListing layers in Felt data library...") @@ -64,7 +64,7 @@ def test_library_workflow(self): # Show first few layers for i, layer in enumerate(felt_library["layers"][:5]): - print(f"Layer {i+1}: {layer['name']} (ID: {layer['id']})") + print(f"Layer {i + 1}: {layer['name']} (ID: {layer['id']})") # Step 3: Create a map with a layer and publish it to the library map_name = f"Library Test Map ({self.timestamp})"