[pyresample] 01/07: New upstream version 1.6.0

Antonio Valentino a_valentino-guest at moszumanska.debian.org
Fri Sep 15 06:13:23 UTC 2017


This is an automated email from the git hooks/post-receive script.

a_valentino-guest pushed a commit to branch master
in repository pyresample.

commit e1687cd9f797143bfbf125e6694807479183cae8
Author: Antonio Valentino <antonio.valentino at tiscali.it>
Date:   Fri Sep 15 05:37:47 2017 +0000

    New upstream version 1.6.0
---
 .bumpversion.cfg                 |  2 +-
 .travis.yml                      |  5 ++-
 changelog.rst                    | 45 +++++++++++++++++++++
 docs/source/geo_def.rst          | 13 ++++--
 pyresample/geometry.py           | 40 +++++++++++-------
 pyresample/kd_tree.py            | 23 ++++++++---
 pyresample/test/test_geometry.py |  9 ++++-
 pyresample/test/test_kd_tree.py  | 10 +++--
 pyresample/test/test_utils.py    | 87 ++++++++++++++++++++++++++++++----------
 pyresample/utils.py              | 72 +++++++++++++++++++++++++++++----
 pyresample/version.py            |  2 +-
 setup.cfg                        |  3 +-
 setup.py                         |  6 ++-
 13 files changed, 251 insertions(+), 66 deletions(-)

diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 4eee916..eed2dcc 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 1.5.0
+current_version = 1.6.0
 commit = True
 tag = True
 
diff --git a/.travis.yml b/.travis.yml
index 6693de1..f433d0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,11 +4,12 @@ python:
 - '3.3'
 - '3.4'
 - '3.5'
+- '3.6'
 before_install:
 - sudo add-apt-repository ppa:ubuntugis/ppa -y
 - sudo apt-get update -qq
 - sudo apt-get install libfreetype6-dev
-- sudo apt-get install libgeos-3.3.8 libgeos-c1 libgeos-dev
+- sudo apt-get install libgeos-dev
 install:
 - if [[ $TRAVIS_PYTHON_VERSION == "2.7" ]]; then pip install "matplotlib>=1.5.0"; fi
 - if [[ $TRAVIS_PYTHON_VERSION == "2.7" ]]; then pip install "sphinx>=1.5.0"; fi
@@ -18,6 +19,8 @@ install:
 - if [[ $TRAVIS_PYTHON_VERSION == "3.4" ]]; then pip install "sphinx>=1.5.0"; fi
 - if [[ $TRAVIS_PYTHON_VERSION == "3.5" ]]; then pip install "matplotlib>=1.5.0"; fi
 - if [[ $TRAVIS_PYTHON_VERSION == "3.5" ]]; then pip install "sphinx>=1.5.0"; fi
+- if [[ $TRAVIS_PYTHON_VERSION == "3.6" ]]; then pip install "matplotlib>=1.5.0"; fi
+- if [[ $TRAVIS_PYTHON_VERSION == "3.6" ]]; then pip install "sphinx>=1.5.0"; fi
 - pip install -r requirements.txt
 - pip install -e ".[pykdtree,quicklook]"
 - pip install coveralls
diff --git a/changelog.rst b/changelog.rst
index d45d4ca..cd16cc8 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -2,6 +2,51 @@ Changelog
 =========
 
 
