def test_serialise_and_deserialise_map_recipe(self):
        recipes_fixtures = [
            fixtures.recipe_with_positive_iso3_code,
            fixtures.recipe_result_one_dataset_per_layer_windows,
            fixtures.recipe_without_positive_iso3_code
        ]

        with mock.patch(
                'mapactionpy_controller.map_recipe.path.exists') as mock_path:
            mock_path.return_value = True

            for fixture_str in recipes_fixtures:
                test_recipe = MapRecipe(fixture_str, self.lyr_props)

                self.assertEqual(
                    test_recipe,
                    jsonpickle.decode(jsonpickle.encode(test_recipe)))
                self.assertEqual(
                    test_recipe,
                    MapRecipe(
                        jsonpickle.encode(test_recipe, unpicklable=False),
                        self.lyr_props))
                self.assertNotEqual(
                    test_recipe,
                    MapRecipe(fixtures.recipe_with_negative_iso3_code,
                              self.lyr_props))
コード例 #2
0
    def test_apply_frame_crs_and_extent(self):
        """
        Because the test can't assume what starting extent the mxd is, the test applies to different
        extents as checks that the mxd changes.
        """
        recipe = MapRecipe(fixtures.fixture_recipe_minimal, self.layer_props)
        recipe_frame = recipe.get_frame(recipe.principal_map_frame)
        my_mxd = arcpy.mapping.MapDocument(self.my_mxd_fpath)
        arc_frame = arcpy.mapping.ListDataFrames(
            my_mxd, recipe.principal_map_frame).pop()

        mc = MapChef(my_mxd, self.cmf, self.event)

        # Approximations of Lebanon in WGS1984 and Web Mercator
        # Case 1 - approx Lebanon in WGS1984
        # Case 2 - Lebanon in Web Mercator
        # Case 3 - Very tall and narrow, the height will dominate the extent
        # Case 4 - Very flat and wide, the width will dominate the extent
        sample_extents = [('epsg:4326', 35, 33, 36, 34),
                          ('epsg:3857', 3907702.338605, 3902606.144123,
                           4076844.286459, 4122112.913080),
                          ('epsg:4326', 1, -70, 2, 70),
                          ('epsg:4326', -170, -2, 170, -1)]

        for extent_def in sample_extents:
            crs, x_min, y_min, x_max, y_max = extent_def

            recipe_frame.crs = crs
            recipe_frame.extent = (x_min, y_min, x_max, y_max)

            mc.apply_frame_crs_and_extent(arc_frame, recipe_frame)

            # Either the height will approx match but the width probably won't
            # OR the width with approx match but the height probably won't
            target_height = y_max - y_min
            target_width = x_max - x_min
            actual_height = arc_frame.extent.YMax - arc_frame.extent.YMin
            actual_width = arc_frame.extent.XMax - arc_frame.extent.XMin

            print(
                'target_height, target_width, actual_height, actual_width = ')
            print(target_height, target_width, actual_height, actual_width)

            # Aim for with 1% tolerance for one  or the two dimensions
            tolerance = 0.01

            passable_height = ((target_height *
                                (1 + tolerance)) > actual_height
                               and (target_height *
                                    (1 - tolerance)) < actual_height)

            passable_width = ((target_width * (1 + tolerance)) > actual_width
                              and (target_width *
                                   (1 - tolerance)) < actual_width)

            print('passable_height = {}'.format(passable_height))
            print('passable_width = {}'.format(passable_width))

            self.assertTrue(any((passable_height, passable_width)))
コード例 #3
0
    def test_map_recipe_with_artbitary_principal_frame_name(self):
        # Test cases where the principal map frame is not called "Main map"
        # This should load without error
        MapRecipe(fixtures.recipe_with_non_standard_principal_map_frame_name,
                  self.lyr_props)

        # This should raise a ValueError
        with self.assertRaises(ValueError):
            MapRecipe(fixtures.recipe_with_invalid_principal_map_frame_name,
                      self.lyr_props)
コード例 #4
0
    def test_get_atlas(self):
        recipe_def = json.loads(fixtures.recipe_with_positive_iso3_code)
        test_recipe = MapRecipe(recipe_def, self.lyr_props)

        self.assertTrue(test_recipe.contains_frame('Main map'))
        self.assertFalse(test_recipe.contains_frame('not-existant'))

        lyr = test_recipe.get_frame('Main map')
        self.assertIsInstance(lyr, RecipeFrame)

        self.assertRaises(ValueError, test_recipe.get_frame, 'not-existant')
コード例 #5
0
    def test_check_layer(self):

        recipe = MapRecipe(fixtures.recipe_with_layer_details_embedded, self.lyr_props)
        lyr = recipe.all_layers().pop()

        # This will pass silently if the lyr is of the right type
        self.assertIsNone(data_search._check_layer(lyr))

        # This case should raise a ValueError
        with self.assertRaises(ValueError):
            data_search._check_layer('string-to-represent-a-layer')
