Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6f98e15

Browse filesBrowse files
committed
Adding lazy loading support for storage default project.
1 parent f47f62c commit 6f98e15
Copy full SHA for 6f98e15

File tree

Expand file treeCollapse file tree

5 files changed

+225
-91
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+225
-91
lines changed

‎gcloud/storage/__init__.py

Copy file name to clipboardExpand all lines: gcloud/storage/__init__.py
+1-20Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from gcloud.storage._implicit_environ import get_default_bucket
4646
from gcloud.storage._implicit_environ import get_default_connection
4747
from gcloud.storage._implicit_environ import get_default_project
48+
from gcloud.storage._implicit_environ import set_default_project
4849
from gcloud.storage.api import create_bucket
4950
from gcloud.storage.api import get_all_buckets
5051
from gcloud.storage.api import get_bucket
@@ -59,7 +60,6 @@
5960
'https://www.googleapis.com/auth/devstorage.read_write')
6061

6162
_BUCKET_ENV_VAR_NAME = 'GCLOUD_BUCKET_NAME'
62-
_PROJECT_ENV_VAR_NAME = 'GCLOUD_PROJECT'
6363

6464

6565
def set_default_bucket(bucket=None):
@@ -88,25 +88,6 @@ def set_default_bucket(bucket=None):
8888
_implicit_environ._DEFAULTS.bucket = bucket
8989

9090

91-
def set_default_project(project=None):
92-
"""Set default bucket name either explicitly or implicitly as fall-back.
93-
94-
In implicit case, currently only supports enviroment variable but will
95-
support App Engine, Compute Engine and other environments in the future.
96-
97-
Local environment variable used is:
98-
- GCLOUD_PROJECT
99-
100-
:type project: string
101-
:param project: Optional. The project name to use as default.
102-
"""
103-
if project is None:
104-
project = os.getenv(_PROJECT_ENV_VAR_NAME)
105-
106-
if project is not None:
107-
_implicit_environ._DEFAULTS.project = project
108-
109-
11091
def set_default_connection(connection=None):
11192
"""Set default connection either explicitly or implicitly as fall-back.
11293

‎gcloud/storage/_implicit_environ.py

Copy file name to clipboardExpand all lines: gcloud/storage/_implicit_environ.py
+60-3Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,55 @@
1919
"""
2020

2121

22+
import os
23+
24+
from gcloud._helpers import _lazy_property_deco
25+
26+
27+
_PROJECT_ENV_VAR_NAME = 'GCLOUD_PROJECT'
28+
29+
30+
def _get_production_project():
31+
"""Gets the production project if it can be inferred."""
32+
return os.getenv(_PROJECT_ENV_VAR_NAME)
33+
34+
35+
def _determine_default_project(project=None):
36+
"""Determine default project ID explicitly or implicitly as fall-back.
37+
38+
In implicit case, currently only supports enviroment variable but will
39+
support App Engine, Compute Engine and other environments in the future.
40+
41+
Local environment variable used is:
42+
- GCLOUD_PROJECT
43+
44+
:type project: string
45+
:param project: Optional. The project name to use as default.
46+
47+
:rtype: string or ``NoneType``
48+
:returns: Default project if it can be determined.
49+
"""
50+
if project is None:
51+
project = _get_production_project()
52+
53+
return project
54+
55+
56+
def set_default_project(project=None):
57+
"""Set default project either explicitly or implicitly as fall-back.
58+
59+
:type project: string
60+
:param project: Optional. The project name to use as default.
61+
62+
:raises: :class:`EnvironmentError` if no project was found.
63+
"""
64+
project = _determine_default_project(project=project)
65+
if project is not None:
66+
_DEFAULTS.project = project
67+
else:
68+
raise EnvironmentError('No project could be inferred.')
69+
70+
2271
class _DefaultsContainer(object):
2372
"""Container for defaults.
2473
@@ -32,8 +81,16 @@ class _DefaultsContainer(object):
3281
:param connection: Persistent implied connection from environment.
3382
"""
3483

35-
def __init__(self, project=None, bucket=None, connection=None):
36-
self.project = project
84+
@_lazy_property_deco
85+
@staticmethod
86+
def project():
87+
"""Return the implicit default project."""
88+
return _determine_default_project()
89+
90+
def __init__(self, project=None, bucket=None, connection=None,
91+
implicit=False):
92+
if project is not None or not implicit:
93+
self.project = project
3794
self.bucket = bucket
3895
self.connection = connection
3996

@@ -65,4 +122,4 @@ def get_default_connection():
65122
return _DEFAULTS.connection
66123

67124

