Exemple #1
0
def add_source(ctx, username, id, features, no_validation, token=None, indent=None):
    """Create/add a tileset source

    tilesets add-source <username> <id> <path/to/source/data>
    """
    mapbox_api = _get_api()
    mapbox_token = _get_token(token)
    url = (
        f"{mapbox_api}/tilesets/v1/sources/{username}/{id}?access_token={mapbox_token}"
    )

    with tempfile.TemporaryFile() as file:
        for feature in features:
            if not no_validation:
                utils.validate_geojson(feature)
            file.write((json.dumps(feature) + "\n").encode("utf-8"))

        file.seek(0)
        m = MultipartEncoder(fields={"file": ("file", file)})
        resp = requests.post(
            url,
            data=m,
            headers={
                "Content-Disposition": "multipart/form-data",
                "Content-type": m.content_type,
            },
        )

    if resp.status_code == 200:
        click.echo(json.dumps(resp.json(), indent=indent))
    else:
        raise errors.TilesetsError(resp.text)
Exemple #2
0
def validate_source(features):
    """Validate your source file.
    $ tilesets validate-source <path/to/your/src/file>
    """
    click.echo("Validating features", err=True)

    for feature in features:
        utils.validate_geojson(feature)

    click.echo("✔ valid")
Exemple #3
0
def estimate_area(features, precision, no_validation=False, force_1cm=False):
    """Estimate area of features with a precision level.

    tilesets estimate-area <features> <precision>

    features must be a list of paths to local files containing GeoJSON feature collections or feature sequences from argument or stdin, or a list of string-encoded coordinate pairs of the form "[lng, lat]", or "lng, lat", or "lng lat".
    """
    area = 0
    if precision == "1cm" and not force_1cm:
        raise errors.TilesetsError(
            "The --force-1cm flag must be present to enable 1cm precision area calculation and may take longer for large feature inputs or data with global extents. 1cm precision for tileset processing is only available upon request after contacting Mapbox support."
        )
    if precision != "1cm" and force_1cm:
        raise errors.TilesetsError(
            "The --force-1cm flag is enabled but the precision is not 1cm."
        )

    # builtins.list because there is a list command in the cli & will thrown an error
    try:
        features = builtins.list(filter_features(features))
    except (ValueError, json.decoder.JSONDecodeError):
        raise errors.TilesetsError(
            "Error with feature parsing. Ensure that feature inputs are valid and formatted correctly. Try 'tilesets estimate-area --help' for help."
        )
    except Exception:
        raise errors.TilesetsError("Error with feature filtering.")

    # expect users to bypass source validation when users rerun command and their features passed validation previously
    if not no_validation:
        for feature in features:
            utils.validate_geojson(feature)

    area = utils.calculate_tiles_area(features, precision)
    area = str(round(area))

    click.echo(
        json.dumps(
            {
                "km2": area,
                "precision": precision,
                "pricing_docs": "For more information, visit https://www.mapbox.com/pricing/#tilesets",
            }
        )
    )
Exemple #4
0
def _upload_source(
    ctx, username, id, features, no_validation, quiet, replace, token=None, indent=None
):
    """Create/add a tileset source

    tilesets add-source <username> <id> <path/to/source/data>
    """
    mapbox_api = utils._get_api()
    mapbox_token = utils._get_token(token)
    s = utils._get_session()
    url = (
        f"{mapbox_api}/tilesets/v1/sources/{username}/{id}?access_token={mapbox_token}"
    )

    method = "post"
    if replace:
        method = "put"

    # This does the decoding by hand instead of using pyjwt because
    # pyjwt rejects tokens that don't pad the base64 with = signs.
    token_parts = mapbox_token.split(".")
    if len(token_parts) < 2:
        raise errors.TilesetsError(
            f"Token {mapbox_token} does not contain a payload component"
        )
    else:
        while len(token_parts[1]) % 4 != 0:
            token_parts[1] = token_parts[1] + "="
        body = json.loads(base64.b64decode(token_parts[1]))
        if "u" in body:
            if username != body["u"]:
                raise errors.TilesetsError(
                    f"Token username {body['u']} does not match username {username}"
                )
        else:
            raise errors.TilesetsError(
                f"Token {mapbox_token} does not contain a username"
            )

    with tempfile.TemporaryFile() as file:
        for feature in features:
            if not no_validation:
                utils.validate_geojson(feature)

            file.write(
                (json.dumps(feature, separators=(",", ":")) + "\n").encode("utf-8")
            )

        file.seek(0)
        m = MultipartEncoder(fields={"file": ("file", file)})

        if quiet:
            resp = getattr(s, method)(
                url,
                data=m,
                headers={
                    "Content-Disposition": "multipart/form-data",
                    "Content-type": m.content_type,
                },
            )
        else:
            prog = click.progressbar(
                length=m.len, fill_char="=", width=0, label="upload progress"
            )
            with prog:

                def callback(m):
                    prog.pos = m.bytes_read
                    prog.update(0)  # Step is 0 because we set pos above

                monitor = MultipartEncoderMonitor(m, callback)
                resp = getattr(s, method)(
                    url,
                    data=monitor,
                    headers={
                        "Content-Disposition": "multipart/form-data",
                        "Content-type": monitor.content_type,
                    },
                )

    if resp.status_code == 200:
        click.echo(json.dumps(resp.json(), indent=indent))
    else:
        raise errors.TilesetsError(resp.text)
Exemple #5
0
def validate_stream(features):
    for feature in features:
        utils.validate_geojson(feature)
        yield feature