コード例 #6
0
    def test_atlas_get_layer(self):
        recipe_def = json.loads(fixtures.recipe_with_positive_iso3_code)
        test_recipe = MapRecipe(recipe_def, self.lyr_props)
        atlas = test_recipe.get_frame('Main map')

        self.assertTrue(atlas.contains_layer('mainmap_stle_stl_pt_s0_allmaps'))
        self.assertFalse(atlas.contains_layer('not-existant'))

        lyr = atlas.get_layer('mainmap_stle_stl_pt_s0_allmaps')
        self.assertIsInstance(lyr, RecipeLayer)

        self.assertRaises(ValueError, atlas.get_layer, 'not-existant')
コード例 #7
0
    def test_calc_data_source_checksum(self):
        test_recipe = MapRecipe(fixtures.recipe_with_layer_name_only, self.lyr_props)

        test_lyr = test_recipe.all_layers().pop()
        # Use a simple test shapefile
        test_lyr.data_source_path = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'test_shp_files',
            'lbn_admn_ad0_py_s1_pp_cdr.shp')

        actual_has_of_shp_file = test_lyr._calc_data_source_checksum()
        expected_hash_of_shp_file = '1acb212b47c8ccb3006ae9b4c5f1cfc0'
        self.assertEqual(actual_has_of_shp_file, expected_hash_of_shp_file)
コード例 #8
0
    def test_calc_layer_file_checksum(self):
        test_recipe = MapRecipe(fixtures.recipe_with_layer_name_only, self.lyr_props)

        test_lyr = test_recipe.all_layers().pop()
        # This is an empty .lyr file
        test_lyr.layer_file_path = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'test_layer_rendering', 'four_files_exact_match',
            'locationmap_stle_stl_pt_s0_locationmaps.lyr')

        test_lyr._calc_layer_file_checksum()
        hash_of_empty_str = 'd41d8cd98f00b204e9800998ecf8427e'
        self.assertEqual(test_lyr.layer_file_checksum, hash_of_empty_str)
コード例 #9
0
    def test_map_recipe_backward_compat(self):
        # This is required in order to get hold of a recipe object. This is because the method being
        # tested is a member of the class.
        recipe_obj = MapRecipe(fixtures.recipe_with_layer_name_only,
                               self.lyr_props)

        test_cases = [(fixtures.recipe_schema_v2_0_with_layer_name_only, 0.2),
                      (fixtures.recipe_with_layer_name_only, 0.3)]

        for recipe_str, expected_result in test_cases:
            recipe_def = json.loads(recipe_str)
            self.assertEqual(
                recipe_obj._check_schemas_with_backward_compat(recipe_def),
                expected_result)
コード例 #10
0
    def test_equality_of_map_recipes(self):
        recipe_def = json.loads(fixtures.recipe_with_positive_iso3_code)
        test_recipe1 = MapRecipe(recipe_def, self.lyr_props)
        test_recipe2 = MapRecipe(recipe_def, self.lyr_props)

        self.assertEqual(test_recipe1, test_recipe2)
        test_recipe1.summary = "something different"
        self.assertNotEqual(test_recipe1, test_recipe2)

        test_recipe3 = MapRecipe(recipe_def, self.lyr_props)
        self.assertEqual(test_recipe2, test_recipe3)
        # Remove an arbitary layer from each Map Frame
        for m_frames in test_recipe3.map_frames:
            m_frames.layers.pop()
        self.assertNotEqual(test_recipe2, test_recipe3)
コード例 #11
0
    def test_get_aspect_ratios_of_templates(self, mock_ListDataFrames,
                                            mock_MapDocument):
        mock_MapDocument.return_value = None
        df_lists = [[self.df1], [self.df2], [self.df3], [self.df4], [self.df5],
                    [self.df6]]
        mock_ListDataFrames.side_effect = df_lists
        tmpl_paths = repeat('/the/path', len(df_lists))
        tmpl_paths = ['/the/path{}'.format(n) for n in range(1, 7)]

        test_lp = LayerProperties(self.cmf, '.lyr')
        test_recipe = MapRecipe(fixtures.fixture_recipe_minimal, test_lp)

        expected_result = [
            ('/the/path1',
             float(self.df1.elementWidth) / self.df1.elementHeight),
            ('/the/path2',
             float(self.df2.elementWidth) / self.df2.elementHeight),
            ('/the/path3',
             float(self.df3.elementWidth) / self.df3.elementHeight),
            ('/the/path4',
             float(self.df4.elementWidth) / self.df4.elementHeight),
            ('/the/path5',
             float(self.df5.elementWidth) / self.df5.elementHeight),
            ('/the/path6',
             float(self.df6.elementWidth) / self.df6.elementHeight)
        ]

        actual_result = self.arcmap_runner.get_aspect_ratios_of_templates(
            tmpl_paths, test_recipe)

        self.assertEqual(actual_result, expected_result)
コード例 #12
0
    def test_map_chef_cook(self):
        my_mxd = arcpy.mapping.MapDocument(self.my_mxd_fpath)

        mc = MapChef(my_mxd, self.cmf, self.event)

        test_recipe = MapRecipe(
            fixtures.fixture_recipe_processed_by_controller, self.layer_props)
        mc.cook(test_recipe)
        self.assertTrue(True)
