1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15+ import sys
16+ import types
1517from unittest import mock
1618
19+ import packaging .version
1720import pytest
1821
1922try :
3134except ImportError :
3235 pandas = None
3336
34- from google . cloud . bigquery import _versions_helpers
35- from google .cloud .bigquery import exceptions
37+ from google import cloud
38+ from google .cloud .bigquery import _versions_helpers , exceptions
3639
3740
3841@pytest .mark .skipif (pyarrow is None , reason = "pyarrow is not installed" )
@@ -59,20 +62,19 @@ def test_try_import_raises_error_w_legacy_pyarrow():
5962 versions .try_import (raise_if_error = True )
6063
6164
62- @pytest .mark .skipif (
63- pyarrow is not None ,
64- reason = "pyarrow is installed, but this test needs it not to be" ,
65- )
6665def test_try_import_raises_error_w_no_pyarrow ():
6766 versions = _versions_helpers .PyarrowVersions ()
68- with pytest .raises (exceptions .LegacyPyarrowError ):
69- versions .try_import (raise_if_error = True )
67+ with mock .patch .dict (sys .modules , {"pyarrow" : None }):
68+ assert versions .try_import (raise_if_error = False ) is None
69+ with pytest .raises (exceptions .LegacyPyarrowError ):
70+ versions .try_import (raise_if_error = True )
7071
7172
7273@pytest .mark .skipif (pyarrow is None , reason = "pyarrow is not installed" )
7374def test_installed_pyarrow_version_returns_cached ():
7475 versions = _versions_helpers .PyarrowVersions ()
7576 versions ._installed_version = object ()
77+
7678 assert versions .installed_version is versions ._installed_version
7779
7880
@@ -122,17 +124,27 @@ def test_returns_none_with_legacy_bqstorage():
122124 assert bq_storage is None
123125
124126
125- @pytest .mark .skipif (
126- bigquery_storage is not None ,
127- reason = "Tests behavior when `google-cloud-bigquery-storage` isn't installed" ,
128- )
129127def test_returns_none_with_bqstorage_uninstalled ():
130- try :
131- bqstorage_versions = _versions_helpers .BQStorageVersions ()
132- bq_storage = bqstorage_versions .try_import ()
133- except exceptions .LegacyBigQueryStorageError : # pragma: NO COVER
134- raise ("NotFound error raised when raise_if_error == False." )
135- assert bq_storage is None
128+ versions = _versions_helpers .BQStorageVersions ()
129+ with (
130+ mock .patch .dict (sys .modules , {"google.cloud.bigquery_storage" : None }),
131+ mock .patch .dict (cloud .__dict__ ),
132+ ):
133+ cloud .__dict__ .pop ("bigquery_storage" , None )
134+
135+ assert versions .try_import () is None
136+
137+
138+ def test_raises_error_with_bqstorage_uninstalled ():
139+ versions = _versions_helpers .BQStorageVersions ()
140+ with (
141+ mock .patch .dict (sys .modules , {"google.cloud.bigquery_storage" : None }),
142+ mock .patch .dict (cloud .__dict__ ),
143+ ):
144+ cloud .__dict__ .pop ("bigquery_storage" , None )
145+
146+ with pytest .raises (exceptions .BigQueryStorageNotFoundError ):
147+ versions .try_import (raise_if_error = True )
136148
137149
138150@pytest .mark .skipif (
@@ -153,6 +165,7 @@ def test_raises_error_w_unknown_bqstorage_version():
153165def test_installed_bqstorage_version_returns_cached ():
154166 bqstorage_versions = _versions_helpers .BQStorageVersions ()
155167 bqstorage_versions ._installed_version = object ()
168+
156169 assert bqstorage_versions .installed_version is bqstorage_versions ._installed_version
157170
158171
@@ -220,20 +233,19 @@ def test_try_import_raises_error_w_legacy_pandas():
220233 versions .try_import (raise_if_error = True )
221234
222235
223- @pytest .mark .skipif (
224- pandas is not None ,
225- reason = "pandas is installed, but this test needs it not to be" ,
226- )
227236def test_try_import_raises_error_w_no_pandas ():
228237 versions = _versions_helpers .PandasVersions ()
229- with pytest .raises (exceptions .LegacyPandasError ):
230- versions .try_import (raise_if_error = True )
238+ with mock .patch .dict (sys .modules , {"pandas" : None }):
239+ assert versions .try_import (raise_if_error = False ) is None
240+ with pytest .raises (exceptions .LegacyPandasError ):
241+ versions .try_import (raise_if_error = True )
231242
232243
233244@pytest .mark .skipif (pandas is None , reason = "pandas is not installed" )
234245def test_installed_pandas_version_returns_cached ():
235246 versions = _versions_helpers .PandasVersions ()
236247 versions ._installed_version = object ()
248+
237249 assert versions .installed_version is versions ._installed_version
238250
239251
@@ -246,3 +258,146 @@ def test_installed_pandas_version_returns_parsed_version():
246258 assert version .major == 1
247259 assert version .minor == 1
248260 assert version .micro == 0
261+
262+
263+ def test_installed_pandas_gbq_version_returns_cached ():
264+ versions = _versions_helpers .PandasGBQVersions ()
265+ versions ._installed_version = object ()
266+
267+ assert versions .installed_version is versions ._installed_version
268+
269+
270+ def test_installed_pandas_gbq_version_returns_parsed_version ():
271+ mock_pandas_gbq = mock .Mock ()
272+ mock_pandas_gbq .__version__ = "1.2.3"
273+ versions = _versions_helpers .PandasGBQVersions ()
274+ with mock .patch .dict (sys .modules , {"pandas_gbq" : mock_pandas_gbq }):
275+ version = versions .installed_version
276+
277+ assert version .major == 1
278+ assert version .minor == 2
279+ assert version .micro == 3
280+
281+
282+ def test_installed_pandas_gbq_version_falls_back_on_import_error ():
283+ versions = _versions_helpers .PandasGBQVersions ()
284+ with mock .patch .dict (sys .modules , {"pandas_gbq" : None }):
285+ version = versions .installed_version
286+
287+ assert version .major == 0
288+ assert version .minor == 0
289+ assert version .micro == 0
290+
291+
292+ def test_installed_pandas_gbq_version_falls_back_on_missing_version_attribute ():
293+ mock_pandas_gbq = types .ModuleType ("pandas_gbq" )
294+ versions = _versions_helpers .PandasGBQVersions ()
295+ with mock .patch .dict (sys .modules , {"pandas_gbq" : mock_pandas_gbq }):
296+ version = versions .installed_version
297+
298+ assert version .major == 0
299+ assert version .minor == 0
300+ assert version .micro == 0
301+
302+
303+ def test_installed_pandas_gbq_version_falls_back_on_other_error ():
304+ class CorruptPandasGBQ :
305+ @property
306+ def __version__ (self ):
307+ raise TypeError ("Corrupted package" )
308+
309+ versions = _versions_helpers .PandasGBQVersions ()
310+ with mock .patch .dict (sys .modules , {"pandas_gbq" : CorruptPandasGBQ ()}):
311+ version = versions .installed_version
312+
313+ assert version .major == 0
314+ assert version .minor == 0
315+ assert version .micro == 0
316+
317+
318+ def test_pandas_gbq_delegation_api_version_returns_cached ():
319+ versions = _versions_helpers .PandasGBQVersions ()
320+ versions ._delegation_api_version = object ()
321+
322+ assert versions .delegation_api_version is versions ._delegation_api_version
323+
324+
325+ def test_pandas_gbq_delegation_api_version_returns_value ():
326+ mock_pandas_gbq = mock .Mock ()
327+ mock_pandas_gbq ._internal_delegation_api_version = "1.2.3"
328+ versions = _versions_helpers .PandasGBQVersions ()
329+ with mock .patch .dict (sys .modules , {"pandas_gbq" : mock_pandas_gbq }):
330+ version = versions .delegation_api_version
331+
332+ assert version .major == 1
333+ assert version .minor == 2
334+ assert version .micro == 3
335+
336+
337+ def test_pandas_gbq_delegation_api_version_supports_integer_value ():
338+ mock_pandas_gbq = mock .Mock ()
339+ mock_pandas_gbq ._internal_delegation_api_version = 1
340+ versions = _versions_helpers .PandasGBQVersions ()
341+ with mock .patch .dict (sys .modules , {"pandas_gbq" : mock_pandas_gbq }):
342+ version = versions .delegation_api_version
343+
344+ assert version .major == 1
345+ assert version .minor == 0
346+ assert version .micro == 0
347+
348+
349+ def test_pandas_gbq_delegation_api_version_falls_back_on_missing_attribute ():
350+ mock_pandas_gbq = types .ModuleType ("pandas_gbq" )
351+ versions = _versions_helpers .PandasGBQVersions ()
352+ with mock .patch .dict (sys .modules , {"pandas_gbq" : mock_pandas_gbq }):
353+ version = versions .delegation_api_version
354+
355+ assert version .major == 0
356+ assert version .minor == 0
357+ assert version .micro == 0
358+
359+
360+ def test_pandas_gbq_delegation_api_version_falls_back_on_import_error ():
361+ versions = _versions_helpers .PandasGBQVersions ()
362+ with mock .patch .dict (sys .modules , {"pandas_gbq" : None }):
363+ version = versions .delegation_api_version
364+
365+ assert version .major == 0
366+ assert version .minor == 0
367+ assert version .micro == 0
368+
369+
370+ def test_pandas_gbq_delegation_api_version_falls_back_on_other_error ():
371+ class CorruptPandasGBQ :
372+ @property
373+ def _internal_delegation_api_version (self ):
374+ raise TypeError ("Corrupted package" )
375+
376+ versions = _versions_helpers .PandasGBQVersions ()
377+ with mock .patch .dict (sys .modules , {"pandas_gbq" : CorruptPandasGBQ ()}):
378+ version = versions .delegation_api_version
379+
380+ assert version .major == 0
381+ assert version .minor == 0
382+ assert version .micro == 0
383+
384+
385+ def test_pandas_gbq_is_delegation_supported_true ():
386+ versions = _versions_helpers .PandasGBQVersions ()
387+ versions ._delegation_api_version = packaging .version .Version ("1.0.0" )
388+
389+ assert versions .is_delegation_supported is True
390+
391+
392+ def test_pandas_gbq_is_delegation_supported_with_sub_minor_version ():
393+ versions = _versions_helpers .PandasGBQVersions ()
394+ versions ._delegation_api_version = packaging .version .Version ("1.2.0" )
395+
396+ assert versions .is_delegation_supported is True
397+
398+
399+ def test_pandas_gbq_is_delegation_supported_false ():
400+ versions = _versions_helpers .PandasGBQVersions ()
401+ versions ._delegation_api_version = packaging .version .Version ("0.9.9" )
402+
403+ assert versions .is_delegation_supported is False
0 commit comments