Skip to content

Commit 9478b3a

Browse files
authored
Merge pull request #165 from mapbox/validate-source-id
validate source-id when uploading
2 parents 3ff6d5c + 721288c commit 9478b3a

File tree

10 files changed

+76
-18
lines changed

10 files changed

+76
-18
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ repos:
22
-
33
repo: 'https://github.com/ambv/black'
44
# 18.6b1
5-
rev: 20.8b1
5+
rev: 22.3.0
66
hooks:
77
- id: black
88
args: ['--safe']

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ python:
33
- '3.6'
44
- '3.7'
55
install:
6+
- pip install -U setuptools importlib-metadata
67
- pip install -r requirements.txt -e .[test]
78
script:
89
- python --version

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
=======
44

5+
# 1.7.4 (2022-07-13)
6+
- validates source id for correct syntax when `upload-source` command to resolve `Connection reset by peer error`
7+
58
# 1.7.3 (2022-03-14)
69
- Loads `supermercado` on request because binaries for arm64 MacOS and Windows are not easily available.
710
- Hide deprecated `add-source` command from command list.

mapbox_tilesets/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""mapbox_tilesets package"""
22

3-
__version__ = "1.7.3"
3+
__version__ = "1.7.4"

mapbox_tilesets/scripts/cli.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import click
77
import cligj
88
import base64
9+
import re
910
from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
1011

1112
import mapbox_tilesets
@@ -509,9 +510,18 @@ def validate_source(features):
509510
click.echo("✔ valid")
510511

511512

513+
def validate_source_id(ctx, param, value):
514+
if re.match("^[a-zA-Z0-9-_]{1,32}$", value):
515+
return value
516+
else:
517+
raise click.BadParameter(
518+
'Tileset Source ID is invalid. Must be no more than 32 characters and only include "-", "_", and alphanumeric characters.'
519+
)
520+
521+
512522
@cli.command("upload-source")
513523
@click.argument("username", required=True, type=str)
514-
@click.argument("id", required=True, type=str)
524+
@click.argument("id", required=True, callback=validate_source_id, type=str)
515525
@cligj.features_in_arg
516526
@click.option("--no-validation", is_flag=True, help="Bypass source file validation")
517527
@click.option("--quiet", is_flag=True, help="Don't show progress bar")

mapbox_tilesets/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def _tile2lng(tile_x, zoom):
157157
-------
158158
longitude
159159
"""
160-
return ((tile_x / 2 ** zoom) * 360.0) - 180.0
160+
return ((tile_x / 2**zoom) * 360.0) - 180.0
161161

162162