コード例 #13
0
 def _parse_json_file(self):
     """
     Reads product "recipes" from Map Cookbook json file
     """
     with open(self.cookbook_json_file) as json_file:
         jsonContents = json.load(json_file)
         for recipe in jsonContents['recipes']:
             rec = MapRecipe(recipe, self.layer_props, self.hum_event)
             self.products[recipe['product']] = rec
コード例 #14
0
    def test_substitute_fields_in_recipe_strings(self):
        recipe_updater = data_search.get_recipe_event_updater(self.event)

        # An example with an iso code within a positive regex lookup
        # (eg '^{e.affected_country_iso3}_stle.....')
        reference_recipe = MapRecipe(
            fixtures.recipe_with_positive_iso3_code, self.lyr_props)
        pos_recipe = MapRecipe(
            fixtures.recipe_without_positive_iso3_code, self.lyr_props)
        updated_pos_recipe = recipe_updater(state=pos_recipe)
        self.assertEqual(updated_pos_recipe, reference_recipe)

        # An example with an iso code within a negitive regex lookup
        # (eg '^(?!({e.affected_country_iso3}))_admn.....')
        reference_recipe = MapRecipe(
            fixtures.recipe_with_negative_iso3_code, self.lyr_props)
        neg_recipe = MapRecipe(
            fixtures.recipe_without_negative_iso3_code, self.lyr_props)
        recipe_updater = data_search.get_recipe_event_updater(self.event)
        updated_neg_recipe = recipe_updater(state=neg_recipe)

        self.assertEqual(updated_neg_recipe, reference_recipe)

        # Reverse of the first example to test a case where nothing needs updating. In this case the same json
        # definition is used for both recipes. There are not string replacement fields within the json definition.
        reference_recipe = MapRecipe(
            fixtures.recipe_with_positive_iso3_code, self.lyr_props)
        pos_recipe = MapRecipe(
            fixtures.recipe_with_positive_iso3_code, self.lyr_props)
        updated_pos_recipe = recipe_updater(state=pos_recipe)
        self.assertEqual(updated_pos_recipe, reference_recipe)
コード例 #15
0
    def test_verify_layer_file_path(self):
        """
        Test the case that a recipe is re-stored with the layer_file_paths already populated, and
        whether or not that path is valid.
        """
        fail_msg = 'The expected layer file'
        with self.assertRaises(ValueError) as arcm:
            MapRecipe(fixtures.recipe_with_invalid_layer_file_path, self.lyr_props)

        if six.PY2:
            self.assertRegexpMatches(str(arcm.exception), fail_msg)
        else:
            self.assertRegex(str(arcm.exception), fail_msg)
コード例 #16
0
    def test_check_lyr_is_in_recipe(self):
        """
        Check that an error is raised if any `step.funcs` attempt to act on a layer object that
        isn't part of the relevant recipe object.
        """
        # Two recipes without a common layer
        recipe_A = MapRecipe(fixtures.recipe_with_layer_name_only, self.lyr_props)
        recipe_B = MapRecipe(fixtures.recipe_with_positive_iso3_code, self.lyr_props)

        test_lyr = recipe_A.all_layers().pop()

        # This should pass without error
        test_lyr._check_lyr_is_in_recipe(recipe_A)

        # This should fail because test_lyr is not from recipe_B
        fail_msg = 'which is not part of the recipe'
        with self.assertRaises(ValueError) as arcm:
            test_lyr._check_lyr_is_in_recipe(recipe_B)

        if six.PY2:
            self.assertRegexpMatches(str(arcm.exception), fail_msg)
        else:
            self.assertRegex(str(arcm.exception), fail_msg)
コード例 #17
0
    def test_calc_extent(self):
        test_recipe = MapRecipe(fixtures.recipe_with_layer_name_only, self.lyr_props)

        test_lyr = test_recipe.all_layers().pop()
        # Use a simple test shapefile
        test_lyr.data_source_path = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'test_shp_files',
            'lbn_admn_ad0_py_s1_pp_cdr.shp')

        # Get the extents shapefile and update the test_lyr object
        test_lyr.calc_extent(state=test_recipe)

        expected_extent = [35.10348736558511, 33.054996785738204, 36.62291533501688, 34.69206915371]
        # expected_crs = (
        #     'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",'
        #     'SPHEROID["WGS_1984",6378137.0,298.257223563]],'
        #     'PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]')
        # expected_crs = {'init': 'epsg:4326'}
        expected_crs = 'epsg:4326'

        for actual, expected in zip(test_lyr.extent, expected_extent):
            self.assertEqual(actual, expected)

        self.assertEqual(test_lyr.crs, expected_crs)