+v1.6.0 (2017-09-12)
+-------------------
+- update changelog. [Martin Raspaud]
+- Bump version: 1.5.0 → 1.6.0. [Martin Raspaud]
+- Make sure x_size and y_size are ints. [Martin Raspaud]
+- Merge pull request #69 from pytroll/bugfix-66. [Martin Raspaud]
+
+  Fix write to mask affecting original mask in future versions of numpy
+
+  Fixes #66
+- Add python 3.6 to travis tests. [davidh-ssec]
+- Fix write to mask affecting original mask in future versions of numpy.
+  [davidh-ssec]
+
+  Fix #66
+
+- Merge pull request #67 from pytroll/bugfix-13. [Martin Raspaud]
+
+  Rename `proj_x/y_coords` to `projection_x/y_coords`
+- Rename `proj_x/y_coords` to `projection_x/y_coords` [davidh-ssec]
+
+  Fix #13
+
+- Merge pull request #63 from pytroll/feature-multiple-area-files.
+  [David Hoese]
+
+  Parse multiple area files
+- Fix tests_require in setup.py. [davidh-ssec]
+- Use libgeos-dev to depend on the C++ libgeos-X.X.X and libgeos-c1.
+  [davidh-ssec]
+- Add simple tests for parsing multiple yaml area strings. [davidh-ssec]
+- Fix indentation in area file parsing functions. [davidh-ssec]
+- Add ability to parse multiple area files at once. [davidh-ssec]
+- Merge pull request #65 from pytroll/fix-numpy-1.13. [Martin Raspaud]
+
+  Fix numpy 1.13 compatibility
+- Fix boolean mask array usage in gaussian resampling. [davidh-ssec]
+
+  In numpy 1.13 it is illegal to index an array with a boolean
+  array of a different size.
+
+- Add mock to test dependencies for python <3.3. [davidh-ssec]
+- Use prepackaged numexpr in bdist_rpm. [Martin Raspaud]
+
+
 v1.5.0 (2017-05-02)
 -------------------
 - update changelog. [Martin Raspaud]
diff --git a/docs/source/geo_def.rst b/docs/source/geo_def.rst
index 2889824..d5e6f82 100644
--- a/docs/source/geo_def.rst
+++ b/docs/source/geo_def.rst
@@ -267,13 +267,18 @@ Geographic coordinates and boundaries
 -------------------------------------
 A ***definition** object allows for retrieval of geographic coordinates using array slicing (slice stepping is currently not supported).
 
-All ***definition** objects exposes the coordinates **lons**, **lats** and **cartesian_coords**.
+All ***definition** objects expose the coordinates **lons**, **lats** and **cartesian_coords**.
 AreaDefinition exposes the full set of projection coordinates as
 **projection_x_coords** and **projection_y_coords**. Note that in the case of
 projection coordinates expressed in longitude and latitude,
 **projection_x_coords** will be longitude and **projection_y_coords** will be
 latitude.
 
+.. versionchanged:: 1.5.1
+
+    Renamed `proj_x_coords` to `projection_x_coords` and `proj_y_coords`
+    to `projection_y_coords`.
+
 Get full coordinate set:
 
 .. doctest::
@@ -306,8 +311,8 @@ Get slice of coordinate set:
  ...                               x_size, y_size, area_extent)
  >>> cart_subset = area_def.get_cartesian_coords()[100:200, 350:]
 
-If only the 1D range of a projection coordinate is required it can be extraxted
-using the **proj_x_coord** or **proj_y_coords** property of a geographic coordinate
+If only the 1D range of a projection coordinate is required it can be extracted
+using the **projection_x_coord** or **projection_y_coords** property of a geographic coordinate
 
 .. doctest::
 
@@ -321,7 +326,7 @@ using the **proj_x_coord** or **proj_y_coords** property of a geographic coordin
  >>> area_extent = (-5326849.0625,-5326849.0625,5326849.0625,5326849.0625)
  >>> area_def = utils.get_area_def(area_id, description, proj_id, projection,
  ...                  			   x_size, y_size, area_extent)
- >>> proj_x_range = area_def.proj_x_coords
+ >>> proj_x_range = area_def.projection_x_coords
 
 Spherical geometry operations
 -----------------------------
diff --git a/pyresample/geometry.py b/pyresample/geometry.py
index 7f6809a..c0f02ca 100644
--- a/pyresample/geometry.py
+++ b/pyresample/geometry.py
@@ -541,8 +541,8 @@ class AreaDefinition(BaseDefinition):
         self.area_id = area_id
         self.name = name
         self.proj_id = proj_id