68-
_DEFAULTS = _DefaultsContainer()
125+
_DEFAULTS = _DefaultsContainer(implicit=True)

‎gcloud/storage/test___init__.py

Copy file name to clipboardExpand all lines: gcloud/storage/test___init__.py
-67Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -135,73 +135,6 @@ def test_set_explicit_None_w_env_var_set(self):
135135
self.assertEqual(default_bucket.connection, CONNECTION)
136136

137137

138-
class Test_set_default_project(unittest2.TestCase):
139-
140-
def setUp(self):
141-
from gcloud.storage._testing import _setup_defaults
142-
_setup_defaults(self)
143-
144-
def tearDown(self):
145-
from gcloud.storage._testing import _tear_down_defaults
146-
_tear_down_defaults(self)
147-
148-
def _callFUT(self, project=None):
149-
from gcloud.storage import set_default_project
150-
return set_default_project(project=project)
151-
152-
def _monkey(self, implicit_project):
153-
import os
154-
from gcloud.storage import _PROJECT_ENV_VAR_NAME
155-
from gcloud._testing import _Monkey
156-
environ = {_PROJECT_ENV_VAR_NAME: implicit_project}
157-
return _Monkey(os, getenv=environ.get)
158-
159-
def test_no_env_var_set(self):
160-
from gcloud.storage import _implicit_environ
161-
with self._monkey(None):
162-
self._callFUT()
163-
self.assertEqual(_implicit_environ.get_default_project(), None)
164-
165-
def test_set_from_env_var(self):
166-
from gcloud.storage import _implicit_environ
167-
IMPLICIT_PROJECT = 'IMPLICIT'
168-
with self._monkey(IMPLICIT_PROJECT):
169-
self._callFUT()
170-
self.assertEqual(_implicit_environ.get_default_project(),
171-
IMPLICIT_PROJECT)
172-
173-
def test_set_explicit_w_env_var_set(self):
174-
from gcloud.storage import _implicit_environ
175-
EXPLICIT_PROJECT = 'EXPLICIT'
176-
with self._monkey(None):
177-
self._callFUT(EXPLICIT_PROJECT)
178-
self.assertEqual(_implicit_environ.get_default_project(),
179-
EXPLICIT_PROJECT)
180-
181-
def test_set_explicit_no_env_var_set(self):
182-
from gcloud.storage import _implicit_environ
183-
IMPLICIT_PROJECT = 'IMPLICIT'
184-
EXPLICIT_PROJECT = 'EXPLICIT'
185-
with self._monkey(IMPLICIT_PROJECT):
186-
self._callFUT(EXPLICIT_PROJECT)
187-
self.assertEqual(_implicit_environ.get_default_project(),
188-
EXPLICIT_PROJECT)
189-
190-
def test_set_explicit_None_wo_env_var_set(self):
191-
from gcloud.storage import _implicit_environ
192-
with self._monkey(None):
193-
self._callFUT(None)
194-
self.assertEqual(_implicit_environ.get_default_project(), None)
195-
196-
def test_set_explicit_None_w_env_var_set(self):
197-
from gcloud.storage import _implicit_environ
198-
IMPLICIT_PROJECT = 'IMPLICIT'
199-
with self._monkey(IMPLICIT_PROJECT):
200-
self._callFUT(None)
201-
self.assertEqual(_implicit_environ.get_default_project(),
202-
IMPLICIT_PROJECT)
203-
204-
205138
class Test_set_default_connection(unittest2.TestCase):
206139