コード例 #18
0
    def test_load_recipe_with_layer_props_inc(self):
        # Test that a MapRecipe read form json with only a layername, combined with the
        # relevant LayerProperties is equal to a MapRecipe with all of the layerdetails embeded.

        # layerpros with
        cmf = CrashMoveFolder(
            os.path.join(self.parent_dir, 'example',
                         'cmf_description_relative_paths_test.json'))
        cmf.layer_properties = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'cookbooks',
            'fixture_layer_properties_for_atlas.json')
        test_lp = LayerProperties(cmf, ".lyr", verify_on_creation=False)

        # recipe with layer name only
        recipe1 = MapRecipe(fixtures.recipe_with_layer_name_only, test_lp)
        # combined recipe with layer props
        recipe2 = MapRecipe(fixtures.recipe_with_layer_details_embedded,
                            test_lp)

        self.assertEqual(recipe1, recipe2)

        # 2) with non-matching layer props schema
        recipe3 = MapRecipe(fixtures.recipe_with_positive_iso3_code, test_lp)
        self.assertNotEqual(recipe1, recipe3)
コード例 #19
0
    def setUp(self):
        self.parent_dir = os.path.dirname(
            os.path.dirname(os.path.realpath(__file__)))
        self.cmf_descriptor_path = os.path.join(
            self.parent_dir, 'example', 'cmf_description_flat_test.json')
        self.cmf = CrashMoveFolder(self.cmf_descriptor_path,
                                   verify_on_creation=False)
        self.event_descriptor_path = os.path.join(self.parent_dir, 'example',
                                                  'event_description.json')
        self.event = Event(self.event_descriptor_path)
        # self.cmf = CrashMoveFolder(self.cmf_descriptor_path)
        self.lyr_props = LayerProperties(self.cmf,
                                         '',
                                         verify_on_creation=False)

        self.recipe_descriptor_path = os.path.join(
            self.parent_dir, 'example', 'example_single_map_recipe.json')
        with open(self.recipe_descriptor_path) as json_file:
            self.recipe_def = json.load(json_file)

        self.recipe = MapRecipe(self.recipe_def, self.lyr_props)
コード例 #20
0
    def test_filter_lyr_for_use_in_frame_extent(self):
        # Have included the digit at the start of the string, so that can be sorted easily.
        cmf = CrashMoveFolder(
            os.path.join(self.parent_dir, 'example',
                         'cmf_description_relative_paths_test.json'))
        cmf.layer_properties = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'cookbooks',
            'fixture_layer_properties_for_atlas.json')
        test_lp = LayerProperties(cmf, ".lyr", verify_on_creation=False)

        # recipe with layer name only
        with open(
                os.path.join(
                    self.parent_dir, 'tests', 'testfiles',
                    'fixture_cookbook_1map_5layers_1frame.json')) as rf:
            cookbook_def = json.load(rf)
        # get the first (only) recipe in the cookbook
        recipe_def = cookbook_def['recipes'].pop()

        generic_lyr_def = json.loads('''{
            "name": "the_name",
            "reg_exp": "^wrl_admn_ad0_py_(.*?)_(.*?)_([phm][phm])(.+)shp$",
            "schema_definition": "admin1_reference.yml",
            "definition_query": "",
            "display": true,
            "add_to_legend": true,
            "label_classes": []
        }''')

        # Case 1
        # test white list
        test_white_list1 = [('1a', True), ('1b', False), ('1c', None),
                            ('1d', True), ('1e', False)]
        expected_white_result1 = ['1a', '1d']

        test_white_list2 = [('2a', True), ('2b', None), ('2c', None),
                            ('2d', True), ('2e', None)]
        expected_white_result2 = ['2a', '2d']

        # Case 2
        # Black List
        test_black_list = [('3a', None), ('3b', False), ('3c', None),
                           ('3d', None), ('3e', False)]
        expected_black_result = ['3a', '3c', '3d']

        # Case 3
        # Default
        test_default_list = [('4a', None), ('4b', None), ('4c', None),
                             ('4d', None), ('4e', None)]
        expected_default_result = ['4a', '4b', '4c', '4d', '4e']

        all_test_params = [(test_white_list1, expected_white_result1),
                           (test_white_list2, expected_white_result2),
                           (test_black_list, expected_black_result),
                           (test_default_list, expected_default_result)]

        for test_list, expected_result in all_test_params:
            test_recipe = MapRecipe(recipe_def, test_lp)

            # Build up a mock list of layer to test
            replacement_lyrs = []
            for test_lyr_details in test_list:
                new_lyr = RecipeLayer(generic_lyr_def,
                                      test_lp,
                                      verify_on_creation=False)
                new_lyr.name = test_lyr_details[0]
                new_lyr.use_for_frame_extent = test_lyr_details[1]
                # vaugely near Lebanon
                new_lyr.extent = (35, 33, 36, 34)
                new_lyr.crs = 'epsg:4326'

                replacement_lyrs.append(new_lyr)

            test_frame = test_recipe.map_frames.pop()
            test_frame.layers = replacement_lyrs
            result_lyrs = test_frame._filter_lyr_for_use_in_frame_extent()
            actual_result = [lyr.name for lyr in result_lyrs]
            self.assertEqual(actual_result, expected_result)
