Repository: neo4j/neo4j-python-driver

Issue:
Prevent Deprecation Warning to users 
## User get DeprecationWarnings

- Operating system: Windows 10

Run install and run [nox](https://nox.thea.codes/en/stable/) on attached archive
[example_python.zip](https://github.com/neo4j/neo4j-python-driver/files/5842343/example_python.zip)

- Expected behavior
pylint should analyze the code and report user erros

- Actual behavior
pylint reports issue in neo4j driver as well!

```
================================================= warnings summary =================================================
<unknown>:339
  <unknown>:339: DeprecationWarning: invalid escape sequence \*

<unknown>:381
  <unknown>:381: DeprecationWarning: invalid escape sequence \*

-- Docs: https://docs.pytest.org/en/stable/warnings.html
============================================= short test summary info ==============================================
FAILED example.py::PYLINT
```

Discussion:

Patch:
diff --git a/neo4j/spatial/__init__.py b/neo4j/spatial/__init__.py
index f7085fd4..36e8d66f 100644
--- a/neo4j/spatial/__init__.py
+++ b/neo4j/spatial/__init__.py
@@ -53,7 +53,7 @@ class Point(tuple):
     srid = None
 
     def __new__(cls, iterable):
-        return tuple.__new__(cls, iterable)
+        return tuple.__new__(cls, map(float, iterable))
 
     def __repr__(self):
         return "POINT(%s)" % " ".join(map(str, self))
diff --git a/neo4j/work/simple.py b/neo4j/work/simple.py
index ef1e6d8c..0ee46e7b 100644
--- a/neo4j/work/simple.py
+++ b/neo4j/work/simple.py
@@ -370,7 +370,7 @@ class Session(Workspace):
             with driver.session() as session:
                 values = session.read_transaction(get_two_tx)
 
-        :param transaction_function: a function that takes a transaction as an argument and does work with the transaction. `tx_function(tx, \*args, \*\*kwargs)`
+        :param transaction_function: a function that takes a transaction as an argument and does work with the transaction. `tx_function(tx, *args, **kwargs)`
         :param args: arguments for the `transaction_function`
         :param kwargs: key word arguments for the `transaction_function`
         :return: a result as returned by the given unit of work
@@ -395,7 +395,7 @@ class Session(Workspace):
                 node_id = session.write_transaction(create_node_tx, "example")
 
 
-        :param transaction_function: a function that takes a transaction as an argument and does work with the transaction. `tx_function(tx, \*args, \*\*kwargs)`
+        :param transaction_function: a function that takes a transaction as an argument and does work with the transaction. `tx_function(tx, *args, **kwargs)`
         :param args: key word arguments for the `transaction_function`
         :param kwargs: key word arguments for the `transaction_function`
         :return: a result as returned by the given unit of work


Test patch:
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index fd5a4a7a..952fa0c2 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -189,12 +189,8 @@ def service(request):
         if existing_service:
             NEO4J_SERVICE = existing_service
         else:
-            try:
-                NEO4J_SERVICE = Neo4jService(auth=NEO4J_AUTH, image=request.param, n_cores=NEO4J_CORES, n_replicas=NEO4J_REPLICAS)
-                NEO4J_SERVICE.start(timeout=300)
-            except urllib.error.HTTPError as error:
-                # pytest.skip(str(error))
-                pytest.xfail(str(error) + " " + request.param)
+            NEO4J_SERVICE = Neo4jService(auth=NEO4J_AUTH, image=request.param, n_cores=NEO4J_CORES, n_replicas=NEO4J_REPLICAS)
+            NEO4J_SERVICE.start(timeout=300)
         yield NEO4J_SERVICE
         if NEO4J_SERVICE is not None:
             NEO4J_SERVICE.stop(timeout=300)
diff --git a/tests/integration/examples/test_driver_introduction_example.py b/tests/integration/examples/test_driver_introduction_example.py
index 5d592680..2496a27a 100644
--- a/tests/integration/examples/test_driver_introduction_example.py
+++ b/tests/integration/examples/test_driver_introduction_example.py
@@ -33,7 +33,7 @@ from neo4j.exceptions import ServiceUnavailable
 from neo4j._exceptions import BoltHandshakeError
 
 
-# python -m pytest tests/integration/examples/test_aura_example.py -s -v
+# python -m pytest tests/integration/examples/test_driver_introduction_example.py -s -v
 
 # tag::driver-introduction-example[]
 class App:
@@ -91,10 +91,9 @@ class App:
 
 
 if __name__ == "__main__":
-    # Aura queries use an encrypted connection using the "neo4j+s" URI scheme
     bolt_url = "%%BOLT_URL_PLACEHOLDER%%"
-    user = "<Username for Neo4j Aura database>"
-    password = "<Password for Neo4j Aura database>"
+    user = "<Username for database>"
+    password = "<Password for database>"
     app = App(bolt_url, user, password)
     app.create_friendship("Alice", "David")
     app.find_person("Alice")
diff --git a/tests/unit/spatial/__init__.py b/tests/unit/spatial/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/unit/spatial/test_cartesian_point.py b/tests/unit/spatial/test_cartesian_point.py
new file mode 100644
index 00000000..ee86e5b9
--- /dev/null
+++ b/tests/unit/spatial/test_cartesian_point.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) "Neo4j"
+# Neo4j Sweden AB [http://neo4j.com]
+#
+# This file is part of Neo4j.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import struct
+from unittest import TestCase
+
+from neo4j.data import DataDehydrator
+from neo4j.packstream import Packer
+from neo4j.spatial import CartesianPoint
+
+
+class CartesianPointTestCase(TestCase):
+
+    def test_alias(self):
+        x, y, z = 3.2, 4.0, -1.2
+        p = CartesianPoint((x, y, z))
+        self.assert_(hasattr(p, "x"))
+        self.assertEqual(p.x, x)
+        self.assert_(hasattr(p, "y"))
+        self.assertEqual(p.y, y)
+        self.assert_(hasattr(p, "z"))
+        self.assertEqual(p.z, z)
+
+    def test_dehydration_3d(self):
+        coordinates = (1, -2, 3.1)
+        p = CartesianPoint(coordinates)
+
+        dehydrator = DataDehydrator()
+        buffer = io.BytesIO()
+        packer = Packer(buffer)
+        packer.pack(dehydrator.dehydrate((p,))[0])
+        self.assertEqual(
+            buffer.getvalue(),
+            b"\xB4Y" +
+            b"\xC9" + struct.pack(">h", 9157) +
+            b"".join(map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates))
+        )
+
+    def test_dehydration_2d(self):
+        coordinates = (.1, 0)
+        p = CartesianPoint(coordinates)
+
+        dehydrator = DataDehydrator()
+        buffer = io.BytesIO()
+        packer = Packer(buffer)
+        packer.pack(dehydrator.dehydrate((p,))[0])
+        self.assertEqual(
+            buffer.getvalue(),
+            b"\xB3X" +
+            b"\xC9" + struct.pack(">h", 7203) +
+            b"".join(map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates))
+        )
diff --git a/tests/unit/spatial/test_point.py b/tests/unit/spatial/test_point.py
new file mode 100644
index 00000000..082f95c5
--- /dev/null
+++ b/tests/unit/spatial/test_point.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) "Neo4j"
+# Neo4j Sweden AB [http://neo4j.com]
+#
+# This file is part of Neo4j.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import struct
+from unittest import TestCase
+
+from neo4j.data import DataDehydrator
+from neo4j.packstream import Packer
+from neo4j.spatial import (
+    Point,
+    point_type,
+)
+
+
+class PointTestCase(TestCase):
+
+    def test_wrong_type_arguments(self):
+        for argument in (("a", "b"), ({"x": 1.0, "y": 2.0})):
+            with self.subTest():
+                with self.assertRaises(ValueError):
+                    Point(argument)
+
+    def test_number_arguments(self):
+        for argument in ((1, 2), (1.2, 2.1)):
+            with self.subTest():
+                p = Point(argument)
+                assert tuple(p) == argument
+
+    def test_dehydration(self):
+        MyPoint = point_type("MyPoint", ["x", "y"], {2: 1234})
+        coordinates = (.1, 0)
+        p = MyPoint(coordinates)
+
+        dehydrator = DataDehydrator()
+        buffer = io.BytesIO()
+        packer = Packer(buffer)
+        packer.pack(dehydrator.dehydrate((p,))[0])
+        self.assertEqual(
+            buffer.getvalue(),
+            b"\xB3X" +
+            b"\xC9" + struct.pack(">h", 1234) +
+            b"".join(map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates))
+        )
+
+    def test_immutable_coordinates(self):
+        MyPoint = point_type("MyPoint", ["x", "y"], {2: 1234})
+        coordinates = (.1, 0)
+        p = MyPoint(coordinates)
+        with self.assertRaises(AttributeError):
+            p.x = 2.0
+        with self.assertRaises(AttributeError):
+            p.y = 2.0
+        with self.assertRaises(TypeError):
+            p[0] = 2.0
+        with self.assertRaises(TypeError):
+            p[1] = 2.0
diff --git a/tests/unit/spatial/test_wgs84_point.py b/tests/unit/spatial/test_wgs84_point.py
new file mode 100644
index 00000000..8f725a58
--- /dev/null
+++ b/tests/unit/spatial/test_wgs84_point.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) "Neo4j"
+# Neo4j Sweden AB [http://neo4j.com]
+#
+# This file is part of Neo4j.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import struct
+from unittest import TestCase
+
+from neo4j.data import DataDehydrator
+from neo4j.packstream import Packer
+from neo4j.spatial import WGS84Point
+
+
+class WGS84PointTestCase(TestCase):
+
+    def test_alias(self):
+        x, y, z = 3.2, 4.0, -1.2
+        p = WGS84Point((x, y, z))
+        self.assert_(hasattr(p, "longitude"))
+        self.assertEqual(p.longitude, x)
+        self.assert_(hasattr(p, "latitude"))
+        self.assertEqual(p.latitude, y)
+        self.assert_(hasattr(p, "height"))
+        self.assertEqual(p.height, z)
+
+    def test_dehydration_3d(self):
+        coordinates = (1, -2, 3.1)
+        p = WGS84Point(coordinates)
+
+        dehydrator = DataDehydrator()
+        buffer = io.BytesIO()
+        packer = Packer(buffer)
+        packer.pack(dehydrator.dehydrate((p,))[0])
+        self.assertEqual(
+            buffer.getvalue(),
+            b"\xB4Y" +
+            b"\xC9" + struct.pack(">h", 4979) +
+            b"".join(map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates))
+        )
+
+    def test_dehydration_2d(self):
+        coordinates = (.1, 0)
+        p = WGS84Point(coordinates)
+
+        dehydrator = DataDehydrator()
+        buffer = io.BytesIO()
+        packer = Packer(buffer)
+        packer.pack(dehydrator.dehydrate((p,))[0])
+        self.assertEqual(
+            buffer.getvalue(),
+            b"\xB3X" +
+            b"\xC9" + struct.pack(">h", 4326) +
+            b"".join(map(lambda c: b"\xC1" + struct.pack(">d", c), coordinates))
+        )