163163
def _tile2lat(tile_y, zoom):
@@ -174,7 +174,7 @@ def _tile2lat(tile_y, zoom):
174174
-------
175175
latitude
176176
"""
177-
n = np.pi - 2 * np.pi * tile_y / 2 ** zoom
177+
n = np.pi - 2 * np.pi * tile_y / 2**zoom
178178
return (180.0 / np.pi) * np.arctan(0.5 * (np.exp(n) - np.exp(-n)))
179179

180180

@@ -198,7 +198,7 @@ def _calculate_tile_area(tile):
198198
bottom = np.deg2rad(_tile2lat(tile[:, 1] + 1, tile[:, 2]))
199199
return (
200200
(np.pi / np.deg2rad(180))
201-
* EARTH_RADIUS ** 2
201+
* EARTH_RADIUS**2
202202
* np.abs(np.sin(top) - np.sin(bottom))
203203
* np.abs(left - right)
204204
)

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
boto3==1.9.99
2-
Click==7.1.2
3-
cligj==0.5.0
2+
Click==8.0.2
3+
cligj==0.7.2
44
numpy==1.19.5
55
requests==2.21.0
66
requests-toolbelt==0.9.1

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ def read(fname):
1616
setup(
1717
name="mapbox-tilesets",
1818
version=__version__,
19-
description=u"CLI for interacting with and preparing data for the Tilesets API",
19+
description="CLI for interacting with and preparing data for the Tilesets API",
2020
long_description=long_description,
2121
long_description_content_type="text/markdown",
2222
classifiers=[],
2323
keywords="",
24-
author=u"Mapbox",
24+
author="Mapbox",
2525
author_email="[email protected]",
2626
url="https://github.com/mapbox/tilesets-cli",
2727
license="BSD-2",
2828
packages=find_packages(exclude=["ez_setup", "examples", "tests"]),
2929
install_requires=[
3030
"boto3",
31-
"click~=7.1.2",
31+
"click~=8.0.2",
3232
"cligj",
3333
"numpy",
3434
"requests",
@@ -48,7 +48,7 @@ def read(fname):
4848
"pytest==4.6.11",
4949
"pytest-cov",
5050
"pre-commit",
51-
"black==20.8b1",
51+
"black==22.3.0",
5252
"pep8",
5353
"supermercado~=0.2.0",
5454
"toml==0.10.2",

tests/test_cli_create.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def test_cli_create_private_invalid(mock_request_post, MockResponse):
140140
)
141141
assert result.exit_code == 2
142142
assert (
143-
"Invalid value for '--privacy' / '-p': invalid choice: invalid-privacy-value. (choose from public, private)"
143+
"Error: Invalid value for '--privacy' / '-p': 'invalid-privacy-value' is not one of 'public', 'private'."
144144
in result.output
145145
)
146146

tests/test_cli_sources.py

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from click.testing import CliRunner
22
import json
33
import os
4+
import click
45
from unittest import mock
56

67
import pytest
@@ -42,10 +43,9 @@ def side_effect(fields):
4243
add_source, ["test-user", "hello-world", "tests/fixtures/valid.ldgeojson"]
4344
)
4445
assert validated_result.exit_code == 0
45-
4646
assert (
4747
validated_result.output
48-
== """{"id": "mapbox://tileset-source/test-user/hello-world"}\n"""
48+
== """upload progress\n{"id": "mapbox://tileset-source/test-user/hello-world"}\n"""
4949
)
5050

5151

@@ -149,10 +149,9 @@ def side_effect(fields):
149149
["test-user", "hello-world", "tests/fixtures/valid.ldgeojson", "--replace"],
150150
)
151151
assert validated_result.exit_code == 0
152-
153152
assert (
154153
validated_result.output
155-
== """{"id": "mapbox://tileset-source/test-user/hello-world"}\n"""
154+
== """upload progress\n{"id": "mapbox://tileset-source/test-user/hello-world"}\n"""
156155
)
157156

158157

@@ -187,8 +186,53 @@ def side_effect(fields):
187186

188187
assert (
189188
validated_result.output
190-
== """{"id": "mapbox://tileset-source/test-user/hello-world"}\n"""
189+
== """upload progress\n{"id": "mapbox://tileset-source/test-user/hello-world"}\n"""
190+
)
191+
192+
193+
@pytest.mark.usefixtures("token_environ")
194+
@mock.patch("mapbox_tilesets.scripts.cli.MultipartEncoder")
195+
@mock.patch("mapbox_tilesets.scripts.cli.MultipartEncoderMonitor")
196+
@mock.patch("requests.Session.post")
197+
def test_cli_upload_source(
198+
mock_request_post,
199+
mock_multipart_encoder_monitor,
200+
mock_multipart_encoder,
201+
MockResponse,
202+
MockMultipartEncoding,
203+
):
204+
okay_response = {"id": "mapbox://tileset-source/test-user/populated-places-source"}
205+
mock_request_post.return_value = MockResponse(okay_response, status_code=200)
206+
207+
expected_json = b'{"type":"Feature","geometry":{"type":"Point","coordinates":[125.6,10.1]},"properties":{"name":"Dinagat Islands"}}\n'
208+
209+
def side_effect(fields):
210+
assert fields["file"][1].read() == expected_json
211+
return MockMultipartEncoding()
212+
213+
mock_multipart_encoder.side_effect = side_effect
214+
215+
runner = CliRunner()
216+
validated_result = runner.invoke(
217+
upload_source,
218+
["test-user", "populated-places-source", "tests/fixtures/valid.ldgeojson"],
219+
)
220+
assert validated_result.exit_code == 0
221+
assert (
222+
validated_result.output
223+
== """upload progress\n{"id": "mapbox://tileset-source/test-user/populated-places-source"}\n"""
224+
)
225+
226+
227+
@pytest.mark.usefixtures("token_environ")
228+
def validate_source_id(self):
229+
self.assertRaises(
230+
click.BadParameter,
231+
value="mapbox://tileset-source/test-user/hello-world",
232+
param=None,
233+
ctx=None,
191234
)
235+
self.assertEqual("hello-world", value="hello-world", param=None, ctx=None)
192236

193237

194238
@pytest.mark.usefixtures("token_environ")

0 commit comments

Comments
 (0)