Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
cdanielw committed Oct 16, 2023
2 parents 931db64 + 8ed12bd commit abdcc2f
Show file tree
Hide file tree
Showing 29 changed files with 1,327 additions and 756 deletions.
Empty file modified demos/export-to-drive/index.html
100755 → 100644
Empty file.
1,223 changes: 613 additions & 610 deletions javascript/build/ee_api_js.js

Large diffs are not rendered by default.

70 changes: 53 additions & 17 deletions javascript/build/ee_api_js_debug.js

Large diffs are not rendered by default.

78 changes: 57 additions & 21 deletions javascript/build/ee_api_js_npm.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion javascript/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@google/earthengine",
"version": "0.1.370",
"version": "0.1.374",
"description": "JavaScript client for Google Earth Engine API.",
"author": "Google LLC",
"license": "Apache-2.0",
Expand Down
15 changes: 8 additions & 7 deletions javascript/src/apiclient.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const {PromiseRequestService} = goog.require('eeapiclient.promise_request_servic
/** @namespace */
const apiclient = {};

const API_CLIENT_VERSION = '0.1.370';
const API_CLIENT_VERSION = '0.1.374';

exports.VERSION = apiVersion.VERSION;
exports.API_CLIENT_VERSION = API_CLIENT_VERSION;
Expand Down Expand Up @@ -533,7 +533,7 @@ apiclient.setAuthToken = function(
}
} else {
apiclient.ensureAuthLibLoaded_(function() {
goog.global['gapi']['auth']['setToken'](tokenObject);
goog.global['gapi']['client']['setToken'](tokenObject);
if (callback) {
callback();
}
Expand Down Expand Up @@ -561,7 +561,8 @@ apiclient.refreshAuthToken = function(success, error, onImmediateFailed) {
const authArgs = {
'client_id': String(apiclient.authClientId_),
'immediate': true,
'scope': apiclient.authScopes_.join(' ')
'scope': apiclient.authScopes_.join(' '),
'plugin_name': 'earthengine',
};

// Start the authorization flow, first trying immediate mode, which tries to
Expand All @@ -575,7 +576,7 @@ apiclient.refreshAuthToken = function(success, error, onImmediateFailed) {
// Refresh the library auth token and handle error propagation.
apiclient.ensureAuthLibLoaded_(function() {
try {
goog.global['gapi']['auth']['setToken'](result);
goog.global['gapi']['client']['setToken'](result);
apiclient.handleAuthResult_(success, error, result);
} catch (e) {
error(e.toString());
Expand Down Expand Up @@ -1128,13 +1129,13 @@ apiclient.ensureAuthLibLoaded_ = function(callback) {
// Speed up auth request by using CORS instead of an iframe.
goog.global['gapi']['config']['update']('client/cors', true);
if (!apiclient.authTokenRefresher_) {
apiclient.setAuthTokenRefresher(goog.global['gapi']['auth']['authorize']);
apiclient.setAuthTokenRefresher(goog.global['gapi']['auth2']['authorize']);
}
callback();
};
if (goog.isObject(goog.global['gapi']) &&
goog.isObject(goog.global['gapi']['auth']) &&
typeof goog.global['gapi']['auth']['authorize'] === 'function') {
goog.isObject(goog.global['gapi']['auth2']) &&
typeof goog.global['gapi']['auth2']['authorize'] === 'function') {
done();
} else {
// The library is not loaded; load it now.
Expand Down
2 changes: 1 addition & 1 deletion javascript/src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ ee.data.authenticate = function(
* @export
*/
ee.data.authenticateViaPopup = function(opt_success, opt_error) {
goog.global['gapi']['auth']['authorize'](
goog.global['gapi']['auth2']['authorize'](
{
'client_id': ee.apiclient.getAuthClientId(),
'immediate': false,
Expand Down
51 changes: 51 additions & 0 deletions javascript/src/imagecollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,57 @@ ee.ImageCollection.prototype.select = function(selectors, opt_names) {
}));
};

/**
* Links images in this collection to matching images from `imageCollection`.
*
* For each source image in this collection, any specified bands or metadata
* will be added to the source image from the matching image found in
* `imageCollection`. If bands or metadata are already present, they will be
* overwritten. If matching images are not found, any new or updated bands will
* be fully masked and any new or updated metadata will be null. The output
* footprint will be the same as the source image footprint.
*
* Matches are determined if a source image and an image in `imageCollection`
* have a specific equivalent metadata property. If more than one collection
* image would match, the collection image selected is arbitrary. By default,
* images are matched on their 'system:index' metadata property.
*
* This linking function is a convenience method for adding bands to target
* images based on a specified shared metadata property and is intended to
* support linking collections that apply different processing/product
* generation to the same source imagery. For more expressive linking known as
* 'joining', see https://developers.google.com/earth-engine/guides/joins_intro.
*
* @param {!ee.ImageCollection} imageCollection The image collection searched to
* find matches from this collection.
* @param {?Array<string>=} opt_linkedBands Optional list of band names to add
* or update from matching images.
* @param {?Array<string>=} opt_linkedProperties Optional list of metadata
* properties to add or update from matching images.
* @param {string=} opt_matchPropertyName The metadata property name to use as a
* match criteria. Defaults to "system:index".
* @return {!ee.ImageCollection} The linked image collection.
* @export
*/
ee.ImageCollection.prototype.linkCollection = function(
imageCollection, opt_linkedBands, opt_linkedProperties,
opt_matchPropertyName) {
let args = ee.arguments.extractFromFunction(
ee.ImageCollection.prototype.linkCollection, arguments);
return /** @type {!ee.ImageCollection} */ (this.map(function(obj) {
let img = /** @type {!ee.Image} */ (obj);
img = /** @type {!ee.Image} */ (
ee.ApiFunction._call(
'Image.linkCollection',
img,
/** @type {!ee.ImageCollection} */ (args['imageCollection']),
/** @type {?Array<string>} */ (args['linkedBands']),
/** @type {?Array<string>} */ (args['linkedProperties']),
/** @type {?string} */ (args['matchPropertyName'])));
return img;
}));
};

/**
* Returns the first entry from a given collection.
*
Expand Down
Empty file modified javascript/src/terrain.js
100755 → 100644
Empty file.
49 changes: 26 additions & 23 deletions python/ee/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""The EE Python library."""

__version__ = '0.1.370'
__version__ = '0.1.374'

# Using lowercase function naming to match the JavaScript names.
# pylint: disable=g-bad-name
Expand All @@ -11,7 +11,7 @@
import inspect
import numbers
import os
from typing import Any, Hashable, Optional, Type
from typing import Any, Hashable, List as ListType, Optional, Sequence, Type, Union

from ee import batch
from ee import data
Expand Down Expand Up @@ -50,7 +50,7 @@
_HAS_DYNAMIC_ATTRIBUTES = True

# A list of autogenerated class names added by _InitializeGenerateClasses.
_generatedClasses = []
_generatedClasses: ListType[str] = []


class _AlgorithmsContainer(dict):
Expand All @@ -63,10 +63,10 @@ def __getattr__(self, name: Hashable) -> Any:
# Match dict's behavior when a key is missing.
raise AttributeError # pylint: disable=raise-missing-from

def __setattr__(self, name, value):
def __setattr__(self, name: Hashable, value: int) -> None:
self[name] = value

def __delattr__(self, name):
def __delattr__(self, name: Hashable) -> None:
del self[name]


Expand All @@ -75,11 +75,12 @@ def __delattr__(self, name):


def Authenticate(
authorization_code=None,
quiet=None,
code_verifier=None,
auth_mode=None,
scopes=None):
authorization_code: Optional[str] = None,
quiet: bool = False,
code_verifier: Optional[str] = None,
auth_mode: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
) -> None:
"""Prompts the user to authorize access to Earth Engine via OAuth2.
Args:
Expand All @@ -100,16 +101,18 @@ def Authenticate(
Returns:
(auth_url, code_verifier) when called with quiet='init_only'
"""
return oauth.authenticate(authorization_code, quiet, code_verifier, auth_mode,
scopes)
oauth.authenticate(
authorization_code, quiet, code_verifier, auth_mode, scopes
)


def Initialize(
credentials='persistent',
opt_url=None,
cloud_api_key=None,
http_transport=None,
project=None):
credentials: Optional[Any] = 'persistent',
opt_url: Optional[str] = None,
cloud_api_key: Optional[str] = None,
http_transport: Optional[Any] = None,
project: Optional[Union[str, int]] = None,
) -> None:
"""Initialize the EE library.
If this hasn't been called by the time any object constructor is used,
Expand Down Expand Up @@ -160,7 +163,7 @@ def Initialize(
_InitializeUnboundMethods()


def Reset():
def Reset() -> None:
"""Reset the library. Useful for re-initializing to a different server."""
data.reset()

Expand All @@ -186,7 +189,7 @@ def Reset():
Algorithms = _AlgorithmsContainer()


def _ResetGeneratedClasses():
def _ResetGeneratedClasses() -> None:
"""Remove the dynamic classes."""
global _generatedClasses

Expand Down Expand Up @@ -362,7 +365,7 @@ def _InitializeGeneratedClasses() -> None:
types._registerClasses(globals()) # pylint: disable=protected-access


def _MakeClass(name):
def _MakeClass(name: str) -> Type[Any]:
"""Generates a dynamic API class for a given name."""

def init(self, *args):
Expand All @@ -380,7 +383,7 @@ def init(self, *args):
onlyOneArg = (len(args) == 1)
# Are we trying to cast something that's already of the right class?
if onlyOneArg and isinstance(args[0], a_class):
result = args[0]
pass
else:
# Decide whether to call a server-side constructor or just do a
# client-side cast.
Expand Down Expand Up @@ -414,8 +417,8 @@ def init(self, *args):
raise EEException(
'Invalid argument for ee.{0}(): {1}. '
'Must be a ComputedObject.'.format(name, args))
else:
result = args[0]

result = args[0]
ComputedObject.__init__(self, result.func, result.args, result.varName)

properties = {'__init__': init, 'name': lambda self: name}
Expand Down
34 changes: 18 additions & 16 deletions python/ee/_cloud_api_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import json
import os
import re
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union
import warnings

import google_auth_httplib2
Expand Down Expand Up @@ -48,12 +48,13 @@ def __init__(self, timeout: Optional[float] = None):

def request( # pylint: disable=invalid-name
self,
uri,
method='GET',
body=None,
headers=None,
redirections=None,
connection_type=None):
uri: str,
method: str = 'GET',
body: Optional[str] = None,
headers: Optional[Dict[str, str]] = None,
redirections: Optional[int] = None,
connection_type: Optional[Type[Any]] = None,
) -> Tuple[httplib2.Response, Any]:
"""Makes an HTTP request using httplib2 semantics."""
del connection_type # Unused

Expand Down Expand Up @@ -89,9 +90,9 @@ def _wrap_request(

# pylint: disable=invalid-name
def builder(
http_transport: Any,
postproc: Any,
uri: Any,
http_transport: httplib2.Http,
postproc: Callable[..., Any],
uri: str,
method: str = 'GET',
body: Optional[Any] = None,
headers: Optional[Any] = None,
Expand Down Expand Up @@ -126,7 +127,7 @@ def set_cloud_api_user_project(cloud_api_user_project: str) -> None:

def build_cloud_resource(
api_base_url: str,
api_key: Optional[Any] = None,
api_key: Optional[str] = None,
credentials: Optional[Any] = None,
timeout: Optional[float] = None,
headers_supplier: Optional[Callable[[], Dict[str, Any]]] = None,
Expand Down Expand Up @@ -189,16 +190,17 @@ def build(**kwargs):
pass # Handle fallback case outside except block, for cleaner stack traces.
if resource is None:
resource = build()
# pylint: disable-next=protected-access
resource._baseUrl = api_base_url
return resource


def build_cloud_resource_from_document(
discovery_document,
http_transport=None,
headers_supplier=None,
response_inspector=None,
raw=False,
discovery_document: Any,
http_transport: Optional[httplib2.Http] = None,
headers_supplier: Optional[Callable[..., Any]] = None,
response_inspector: Optional[Callable[..., Any]] = None,
raw: bool = False,
) -> discovery.Resource:
"""Builds an Earth Engine Cloud API resource from a description of the API.
Expand Down
19 changes: 15 additions & 4 deletions python/ee/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@
import contextlib
import json
import sys
from typing import Any, Dict, Iterator, Optional, TextIO, Union

from google.auth import crypt
from google.oauth2 import service_account

from ee import apifunction
from ee import computedobject
from ee import data
from ee import oauth


def ServiceAccountCredentials(email, key_file=None, key_data=None):
def ServiceAccountCredentials(
email: str, key_file: Optional[str] = None, key_data: Optional[str] = None
) -> service_account.Credentials:
"""Configure OAuth2 credentials for a Google Service Account.
Args:
Expand Down Expand Up @@ -58,7 +64,9 @@ def ServiceAccountCredentials(email, key_file=None, key_data=None):
signer, email, oauth.TOKEN_URI, scopes=oauth.SCOPES)


def call(func, *args, **kwargs):
def call(
func: Union[str, apifunction.ApiFunction], *args, **kwargs
) -> computedobject.ComputedObject:
"""Invoke the given algorithm with the specified args.
Args:
Expand All @@ -77,7 +85,10 @@ def call(func, *args, **kwargs):
return func.call(*args, **kwargs)


def apply(func, named_args): # pylint: disable=redefined-builtin
# pylint: disable-next=redefined-builtin
def apply(
func: Union[str, apifunction.ApiFunction], named_args: Dict[str, Any]
) -> computedobject.ComputedObject:
"""Call a function with a dictionary of named arguments.
Args:
Expand All @@ -96,7 +107,7 @@ def apply(func, named_args): # pylint: disable=redefined-builtin


@contextlib.contextmanager
def profilePrinting(destination=sys.stderr):
def profilePrinting(destination: TextIO = sys.stderr) -> Iterator[None]:
# pylint: disable=g-doc-return-or-yield
"""Returns a context manager that prints a profile of enclosed API calls.
Expand Down
Loading

0 comments on commit abdcc2f

Please sign in to comment.