Repository: googleapis/google-cloud-python

Issue:
Spanner docs are outdated
Spanner docs still talk about [checking out a session](https://github.com/GoogleCloudPlatform/google-cloud-python/blob/master/docs/spanner/snapshot-usage.rst) and then doing operations on that such as `session.snapshot` and `session.batch`. 
We changed the API long time back where such operations can be done directly on the database object and that is the API we want to promote. Please audit all the docs to scrub out all the calls directly made on session object and replace those with calls on Database object. This should be doe before Beta since we expect an uptick in usage once we mark the client as Beta and we want to people to use the preferred API. 


Discussion:
cc @lukesneeringer @bjwatson @danoscarmike 
Also the snapshot doc should talk about nuances of using Snapshots with multi use and single use and the fact that users need to call `begin` if they need to have multiple pending operations. 
I presume we will drop discussion of sessions from the narrative / usage docs, but leave the API docs pages in place (since users might still come across them, e.g. in tracebacks).
Yeah I agree leaving the API docs pages in place is OK. We can probably emphasise on those API docs that most users need not interact with these objects directly.

Resolving patch:
diff --git a/spanner/google/cloud/spanner/database.py b/spanner/google/cloud/spanner/database.py
--- a/spanner/google/cloud/spanner/database.py
+++ b/spanner/google/cloud/spanner/database.py
@@ -315,6 +315,36 @@ def session(self):
         """
         return Session(self)
 
+    def snapshot(self, **kw):
+        """Return an object which wraps a snapshot.
+
+        The wrapper *must* be used as a context manager, with the snapshot
+        as the value returned by the wrapper.
+
+        See
+        https://cloud.google.com/spanner/reference/rpc/google.spanner.v1#google.spanner.v1.TransactionOptions.ReadOnly
+
+        :type kw: dict
+        :param kw:
+            Passed through to
+            :class:`~google.cloud.spanner.snapshot.Snapshot` constructor.
+
+        :rtype: :class:`~google.cloud.spanner.database.SnapshotCheckout`
+        :returns: new wrapper
+        """
+        return SnapshotCheckout(self, **kw)
+
+    def batch(self):
+        """Return an object which wraps a batch.
+
+        The wrapper *must* be used as a context manager, with the batch
+        as the value returned by the wrapper.
+
+        :rtype: :class:`~google.cloud.spanner.database.BatchCheckout`
+        :returns: new wrapper
+        """
+        return BatchCheckout(self)
+
     def run_in_transaction(self, func, *args, **kw):
         """Perform a unit of work in a transaction, retrying on abort.
 
@@ -349,36 +379,6 @@ def run_in_transaction(self, func, *args, **kw):
         finally:
             self._local.transaction_running = False
 
-    def batch(self):
-        """Return an object which wraps a batch.
-
-        The wrapper *must* be used as a context manager, with the batch
-        as the value returned by the wrapper.
-
-        :rtype: :class:`~google.cloud.spanner.database.BatchCheckout`
-        :returns: new wrapper
-        """
-        return BatchCheckout(self)
-
-    def snapshot(self, **kw):
-        """Return an object which wraps a snapshot.
-
-        The wrapper *must* be used as a context manager, with the snapshot
-        as the value returned by the wrapper.
-
-        See
-        https://cloud.google.com/spanner/reference/rpc/google.spanner.v1#google.spanner.v1.TransactionOptions.ReadOnly
-
-        :type kw: dict
-        :param kw:
-            Passed through to
-            :class:`~google.cloud.spanner.snapshot.Snapshot` constructor.
-
-        :rtype: :class:`~google.cloud.spanner.database.SnapshotCheckout`
-        :returns: new wrapper
-        """
-        return SnapshotCheckout(self, **kw)
-
 
 class BatchCheckout(object):
     """Context manager for using a batch from a database.


Test patch:
diff --git a/spanner/tests/unit/test_database.py b/spanner/tests/unit/test_database.py
--- a/spanner/tests/unit/test_database.py
+++ b/spanner/tests/unit/test_database.py
@@ -621,6 +621,55 @@ def test_session_factory(self):
         self.assertIs(session.session_id, None)
         self.assertIs(session._database, database)
 
+    def test_snapshot_defaults(self):
+        from google.cloud.spanner.database import SnapshotCheckout
+
+        client = _Client()
+        instance = _Instance(self.INSTANCE_NAME, client=client)
+        pool = _Pool()
+        session = _Session()
+        pool.put(session)
+        database = self._make_one(self.DATABASE_ID, instance, pool=pool)
+
+        checkout = database.snapshot()
+        self.assertIsInstance(checkout, SnapshotCheckout)
+        self.assertIs(checkout._database, database)
+        self.assertEqual(checkout._kw, {})
+
+    def test_snapshot_w_read_timestamp_and_multi_use(self):
+        import datetime
+        from google.cloud._helpers import UTC
+        from google.cloud.spanner.database import SnapshotCheckout
+
+        now = datetime.datetime.utcnow().replace(tzinfo=UTC)
+        client = _Client()
+        instance = _Instance(self.INSTANCE_NAME, client=client)
+        pool = _Pool()
+        session = _Session()
+        pool.put(session)
+        database = self._make_one(self.DATABASE_ID, instance, pool=pool)
+
+        checkout = database.snapshot(read_timestamp=now, multi_use=True)
+
+        self.assertIsInstance(checkout, SnapshotCheckout)
+        self.assertIs(checkout._database, database)
+        self.assertEqual(
+            checkout._kw, {'read_timestamp': now, 'multi_use': True})
+
+    def test_batch(self):
+        from google.cloud.spanner.database import BatchCheckout
+
+        client = _Client()
+        instance = _Instance(self.INSTANCE_NAME, client=client)
+        pool = _Pool()
+        session = _Session()
+        pool.put(session)
+        database = self._make_one(self.DATABASE_ID, instance, pool=pool)
+
+        checkout = database.batch()
+        self.assertIsInstance(checkout, BatchCheckout)
+        self.assertIs(checkout._database, database)
+
     def test_run_in_transaction_wo_args(self):
         import datetime
 
@@ -686,55 +735,6 @@ def nested_unit_of_work():
             database.run_in_transaction(nested_unit_of_work)
         self.assertEqual(inner.call_count, 0)
 
-    def test_batch(self):
-        from google.cloud.spanner.database import BatchCheckout
-
-        client = _Client()
-        instance = _Instance(self.INSTANCE_NAME, client=client)
-        pool = _Pool()
-        session = _Session()
-        pool.put(session)
-        database = self._make_one(self.DATABASE_ID, instance, pool=pool)
-
-        checkout = database.batch()
-        self.assertIsInstance(checkout, BatchCheckout)
-        self.assertIs(checkout._database, database)
-
-    def test_snapshot_defaults(self):
-        from google.cloud.spanner.database import SnapshotCheckout
-
-        client = _Client()
-        instance = _Instance(self.INSTANCE_NAME, client=client)
-        pool = _Pool()
-        session = _Session()
-        pool.put(session)
-        database = self._make_one(self.DATABASE_ID, instance, pool=pool)
-
-        checkout = database.snapshot()
-        self.assertIsInstance(checkout, SnapshotCheckout)
-        self.assertIs(checkout._database, database)
-        self.assertEqual(checkout._kw, {})
-
-    def test_snapshot_w_read_timestamp_and_multi_use(self):
-        import datetime
-        from google.cloud._helpers import UTC
-        from google.cloud.spanner.database import SnapshotCheckout
-
-        now = datetime.datetime.utcnow().replace(tzinfo=UTC)
-        client = _Client()
-        instance = _Instance(self.INSTANCE_NAME, client=client)
-        pool = _Pool()
-        session = _Session()
-        pool.put(session)
-        database = self._make_one(self.DATABASE_ID, instance, pool=pool)
-
-        checkout = database.snapshot(read_timestamp=now, multi_use=True)
-
-        self.assertIsInstance(checkout, SnapshotCheckout)
-        self.assertIs(checkout._database, database)
-        self.assertEqual(
-            checkout._kw, {'read_timestamp': now, 'multi_use': True})
-
 
 class TestBatchCheckout(_BaseTest):