diff --git a/.librarian/generator-input/librarian.py b/.librarian/generator-input/librarian.py index 46c2e8dbb4..e458f64615 100644 --- a/.librarian/generator-input/librarian.py +++ b/.librarian/generator-input/librarian.py @@ -250,4 +250,4 @@ # Use a python runtime which is available in the owlbot post processor here # https://github.com/googleapis/synthtool/blob/master/docker/owlbot/python/Dockerfile -s.shell.run(["nox", "-s", "blacken-3.14"], hide_output=False) +s.shell.run(["nox", "-s", "format-3.14"], hide_output=False) diff --git a/.librarian/generator-input/noxfile.py b/.librarian/generator-input/noxfile.py index 82715de072..cdcdcd9f6f 100644 --- a/.librarian/generator-input/noxfile.py +++ b/.librarian/generator-input/noxfile.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Generated by synthtool. DO NOT EDIT! from __future__ import absolute_import @@ -64,6 +65,7 @@ SYSTEM_TEST_STANDARD_DEPENDENCIES: List[str] = [ "mock", "pytest", + "pytest-asyncio", "google-cloud-testutils", ] SYSTEM_TEST_EXTERNAL_DEPENDENCIES: List[str] = [] @@ -217,9 +219,8 @@ def unit(session, protobuf_implementation): session.install("protobuf<4") # Run py.test against the unit tests. - session.run( + args = [ "py.test", - "--quiet", "-s", f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google", @@ -228,8 +229,13 @@ def unit(session, protobuf_implementation): "--cov-config=.coveragerc", "--cov-report=", "--cov-fail-under=0", - os.path.join("tests", "unit"), - *session.posargs, + ] + if not session.posargs: + args.append(os.path.join("tests", "unit")) + args.extend(session.posargs) + + session.run( + *args, env={ "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, }, @@ -362,12 +368,19 @@ def system(session, protobuf_implementation, database_dialect): # Run py.test against the system tests. if system_test_exists: - session.run( + args = [ "py.test", "--quiet", + "-o", + "asyncio_mode=auto", f"--junitxml=system_{session.python}_sponge_log.xml", - system_test_path, - *session.posargs, + ] + if not session.posargs: + args.append(system_test_path) + args.extend(session.posargs) + + session.run( + *args, env={ "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, "SPANNER_DATABASE_DIALECT": database_dialect, @@ -375,12 +388,47 @@ def system(session, protobuf_implementation, database_dialect): }, ) elif system_test_folder_exists: + # Run sync tests + sync_args = [ + "py.test", + "--quiet", + "-o", + "asyncio_mode=auto", + f"--junitxml=system_{session.python}_sync_sponge_log.xml", + ] + if not session.posargs: + sync_args.append(os.path.join("tests", "system")) + sync_args.append("--ignore=tests/system/_async") + else: + sync_args.extend(session.posargs) + session.run( + *sync_args, + env={ + "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, + "SPANNER_DATABASE_DIALECT": database_dialect, + "SKIP_BACKUP_TESTS": "true", + }, + ) + + # Run async tests + async_args = [ "py.test", "--quiet", - f"--junitxml=system_{session.python}_sponge_log.xml", - system_test_folder_path, - *session.posargs, + "-o", + "asyncio_mode=auto", + f"--junitxml=system_{session.python}_async_sponge_log.xml", + ] + if not session.posargs: + async_args.append(os.path.join("tests", "system", "_async")) + else: + # If posargs are provided, only run if they match async tests + # or just skip if they were already run in sync. + # For simplicity, we only run async folder if no posargs. + return + + session.run( + *async_args, env={ "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, "SPANNER_DATABASE_DIALECT": database_dialect, @@ -551,6 +599,10 @@ def prerelease_deps(session, protobuf_implementation, database_dialect): "google-cloud-testutils", # dependencies of google-cloud-testutils" "click", + # dependency of google-auth + "cffi", + "cryptography", + "cachetools", ] for dep in prerel_deps: @@ -589,6 +641,8 @@ def prerelease_deps(session, protobuf_implementation, database_dialect): session.run( "py.test", "--verbose", + "-o", + "asyncio_mode=auto", f"--junitxml=system_{session.python}_sponge_log.xml", system_test_path, *session.posargs, @@ -602,6 +656,8 @@ def prerelease_deps(session, protobuf_implementation, database_dialect): session.run( "py.test", "--verbose", + "-o", + "asyncio_mode=auto", f"--junitxml=system_{session.python}_sponge_log.xml", system_test_folder_path, *session.posargs, @@ -611,3 +667,10 @@ def prerelease_deps(session, protobuf_implementation, database_dialect): "SKIP_BACKUP_TESTS": "true", }, ) + + +@nox.session(python=DEFAULT_PYTHON_VERSION) +def generate(session): + """Regenerate synchronous code from asynchronous code.""" + session.install("black", "autoflake") + session.run("python", ".cross_sync/generate.py", "google/cloud/spanner_v1") diff --git a/.librarian/state.yaml b/.librarian/state.yaml index bc132b9050..9547debffc 100644 --- a/.librarian/state.yaml +++ b/.librarian/state.yaml @@ -21,7 +21,8 @@ libraries: - ^google/cloud/spanner_v1/types - ^google/cloud/spanner_admin_database_v1 - ^google/cloud/spanner_admin_instance_v1 - - ^tests/unit/gapic + - ^tests/unit/gapic/spanner + - ^tests/unit/gapic/__init__.py - ^tests/__init__.py - ^tests/unit/__init__.py - ^.pre-commit-config.yaml diff --git a/google/cloud/spanner_v1/__init__.py b/google/cloud/spanner_v1/__init__.py index c1e29e5576..ed7a32de70 100644 --- a/google/cloud/spanner_v1/__init__.py +++ b/google/cloud/spanner_v1/__init__.py @@ -63,7 +63,6 @@ BatchWriteRequest, BatchWriteResponse, BeginTransactionRequest, - ClientContext, CommitRequest, CreateSessionRequest, DeleteSessionRequest, @@ -124,7 +123,6 @@ "BatchWriteRequest", "BatchWriteResponse", "BeginTransactionRequest", - "ClientContext", "CommitRequest", "CommitResponse", "CreateSessionRequest", diff --git a/google/cloud/spanner_v1/_helpers.py b/google/cloud/spanner_v1/_helpers.py index a2772d434a..667b88bc05 100644 --- a/google/cloud/spanner_v1/_helpers.py +++ b/google/cloud/spanner_v1/_helpers.py @@ -32,7 +32,6 @@ from google.rpc.error_details_pb2 import RetryInfo from google.cloud._helpers import _date_from_iso8601_date -from google.cloud.spanner_v1.types import ClientContext from google.cloud.spanner_v1.types import RequestOptions from google.cloud.spanner_v1.data_types import JsonObject, Interval from google.cloud.spanner_v1.exceptions import wrap_with_request_id @@ -196,17 +195,17 @@ def _merge_query_options(base, merge): def _merge_client_context(base, merge): """Merge higher precedence ClientContext with current ClientContext. - :type base: :class:`~google.cloud.spanner_v1.types.ClientContext` + :type base: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` or :class:`dict` or None :param base: The current ClientContext that is intended for use. - :type merge: :class:`~google.cloud.spanner_v1.types.ClientContext` + :type merge: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` or :class:`dict` or None :param merge: The ClientContext that has a higher priority than base. These options should overwrite the fields in base. - :rtype: :class:`~google.cloud.spanner_v1.types.ClientContext` + :rtype: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` or None :returns: ClientContext object formed by merging the two given ClientContexts. @@ -215,15 +214,23 @@ def _merge_client_context(base, merge): return None # Avoid in-place modification of base - combined_pb = ClientContext()._pb + combined_pb = RequestOptions.ClientContext()._pb if base: - base_pb = ClientContext(base)._pb if isinstance(base, dict) else base._pb + base_pb = ( + RequestOptions.ClientContext(base)._pb + if isinstance(base, dict) + else base._pb + ) combined_pb.MergeFrom(base_pb) if merge: - merge_pb = ClientContext(merge)._pb if isinstance(merge, dict) else merge._pb + merge_pb = ( + RequestOptions.ClientContext(merge)._pb + if isinstance(merge, dict) + else merge._pb + ) combined_pb.MergeFrom(merge_pb) - combined = ClientContext(combined_pb) + combined = RequestOptions.ClientContext(combined_pb) if not combined.secure_context: return None @@ -233,18 +240,18 @@ def _merge_client_context(base, merge): def _validate_client_context(client_context): """Validate and convert client_context. - :type client_context: :class:`~google.cloud.spanner_v1.types.ClientContext` + :type client_context: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` or :class:`dict` :param client_context: (Optional) Client context to use. - :rtype: :class:`~google.cloud.spanner_v1.types.ClientContext` + :rtype: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` :returns: Validated ClientContext object or None. :raises TypeError: if client_context is not a ClientContext or a dict. """ if client_context is not None: if isinstance(client_context, dict): - client_context = ClientContext(client_context) - elif not isinstance(client_context, ClientContext): + client_context = RequestOptions.ClientContext(client_context) + elif not isinstance(client_context, RequestOptions.ClientContext): raise TypeError("client_context must be a ClientContext or a dict") return client_context @@ -256,7 +263,7 @@ def _merge_request_options(request_options, client_context): or :class:`dict` or None :param request_options: The current RequestOptions that is intended for use. - :type client_context: :class:`~google.cloud.spanner_v1.types.ClientContext` + :type client_context: :class:`~google.cloud.spanner_v1.types.RequestOptions.ClientContext` or :class:`dict` or None :param client_context: The ClientContext to merge into request_options. diff --git a/noxfile.py b/noxfile.py index 9136bbde98..cdcdcd9f6f 100644 --- a/noxfile.py +++ b/noxfile.py @@ -14,9 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# DO NOT EDIT THIS FILE OUTSIDE OF `.librarian/generator-input` -# The source of truth for this file is `.librarian/generator-input` - # Generated by synthtool. DO NOT EDIT! diff --git a/tests/unit/test_client_context.py b/tests/unit/test_client_context.py index 3d03d30cc6..6e08b02d03 100644 --- a/tests/unit/test_client_context.py +++ b/tests/unit/test_client_context.py @@ -22,7 +22,6 @@ _merge_request_options, ) from google.cloud.spanner_v1.types import ( - ClientContext, ExecuteSqlRequest, RequestOptions, ) @@ -33,23 +32,27 @@ def test__merge_client_context_both_none(self): self.assertIsNone(_merge_client_context(None, None)) def test__merge_client_context_base_none(self): - merge = ClientContext(secure_context={"a": struct_pb2.Value(string_value="A")}) + merge = RequestOptions.ClientContext( + secure_context={"a": struct_pb2.Value(string_value="A")} + ) result = _merge_client_context(None, merge) self.assertEqual(result.secure_context["a"], "A") def test__merge_client_context_merge_none(self): - base = ClientContext(secure_context={"a": struct_pb2.Value(string_value="A")}) + base = RequestOptions.ClientContext( + secure_context={"a": struct_pb2.Value(string_value="A")} + ) result = _merge_client_context(base, None) self.assertEqual(result.secure_context["a"], "A") def test__merge_client_context_both_set(self): - base = ClientContext( + base = RequestOptions.ClientContext( secure_context={ "a": struct_pb2.Value(string_value="A"), "b": struct_pb2.Value(string_value="B1"), } ) - merge = ClientContext( + merge = RequestOptions.ClientContext( secure_context={ "b": struct_pb2.Value(string_value="B2"), "c": struct_pb2.Value(string_value="C"), @@ -62,7 +65,7 @@ def test__merge_client_context_both_set(self): def test__merge_request_options_with_client_context(self): request_options = RequestOptions(priority=RequestOptions.Priority.PRIORITY_LOW) - client_context = ClientContext( + client_context = RequestOptions.ClientContext( secure_context={"a": struct_pb2.Value(string_value="A")} ) @@ -91,7 +94,7 @@ def test_client_init_with_client_context(self): disable_builtin_metrics=True, ) - self.assertIsInstance(client._client_context, ClientContext) + self.assertIsInstance(client._client_context, RequestOptions.ClientContext) self.assertEqual(client._client_context.secure_context["a"], "A") def test_snapshot_execute_sql_propagates_client_context(self): @@ -106,11 +109,11 @@ def test_snapshot_execute_sql_propagates_client_context(self): client = database._instance._client = mock.Mock() client._query_options = None - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"client": struct_pb2.Value(string_value="from-client")} ) - snapshot_context = ClientContext( + snapshot_context = RequestOptions.ClientContext( secure_context={"snapshot": struct_pb2.Value(string_value="from-snapshot")} ) snapshot = Snapshot(session, client_context=snapshot_context) @@ -148,11 +151,11 @@ def test_transaction_commit_propagates_client_context(self): database._next_nth_request = 1 client = database._instance._client = mock.Mock() - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"client": struct_pb2.Value(string_value="from-client")} ) - transaction_context = ClientContext( + transaction_context = RequestOptions.ClientContext( secure_context={"txn": struct_pb2.Value(string_value="from-txn")} ) transaction = Transaction(session, client_context=transaction_context) @@ -196,11 +199,11 @@ def test_snapshot_execute_sql_request_level_override(self): client = database._instance._client = mock.Mock() client._query_options = None - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"a": struct_pb2.Value(string_value="from-client")} ) - snapshot_context = ClientContext( + snapshot_context = RequestOptions.ClientContext( secure_context={ "a": struct_pb2.Value(string_value="from-snapshot"), "b": struct_pb2.Value(string_value="B"), @@ -209,7 +212,7 @@ def test_snapshot_execute_sql_request_level_override(self): snapshot = Snapshot(session, client_context=snapshot_context) request_options = RequestOptions( - client_context=ClientContext( + client_context=RequestOptions.ClientContext( secure_context={"a": struct_pb2.Value(string_value="from-request")} ) ) @@ -241,11 +244,11 @@ def test_batch_commit_propagates_client_context(self): database.with_error_augmentation.return_value = (None, mock.MagicMock()) database._next_nth_request = 1 client = database._instance._client = mock.Mock() - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"client": struct_pb2.Value(string_value="from-client")} ) - batch_context = ClientContext( + batch_context = RequestOptions.ClientContext( secure_context={"batch": struct_pb2.Value(string_value="from-batch")} ) batch = Batch(session, client_context=batch_context) @@ -285,11 +288,11 @@ def test_transaction_execute_update_propagates_client_context(self): client = database._instance._client = mock.Mock() client._query_options = None - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"client": struct_pb2.Value(string_value="from-client")} ) - transaction_context = ClientContext( + transaction_context = RequestOptions.ClientContext( secure_context={"txn": struct_pb2.Value(string_value="from-txn")} ) transaction = Transaction(session, client_context=transaction_context) @@ -329,11 +332,11 @@ def test_mutation_groups_batch_write_propagates_client_context(self): database._next_nth_request = 1 client = database._instance._client = mock.Mock() - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"client": struct_pb2.Value(string_value="from-client")} ) - mg_context = ClientContext( + mg_context = RequestOptions.ClientContext( secure_context={"mg": struct_pb2.Value(string_value="from-mg")} ) mg = MutationGroups(session, client_context=mg_context) @@ -363,11 +366,11 @@ def test_batch_snapshot_propagates_client_context(self): database.name = "database-name" client = database._instance._client = mock.Mock() client._query_options = None - client._client_context = ClientContext( + client._client_context = RequestOptions.ClientContext( secure_context={"client": struct_pb2.Value(string_value="from-client")} ) - batch_context = ClientContext( + batch_context = RequestOptions.ClientContext( secure_context={"batch": struct_pb2.Value(string_value="from-batch")} ) batch_snapshot = BatchSnapshot(database, client_context=batch_context)