def load_models_from_sdml(self, sdml):
     """ Load data models from an SDML literal. """
     models = [] 
     for model in SDML(sdml).get_output():
         attach_filter_fields(model)
         models.append(model)
     self.load_models(models)
     return models
 def cause_exception(doc):
     parser = SDML(doc)
     output = [obj for obj in parser.get_output()]
 def setUp(self):
     super(SDMLUnitTests, self).setUp()
     self.instance = SDML(TEST_SDML_DOCS[0])
class SDMLUnitTests(InternalTests):
    def setUp(self):
        super(SDMLUnitTests, self).setUp()
        self.instance = SDML(TEST_SDML_DOCS[0])

    def tearDown(self):
        self.remove_model_from_cache('TestMedication2')
        self.remove_model_from_cache('TestPrescription2')
        self.remove_model_from_cache('TestFill2')
        self.instance = None
        super(SDMLUnitTests, self).tearDown()

    def test_get_output(self):
        output_classes = [obj for obj in self.instance.get_output()]
        self.assertEqual(len(output_classes), 3) # Three models in the definition
        
        med_klass = scrip_klass = fill_klass = None
        for klass in output_classes:
            klass_name = klass.__name__
            if klass_name == 'TestMedication2':
                med_klass = klass
            elif klass_name == 'TestPrescription2':
                scrip_klass = klass
            elif klass_name == 'TestFill2':
                fill_klass = klass
            else:
                self.fail('SDML parsing produced an invalid class %s'%klass_name)
                
        if not med_klass:
            self.fail('SDML parsing did not produce a TestMedication2 class')
        if not scrip_klass:
            self.fail('SDML parsing did not produce a TestPrescription2 class')
        if not fill_klass:
            self.fail('SDML parsing did not produce a TestFill2 class')

        # Make sure the testmedication2 class parsed as expected
        med_expected_fields = {
            'name': models.CharField,
            'date_started': models.DateTimeField,
            'date_stopped': models.DateTimeField,
            'brand_name': models.CharField,
            'route': models.CharField,
            }
        self.check_class_fields(med_klass, med_expected_fields)

        # The 'prescription' field should be a OneToOne field, pointing at TestPrescription2
        prescription_field = med_klass._meta.get_field('prescription')
        self.assertTrue(isinstance(prescription_field, models.OneToOneField))
        self.assertEqual(prescription_field.rel.to, scrip_klass)

        # The 'fills' field should be the reverse side of a ForeignKey from TestFill2 to TestMedication2
        fills_field = med_klass.fills
        self.assertTrue(isinstance(fills_field, models.fields.related.ForeignRelatedObjectsDescriptor))
        self.assertEqual(fills_field.related.model, fill_klass)

        # Make sure the testprescription2 class parsed as expected
        scrip_expected_fields = {
            'prescribed_by_name': models.CharField,
            'prescribed_by_institution': models.CharField,
            'prescribed_on': models.DateTimeField,
            'prescribed_stop_on': models.DateTimeField,
            }
        self.check_class_fields(scrip_klass, scrip_expected_fields)

        # The TestPrescription2 model should have a 'testmedication2' field pointing to the Medication class
        # (the reverse link of the OneToOne from the TestMedication2)
        scrip_parent_link = scrip_klass.testmedication2
        self.assertTrue(isinstance(scrip_parent_link, models.fields.related.SingleRelatedObjectDescriptor))
        self.assertEqual(scrip_parent_link.related.model, med_klass)

        # Make sure the testfill2 class parsed as expected
        fill_expected_fields = {
            'date_filled': models.DateField,
            'supply_days': models.FloatField,
            'filled_at_name': models.CharField,
            'code_identifier': models.CharField, # CodedValues should be expanded
            'code_title': models.CharField,
            'code_system': models.CharField,
            'quantity_value': models.CharField, # ValueAndUnit fields should be expanded
            'quantity_unit': models.CharField,
            'pharmacy_ncpdpid': models.CharField, # Pharmacy fields should be expanded
            'pharmacy_org': models.CharField,
            'pharmacy_adr_country': models.CharField, # Address fields should be expanded (recursively, from Pharmacy)
            'pharmacy_adr_city': models.CharField,
            'pharmacy_adr_postalcode': models.CharField,
            'pharmacy_adr_region': models.CharField,
            'pharmacy_adr_street': models.CharField,
            'prescriber_dea_number': models.CharField, # Provider fields should be expanded
            'prescriber_ethnicity': models.CharField,
            'prescriber_npi_number': models.CharField,
            'prescriber_preferred_language': models.CharField,
            'prescriber_race': models.CharField,
            'prescriber_adr_country': models.CharField, # Address fields should be expanded (recursively, from Prescriber)
            'prescriber_adr_city': models.CharField,
            'prescriber_adr_postalcode': models.CharField,
            'prescriber_adr_region': models.CharField,
            'prescriber_adr_street': models.CharField,
            'prescriber_bday': models.DateField,
            'prescriber_email': models.EmailField,
            'prescriber_name_family': models.CharField, # Name fields should be expanded (recursively, from Prescriber)
            'prescriber_name_given': models.CharField,
            'prescriber_name_prefix': models.CharField,
            'prescriber_name_suffix': models.CharField,
            'prescriber_gender': models.CharField,
            'prescriber_tel_1_type': models.CharField, # Telephone fields should be expanded (recursively, from Prescriber)
            'prescriber_tel_1_number': models.CharField, 
            'prescriber_tel_1_preferred_p': models.BooleanField,
            'prescriber_tel_2_type': models.CharField,
            'prescriber_tel_2_number': models.CharField,
            'prescriber_tel_2_preferred_p': models.BooleanField,               
            }
        self.check_class_fields(fill_klass, fill_expected_fields)

        # The TestFill2 model should have a ForeignKey field named 'testmedication2' pointing to the Medication class
        fill_parent_link = fill_klass._meta.get_field('testmedication2')
        self.assertTrue(isinstance(fill_parent_link, models.ForeignKey))
        self.assertEqual(fill_parent_link.rel.to, med_klass)

    def test_invalid_schemas(self):
        def cause_exception(doc):
            parser = SDML(doc)
            output = [obj for obj in parser.get_output()]

        for doc in INVALID_TEST_SDML_DOCS:
            self.assertRaises(SDMException, cause_exception, doc)

    def check_class_fields(self, klass, expected_fields):
        for field_name, field_class in expected_fields.iteritems():
            try:
                field = klass._meta.get_field(field_name)
            except FieldDoesNotExist:
                self.fail('SDML parsing did not produce field %s on class %s'%(field_name, klass.__name__))
            self.assertTrue(isinstance(field, field_class))
 def cause_exception(doc):
     parser = SDML(doc)
     output = [obj for obj in parser.get_output()]
 def setUp(self):
     super(SDMLUnitTests, self).setUp()
     self.instance = SDML(TEST_SDML_DOCS[0])