-        self.x_size = x_size
-        self.y_size = y_size
+        self.x_size = int(x_size)
+        self.y_size = int(y_size)
         self.shape = (y_size, x_size)
         if lons is not None:
             if lons.shape != self.shape:
@@ -575,8 +575,8 @@ class AreaDefinition(BaseDefinition):
         self.pixel_offset_x = -self.area_extent[0] / self.pixel_size_x
         self.pixel_offset_y = self.area_extent[3] / self.pixel_size_y
 
-        self.projection_x_coords = None
-        self.projection_y_coords = None
+        self._projection_x_coords = None
+        self._projection_y_coords = None
 
         self.dtype = dtype
 
@@ -659,8 +659,8 @@ class AreaDefinition(BaseDefinition):
         (see get_lonlats).
         """
         p = _spatial_mp.Proj(self.proj4_string)
-        x = self.proj_x_coords
-        y = self.proj_y_coords
+        x = self.projection_x_coords
+        y = self.projection_y_coords
         return p(y[y.size - cols], x[x.size - rows], inverse=True)
 
     def lonlat2colrow(self, lons, lats):
@@ -807,12 +807,12 @@ class AreaDefinition(BaseDefinition):
                 else:
                     return val
 
-        if self.projection_x_coords is not None and self.projection_y_coords is not None:
+        if self._projection_x_coords is not None and self._projection_y_coords is not None:
             # Projection coords are cached
             if data_slice is None:
-                return self.projection_x_coords, self.projection_y_coords
+                return self._projection_x_coords, self._projection_y_coords
             else:
-                return self.projection_x_coords[data_slice], self.projection_y_coords[data_slice]
+                return self._projection_x_coords[data_slice], self._projection_y_coords[data_slice]
 
         is_single_value = False
         is_1d_select = False
@@ -893,20 +893,30 @@ class AreaDefinition(BaseDefinition):
 
         if cache and data_slice is None:
             # Cache the result if requested
-            self.projection_x_coords = target_x
-            self.projection_y_coords = target_y
+            self._projection_x_coords = target_x
+            self._projection_y_coords = target_y
 
         return target_x, target_y
 
     @property
-    def proj_x_coords(self):
+    def projection_x_coords(self):
         return self.get_proj_coords(data_slice=(0, slice(None)))[0]
 
     @property
-    def proj_y_coords(self):
+    def projection_y_coords(self):
         return self.get_proj_coords(data_slice=(slice(None), 0))[1]
 
     @property
+    def proj_x_coords(self):
+        warnings.warn("Deprecated, use 'projection_x_coords' instead", DeprecationWarning)
+        return self.projection_x_coords
+
+    @property
+    def proj_y_coords(self):
+        warnings.warn("Deprecated, use 'projection_y_coords' instead", DeprecationWarning)
+        return self.projection_y_coords
+
+    @property
     def outer_boundary_corners(self):
         """Returns the lon,lat of the outer edges of the corner points
         """
@@ -1026,8 +1036,8 @@ def concatenate_area_defs(area1, area2, axis=0):
 
     if axis == 0:
         area_extent = combine_area_extents_vertical(area1, area2)
-        x_size = area1.x_size
-        y_size = area1.y_size + area2.y_size
+        x_size = int(area1.x_size)
+        y_size = int(area1.y_size + area2.y_size)
     else:
         raise NotImplementedError('Only vertical contatenation is supported.')
     return AreaDefinition(area1.area_id, area1.name, area1.proj_id,
diff --git a/pyresample/kd_tree.py b/pyresample/kd_tree.py
index e08ca84..4be4322 100644
--- a/pyresample/kd_tree.py
+++ b/pyresample/kd_tree.py
@@ -716,7 +716,7 @@ def get_sample_from_neighbour_info(resample_type, output_shape, data,
         # Get nearest neighbour using array indexing
         index_mask = (index_array == input_size)
         new_index_array = np.where(index_mask, 0, index_array)
-        result = new_data[new_index_array]
+        result = new_data[new_index_array].copy()
         result[index_mask] = fill_value
     else:
         # Calculate result using weighting.
@@ -807,11 +807,22 @@ def get_sample_from_neighbour_info(resample_type, output_shape, data,
 
             # Calculate final stddev
             new_valid_index = (count > 1)
-            v1 = norm[new_valid_index]
-            v2 = norm_sqr[new_valid_index]
-            stddev[new_valid_index] = np.sqrt(
-                (v1 / (v1 ** 2 - v2)) * stddev[new_valid_index])
-            stddev[~new_valid_index] = np.NaN
+            if stddev.ndim >= 2:
+                # If given more than 1 input data array
+                new_valid_index = new_valid_index[:, 0]
+                for i in range(stddev.shape[-1]):
+                    v1 = norm[new_valid_index, i]
+                    v2 = norm_sqr[new_valid_index, i]
+                    stddev[new_valid_index, i] = np.sqrt(
+                        (v1 / (v1 ** 2 - v2)) * stddev[new_valid_index, i])
+                    stddev[~new_valid_index, i] = np.NaN
+            else:
+                # If given single input data array
+                v1 = norm[new_valid_index]
+                v2 = norm_sqr[new_valid_index]
+                stddev[new_valid_index] = np.sqrt(
+                    (v1 / (v1 ** 2 - v2)) * stddev[new_valid_index])
+                stddev[~new_valid_index] = np.NaN
 
         # Add fill values
         result[np.invert(result_valid_index)] = fill_value
diff --git a/pyresample/test/test_geometry.py b/pyresample/test/test_geometry.py
index 470ad52..164d32c 100644
--- a/pyresample/test/test_geometry.py
+++ b/pyresample/test/test_geometry.py
@@ -4,7 +4,6 @@ import random
 import sys
 
 import numpy as np
-from mock import MagicMock, patch
 
 from pyresample import geo_filter, geometry
 from pyresample.geometry import (IncompatibleAreas,
@@ -12,6 +11,12 @@ from pyresample.geometry import (IncompatibleAreas,
                                  concatenate_area_defs)
 from pyresample.test.utils import catch_warnings
 
+try:
+    from unittest.mock import MagicMock, patch
+except ImportError:
+    # separate mock package py<3.3
+    from mock import MagicMock, patch
+
 if sys.version_info < (2, 7):
     import unittest2 as unittest
 else:
@@ -505,7 +510,7 @@ class Test(unittest.TestCase):
                                                -909968.64000000001,
                                                1029087.28,
                                                1490031.3600000001])
-        proj_x_boundary, proj_y_boundary = area_def.proj_x_coords, area_def.proj_y_coords
+        proj_x_boundary, proj_y_boundary = area_def.projection_x_coords, area_def.projection_y_coords
         expected_x = np.array([-1250912.72, -1010912.72, -770912.72,
                                -530912.72, -290912.72, -50912.72, 189087.28,
                                429087.28, 669087.28, 909087.28])
diff --git a/pyresample/test/test_kd_tree.py b/pyresample/test/test_kd_tree.py
index 80dbec0..eafc689 100644
--- a/pyresample/test/test_kd_tree.py
+++ b/pyresample/test/test_kd_tree.py
@@ -345,17 +345,19 @@ class Test(unittest.TestCase):
             self.assertTrue(any(['Possible more' in str(
                 x.message) for x in w]), 'Failed to create correct neighbour radius warning')
         cross_sum = res.sum()
-        cross_sum_stddev = stddev.sum()
         cross_sum_counts = counts.sum()
         expected = 1461.84313918
-        expected_stddev = 0.446204424799
+        expected_stddev = [0.446193170875, 0.443606880035, 0.438586349519]
         expected_counts = 4934802.0
         self.assertTrue(res.shape == stddev.shape and stddev.shape ==
                         counts.shape and counts.shape == (800, 800, 3))
         self.assertAlmostEqual(cross_sum, expected,
                                msg='Swath multi channel resampling gauss failed on data')
-        self.assertAlmostEqual(cross_sum_stddev, expected_stddev,
-                               msg='Swath multi channel resampling gauss failed on stddev')
+        for i, e_stddev in enumerate(expected_stddev):
+            cross_sum_stddev = stddev[:, :, i].sum()
+            print(cross_sum_stddev, e_stddev)
+            self.assertAlmostEqual(cross_sum_stddev, e_stddev,
+                                   msg='Swath multi channel resampling gauss failed on stddev (channel {})'.format(i))
         self.assertAlmostEqual(cross_sum_counts, expected_counts,
                                msg='Swath multi channel resampling gauss failed on counts')
 
diff --git a/pyresample/test/test_utils.py b/pyresample/test/test_utils.py
index 4162fe0..d79af05 100644
--- a/pyresample/test/test_utils.py
+++ b/pyresample/test/test_utils.py
@@ -11,8 +11,7 @@ def tmp(f):
     return f
 
 
-class Test(unittest.TestCase):
-
+class TestLegacyAreaParser(unittest.TestCase):
     def test_area_parser_legacy(self):
         """Test legacy area parser."""
         ease_nh, ease_sh = utils.parse_area_file(os.path.join(os.path.dirname(__file__),
@@ -37,6 +36,27 @@ Number of rows: 425
 Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
         self.assertEquals(ease_sh.__str__(), sh_str)
 
+    def test_load_area(self):
+        ease_nh = utils.load_area(os.path.join(os.path.dirname(__file__),
+                                               'test_files',
+                                               'areas.cfg'), 'ease_nh')
+        nh_str = """Area ID: ease_nh
+Description: Arctic EASE grid
+Projection ID: ease_nh
+Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
+Number of columns: 425
+Number of rows: 425
+Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
+        self.assertEquals(nh_str, ease_nh.__str__())
+
+    def test_not_found_exception(self):
+        self.assertRaises(utils.AreaNotFound, utils.parse_area_file,
+                          os.path.join(
+                              os.path.dirname(__file__), 'test_files', 'areas.cfg'),
+                          'no_area')
+
+
+class TestYAMLAreaParser(unittest.TestCase):
     def test_area_parser_yaml(self):
         """Test YAML area parser."""
         ease_nh, ease_sh = utils.parse_area_file(os.path.join(os.path.dirname(__file__),
@@ -60,25 +80,46 @@ Number of rows: 425
 Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
         self.assertEquals(ease_sh.__str__(), sh_str)
 
-    def test_load_area(self):
-        ease_nh = utils.load_area(os.path.join(os.path.dirname(__file__),
-                                               'test_files',
-                                               'areas.cfg'), 'ease_nh')
-        nh_str = """Area ID: ease_nh
-Description: Arctic EASE grid
-Projection ID: ease_nh
-Projection: {'a': '6371228.0', 'lat_0': '90', 'lon_0': '0', 'proj': 'laea', 'units': 'm'}
-Number of columns: 425
-Number of rows: 425
-Area extent: (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)"""
-        self.assertEquals(nh_str, ease_nh.__str__())
-
-    def test_not_found_exception(self):
-        self.assertRaises(utils.AreaNotFound, utils.parse_area_file,
-                          os.path.join(
-                              os.path.dirname(__file__), 'test_files', 'areas.cfg'),
-                          'no_area')
-
+    def test_multiple_file_content(self):
+        area_list = ["""ease_sh:
+  description: Antarctic EASE grid
+  projection:
+    a: 6371228.0
+    units: m
+    lon_0: 0
+    proj: laea
+    lat_0: -90
+  shape:
+    height: 425
+    width: 425
+  area_extent:
+    lower_left_xy: [-5326849.0625, -5326849.0625]
+    upper_right_xy: [5326849.0625, 5326849.0625]
+    units: m
+""",
+                     """ease_sh2:
+  description: Antarctic EASE grid
+  projection:
+    a: 6371228.0
+    units: m
+    lon_0: 0
+    proj: laea
+    lat_0: -90
+  shape:
+    height: 425
+    width: 425
+  area_extent:
+    lower_left_xy: [-5326849.0625, -5326849.0625]
+    upper_right_xy: [5326849.0625, 5326849.0625]
+    units: m
+"""]
+        results = utils.parse_area_file(area_list)
+        self.assertEquals(len(results), 2)
+        self.assertIn(results[0].area_id, ('ease_sh', 'ease_sh2'))
+        self.assertIn(results[1].area_id, ('ease_sh', 'ease_sh2'))
+
+
+class TestMisc(unittest.TestCase):
     def test_wrap_longitudes(self):
         # test that we indeed wrap to [-180:+180[
         step = 60
@@ -102,6 +143,8 @@ def suite():
     """
     loader = unittest.TestLoader()
     mysuite = unittest.TestSuite()
-    mysuite.addTest(loader.loadTestsFromTestCase(Test))
+    mysuite.addTest(loader.loadTestsFromTestCase(TestLegacyAreaParser))
+    mysuite.addTest(loader.loadTestsFromTestCase(TestYAMLAreaParser))
+    mysuite.addTest(loader.loadTestsFromTestCase(TestMisc))
 
     return mysuite
diff --git a/pyresample/utils.py b/pyresample/utils.py
index 9284752..2bb70ed 100644
--- a/pyresample/utils.py
+++ b/pyresample/utils.py
@@ -23,10 +23,12 @@
 
 from __future__ import absolute_import
 
+import os
 import numpy as np
 import six
 import yaml
 from configobj import ConfigObj
+from collections import Mapping
 
 import pyresample as pr
 
@@ -95,12 +97,34 @@ def parse_area_file(area_file_name, *regions):
         return _parse_legacy_area_file(area_file_name, *regions)
 
 
+def _read_yaml_area_file_content(area_file_name):
+    """Read one or more area files in to a single dict object."""
+    if isinstance(area_file_name, (str, six.text_type)):
+        area_file_name = [area_file_name]
+
+    area_dict = {}
+    for area_file_obj in area_file_name:
+        if (isinstance(area_file_obj, (str, six.text_type)) and
+           os.path.isfile(area_file_obj)):
+            # filename
+            area_file_obj = open(area_file_obj)
+        tmp_dict = yaml.load(area_file_obj)
+        area_dict = recursive_dict_update(area_dict, tmp_dict)
+    return area_dict
+
+
 def _parse_yaml_area_file(area_file_name, *regions):
-    """Parse area information from a yaml area file."""
+    """Parse area information from a yaml area file.
 
-    with open(area_file_name) as fd_:
-        area_dict = yaml.load(fd_)
+    Args:
+        area_file_name: filename, file-like object, yaml string, or list of
+                        these.
 
+    The result of loading multiple area files is the combination of all
+    the files, using the first file as the "base", replacing things after
+    that.
+    """
+    area_dict = _read_yaml_area_file_content(area_file_name)
     area_list = regions or area_dict.keys()
 
     res = []
@@ -124,10 +148,29 @@ def _parse_yaml_area_file(area_file_name, *regions):
     return res
 
 
+def _read_legacy_area_file_lines(area_file_name):
+    if isinstance(area_file_name, (str, six.text_type)):
+        area_file_name = [area_file_name]
+
+    for area_file_obj in area_file_name:
+        if (isinstance(area_file_obj, (str, six.text_type)) and
+           not os.path.isfile(area_file_obj)):
+            # file content string
+            for line in area_file_obj.splitlines():
+                yield line
+            continue
+        elif isinstance(area_file_obj, (str, six.text_type)):
+            # filename
+            area_file_obj = open(area_file_obj, 'r')
+
+        for line in area_file_obj.readlines():
+            yield line
+
+
 def _parse_legacy_area_file(area_file_name, *regions):
     """Parse area information from a legacy area file."""
 
-    area_file = open(area_file_name, 'r')
+    area_file = _read_legacy_area_file_lines(area_file_name)
     area_list = list(regions)
     if len(area_list) == 0:
         select_all_areas = True
@@ -138,7 +181,7 @@ def _parse_legacy_area_file(area_file_name, *regions):
 
     # Extract area from file
     in_area = False
-    for line in area_file.readlines():
+    for line in area_file:
         if not in_area:
             if 'REGION' in line:
                 area_id = line.replace('REGION:', ''). \
@@ -156,8 +199,6 @@ def _parse_legacy_area_file(area_file_name, *regions):
         else:
             area_content += line
 
-    area_file.close()
-
     # Check if all specified areas were found
     if not select_all_areas:
         for i, area in enumerate(area_defs):
@@ -393,3 +434,20 @@ def wrap_longitudes(lons):
     """
     lons_wrap = (lons + 180) % (360) - 180
     return lons_wrap.astype(lons.dtype)
+
+
+def recursive_dict_update(d, u):
+    """Recursive dictionary update using
+
+    Copied from:
+
+        http://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth
+
+    """
+    for k, v in u.items():
+        if isinstance(v, Mapping):
+            r = recursive_dict_update(d.get(k, {}), v)
+            d[k] = r
+        else:
+            d[k] = u[k]
+    return d
diff --git a/pyresample/version.py b/pyresample/version.py
index d73a813..ee9fd28 100644
--- a/pyresample/version.py
+++ b/pyresample/version.py
@@ -15,4 +15,4 @@
 # You should have received a copy of the GNU Lesser General Public License along
 # with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-__version__ = '1.5.0'
+__version__ = '1.6.0'
diff --git a/setup.cfg b/setup.cfg
index 97c8d8b..47d15b6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,4 @@
 [bdist_rpm]
-requires=numpy pykdtree numexpr pyproj python-configobj
+requires=numpy pykdtree python2-numexpr pyproj python-configobj
 release=1
 doc_files = docs/Makefile docs/source/*.rst
-
diff --git a/setup.py b/setup.py
index a1a38c1..7b666f7 100644
--- a/setup.py
+++ b/setup.py
@@ -27,11 +27,14 @@ from setuptools.command.build_ext import build_ext as _build_ext
 version = imp.load_source('pyresample.version', 'pyresample/version.py')
 
 requirements = ['setuptools>=3.2', 'pyproj', 'numpy', 'configobj',
-                'pykdtree>=1.1.1', 'pyyaml']
+                'pykdtree>=1.1.1', 'pyyaml', 'six']
 extras_require = {'pykdtree': ['pykdtree>=1.1.1'],
                   'numexpr': ['numexpr'],
                   'quicklook': ['matplotlib', 'basemap', 'pillow']}
 
+test_requires = []
+if sys.version_info < (3, 3):
+    test_requires.append('mock')
 if sys.version_info < (2, 6):
     # multiprocessing is not in the standard library
     requirements.append('multiprocessing')
@@ -110,6 +113,7 @@ if __name__ == "__main__":
           setup_requires=['numpy'],
           install_requires=requirements,
           extras_require=extras_require,
+          tests_require=test_requires,
           cmdclass={'build_ext': build_ext},
           ext_modules=cythonize(extensions),
           test_suite='pyresample.test.suite',

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pyresample.git



More information about the Pkg-grass-devel mailing list