コード例 #21
0
    def test_get_schema_checker(self):
        test_recipe = MapRecipe(fixtures.recipe_with_layer_name_only, self.lyr_props)

        test_lyr = test_recipe.all_layers().pop()
        # Use a simple test shapefile
        test_lyr.data_source_path = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'test_shp_files',
            'lbn_admn_ad0_py_s1_pp_cdr.shp')

        passing_schema = yaml.safe_load(r"""
required:
    - admin0Name
    - admin0Na_1
    - admin0Pcod
    - admin0RefN
    - admin0AltN
properties:
    geometry_type:
        items:
            enum:
                - MultiPolygon
                - Polygon
        additionalItems: false
    additionalItems: true
""")

        incorrect_geom_schema = yaml.safe_load(r"""
required:
    - admin0Name
    - admin0Na_1
    - admin0Pcod
    - admin0RefN
    - admin0AltN
properties:
    geometry_type:
        items:
            enum:
                - Point
        additionalItems: false
    additionalItems: true
""")

        incorrect_columns_schema = yaml.safe_load(r"""
required:
    - county_name,
    - parish_name
properties:
    geometry_type:
        items:
            enum:
                - MultiPolygon
                - Polygon
        additionalItems: false
    additionalItems: true
""")

        incorrect_columns_and_geom_schema = yaml.safe_load(r"""
required:
    - county_name,
    - parish_name
properties:
    geometry_type:
        items:
            enum:
                - Point
        additionalItems: false
    additionalItems: true
""")

        # Case where data matches schema
        for test_schema in [passing_schema]:
            test_lyr.data_schema = test_schema
            result = test_lyr.check_data_against_schema(state=test_recipe)
            self.assertTrue(result)

        # Cases where data doesn't match schema
        for test_schema in [incorrect_geom_schema, incorrect_columns_schema, incorrect_columns_and_geom_schema]:
            test_lyr.data_schema = test_schema
            with self.assertRaises(ValueError) as arcm:
                test_lyr.check_data_against_schema(state=test_recipe)

            ve = arcm.exception
            self.assertIsInstance(ve.args[0], recipe_layer.FixSchemaErrorTask)

        # test a logger is call for case where a raster layer is tested. This unittest
        # is only available for py3.4+, though the production code is required for py2.7
        if six.PY3:
            test_lyr.data_source_path = os.path.join(
                self.parent_dir, 'tests', 'testfiles', 'test_shp_files',
                'lbn_evel_dem_ras_s1_pp_cdr.tif')
            test_lyr.data_schema = passing_schema

            with self.assertLogs(level='INFO') as cm:
                result = test_lyr.check_data_against_schema(state=test_recipe)

            print('cm.output = {}'.format(cm.output))
            self.assertRegexpMatches(
                cm.output.pop(),
                'Unable to check schema on for data sources which aren.t shapefiles'
            )
コード例 #22
0
    def test_layer_data_schema(self):

        null_schema = True

        passing_schema = yaml.safe_load(r"""
required:
    - name_en
properties:
    geometry_type:
        items:
            enum:
                - MultiPolygon
                - Polygon
        additionalItems: false
    crs:
        items:
            enum:
                - EPSG:2090
        additionalItems: false
""")

        # Note the missing `enum` blocks
        failing_schema = yaml.safe_load(r"""
required:
    - name_en
properties:
    geometry_type:
        items:
            - MultiPolygon
            - Polygon
        additionalItems: false
    crs:
        items:
            - EPSG:2090
        additionalItems: false
""")

        cmf = CrashMoveFolder(
            os.path.join(self.parent_dir, 'example', 'cmf_description_relative_paths_test.json'))
        cmf.layer_properties = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'cookbooks', 'fixture_layer_properties_for_atlas.json'
        )

        # Two cases where data schema is valid yaml
        for test_schema in [null_schema, passing_schema]:
            with mock.patch('mapactionpy_controller.data_schemas.yaml.safe_load') as mock_safe_load:
                mock_safe_load.return_value = test_schema
                test_lp = LayerProperties(cmf, ".lyr", verify_on_creation=False)

                MapRecipe(fixtures.recipe_with_positive_iso3_code, test_lp)
                self.assertTrue(True, 'validated jsonschema')

        # case where data schema file itself malformed somehow
        with mock.patch('mapactionpy_controller.data_schemas.yaml.safe_load') as mock_safe_load:
            mock_safe_load.return_value = failing_schema

            self.assertRaises(
                jsonschema.exceptions.SchemaError,
                MapRecipe,
                fixtures.recipe_with_positive_iso3_code,
                test_lp
            )
