Skip to content

Commit a668075

Browse files
committed
Merge branch 'master' of github.com:Kaggle/docker-python
2 parents 7ef4a5e + 724844a commit a668075

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ RUN apt-get -y install zlib1g-dev liblcms2-dev libwebp-dev libgeos-dev && \
137137
pip install cartopy && \
138138
# MXNet
139139
pip install mxnet && \
140-
pip install --upgrade numpy && \
140+
# b/140423854 v1.17 prints annoying deprecation warning messages with TensorFlow 1.14.0. Remove once we upgrade to TF 1.14.1 or 2.x
141+
pip install numpy==1.16.4 && \
141142
pip install gluonnlp && \
142143
pip install gluoncv && \
143144
# h2o (requires java)
@@ -432,8 +433,9 @@ RUN pip install bcolz && \
432433
RUN pip install jsonnet overrides tensorboardX && \
433434
pip install flask>=1.0.2 flask-cors>=3.0.7 gevent>=1.3.6 && \
434435
pip install unidecode parsimonious>=0.8.0 sqlparse>=0.2.4 word2number>=1.1 && \
435-
pip install pytorch-pretrained-bert>=0.6.0 jsonpickle && \
436+
pip install pytorch-pretrained-bert>=0.6.0 pytorch-transformers==1.1.0 jsonpickle && \
436437
pip install requests>=2.18 editdistance conllu==0.11 && \
438+
pip install conllu==1.3.1 && \
437439
pip install --no-dependencies allennlp && \
438440
/tmp/clean-layer.sh
439441

patches/kaggle_secrets.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class CredentialError(Exception):
2626
class BackendError(Exception):
2727
pass
2828

29+
30+
class ValidationError(Exception):
31+
pass
32+
2933
@unique
3034
class GcpTarget(Enum):
3135
"""Enum class to store GCP targets."""
@@ -47,6 +51,7 @@ def service(self):
4751

4852
class UserSecretsClient():
4953
GET_USER_SECRET_ENDPOINT = '/requests/GetUserSecretRequest'
54+
GET_USER_SECRET_BY_LABEL_ENDPOINT = '/requests/GetUserSecretByLabelRequest'
5055
BIGQUERY_TARGET_VALUE = 1
5156

5257
def __init__(self):
@@ -60,8 +65,8 @@ def __init__(self):
6065
f'but none found in environment variable {_KAGGLE_USER_SECRETS_TOKEN_ENV_VAR_NAME}')
6166
self.headers = {'Content-type': 'application/json'}
6267

63-
def _make_post_request(self, data: dict) -> dict:
64-
url = f'{self.url_base}{self.GET_USER_SECRET_ENDPOINT}'
68+
def _make_post_request(self, data: dict, endpoint: str = GET_USER_SECRET_ENDPOINT) -> dict:
69+
url = f'{self.url_base}{endpoint}'
6570
request_body = dict(data)
6671
request_body['JWE'] = self.jwt_token
6772
req = urllib.request.Request(url, headers=self.headers, data=bytes(
@@ -88,6 +93,26 @@ def _make_post_request(self, data: dict) -> dict:
8893
' Please ensure you have access to the resource.') from e
8994
raise BackendError('Unexpected response from the service.') from e
9095

96+
def get_secret(self, label) -> str:
97+
"""Retrieves a user secret value by its label.
98+
99+
This returns the value of the secret with the given label,
100+
if it attached to the current kernel.
101+
Example usage:
102+
client = UserSecretsClient()
103+
secret = client.get_secret('my_db_password')
104+
"""
105+
if label is None or len(label) == 0:
106+
raise ValidationError("Label must be non-empty.")
107+
request_body = {
108+
'Label': label,
109+
}
110+
response_json = self._make_post_request(request_body, self.GET_USER_SECRET_BY_LABEL_ENDPOINT)
111+
if 'secret' not in response_json:
112+
raise BackendError(
113+
f'Unexpected response from the service. Response: {response_json}')
114+
return response_json['secret']
115+
91116
def get_bigquery_access_token(self) -> Tuple[str, Optional[datetime]]:
92117
"""Retrieves BigQuery access token information from the UserSecrets service.
93118

tests/test_user_secrets.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
from google.cloud import bigquery
1313
from kaggle_secrets import (_KAGGLE_URL_BASE_ENV_VAR_NAME,
1414
_KAGGLE_USER_SECRETS_TOKEN_ENV_VAR_NAME,
15-
CredentialError, GcpTarget, UserSecretsClient, BackendError)
15+
CredentialError, GcpTarget, UserSecretsClient,
16+
BackendError, ValidationError)
1617

1718
_TEST_JWT = 'test-secrets-key'
1819

@@ -37,7 +38,7 @@ def do_POST(s):
3738

3839

3940
class TestUserSecrets(unittest.TestCase):
40-
SERVER_ADDRESS = urlparse(os.getenv(_KAGGLE_URL_BASE_ENV_VAR_NAME))
41+
SERVER_ADDRESS = urlparse(os.getenv(_KAGGLE_URL_BASE_ENV_VAR_NAME, default="http://127.0.0.1:8001"))
4142

4243
def _test_client(self, client_func, expected_path, expected_body, secret=None, success=True):
4344
_request = {}
@@ -84,6 +85,34 @@ def test_no_token_fails(self):
8485
with self.assertRaises(CredentialError):
8586
client = UserSecretsClient()
8687

88+
def test_get_secret_succeeds(self):
89+
secret = '12345'
90+
91+
def call_get_secret():
92+
client = UserSecretsClient()
93+
secret_response = client.get_secret("secret_label")
94+
self.assertEqual(secret_response, secret)
95+
self._test_client(call_get_secret,
96+
'/requests/GetUserSecretByLabelRequest', {'Label': "secret_label", 'JWE': _TEST_JWT},
97+
secret=secret)
98+
99+
def test_get_secret_handles_unsuccessful(self):
100+
def call_get_secret():
101+
client = UserSecretsClient()
102+
with self.assertRaises(BackendError):
103+
secret_response = client.get_secret("secret_label")
104+
self._test_client(call_get_secret,
105+
'/requests/GetUserSecretByLabelRequest', {'Label': "secret_label", 'JWE': _TEST_JWT},
106+
success=False)
107+
108+
def test_get_secret_validates_label(self):
109+
env = EnvironmentVarGuard()
110+
env.set(_KAGGLE_USER_SECRETS_TOKEN_ENV_VAR_NAME, _TEST_JWT)
111+
with env:
112+
client = UserSecretsClient()
113+
with self.assertRaises(ValidationError):
114+
secret_response = client.get_secret("")
115+
87116
@mock.patch('kaggle_secrets.datetime')
88117
def test_get_access_token_succeeds(self, mock_dt):
89118
secret = '12345'

0 commit comments

Comments
 (0)