207140
def setUp(self):
+162Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Copyright 2014 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import unittest2
16+
17+
18+
class Test__get_production_project(unittest2.TestCase):
19+
20+
def _callFUT(self):
21+
from gcloud.storage import _implicit_environ
22+
return _implicit_environ._get_production_project()
23+
24+
def test_no_value(self):
25+
import os
26+
from gcloud._testing import _Monkey
27+
28+
environ = {}
29+
with _Monkey(os, getenv=environ.get):
30+
project = self._callFUT()
31+
self.assertEqual(project, None)
32+
33+
def test_value_set(self):
34+
import os
35+
from gcloud._testing import _Monkey
36+
from gcloud.storage._implicit_environ import _PROJECT_ENV_VAR_NAME
37+
38+
MOCK_PROJECT = object()
39+
environ = {_PROJECT_ENV_VAR_NAME: MOCK_PROJECT}
40+
with _Monkey(os, getenv=environ.get):
41+
project = self._callFUT()
42+
self.assertEqual(project, MOCK_PROJECT)
43+
44+
45+
class Test__determine_default_project(unittest2.TestCase):
46+
47+
def _callFUT(self, project=None):
48+
from gcloud.storage._implicit_environ import _determine_default_project
49+
return _determine_default_project(project=project)
50+
51+
def _determine_default_helper(self, prod=None, project=None):
52+
from gcloud._testing import _Monkey
53+
from gcloud.storage import _implicit_environ
54+
55+
_callers = []
56+
57+
def prod_mock():
58+
_callers.append('prod_mock')
59+
return prod
60+
61+
patched_methods = {
62+
'_get_production_project': prod_mock,
63+
}
64+
65+
with _Monkey(_implicit_environ, **patched_methods):
66+
returned_project = self._callFUT(project)
67+
68+
return returned_project, _callers
69+
70+
def test_no_value(self):
71+
project, callers = self._determine_default_helper()
72+
self.assertEqual(project, None)
73+
self.assertEqual(callers, ['prod_mock'])
74+
75+
def test_explicit(self):
76+
PROJECT = object()
77+
project, callers = self._determine_default_helper(project=PROJECT)
78+
self.assertEqual(project, PROJECT)
79+
self.assertEqual(callers, [])
80+
81+
def test_prod(self):
82+
PROJECT = object()
83+
project, callers = self._determine_default_helper(prod=PROJECT)
84+
self.assertEqual(project, PROJECT)
85+
self.assertEqual(callers, ['prod_mock'])
86+
87+
88+
class Test_set_default_project(unittest2.TestCase):
89+
90+
def setUp(self):
91+
from gcloud.storage._testing import _setup_defaults
92+
_setup_defaults(self)
93+
94+
def tearDown(self):
95+
from gcloud.storage._testing import _tear_down_defaults
96+
_tear_down_defaults(self)
97+
98+
def _callFUT(self, project=None):
99+
from gcloud.storage._implicit_environ import set_default_project
100+
return set_default_project(project=project)
101+
102+
def test_raises(self):
103+
from gcloud._testing import _Monkey
104+
from gcloud.storage import _implicit_environ
105+
106+
_called_project = []
107+
108+
def mock_determine(project):
109+
_called_project.append(project)
110+
return None
111+
112+
with _Monkey(_implicit_environ,
113+
_determine_default_project=mock_determine):
114+
self.assertRaises(EnvironmentError, self._callFUT)
115+
116+
self.assertEqual(_called_project, [None])
117+
118+
def test_set_correctly(self):
119+
from gcloud._testing import _Monkey
120+
from gcloud.storage import _implicit_environ
121+
122+
self.assertEqual(_implicit_environ._DEFAULTS.project, None)
123+
124+
PROJECT = object()
125+
_called_project = []
126+
127+
def mock_determine(project):
128+
_called_project.append(project)
129+
return PROJECT
130+
131+
with _Monkey(_implicit_environ,
132+
_determine_default_project=mock_determine):
133+
self._callFUT()
134+
135+
self.assertEqual(_implicit_environ._DEFAULTS.project, PROJECT)
136+
self.assertEqual(_called_project, [None])
137+
138+
139+
class Test_lazy_loading(unittest2.TestCase):
140+
141+
def setUp(self):
142+
from gcloud.storage._testing import _setup_defaults
143+
_setup_defaults(self, implicit=True)
144+
145+
def tearDown(self):
146+
from gcloud.storage._testing import _tear_down_defaults
147+
_tear_down_defaults(self)
148+
149+
def test_descriptor_for_project(self):
150+
from gcloud._testing import _Monkey
151+
from gcloud.storage import _implicit_environ
152+
153+
self.assertFalse('project' in _implicit_environ._DEFAULTS.__dict__)
154+
155+
DEFAULT = object()
156+
157+
with _Monkey(_implicit_environ,
158+
_determine_default_project=lambda: DEFAULT):
159+
lazy_loaded = _implicit_environ._DEFAULTS.project
160+
161+
self.assertEqual(lazy_loaded, DEFAULT)
162+
self.assertTrue('project' in _implicit_environ._DEFAULTS.__dict__)

‎regression/storage.py

Copy file name to clipboardExpand all lines: regression/storage.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@
2020
from gcloud import exceptions
2121
from gcloud import storage
2222
from gcloud.storage._helpers import _base64_md5hash
23+
from gcloud.storage import _implicit_environ
2324
from gcloud.storage.batch import Batch
2425

2526

2627
HTTP = httplib2.Http()
2728
SHARED_BUCKETS = {}
2829

29-
storage._PROJECT_ENV_VAR_NAME = 'GCLOUD_TESTS_PROJECT_ID'
30+
_implicit_environ._PROJECT_ENV_VAR_NAME = 'GCLOUD_TESTS_PROJECT_ID'
3031
storage.set_defaults()
3132

3233

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.