Repository: opendatacube/datacube-core

Issue:
Unnecessary dependency on `pathlib` when running in python3
### Expected behaviour
Datacube shouldn't depend on unnecessary packages when running in Python 3.

### Actual behaviour
There's a dependency on `pathlib`, which is included in the Python 3 standard library, and so doesn't need to be installed.

This causes trouble on the NCI deployment when trying to load `stats` modules which use the `setuptools` entry_points for their registration. And returns error messages to users trying to load them.

### Steps to reproduce the behaviour
```
module load agdc-py3-prod agdc_statistics
dra547@raijin4:~ $ python
Python 3.6.3 | packaged by conda-forge | (default, Nov  4 2017, 10:10:56)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import datacube_stats.statistics
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/g/data/v10/public/modules/agdc_statistics/0.9a7/lib/python3.6/site-packages/datacube_stats/statistics.py", line 769, in <module>
    STATS[entry_point.name] = entry_point.load()
  File "/g/data/v10/public/modules/agdc-py3-env/20171214/envs/agdc/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2404, in load
    self.require(*args, **kwargs)
  File "/g/data/v10/public/modules/agdc-py3-env/20171214/envs/agdc/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2427, in require
    items = working_set.resolve(reqs, env, installer, extras=self.extras)
  File "/g/data/v10/public/modules/agdc-py3-env/20171214/envs/agdc/lib/python3.6/site-packages/pkg_resources/__init__.py", line 870, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'pathlib' distribution was not found and is required by datacube
>>>
```

### The Fix
Modify `setup.py` to use [platform specific dependencies](https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-platform-specific-dependencies) to only require `pathlib` when not running on python 3.


Discussion:

Resolving patch:
diff --git a/datacube/utils/geometry.py b/datacube/utils/geometry.py
--- a/datacube/utils/geometry.py
+++ b/datacube/utils/geometry.py
@@ -690,18 +690,6 @@ class GeoBox(object):
     Defines the location and resolution of a rectangular grid of data,
     including it's :py:class:`CRS`.
 
-    >>> from affine import Affine
-    >>> t = GeoBox(4000, 4000, Affine(0.00025, 0.0, 151.0, 0.0, -0.00025, -29.0), CRS('EPSG:4326'))
-    >>> t.coordinates['latitude'].values
-    array([-29.000125, -29.000375, -29.000625, ..., -29.999375, -29.999625,
-           -29.999875])
-    >>> t.coordinates['longitude'].values
-    array([ 151.000125,  151.000375,  151.000625, ...,  151.999375,
-            151.999625,  151.999875])
-    >>> t.resolution
-    (-0.00025, 0.00025)
-
-
     :param geometry.CRS crs: Coordinate Reference System
     :param affine.Affine affine: Affine transformation defining the location of the geobox
     """
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -71,7 +71,7 @@
         'jsonschema',
         'netcdf4',
         'numpy',
-        'pathlib',
+        'pathlib;python_version<"3"',
         'psycopg2',
         'pypeg2',
         'python-dateutil',


Test patch:
diff --git a/tests/test_geometry.py b/tests/test_geometry.py
--- a/tests/test_geometry.py
+++ b/tests/test_geometry.py
@@ -1,6 +1,7 @@
 
 from __future__ import absolute_import
 
+import numpy as np
 import osgeo
 import pytest
 try:
@@ -18,6 +19,26 @@ def test_pickleable():
     assert poly == unpickled
 
 
+def test_geobox_simple():
+    from affine import Affine
+    t = geometry.GeoBox(4000, 4000,
+                        Affine(0.00025, 0.0, 151.0, 0.0, -0.00025, -29.0),
+                        geometry.CRS('EPSG:4326'))
+
+    expect_lon = np.asarray([151.000125,  151.000375,  151.000625,  151.000875,  151.001125,
+                             151.001375,  151.001625,  151.001875,  151.002125,  151.002375])
+
+    expect_lat = np.asarray([-29.000125, -29.000375, -29.000625, -29.000875, -29.001125,
+                             -29.001375, -29.001625, -29.001875, -29.002125, -29.002375])
+    expect_resolution = np.asarray([-0.00025, 0.00025])
+
+    assert (np.abs(np.r_[t.resolution] - expect_resolution) < 1e-6).all()
+    assert t.coordinates['latitude'].values.shape == (4000,)
+    assert t.coordinates['longitude'].values.shape == (4000,)
+    assert (np.abs(t.coords['latitude'].values[:10] - expect_lat) < 1e-6).all()
+    assert (np.abs(t.coords['longitude'].values[:10] - expect_lon) < 1e-6).all()
+
+
 def test_props():
     box1 = geometry.box(10, 10, 30, 30, crs=geometry.CRS('EPSG:4326'))
     assert box1