コード例 #23
0
    def test_search_for_shapefiles(self):
        # ds = data_search.DataSearch(self.event)

        with mock.patch('mapactionpy_controller.data_search.glob.glob') as mock_glob:
            # We use two different mock values becuase we are matching absolute paths as strings
            # The underlying production code does not differencate between platforms.
            if platform.system() == 'Windows':
                mock_single_file_glob = fixtures.glob_single_stle_file_search_windows
                mock_multiple_file_glob = fixtures.glob_multiple_stle_file_search_windows
                mock_no_file_glob = fixtures.glob_no_stle_file_search_windows
                ref_recipe_str = fixtures.recipe_result_one_dataset_per_layer_windows
            else:
                mock_single_file_glob = fixtures.glob_single_stle_file_search_linux
                mock_multiple_file_glob = fixtures.glob_multiple_stle_file_search_linux
                mock_no_file_glob = fixtures.glob_no_stle_file_search_linux
                ref_recipe_str = fixtures.recipe_result_one_dataset_per_layer_linux

            reference_recipe = MapRecipe(ref_recipe_str, self.lyr_props)

            # Case A
            # where there is exactly one dataset per query
            test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            mock_glob.return_value = mock_single_file_glob
            all_gis_files = [(f_path, os.path.basename(f_path)) for f_path in data_search.get_all_gisfiles(self.cmf)]
            self.assertNotEqual(test_recipe, reference_recipe)

            # get the first layer from the test_recipe
            test_lyr = test_recipe.all_layers().pop()
            data_finder = test_lyr.get_data_finder(self.cmf, all_gis_files)
            updated_test_recipe = data_finder(state=test_recipe)

            self.assertEqual(updated_test_recipe, test_recipe)
            self.assertTrue(updated_test_recipe == test_recipe)
            self.assertEqual(updated_test_recipe, reference_recipe)

            # Case B
            # where there is multiple matching datasets
            test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            mock_glob.return_value = mock_multiple_file_glob
            all_gis_files = [(f_path, os.path.basename(f_path)) for f_path in data_search.get_all_gisfiles(self.cmf)]
            self.assertNotEqual(test_recipe, reference_recipe)

            # get the first layer from the test_recipe
            test_lyr = test_recipe.all_layers().pop()
            data_finder = test_lyr.get_data_finder(self.cmf, all_gis_files)
            with self.assertRaises(ValueError) as arcm:
                updated_test_recipe = data_finder(state=test_recipe)

            ve = arcm.exception
            print('ve.args[0] is instance of: {}'.format(type(ve.args[0])))
            self.assertIsInstance(ve.args[0], recipe_layer.FixMultipleMatchingFilesTask)

            # Case C
            # where there are no matching datasets
            test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            mock_glob.return_value = mock_no_file_glob
            all_gis_files = [(f_path, os.path.basename(f_path)) for f_path in data_search.get_all_gisfiles(self.cmf)]
            self.assertNotEqual(test_recipe, reference_recipe)

            # get the first layer from the test_recipe
            test_lyr = test_recipe.all_layers().pop()
            data_finder = test_lyr.get_data_finder(self.cmf, all_gis_files)
            with self.assertRaises(ValueError) as arcm:
                updated_test_recipe = data_finder(state=test_recipe)

            ve = arcm.exception
            print('ve.args[0] is instance of: {}'.format(type(ve.args[0])))
            self.assertIsInstance(ve.args[0], recipe_layer.FixMissingGISDataTask)

            # Case D
            # Case insensitive search. Like Case A, but we force the regex itself into upper and lower case.
            test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            mock_glob.return_value = mock_single_file_glob
            all_gis_files = [(f_path, os.path.basename(f_path)) for f_path in data_search.get_all_gisfiles(self.cmf)]
            self.assertNotEqual(test_recipe, reference_recipe)

            # get the first layer from the test_recipe
            test_lyr = test_recipe.all_layers().pop()
            for new_reg_exp in [test_lyr.reg_exp.upper(), test_lyr.reg_exp.lower()]:
                # save the old Reg Exp in order to use to compare recipes later
                old_reg_exp = test_lyr.reg_exp
                test_lyr.reg_exp = new_reg_exp
                data_finder = test_lyr.get_data_finder(self.cmf, all_gis_files)
                updated_test_recipe = data_finder(state=test_recipe)
                # Now replace the origional reg_exp
                test_lyr.reg_exp = old_reg_exp

                self.assertEqual(updated_test_recipe, test_recipe)
                self.assertTrue(updated_test_recipe == test_recipe)
                self.assertEqual(updated_test_recipe, reference_recipe)

            # Case E
            # Check whether or not it is enforced that a regex is matches the beginning of the string or at any
            # point in the string. Simular to Case A
            test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            mock_glob.return_value = mock_single_file_glob
            all_gis_files = [(f_path, os.path.basename(f_path)) for f_path in data_search.get_all_gisfiles(self.cmf)]
            self.assertNotEqual(test_recipe, reference_recipe)

            # get the first layer from the test_recipe
            test_lyr = test_recipe.all_layers().pop()
            # save the old Reg Exp in order to use to compare recipes later
            old_reg_exp = test_lyr.reg_exp
            # force an regex that doesn't have an anchor at the begining of the string, nor does it match the
            # beginning of the filename
            test_lyr.reg_exp = 'stle_ste_pt_(.*?)_(.*?)_([phm][phm])(.*?)'

            data_finder = test_lyr.get_data_finder(self.cmf, all_gis_files)
            updated_test_recipe = data_finder(state=test_recipe)

            # Now replace the origional reg_exp
            test_lyr.reg_exp = old_reg_exp

            self.assertEqual(updated_test_recipe, test_recipe)
            self.assertTrue(updated_test_recipe == test_recipe)
            self.assertEqual(updated_test_recipe, reference_recipe)

            # Case F
            # Check case where filesystem has case sensitive filenames, meaning that we could match on two
            # seperate files whose names only different by case.
            # Very simular to Case B
            test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            mock_glob.return_value = fixtures.glob_multiple_stle_file_search_case_difference_linux
            all_gis_files = [(f_path, os.path.basename(f_path)) for f_path in data_search.get_all_gisfiles(self.cmf)]
            self.assertNotEqual(test_recipe, reference_recipe)

            # get the first layer from the test_recipe
            test_lyr = test_recipe.all_layers().pop()
            data_finder = test_lyr.get_data_finder(self.cmf, all_gis_files)
            with self.assertRaises(ValueError) as arcm:
                updated_test_recipe = data_finder(state=test_recipe)

            ve = arcm.exception
            self.assertIsInstance(ve.args[0], recipe_layer.FixMultipleMatchingFilesTask)
