Skip to content

Commit dd4e672

Browse files
committed
test new raster upload cmd
1 parent 9a9b5a7 commit dd4e672

File tree

2 files changed

+105
-4
lines changed

2 files changed

+105
-4
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@ target/
5757

5858
# OS X
5959
.DS_Store
60+
61+
# temp
62+
tmp/

mapbox_tilesets/scripts/cli.py

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
"""Tilesets command line interface"""
2+
3+
import base64
24
import builtins
35
import json
6+
import re
47
import tempfile
5-
from urllib.parse import urlencode, urlparse, parse_qs
8+
from urllib.parse import parse_qs, urlencode, urlparse
69

710
import click
811
import cligj
9-
import base64
10-
import re
1112
from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
1213

1314
import mapbox_tilesets
14-
from mapbox_tilesets import utils, errors
15+
from mapbox_tilesets import errors, utils
1516

1617

1718
@click.version_option(version=mapbox_tilesets.__version__, message="%(version)s")
@@ -629,6 +630,103 @@ def callback(m):
629630
raise errors.TilesetsError(resp.text)
630631

631632

633+
@cli.command("upload-raster-source")
634+
@click.argument("username", required=True, type=str)
635+
@click.argument("id", required=True, callback=validate_source_id, type=str)
636+
@click.argument("inputs", nargs=-1, required=True, type=click.File("r"))
637+
@click.option("--quiet", is_flag=True, help="Don't show progress bar")
638+
@click.option(
639+
"--replace",
640+
is_flag=True,
641+
help="Upload raster source file",
642+
)
643+
@click.option("--token", "-t", required=False, type=str, help="Mapbox access token")
644+
@click.option("--indent", type=int, default=None, help="Indent for JSON output")
645+
@click.pass_context
646+
def upload_source(ctx, username, id, inputs, quiet, replace, token=None, indent=None):
647+
"""Create a new tileset source, or add data to an existing tileset source.
648+
Optionally, replace an existing tileset source.
649+
650+
tilesets upload-source <username> <source_id> <path/to/source/data>
651+
"""
652+
return _upload_source(ctx, username, id, inputs, quiet, replace, token, indent)
653+
654+
655+
def _upload_source(ctx, username, id, inputs, quiet, replace, token=None, indent=None):
656+
mapbox_api = utils._get_api()
657+
mapbox_token = utils._get_token(token)
658+
s = utils._get_session()
659+
url = (
660+
f"{mapbox_api}/tilesets/v1/sources/{username}/{id}?access_token={mapbox_token}"
661+
)
662+
663+
method = "post"
664+
if replace:
665+
method = "put"
666+
667+
# This does the decoding by hand instead of using pyjwt because
668+
# pyjwt rejects tokens that don't pad the base64 with = signs.
669+
token_parts = mapbox_token.split(".")
670+
if len(token_parts) < 2:
671+
raise errors.TilesetsError(
672+
f"Token {mapbox_token} does not contain a payload component"
673+
)
674+
else:
675+
while len(token_parts[1]) % 4 != 0:
676+
token_parts[1] = token_parts[1] + "="
677+
body = json.loads(base64.b64decode(token_parts[1]))
678+
if "u" in body:
679+
if username != body["u"]:
680+
raise errors.TilesetsError(
681+
f"Token username {body['u']} does not match username {username}"
682+
)
683+
else:
684+
raise errors.TilesetsError(
685+
f"Token {mapbox_token} does not contain a username"
686+
)
687+
688+
if len(inputs) > 10:
689+
raise errors.TilesetsError("Maximum 10 files can be uploaded at once.")
690+
691+
for item in inputs:
692+
m = MultipartEncoder(
693+
fields={"file": ("file", open(item.name, "rb"), "multipart/form-data")}
694+
)
695+
if quiet:
696+
resp = getattr(s, method)(
697+
url,
698+
data=m,
699+
headers={
700+
"Content-Disposition": "multipart/form-data",
701+
"Content-type": m.content_type,
702+
},
703+
)
704+
else:
705+
prog = click.progressbar(
706+
length=m.len, fill_char="=", width=0, label="upload progress"
707+
)
708+
with prog:
709+
710+
def callback(m):
711+
prog.pos = m.bytes_read
712+
prog.update(0) # Step is 0 because we set pos above
713+
714+
monitor = MultipartEncoderMonitor(m, callback)
715+
resp = getattr(s, method)(
716+
url,
717+
data=monitor,
718+
headers={
719+
"Content-Disposition": "multipart/form-data",
720+
"Content-type": monitor.content_type,
721+
},
722+
)
723+
724+
if resp.status_code == 200:
725+
click.echo(json.dumps(resp.json(), indent=indent))
726+
else:
727+
raise errors.TilesetsError(resp.text)
728+
729+
632730
@cli.command("add-source", hidden=True)
633731
@click.argument("username", required=True, type=str)
634732
@click.argument("id", required=True, type=str)

0 commit comments

Comments
 (0)