class SDMLUnitTests(InternalTests):
    def setUp(self):
        super(SDMLUnitTests, self).setUp()
        self.instance = SDML(TEST_SDML_DOCS[0])

    def tearDown(self):
        self.remove_model_from_cache('TestMedication2')
        self.remove_model_from_cache('TestPrescription2')
        self.remove_model_from_cache('TestFill2')
        self.instance = None
        super(SDMLUnitTests, self).tearDown()

    def test_get_output(self):
        output_classes = [obj for obj in self.instance.get_output()]
        self.assertEqual(len(output_classes),
                         3)  # Three models in the definition

        med_klass = scrip_klass = fill_klass = None
        for klass in output_classes:
            klass_name = klass.__name__
            if klass_name == 'TestMedication2':
                med_klass = klass
            elif klass_name == 'TestPrescription2':
                scrip_klass = klass
            elif klass_name == 'TestFill2':
                fill_klass = klass
            else:
                self.fail('SDML parsing produced an invalid class %s' %
                          klass_name)

        if not med_klass:
            self.fail('SDML parsing did not produce a TestMedication2 class')
        if not scrip_klass:
            self.fail('SDML parsing did not produce a TestPrescription2 class')
        if not fill_klass:
            self.fail('SDML parsing did not produce a TestFill2 class')

        # Make sure the testmedication2 class parsed as expected
        med_expected_fields = {
            'name': models.CharField,
            'date_started': models.DateTimeField,
            'date_stopped': models.DateTimeField,
            'brand_name': models.CharField,
            'route': models.CharField,
        }
        self.check_class_fields(med_klass, med_expected_fields)

        # The 'prescription' field should be a OneToOne field, pointing at TestPrescription2
        prescription_field = med_klass._meta.get_field('prescription')
        self.assertTrue(isinstance(prescription_field, models.OneToOneField))
        self.assertEqual(prescription_field.rel.to, scrip_klass)

        # The 'fills' field should be the reverse side of a ForeignKey from TestFill2 to TestMedication2
        fills_field = med_klass.fills
        self.assertTrue(
            isinstance(fills_field,
                       models.fields.related.ForeignRelatedObjectsDescriptor))
        self.assertEqual(fills_field.related.model, fill_klass)

        # Make sure the testprescription2 class parsed as expected
        scrip_expected_fields = {
            'prescribed_by_name': models.CharField,
            'prescribed_by_institution': models.CharField,
            'prescribed_on': models.DateTimeField,
            'prescribed_stop_on': models.DateTimeField,
        }
        self.check_class_fields(scrip_klass, scrip_expected_fields)

        # The TestPrescription2 model should have a 'testmedication2' field pointing to the Medication class
        # (the reverse link of the OneToOne from the TestMedication2)
        scrip_parent_link = scrip_klass.testmedication2
        self.assertTrue(
            isinstance(scrip_parent_link,
                       models.fields.related.SingleRelatedObjectDescriptor))
        self.assertEqual(scrip_parent_link.related.model, med_klass)

        # Make sure the testfill2 class parsed as expected
        fill_expected_fields = {
            'date_filled': models.DateField,
            'supply_days': models.FloatField,
            'filled_at_name': models.CharField,
            'code_identifier':
            models.CharField,  # CodedValues should be expanded
            'code_title': models.CharField,
            'code_system': models.CharField,
            'quantity_value':
            models.CharField,  # ValueAndUnit fields should be expanded
            'quantity_unit': models.CharField,
            'pharmacy_ncpdpid':
            models.CharField,  # Pharmacy fields should be expanded
            'pharmacy_org': models.CharField,
            'pharmacy_adr_country': models.
            CharField,  # Address fields should be expanded (recursively, from Pharmacy)
            'pharmacy_adr_city': models.CharField,
            'pharmacy_adr_postalcode': models.CharField,
            'pharmacy_adr_region': models.CharField,
            'pharmacy_adr_street': models.CharField,
            'prescriber_dea_number':
            models.CharField,  # Provider fields should be expanded
            'prescriber_ethnicity': models.CharField,
            'prescriber_npi_number': models.CharField,
            'prescriber_preferred_language': models.CharField,
            'prescriber_race': models.CharField,
            'prescriber_adr_country': models.
            CharField,  # Address fields should be expanded (recursively, from Prescriber)
            'prescriber_adr_city': models.CharField,
            'prescriber_adr_postalcode': models.CharField,
            'prescriber_adr_region': models.CharField,
            'prescriber_adr_street': models.CharField,
            'prescriber_bday': models.DateField,
            'prescriber_email': models.EmailField,
            'prescriber_name_family': models.
            CharField,  # Name fields should be expanded (recursively, from Prescriber)
            'prescriber_name_given': models.CharField,
            'prescriber_name_prefix': models.CharField,
            'prescriber_name_suffix': models.CharField,
            'prescriber_gender': models.CharField,
            'prescriber_tel_1_type': models.
            CharField,  # Telephone fields should be expanded (recursively, from Prescriber)
            'prescriber_tel_1_number': models.CharField,
            'prescriber_tel_1_preferred_p': models.BooleanField,
            'prescriber_tel_2_type': models.CharField,
            'prescriber_tel_2_number': models.CharField,
            'prescriber_tel_2_preferred_p': models.BooleanField,
        }
        self.check_class_fields(fill_klass, fill_expected_fields)

        # The TestFill2 model should have a ForeignKey field named 'testmedication2' pointing to the Medication class
        fill_parent_link = fill_klass._meta.get_field('testmedication2')
        self.assertTrue(isinstance(fill_parent_link, models.ForeignKey))
        self.assertEqual(fill_parent_link.rel.to, med_klass)

    def test_invalid_schemas(self):
        def cause_exception(doc):
            parser = SDML(doc)
            output = [obj for obj in parser.get_output()]

        for doc in INVALID_TEST_SDML_DOCS:
            self.assertRaises(SDMException, cause_exception, doc)

    def check_class_fields(self, klass, expected_fields):
        for field_name, field_class in expected_fields.iteritems():
            try:
                field = klass._meta.get_field(field_name)
            except FieldDoesNotExist:
                self.fail('SDML parsing did not produce field %s on class %s' %
                          (field_name, klass.__name__))
            self.assertTrue(isinstance(field, field_class))