Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename get_api_key to get_env_var #2151

Merged
merged 2 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions geemap/ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import ipywidgets as widgets
from IPython.display import display, HTML
from typing import Optional
from .common import get_api_key, temp_file_path
from .common import get_env_var, temp_file_path
from .geemap import Map, ee_initialize

try:
Expand Down Expand Up @@ -57,14 +57,14 @@ def __init__(
# Initialization

if project is None:
project = get_api_key("EE_PROJECT_ID") or get_api_key("GOOGLE_PROJECT_ID")
project = get_env_var("EE_PROJECT_ID") or get_env_var("GOOGLE_PROJECT_ID")
if project is None:
raise ValueError(
"Please provide a valid project ID via the 'project' parameter."
)

if google_api_key is None:
google_api_key = get_api_key("GOOGLE_API_KEY")
google_api_key = get_env_var("GOOGLE_API_KEY")
if google_api_key is None:
raise ValueError(
"Please provide a valid Google API key via the 'google_api_key' parameter."
Expand Down
49 changes: 21 additions & 28 deletions geemap/coreutils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import os
import sys
import zipfile

import ee
Expand All @@ -13,32 +14,29 @@
pass


def get_api_key(name: Optional[str] = None, key: Optional[str] = None) -> Optional[str]:
"""
Retrieves an API key. If a key is provided, it is returned directly. If a
name is provided, the function attempts to retrieve the key from user data
(if running in Google Colab) or from environment variables.
def get_env_var(key: str) -> Optional[str]:
"""Retrieves an environment variable or Colab secret for the given key.

Colab secrets have precedence over environment variables.

Args:
name (Optional[str], optional): The name of the key to retrieve. Defaults to None.
key (Optional[str], optional): The key to return directly. Defaults to None.
key (str): The key that's used to fetch the environment variable.

Returns:
Optional[str]: The retrieved key, or None if no key was found.
Optional[str]: The retrieved key, or None if no environment variable was found.
"""
if not key:
return None

if key is not None:
return key
elif name is not None:
if in_colab_shell():
from google.colab import userdata
if in_colab_shell():
from google.colab import userdata

try:
return userdata.get(name)
except (userdata.SecretNotFoundError, userdata.NotebookAccessError):
return os.environ.get(name)
else:
return os.environ.get(name)
try:
return userdata.get(key)
except (userdata.SecretNotFoundError, userdata.NotebookAccessError):
pass

return os.environ.get(key)


def ee_initialize(
Expand Down Expand Up @@ -85,7 +83,7 @@ def ee_initialize(
kwargs["http_transport"] = httplib2.Http()

if project is None:
kwargs["project"] = get_api_key("EE_PROJECT_ID")
kwargs["project"] = get_env_var("EE_PROJECT_ID")
else:
kwargs["project"] = project

Expand All @@ -100,7 +98,7 @@ def ee_initialize(
auth_args["auth_mode"] = auth_mode

if ee.data._credentials is None:
ee_token = get_api_key(token_name)
ee_token = get_env_var(token_name)
if service_account:
try:
credential_file_path = os.path.expanduser(
Expand Down Expand Up @@ -342,7 +340,7 @@ def get_google_maps_api_key(key: str = "GOOGLE_MAPS_API_KEY") -> Optional[str]:
Returns:
str: The API key, or None if it could not be found.
"""
if api_key := get_api_key(key):
if api_key := get_env_var(key):
return api_key
return os.environ.get(key, None)

Expand All @@ -354,12 +352,7 @@ def in_colab_shell() -> bool:
Returns:
bool: True if running in Google Colab, False otherwise.
"""
import sys

if "google.colab" in sys.modules:
return True
else:
return False
return "google.colab" in sys.modules


def check_color(in_color: Union[str, Tuple[int, int, int]]) -> str:
Expand Down
12 changes: 6 additions & 6 deletions geemap/maplibregl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1292,8 +1292,8 @@ def to_html(
html = html.replace(div_before, div_after)

if replace_key or (os.getenv("MAPTILER_REPLACE_KEY") is not None):
key_before = get_api_key("MAPTILER_KEY")
key_after = get_api_key("MAPTILER_KEY_PUBLIC")
key_before = get_env_var("MAPTILER_KEY")
key_after = get_env_var("MAPTILER_KEY_PUBLIC")
if key_after is not None:
html = html.replace(key_before, key_after)

Expand Down Expand Up @@ -2217,7 +2217,7 @@ def _get_3d_terrain_style(
"""

if api_key is None:
api_key = get_api_key(token)
api_key = get_env_var(token)

if api_key is None:
print("An API key is required to use the 3D terrain feature.")
Expand Down Expand Up @@ -2748,7 +2748,7 @@ def add_3d_buildings(
None
"""

MAPTILER_KEY = get_api_key("MAPTILER_KEY")
MAPTILER_KEY = get_env_var("MAPTILER_KEY")
source = {
"url": f"https://api.maptiler.com/tiles/v3/tiles.json?key={MAPTILER_KEY}",
"type": "vector",
Expand Down Expand Up @@ -2913,7 +2913,7 @@ def construct_maptiler_style(style: str, api_key: Optional[str] = None) -> str:
"""

if api_key is None:
api_key = get_api_key("MAPTILER_KEY")
api_key = get_env_var("MAPTILER_KEY")

url = f"https://api.maptiler.com/maps/{style}/style.json?key={api_key}"

Expand Down Expand Up @@ -2965,7 +2965,7 @@ def maptiler_3d_style(
"""

if api_key is None:
api_key = get_api_key(token)
api_key = get_env_var(token)

if api_key is None:
print("An API key is required to use the 3D terrain feature.")
Expand Down
56 changes: 56 additions & 0 deletions tests/test_coreutils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python

"""Tests for `coreutils` module."""
import os
import sys
import unittest
from unittest import mock

from geemap import coreutils


class FakeSecretNotFoundError(Exception):
"""google.colab.userdata.SecretNotFoundError fake."""


class FakeNotebookAccessError(Exception):
"""google.colab.userdata.NotebookAccessError fake."""


class TestCoreUtils(unittest.TestCase):
"""Tests for core utilss."""

def test_get_environment_invalid_key(self):
"""Verifies None is returned if keys are invalid."""
self.assertIsNone(coreutils.get_env_var(None))
self.assertIsNone(coreutils.get_env_var(""))

@mock.patch.dict(os.environ, {"key": "value"})
def test_get_env_var_unknown_key(self):
"""Verifies None is returned if the environment variable could not be found."""
self.assertIsNone(coreutils.get_env_var("unknown-key"))

@mock.patch.dict(os.environ, {"key": "value"})
def test_get_env_var_from_env(self):
"""Verifies environment variables are read from environment variables."""
self.assertEqual(coreutils.get_env_var("key"), "value")

@mock.patch.dict("sys.modules", {"google.colab": mock.Mock()})
def test_get_env_var_from_colab(self):
"""Verifies environment variables are read from Colab secrets."""
mock_colab = sys.modules["google.colab"]
mock_colab.userdata.get.return_value = "colab-value"

self.assertEqual(coreutils.get_env_var("key"), "colab-value")
mock_colab.userdata.get.assert_called_once_with("key")

@mock.patch.dict(os.environ, {"key": "environ-value"})
@mock.patch.dict("sys.modules", {"google.colab": mock.Mock()})
def test_get_env_var_colab_fails_fallback_to_env(self):
"""Verifies environment variables are read if a Colab secret read fails."""
mock_colab = sys.modules["google.colab"]
mock_colab.userdata.SecretNotFoundError = FakeSecretNotFoundError
mock_colab.userdata.NotebookAccessError = FakeNotebookAccessError
mock_colab.userdata.get.side_effect = FakeNotebookAccessError()

self.assertEqual(coreutils.get_env_var("key"), "environ-value")