def _cached_add_inferred_export_properties(sender, domain, case_type, properties): from corehq.apps.export.models import MAIN_TABLE, PathNode, CaseInferredSchema, ScalarItem """ Adds inferred properties to the inferred schema for a case type. :param: sender - The signal sender :param: domain :param: case_type :param: properties - An iterable of case properties to add to the inferred schema """ assert domain, 'Must have domain' assert case_type, 'Must have case type' assert all(['.' not in prop for prop in properties]), 'Properties should not have periods' inferred_schema = get_case_inferred_schema(domain, case_type) if not inferred_schema: inferred_schema = CaseInferredSchema( domain=domain, case_type=case_type, ) group_schema = inferred_schema.put_group_schema(MAIN_TABLE) add_properties_to_data_dictionary(domain, case_type, properties) for case_property in properties: path = [PathNode(name=case_property)] system_property_column = list( filter( lambda column: column.item.path == path and column.item. transform is None, MAIN_CASE_TABLE_PROPERTIES, )) if system_property_column: assert len(system_property_column) == 1 column = system_property_column[0] group_schema.put_item(path, inferred_from=sender, item_cls=column.item.__class__) else: group_schema.put_item(path, inferred_from=sender, item_cls=ScalarItem) inferred_schema.save()
class TestBuildingSchemaFromApplication(TestCase, TestXmlMixin): file_path = ['data'] root = os.path.dirname(__file__) case_type = 'wonderwoman' domain = 'aspace' @classmethod def setUpClass(cls): super(TestBuildingSchemaFromApplication, cls).setUpClass() cls.current_app = Application.wrap(cls.get_json('basic_application')) cls.first_build = Application.wrap(cls.get_json('basic_application')) cls.first_build._id = '123' cls.first_build.copy_of = cls.current_app.get_id cls.first_build.version = 3 cls.first_build.has_submissions = True factory = AppFactory(build_version='2.36.0') m0, f0 = factory.new_advanced_module('mod0', 'advanced') f0.source = cls.get_xml('repeat_group_form').decode('utf-8') f0.xmlns = 'repeat-xmlns' factory.form_requires_case(f0, 'case0') f0.actions.open_cases = [ AdvancedOpenCaseAction( case_type="advanced", case_tag="open_case_0", name_path="/data/question3/question4", repeat_context="/data/question3", case_indices=[CaseIndex(tag='load_case0_0')] ) ] cls.advanced_app = factory.app cls.advanced_app.save() cls.apps = [ cls.current_app, cls.first_build, cls.advanced_app, ] with drop_connected_signals(app_post_save): for app in cls.apps: app.save() @classmethod def tearDownClass(cls): for app in cls.apps: app.delete() super(TestBuildingSchemaFromApplication, cls).tearDownClass() def setUp(self): self.inferred_schema = CaseInferredSchema( domain=self.domain, case_type=self.case_type, group_schemas=[ InferredExportGroupSchema( path=MAIN_TABLE, items=[ ExportItem( path=[PathNode(name='data'), PathNode(name='case_property')], label='Inferred 1', inferred=True ), ExportItem( path=[PathNode(name='data'), PathNode(name='case_property_2')], label='Inferred 1', inferred=True ), ], inferred=True ), ] ) self.inferred_schema.save() def tearDown(self): delete_all_export_data_schemas() def test_basic_application_schema(self): app = self.current_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns' ) self.assertEqual(len(schema.group_schemas), 1) @softer_assert() def test_process_app_failure(self): ''' This ensures that the schema generated will not fail if there is an error processing one of the applications. ''' with patch( 'corehq.apps.export.models.new.FormExportDataSchema._process_app_build', side_effect=Exception('boom')): FormExportDataSchema.generate_schema_from_builds( self.current_app.domain, self.current_app._id, 'my_sweet_xmlns' ) def test_build_from_saved_schema(self): app = self.current_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns' ) self.assertEqual(len(schema.group_schemas), 1) self.assertEqual(schema.last_app_versions[app._id], self.first_build.version) # After the first schema has been saved let's add a second app to process second_build = Application.wrap(self.get_json('basic_application')) second_build._id = '456' second_build.copy_of = app.get_id second_build.version = 6 second_build.has_submissions = True second_build.save() self.addCleanup(second_build.delete) new_schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns' ) self.assertEqual(new_schema._id, schema._id) self.assertEqual(new_schema.last_app_versions[app._id], second_build.version) self.assertEqual(len(new_schema.group_schemas), 1) def test_build_with_inferred_schema(self): app = self.current_app schema = CaseExportDataSchema.generate_schema_from_builds( app.domain, app._id, self.case_type, ) group_schema = schema.group_schemas[0] self.assertEqual(group_schema.path, MAIN_TABLE) self.assertTrue(group_schema.inferred) inferred_items = [item for item in group_schema.items if item.inferred] self.assertEqual(len(inferred_items), 2) def test_build_with_advanced_app(self): app = self.advanced_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, "repeat-xmlns", ) group_schema = schema.group_schemas[1] # The repeat schema # Assert that all proper case attributes are added to advanced forms that open # cases with repeats assertContainsExportItems( [ ('form.question3.question4', 'question4'), ('form.question3.case.create.case_name', 'case_open_case_0.create.case_name'), ('form.question3.case.create.case_type', 'case_open_case_0.create.case_type'), ('form.question3.case.create.owner_id', 'case_open_case_0.create.owner_id'), ('form.question3.case.index.parent.#text', 'case_open_case_0.index.#text'), ('form.question3.case.index.parent.@case_type', 'case_open_case_0.index.@case_type'), ('form.question3.case.@case_id', 'case_open_case_0.@case_id'), ('form.question3.case.@date_modified', 'case_open_case_0.@date_modified'), ('form.question3.case.@user_id', 'case_open_case_0.@user_id'), ], group_schema ) path_suffixes = set([item.path[-1].name for item in group_schema.items]) self.assertEqual(len(path_suffixes & set(CASE_ATTRIBUTES)), len(CASE_ATTRIBUTES))
class TestBuildingSchemaFromApplication(TestCase, TestXmlMixin): file_path = ['data'] root = os.path.dirname(__file__) case_type = 'wonderwoman' domain = 'aspace' @classmethod def setUpClass(cls): super(TestBuildingSchemaFromApplication, cls).setUpClass() cls.current_app = Application.wrap(cls.get_json('basic_application')) cls.first_build = Application.wrap(cls.get_json('basic_application')) cls.first_build._id = '123' cls.first_build.copy_of = cls.current_app.get_id cls.first_build.version = 3 cls.first_build.has_submissions = True factory = AppFactory(build_version='2.36.0') m0, f0 = factory.new_advanced_module('mod0', 'advanced') f0.source = cls.get_xml('repeat_group_form').decode('utf-8') f0.xmlns = 'repeat-xmlns' factory.form_requires_case(f0, 'case0') f0.actions.open_cases = [ AdvancedOpenCaseAction( case_type="advanced", case_tag="open_case_0", name_path="/data/question3/question4", repeat_context="/data/question3", case_indices=[CaseIndex(tag='load_case0_0')]) ] cls.advanced_app = factory.app cls.advanced_app.save() cls.apps = [ cls.current_app, cls.first_build, cls.advanced_app, ] with drop_connected_signals(app_post_save): for app in cls.apps: app.save() @classmethod def tearDownClass(cls): for app in cls.apps: app.delete() super(TestBuildingSchemaFromApplication, cls).tearDownClass() def setUp(self): self.inferred_schema = CaseInferredSchema( domain=self.domain, case_type=self.case_type, group_schemas=[ InferredExportGroupSchema( path=MAIN_TABLE, items=[ ExportItem(path=[ PathNode(name='data'), PathNode(name='case_property') ], label='Inferred 1', inferred=True), ExportItem(path=[ PathNode(name='data'), PathNode(name='case_property_2') ], label='Inferred 1', inferred=True), ], inferred=True), ]) self.inferred_schema.save() def tearDown(self): delete_all_export_data_schemas() def test_basic_application_schema(self): app = self.current_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns') self.assertEqual(len(schema.group_schemas), 1) @softer_assert() def test_process_app_failure(self): ''' This ensures that the schema generated will not fail if there is an error processing one of the applications. ''' with patch( 'corehq.apps.export.models.new.FormExportDataSchema._process_app_build', side_effect=Exception('boom')): FormExportDataSchema.generate_schema_from_builds( self.current_app.domain, self.current_app._id, 'my_sweet_xmlns') def test_build_from_saved_schema(self): app = self.current_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns') self.assertEqual(len(schema.group_schemas), 1) self.assertEqual(schema.last_app_versions[app._id], self.first_build.version) # After the first schema has been saved let's add a second app to process second_build = Application.wrap(self.get_json('basic_application')) second_build._id = '456' second_build.copy_of = app.get_id second_build.version = 6 second_build.has_submissions = True second_build.save() self.addCleanup(second_build.delete) new_schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns') self.assertEqual(new_schema._id, schema._id) self.assertEqual(new_schema.last_app_versions[app._id], second_build.version) self.assertEqual(len(new_schema.group_schemas), 1) def test_build_with_inferred_schema(self): app = self.current_app schema = CaseExportDataSchema.generate_schema_from_builds( app.domain, app._id, self.case_type, ) group_schema = schema.group_schemas[0] self.assertEqual(group_schema.path, MAIN_TABLE) self.assertTrue(group_schema.inferred) inferred_items = [item for item in group_schema.items if item.inferred] self.assertEqual(len(inferred_items), 2) def test_build_with_advanced_app(self): app = self.advanced_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, "repeat-xmlns", ) group_schema = schema.group_schemas[1] # The repeat schema # Assert that all proper case attributes are added to advanced forms that open # cases with repeats assertContainsExportItems([ ('form.question3.question4', 'question4'), ('form.question3.case.create.case_name', 'case_open_case_0.create.case_name'), ('form.question3.case.create.case_type', 'case_open_case_0.create.case_type'), ('form.question3.case.create.owner_id', 'case_open_case_0.create.owner_id'), ('form.question3.case.index.parent.#text', 'case_open_case_0.index.#text'), ('form.question3.case.index.parent.@case_type', 'case_open_case_0.index.@case_type'), ('form.question3.case.@case_id', 'case_open_case_0.@case_id'), ('form.question3.case.@date_modified', 'case_open_case_0.@date_modified'), ('form.question3.case.@user_id', 'case_open_case_0.@user_id'), ], group_schema) path_suffixes = set( [item.path[-1].name for item in group_schema.items]) self.assertEqual(len(path_suffixes & set(CASE_ATTRIBUTES)), len(CASE_ATTRIBUTES))
class TestBuildingSchemaFromApplication(TestCase, TestXmlMixin): file_path = ['data'] root = os.path.dirname(__file__) case_type = 'wonderwoman' domain = 'aspace' @classmethod def setUpClass(cls): cls.current_app = Application.wrap(cls.get_json('basic_application')) cls.first_build = Application.wrap(cls.get_json('basic_application')) cls.first_build._id = '123' cls.first_build.copy_of = cls.current_app.get_id cls.first_build.version = 3 cls.first_build.has_submissions = True cls.advanced_app = Application.new_app('domain', "Untitled Application") module = cls.advanced_app.add_module(AdvancedModule.new_module('Untitled Module', None)) form = module.new_form("Untitled Form", cls.get_xml('repeat_group_form')) form.xmlns = 'repeat-xmlns' form.actions.open_cases = [ AdvancedOpenCaseAction( case_type="advanced", case_tag="open_case_0", name_path="/data/question3/question4", repeat_context="/data/question3", ) ] cls.apps = [ cls.current_app, cls.first_build, cls.advanced_app, ] with drop_connected_signals(app_post_save): for app in cls.apps: app.save() @classmethod def tearDownClass(cls): for app in cls.apps: app.delete() def setUp(self): self.inferred_schema = CaseInferredSchema( domain=self.domain, case_type=self.case_type, group_schemas=[ InferredExportGroupSchema( path=MAIN_TABLE, items=[ ExportItem( path=[PathNode(name='data'), PathNode(name='case_property')], label='Inferred 1', inferred=True ), ExportItem( path=[PathNode(name='data'), PathNode(name='case_property_2')], label='Inferred 1', inferred=True ), ], inferred=True ), ] ) self.inferred_schema.save() def tearDown(self): delete_all_export_data_schemas() def test_basic_application_schema(self): app = self.current_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns' ) self.assertEqual(len(schema.group_schemas), 1) @softer_assert() def test_process_app_failure(self): ''' This ensures that the schema generated will not fail if there is an error processing one of the applications. ''' with patch( 'corehq.apps.export.models.new.FormExportDataSchema._process_app_build', side_effect=Exception('boom')): FormExportDataSchema.generate_schema_from_builds( self.current_app.domain, self.current_app._id, 'my_sweet_xmlns' ) def test_build_from_saved_schema(self): app = self.current_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns' ) self.assertEqual(len(schema.group_schemas), 1) self.assertEqual(schema.last_app_versions[app._id], self.first_build.version) # After the first schema has been saved let's add a second app to process second_build = Application.wrap(self.get_json('basic_application')) second_build._id = '456' second_build.copy_of = app.get_id second_build.version = 6 second_build.has_submissions = True second_build.save() self.addCleanup(second_build.delete) new_schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, 'my_sweet_xmlns' ) self.assertEqual(new_schema._id, schema._id) self.assertEqual(new_schema.last_app_versions[app._id], second_build.version) self.assertEqual(len(new_schema.group_schemas), 1) def test_build_with_inferred_schema(self): app = self.current_app schema = CaseExportDataSchema.generate_schema_from_builds( app.domain, app._id, self.case_type, ) group_schema = schema.group_schemas[0] self.assertEqual(group_schema.path, MAIN_TABLE) self.assertTrue(group_schema.inferred) inferred_items = filter(lambda item: item.inferred, group_schema.items) self.assertEqual(len(inferred_items), 2) def test_build_with_advanced_app(self): app = self.advanced_app schema = FormExportDataSchema.generate_schema_from_builds( app.domain, app._id, "repeat-xmlns", ) group_schema = schema.group_schemas[1] # The repeat schema # Assert that all proper case attributes are added to advanced forms that open # cases with repeats path_suffixes = set(map(lambda item: item.path[-1].name, group_schema.items)) self.assertEqual(len(path_suffixes & set(CASE_ATTRIBUTES)), len(CASE_ATTRIBUTES))