def _update_calculated(self, replace_id, dataset_id):
        """Update the calculated dataset properties (dataset_id) from the specified 
        dataset (replace_id).
        Any existing calculated properties are left unchanged."""
        # Look up the two datasets, exit on dataset not found
        try:
            data_set = DataSet.objects.get(pk=dataset_id)
        except DataSet.DoesNotExist:
            raise CommandError("DataSet not found: %s\n" % dataset_id)
        try:
            replace_set = DataSet.objects.get(pk=replace_id)
        except DataSet.DoesNotExist:
            raise CommandError("DataSet not found: %s\n" % replace_id)

        #
        # Copy the properties from the replacement set in to the target set
        #
        # We can't simply delete the old properties and replace due to the
        # default filter foreign key from the DataSet.
        #
        # Iterate over all the properties one by one and update the target
        # dataset properties.
        #
        properties = DataSetProperty.objects.filter(dataset=replace_set, is_computed=True)
        i = 0
        for source_prop in properties:
            prop_id = source_prop.name
            existing_prop = DataSetProperty.objects.filter(dataset=data_set, name=prop_id)
            if len(existing_prop) == 1:
                existing_prop = existing_prop[0]
            elif len(existing_prop) == 0:
                existing_prop = DataSetProperty(dataset=data_set)
            else:
                raise CommandError("Multiple properties found - should never get here")
            for field in source_prop._meta.fields:
                # Don't copy relations or the primary key
                if field.primary_key:
                    continue
                if field.rel is not None:
                    continue
                if int(self._options["verbosity"]) > 1:
                    print (
                        u"Set {name} from {old} to {new}".format(
                            name=field.name,
                            old=getattr(existing_prop, field.name),
                            new=getattr(source_prop, field.name),
                        )
                    )
                setattr(existing_prop, field.name, getattr(source_prop, field.name))
            existing_prop.save()
            i += 1
        print (
            "Replaced {i} properties from {replace} to {dest}".format(i=i, replace=str(replace_set), dest=str(data_set))
        )
        return
    def _load_properties(self, data_set, xml_filename):
        """Replace the existing properties for the nominated dataset."""
        # Delete the existing properties
        properties = DataSetProperty.objects.filter(dataset=data_set)
        properties.delete()

        # Iterate over the supplied file and load the new properties
        tree = ET.ElementTree(file=xml_filename)
        fields = tree.getroot().find("properties")
        for field in fields:
            data_type_name = field.attrib.get("Type", None)
            data_type = DataSetProperty.data_type_enum(data_type_name)
            label = field.text
            field_name = field.attrib.get("DBFieldName", label)
            is_computed = field.attrib.get("IsComputedField", False)
            is_filter = field.attrib.get("IsFilterField", True)
            is_output = field.attrib.get("IsOutputField", True)
            description = field.attrib.get("FieldDesc", "")
            units = field.attrib.get("Units", "")
            if int(self._options["verbosity"]) >= 2:
                print ("Adding {field}...".format(field=field_name))
            new_property = DataSetProperty(
                dataset=data_set,
                name=field_name,
                label=label,
                data_type=data_type,
                units=units,
                is_computed=is_computed,
                is_filter=is_filter,
                is_output=is_output,
                description=description,
            )
            new_property.save()

        snapshots = Snapshot.objects.filter(dataset=data_set)
        snapshots.delete()

        redshifts = tree.getroot().find("snapshots")
        if redshifts is None:
            # redshifts are optional
            redshifts = []
        for redshift in redshifts:
            value = redshift.text
            new_redshift = Snapshot(dataset=data_set, redshift=value)
            new_redshift.save()
    def _replace_properties(self, replace_properties, dataset_id):
        """Replace the dataset properties (dataset_id) from the specified 
        dataset (replace_properties)"""
        # Look up the two datasets, exit on dataset not found
        try:
            data_set = DataSet.objects.get(pk=dataset_id)
        except DataSet.DoesNotExist:
            raise CommandError("DataSet not found: %s\n" % dataset_id)
        try:
            replace_set = DataSet.objects.get(pk=replace_properties)
        except DataSet.DoesNotExist:
            raise CommandError("DataSet not found: %s\n" % replace_properties)

        #
        # Copy the properties from the replacement set in to the target set
        #
        # We can't simply delete the old properties and replace due to the
        # default filter foreign key from the DataSet.
        #
        # Iterate over all the properties one by one and update the target
        # dataset properties.  Then delete any missed properties, as long
        # as they aren't part of the default filter.
        #
        properties = DataSetProperty.objects.filter(dataset=replace_set)
        existing_properties = DataSetProperty.objects.filter(dataset=data_set)
        existing_properties = [x.id for x in existing_properties]
        i = 0
        for source_prop in properties:
            prop_id = source_prop.name
            existing_prop = DataSetProperty.objects.filter(dataset=data_set, name=prop_id)
            if len(existing_prop) == 1:
                existing_prop = existing_prop[0]
                # Mark the property as processed
                existing_properties.remove(existing_prop.id)
            elif len(existing_prop) == 0:
                existing_prop = DataSetProperty(dataset=data_set)
            else:
                raise CommandError("Multiple properties found - should never get here")
            for field in source_prop._meta.fields:
                # Don't copy relations or the primary key
                if field.primary_key:
                    continue
                if field.rel is not None:
                    continue
                if int(self._options["verbosity"]) > 1:
                    print (
                        u"Set {name} from {old} to {new}".format(
                            name=field.name,
                            old=getattr(existing_prop, field.name),
                            new=getattr(source_prop, field.name),
                        )
                    )
                setattr(existing_prop, field.name, getattr(source_prop, field.name))
            existing_prop.save()
            i += 1
        print (
            "Replaced {i} properties from {replace} to {dest}".format(i=i, replace=str(replace_set), dest=str(data_set))
        )
        #
        # Delete any remaining properties from the target dataset.
        # If the property is a default filter, notify the user and
        # remove the filter
        #
        for id in existing_properties:
            prop = DataSetProperty.objects.get(pk=id)
            filters = DataSet.objects.filter(default_filter_field=prop)
            if len(filters) > 0:
                print ("Untested...")
                import pdb

                pdb.set_trace()
                for filter in filters:
                    print (u"Clearing default filter in: {0}".format(str(filter)))
                    filter.default_filter_field = None
                    filter.save()
            print ("Deleting old property: {0}".format(str(prop)))
            prop.delete()