コード例 #24
0
    def test_get_map_frame_extents(self):
        cmf = CrashMoveFolder(
            os.path.join(self.parent_dir, 'example',
                         'cmf_description_relative_paths_test.json'))
        cmf.layer_properties = os.path.join(
            self.parent_dir, 'tests', 'testfiles', 'cookbooks',
            'fixture_layer_properties_for_atlas.json')
        test_lp = LayerProperties(cmf, ".lyr", verify_on_creation=False)

        # recipe with layer name only
        with open(
                os.path.join(
                    self.parent_dir, 'tests', 'testfiles',
                    'fixture_cookbook_1map_5layers_1frame.json')) as rf:
            cookbook_def = json.load(rf)
        # get the first (only) recipe in the cookbook
        recipe_def = cookbook_def['recipes'].pop()

        generic_lyr_def = json.loads('''{
            "name": "the_name",
            "reg_exp": "^wrl_admn_ad0_py_(.*?)_(.*?)_([phm][phm])(.+)shp$",
            "schema_definition": "admin1_reference.yml",
            "definition_query": "",
            "display": true,
            "add_to_legend": true,
            "label_classes": []
        }''')

        # Case 1
        # One or more layers does not have it's extent defined
        case1_list = [('case1_lyrA', (35, 33, 36, 34), 'epsg:4326'),
                      ('case1_lyrB', None, None)]
        case1_result = (35, 33, 36, 34)

        # Case 2
        # Simple union with two lyrs of same crs
        case2_list = [('case2_lyrA', (33, 51, 36, 58), 'epsg:4326'),
                      ('case2_lyrB', (15, 52, 35, 55), 'epsg:4326')]
        case2_result = (15, 51, 36, 58)

        # Case 3
        # Union with two lyrs of with different crs
        # 'epsg:4326'== WGS1984, 'epsg:3785' == Web Mercator
        case3_list = [('case3_lyrA', (33, 51, 36, 58), 'epsg:4326'),
                      ('case3_lyrB', (1669792.36, 6800125.45, 3896182.18,
                                      7361866.11), 'epsg:3785')]
        case3_result = (15, 51, 36, 58)

        # Case 4
        # One layer which stradles 180 degree meridian

        all_test_params = [(case1_list, case1_result),
                           (case2_list, case2_result),
                           (case3_list, case3_result)]

        for test_list, expected_result in all_test_params:
            test_recipe = MapRecipe(recipe_def, test_lp)

            # Build up a mock list of layer to test
            replacement_lyrs = []
            for name, extent, crs in test_list:
                new_lyr = RecipeLayer(generic_lyr_def,
                                      test_lp,
                                      verify_on_creation=False)
                new_lyr.name = name
                new_lyr.use_for_frame_extent = bool(extent)
                # vaugely near Lebanon
                new_lyr.extent = extent
                new_lyr.crs = crs

                replacement_lyrs.append(new_lyr)

            # print('test_get_map_frame_extents')
            # print('expected_result = {}'.format(expected_result))
            test_frame = test_recipe.map_frames.pop()
            test_frame.crs = 'epsg:4326'
            test_frame.layers = replacement_lyrs
            test_frame.calc_extent(state=test_recipe)
            actual_result = test_frame.extent
            # print('actual_result = {}'.format(actual_result))
            for actual, expected in zip(actual_result, expected_result):
                self.assertAlmostEqual(actual, expected)
コード例 #25
0
def main(args):
    args = parser.parse_args()
    event = Event(args.eventDescriptionFile)
    runner = ArcProRunner(event)

    recipe_without_positive_iso3_code = ('''{
            "mapnumber": "MA001",
            "category": "Reference",
            "product": "DJI Overview Map",
            "summary": "Overview of DJI with topography displayed",
            "export": true,
            "template": "reference",
            "map_frames": [
                {
                    "name": "Main map",
                    "layers": [
                        {
                            "name": "mainmap-stle-stl-pt-s0-allmaps",
                            "reg_exp": "^[a-z][a-z][a-z]_stle_stl_pt_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "stle_ste_pt.yml",
                            "definition_query": "fclass IN ('national_capital', 'city', 'capital', 'town')",
                            "display": true,
                            "add_to_legend": true,
                            "label_classes": [
                                {
                                    "class_name": "National Capital",
                                    "expression": "[name]",
                                    "sql_query": "('fclass' = 'national_capital')",
                                    "show_class_labels": true
                                },
                                {
                                    "class_name": "Admin 1 Capital",
                                    "expression": "[name]",
                                    "sql_query": "('fclass' = 'town')",
                                    "show_class_labels": true
                                }
                            ]
                        },
                        {
                            "name": "mainmap-carto-fea-py-s0-allmaps",
                            "reg_exp": "^[a-z][a-z][a-z]_carto_fea_py_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "null-schema.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": false,
                            "label_classes": []
                        },
                        {
                            "name": "mainmap-elev-cst-ln-s0-allmaps",
                            "reg_exp": "^[a-z][a-z][a-z]_elev_cst_ln_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "null-schema.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": false,
                            "label_classes": []
                        },
                        {
                            "name": "mainmap-admn-ad0-ln-s0-reference",
                            "reg_exp": "^[a-z][a-z][a-z]_admn_ad0_ln_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "null-schema.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": false,
                            "label_classes": []
                        },
                        {
                            "name": "mainmap-admn-ad1-ln-s0-reference",
                            "reg_exp": "^[a-z][a-z][a-z]_admn_ad1_ln_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "admin1_reference.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": true,
                            "label_classes": []
                        },
                        {
                            "name": "mainmap-phys-riv-ln-s0-reference",
                            "reg_exp": "^[a-z][a-z][a-z]_phys_riv_ln_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "null-schema.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": true,
                            "label_classes": []
                        },
                        {
                            "name": "mainmap-admn-ad1-py-s0-reference",
                            "reg_exp": "^[a-z][a-z][a-z]_admn_ad1_py_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "admin1_reference.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": true,
                            "label_classes": []
                        },
                        {
                            "name": "mainmap-admn-ad0-ln-s0-surroundingcountries",
                            "reg_exp": "^[a-z][a-z][a-z]_admn_ad0_ln_(.*?)_(.*?)_([phm][phm])(.*?).shp$",
                            "schema_definition": "null-schema.yml",
                            "definition_query": "",
                            "display": true,
                            "add_to_legend": true,
                            "label_classes": []
                        }
                    ]
                }
            ]
        }''')

    layerProperties = LayerProperties(event.cmf_descriptor_path,
                                      '.lyr',
                                      verify_on_creation=False)
    recipe = MapRecipe(recipe_without_positive_iso3_code, layerProperties)
    recipe = runner.get_templates(state=recipe)
    recipe = runner.create_ouput_map_project(state=recipe)
    recipe = runner.build_project_files(state=recipe)

    themes = set()
    themes.add("Health")
    propertiesDict = {}
    propertiesDict['themes'] = themes
    propertiesDict['accessnotes'] = "My super access note"
    recipe = runner.export_maps(state=recipe, properties=propertiesDict)
コード例 #26
0
    def test_get_templates(self):

        # Case 1
        # Pre-existing valid `map_project_path` value
        expect_result = MapRecipe(
            fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
        test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles,
                                self.lyr_props)
        expect_result.map_project_path = '/path/that/exists.mxd'
        test_recipe.map_project_path = '/path/that/exists.mxd'

        with mock.patch('mapactionpy_controller.plugin_base.os.path.exists'
                        ) as mock_path_exists:
            mock_path_exists.return_value = True
            actual_result = self.dummy_runner.get_templates(state=test_recipe)

        self.assertEqual(actual_result, expect_result)

        # Case 2
        # Non-None `map_project_path` value which points of non-existing file
        test_recipe = MapRecipe(fixtures.recipe_test_for_search_for_shapefiles,
                                self.lyr_props)
        test_recipe.map_project_path = '/path/that/does/not/exists.mxd'

        with mock.patch('mapactionpy_controller.plugin_base.os.path.exists'
                        ) as mock_path_exists:
            mock_path_exists.return_value = False
            with self.assertRaises(ValueError):
                self.dummy_runner.get_templates(state=test_recipe)

        # Case 3 & 4
        # mf.extent exists and has a valid value
        # mf.entent is None
        test_extents = [('one', (1, 1, 5, 5)), ('two', (1, 1, 9, 5)),
                        ('one', None)]

        for expected_result, extent in test_extents:
            print(expected_result, extent)
            test_recipe = MapRecipe(
                fixtures.recipe_test_for_search_for_shapefiles, self.lyr_props)
            test_recipe.map_frames[0].extent = extent
            # mf.extent = extent
            actual_recipe = self.dummy_runner.get_templates(state=test_recipe)
            self.assertEquals(expected_result, actual_recipe.template_path)