Beispiel #1
0
class ExperimentParameter(models.Model):
    parameterset = models.ForeignKey(ExperimentParameterSet)
    name = models.ForeignKey(ParameterName)
    string_value = models.TextField(null=True, blank=True, db_index=True)
    numerical_value = models.FloatField(null=True, blank=True, db_index=True)
    datetime_value = models.DateTimeField(null=True, blank=True, db_index=True)
    objects = OracleSafeManager()

    def save(self, *args, **kwargs):
        super(ExperimentParameter, self).save(*args, **kwargs)
        try:
            from .hooks import publish_public_expt_rifcs
            publish_public_expt_rifcs(self.parameterset.experiment)
        except StandardError:
            logger.exception('')

    def get(self):
        return _getParameter(self)

    def __unicode__(self):
        return 'Experiment Param: %s=%s' % (self.name.name, self.get())

    class Meta:
        app_label = 'tardis_portal'
        ordering = ['name']
Beispiel #2
0
class Dataset(models.Model):
    """Class to link datasets to experiments

    :attribute experiment: a forign key to the
       :class:`tardis.tardis_portal.models.Experiment`
    :attribute description: description of this dataset
    """

    experiment = models.ForeignKey(Experiment)
    description = models.TextField(blank=True)
    immutable = models.BooleanField(default=False)
    objects = OracleSafeManager()

    def getParameterSets(self, schemaType=None):
        """Return the dataset parametersets associated with this
        experiment.

        """
        if schemaType == Schema.DATASET or schemaType is None:
            return self.datasetparameterset_set.filter(
                schema__type=Schema.DATASET)
        else:
            raise Schema.UnsupportedType

    def addDatafile(self,
                    filepath,
                    protocol='',
                    url='',
                    size=None,
                    commit=True):
        """Add Datafile helper function

        :param filepath: the file path within the repository
        :type filepath: string
        """
        full_file_path = path.join(settings.FILE_STORE_PATH,
                                   str(self.experiment.id), filepath)

        datafile = Dataset_File(dataset=self)
        datafile.filename = path.basename(filepath)
        if protocol:
            datafile.protocol = protocol

        if url:
            datafile.url = url
        else:
            datafile.url = 'file://' + filepath

        if size:
            datafile.size = size
        elif path.exists(full_file_path):
            datafile.size = path.getsize(full_file_path)

    def __unicode__(self):
        return self.description

    def get_absolute_filepath(self):
        return path.join(self.experiment.get_absolute_filepath(), str(self.id))
Beispiel #3
0
class Parameter(models.Model):
    name = models.ForeignKey(ParameterName)
    string_value = models.TextField(null=True, blank=True, db_index=True)
    numerical_value = models.FloatField(null=True, blank=True, db_index=True)
    datetime_value = models.DateTimeField(null=True, blank=True, db_index=True)
    objects = OracleSafeManager()
    parameter_type = 'Abstract'

    class Meta:
        abstract = True
        app_label = 'tardis_portal'
        ordering = ['name']

    def get(self):
        return _getParameter(self)

    def __unicode__(self):
        try:
            return '%s Param: %s=%s' % (self.parameter_type, self.name.name,
                                        self.get())
        except:
            return 'Unitialised %sParameter' % self.parameter_type

    def set_value(self, value):
        if self.name.isNumeric():
            self.numerical_value = float(value)
        elif self.name.isDateTime():
            if settings.USE_TZ and is_naive(value):
                value = make_aware(value, LOCAL_TZ)
            elif not settings.USE_TZ and is_aware(value):
                value = make_naive(value, LOCAL_TZ)
            self.datetime_value = value
        else:
            self.string_value = unicode(value)

    def _has_any_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False
        return self.parameterset

    def _has_view_perm(self, user_obj):
        return self._has_any_perm(user_obj)

    def _has_change_perm(self, user_obj):
        return self._has_any_perm(user_obj)

    def _has_delete_perm(self, user_obj):
        return self._has_any_perm(user_obj)
Beispiel #4
0
class DatasetParameter(models.Model):

    parameterset = models.ForeignKey(DatasetParameterSet)
    name = models.ForeignKey(ParameterName)
    string_value = models.TextField(null=True, blank=True, db_index=True)
    numerical_value = models.FloatField(null=True, blank=True, db_index=True)
    datetime_value = models.DateTimeField(null=True, blank=True, db_index=True)
    objects = OracleSafeManager()

    def get(self):
        return _getParameter(self)

    def __unicode__(self):
        return 'Dataset Param: %s=%s' % (self.name.name, self.get())

    class Meta:
        app_label = 'tardis_portal'
        ordering = ['name']
Beispiel #5
0
class DatafileParameter(models.Model):

    parameterset = models.ForeignKey(DatafileParameterSet)
    name = models.ForeignKey(ParameterName)
    string_value = models.TextField(null=True, blank=True, db_index=True)
    numerical_value = models.FloatField(null=True, blank=True, db_index=True)
    datetime_value = models.DateTimeField(null=True, blank=True, db_index=True)
    objects = OracleSafeManager()

    def get(self):
        return _getParameter(self)

    def getExpId(self):
        return self.parameterset.dataset_file.dataset.experiment.id

    def __unicode__(self):
        return 'Datafile Param: %s=%s' % (self.name.name, self.get())

    class Meta:
        ordering = ['name']
Beispiel #6
0
class Token(models.Model):

    token = models.CharField(max_length=30, unique=True)
    experiment = models.ForeignKey(Experiment)

    expiry_date = models.DateField(default=_token_expiry)

    user = models.ForeignKey(User)

    _TOKEN_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

    objects = OracleSafeManager()

    class Meta:
        app_label = 'tardis_portal'

    def __unicode__(self):
        return '%s %s' % (self.expiry_date, self.token)

    def _randomise_token(self):
        from random import choice
        self.token = ''.join(
            choice(self._TOKEN_CHARS) for _ in range(settings.TOKEN_LENGTH))

    def save_with_random_token(self):
        from django.db import IntegrityError

        if not self.user or not self.experiment:  # fail if success impossible
            self.save()

        for _ in range(30):  # 30 is an arbitrary number
            self._randomise_token()
            try:
                logger.debug(self.token)
                self.save()
            except IntegrityError as e:
                logger.debug(e)
                continue
            else:
                return
        logger.warning('failed to generate a random token')
        self.save()  # give up and raise the exception

    @models.permalink
    def get_absolute_url(self):
        return ('tardis.tardis_portal.views.token_login', (), {
            'token': self.token
        })

    def is_expired(self):
        import datetime as dt
        return self.expiry_date and self.expiry_date < dt.datetime.now().date()

    def _get_expiry_as_datetime(self):
        import datetime as dt
        exp = self.expiry_date
        return dt.datetime(exp.year, exp.month, exp.day, 23, 59, 59)

    @staticmethod
    def _tomorrow_4am():
        import datetime as dt
        today = dt.datetime.now().date()
        tomorrow = today + dt.timedelta(1)
        tomorrow_4am = dt.datetime(tomorrow.year, tomorrow.month, tomorrow.day,
                                   4)
        return tomorrow_4am

    def get_session_expiry(self):
        '''
            A token login should expire at the earlier of
            a) tomorrow at 4am
            b) the (end of) the token's expiry date

            It is the responsibility of token_auth to set the session expiry
        '''
        if self.is_expired():
            import datetime as dt
            return dt.datetime.now()

        expire_tomorrow_morning = self._tomorrow_4am()
        token_as_datetime = self._get_expiry_as_datetime()

        print expire_tomorrow_morning
        print token_as_datetime

        if expire_tomorrow_morning < token_as_datetime:
            return expire_tomorrow_morning
        else:
            return token_as_datetime
Beispiel #7
0
class Dataset(models.Model):
    """Class to link datasets to experiments

    :attribute experiment: a forign key to the
       :class:`tardis.tardis_portal.models.Experiment`
    :attribute description: description of this dataset
    """

    experiments = models.ManyToManyField(Experiment, related_name='datasets')
    description = models.TextField(blank=True)
    directory = DirectoryField(blank=True, null=True)
    immutable = models.BooleanField(default=False)
    objects = OracleSafeManager()

    class Meta:
        app_label = 'tardis_portal'
        ordering = ['-id']

    def getParameterSets(self, schemaType=None):
        """Return the dataset parametersets associated with this
        experiment.

        """
        from tardis.tardis_portal.models.parameters import Schema
        if schemaType == Schema.DATASET or schemaType is None:
            return self.datasetparameterset_set.filter(
                schema__type=Schema.DATASET)
        else:
            raise Schema.UnsupportedType

    def __unicode__(self):
        return self.description

    def get_first_experiment(self):
        return self.experiments.order_by('created_time')[:1].get()

    def get_path(self):
        return path.join(str(self.get_first_experiment().id), str(self.id))

    @models.permalink
    def get_absolute_url(self):
        """Return the absolute url to the current ``Dataset``"""
        return ('tardis.tardis_portal.views.view_dataset', (), {
            'dataset_id': self.id
        })

    @models.permalink
    def get_edit_url(self):
        """Return the absolute url to the edit view of the current
        ``Dataset``
        """
        return ('tardis.tardis_portal.views.edit_dataset', (self.id, ))

    def get_images(self):
        from .datafile import IMAGE_FILTER
        images = self.dataset_file_set.order_by('filename')\
                                      .filter(IMAGE_FILTER)
        return images

    def _get_image(self):
        try:
            return self.get_images()[0]
        except IndexError:
            return None

    image = property(_get_image)

    def get_thumbnail_url(self):
        if self.image is None:
            return None
        return reverse('tardis.tardis_portal.iiif.download_image',
                       kwargs={
                           'datafile_id': self.image.id,
                           'region': 'full',
                           'size': '100,',
                           'rotation': 0,
                           'quality': 'native',
                           'format': 'jpg'
                       })

    def get_size(self):
        from .datafile import Dataset_File
        return Dataset_File.sum_sizes(self.dataset_file_set)

    def _has_any_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False
        return self.experiments.all()

    def _has_view_perm(self, user_obj):
        return self._has_any_perm(user_obj)

    def _has_change_perm(self, user_obj):
        if self.immutable:
            return False
        return self._has_any_perm(user_obj)

    def _has_delete_perm(self, user_obj):
        if self.immutable:
            return False
        return self._has_any_perm(user_obj)
Beispiel #8
0
class Experiment(models.Model):
    """The ``Experiment`` model inherits from :class:`django.db.models.Model`

    :attribute url: **Undocumented**
    :attribute approved: **Undocumented**
    :attribute title: the title of the experiment.
    :attribute institution_name: the name of the institution who created
       the dataset.
    :attribute start_time: **Undocumented**
    :attribute end_time: **Undocumented**
    :attribute created_time: **Undocumented**
    :attribute handle: **Undocumented**
    :attribute public: **Undocumented**
    :attribute objects: default model manager
    :attribute safe: ACL aware model manager

    """
    url = models.URLField(verify_exists=False,
                          max_length=255,
                          null=True,
                          blank=True)
    approved = models.BooleanField()
    title = models.CharField(max_length=400)
    institution_name = models.CharField(max_length=400,
                                        default=settings.DEFAULT_INSTITUTION)
    description = models.TextField(blank=True)
    start_time = models.DateTimeField(null=True, blank=True)
    end_time = models.DateTimeField(null=True, blank=True)
    created_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
    created_by = models.ForeignKey(User)
    handle = models.TextField(null=True, blank=True)
    public = models.BooleanField()
    objects = OracleSafeManager()
    safe = ExperimentManager()  # The acl-aware specific manager.

    def save(self, *args, **kwargs):
        super(Experiment, self).save(*args, **kwargs)
        _publish_public_expt_rifcs(self)

    def getParameterSets(self, schemaType=None):
        """Return the experiment parametersets associated with this
        experiment.

        """
        if schemaType == Schema.EXPERIMENT or schemaType is None:
            return self.experimentparameterset_set.filter(
                schema__type=Schema.EXPERIMENT)
        else:
            raise Schema.UnsupportedType

    def __unicode__(self):
        return self.title

    def get_absolute_filepath(self):
        """Return the absolute storage path
        to the current ``Experiment``"""
        store = settings.FILE_STORE_PATH
        return path.join(store, str(self.id))

    def get_or_create_directory(self):
        dirname = path.join(settings.FILE_STORE_PATH, str(self.id))
        if not path.exists(dirname):
            from os import chmod, mkdir
            try:
                mkdir(dirname)
                chmod(dirname, 0770)
            except:
                dirname = None
        return dirname

    @models.permalink
    def get_absolute_url(self):
        """Return the absolute url to the current ``Experiment``"""
        return ('tardis.tardis_portal.views.view_experiment', (), {
            'experiment_id': self.id
        })

    @models.permalink
    def get_edit_url(self):
        """Return the absolute url to the edit view of the current
        ``Experiment``

        """
        return ('tardis.tardis_portal.views.edit_experiment', (), {
            'experiment_id': self.id
        })

    @models.permalink
    def get_create_token_url(self):
        """Return the absolute url to the create token view of the current
        ``Experiment``
        """
        return ('tardis.tardis_portal.views.create_token', (), {
            'experiment_id': self.id
        })

    def get_download_urls(self, comptype="zip"):
        urls = {}
        kwargs = {'experiment_id': self.id, 'comptype': comptype}
        distinct = Dataset_File.objects.filter(dataset__experiment=self.id)\
            .values('protocol').distinct()
        for key_value in distinct:
            protocol = key_value['protocol']
            if protocol in ['', 'tardis', 'file', 'http', 'https']:
                view = 'tardis.tardis_portal.download.download_experiment'
                if not '' in urls:
                    urls[''] = reverse(view, kwargs=kwargs)
            else:
                try:
                    for module in settings.DOWNLOAD_PROVIDERS:
                        if module[0] == protocol:
                            view = '%s.download_experiment' % module[1]
                            urls[protocol] = reverse(view, kwargs=kwargs)
                except AttributeError:
                    pass

        return urls
class Experiment(models.Model):
    """The ``Experiment`` model inherits from :class:`django.db.models.Model`

    :attribute url: **Undocumented**
    :attribute approved: **Undocumented**
    :attribute title: the title of the experiment.
    :attribute institution_name: the name of the institution who created
       the dataset.
    :attribute start_time: **Undocumented**
    :attribute end_time: **Undocumented**
    :attribute created_time: **Undocumented**
    :attribute handle: **Undocumented**
    :attribute public: **Undocumented**
    :attribute objects: default model manager
    :attribute safe: ACL aware model manager

    """

    PUBLIC_ACCESS_NONE = 1
    PUBLIC_ACCESS_METADATA = 50
    PUBLIC_ACCESS_FULL = 100

    PUBLIC_ACCESS_CHOICES = (
        (PUBLIC_ACCESS_NONE,        'No public access (hidden)'),
        (PUBLIC_ACCESS_METADATA,    'Metadata only (no data file access)'),
        (PUBLIC_ACCESS_FULL,        'Everything'),
    )

    url = models.URLField(verify_exists=False, max_length=255,
                          null=True, blank=True)
    approved = models.BooleanField()
    title = models.CharField(max_length=400)
    institution_name = models.CharField(max_length=400,
            default=settings.DEFAULT_INSTITUTION)
    description = models.TextField(blank=True)
    start_time = models.DateTimeField(null=True, blank=True)
    end_time = models.DateTimeField(null=True, blank=True)
    created_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
    created_by = models.ForeignKey(User)
    handle = models.TextField(null=True, blank=True)
    locked = models.BooleanField()
    public_access = \
        models.PositiveSmallIntegerField(choices=PUBLIC_ACCESS_CHOICES,
                                         null=False,
                                         default=PUBLIC_ACCESS_NONE)
    license = models.ForeignKey(License, #@ReservedAssignment
                                blank=True, null=True)
    objects = OracleSafeManager()
    safe = ExperimentManager()  # The acl-aware specific manager.

    class Meta:
        app_label = 'tardis_portal'

    def save(self, *args, **kwargs):
        super(Experiment, self).save(*args, **kwargs)
        from .hooks import publish_public_expt_rifcs
        publish_public_expt_rifcs(self)

    def getParameterSets(self, schemaType=None):
        """Return the experiment parametersets associated with this
        experiment.

        """
        from tardis.tardis_portal.models.parameters import Schema
        if schemaType == Schema.EXPERIMENT or schemaType is None:
            return self.experimentparameterset_set.filter(
                schema__type=Schema.EXPERIMENT)
        else:
            raise Schema.UnsupportedType

    def __unicode__(self):
        return self.title

    def get_or_create_directory(self):
        dirname = path.join(settings.FILE_STORE_PATH,
                            str(self.id))
        if not path.exists(dirname):
            from os import chmod, mkdir
            try:
                mkdir(dirname)
                chmod(dirname, 0770)
            except:
                dirname = None
        return dirname

    @models.permalink
    def get_absolute_url(self):
        """Return the absolute url to the current ``Experiment``"""
        return ('tardis.tardis_portal.views.view_experiment', (),
                {'experiment_id': self.id})

    @models.permalink
    def get_edit_url(self):
        """Return the absolute url to the edit view of the current
        ``Experiment``

        """
        return ('tardis.tardis_portal.views.edit_experiment', (),
                {'experiment_id': self.id})

    @models.permalink
    def get_create_token_url(self):
        """Return the absolute url to the create token view of the current
        ``Experiment``
        """
        return ('tardis.tardis_portal.views.create_token', (),
                {'experiment_id': self.id})

    def get_datafiles(self):
        from .datafile import Dataset_File
        return Dataset_File.objects.filter(dataset__experiments=self)

    def get_download_urls(self):
        from .datafile import Dataset_File
        urls = {}
        params = (('experiment_id', self.id),)
        protocols = frozenset(self.get_datafiles()\
                                  .values_list('protocol', flat=True)\
                                  .distinct())
        # Get built-in download links
        local_protocols = frozenset(('', 'tardis', 'file', 'http', 'https'))
        if any(p in protocols for p in local_protocols):
            view = 'tardis.tardis_portal.download.download_experiment'
            for comptype in ['tar', 'zip']:
                kwargs = dict(params+(('comptype', comptype),))
                urls[comptype] = reverse(view, kwargs=kwargs)

        # Get links from download providers
        for protocol in protocols - local_protocols:
            try:
                for module in settings.DOWNLOAD_PROVIDERS:
                    if module[0] == protocol:
                        view = '%s.download_experiment' % module[1]
                        urls[protocol] = reverse(view, kwargs=dict(params))
            except AttributeError:
                pass

        return urls

    def get_images(self):
        from .datafile import IMAGE_FILTER
        return self.get_datafiles().order_by('-modification_time',
                                              '-created_time') \
                                   .filter(IMAGE_FILTER)

    def get_size(self):
        from .datafile import Dataset_File
        return Dataset_File.sum_sizes(self.get_datafiles())

    @classmethod
    def public_access_implies_distribution(cls, public_access_level):
        '''
        Determines if a level of public access implies that distribution should
        be allowed, or alternately if it should not be allowed. Used to
        prevent free-distribution licences for essentially private data, and
        overly-restrictive licences for public data.
        '''
        return public_access_level > cls.PUBLIC_ACCESS_METADATA

    def get_owners(self):
        acls = ExperimentACL.objects.filter(pluginId='django_user',
                                            experiment=self,
                                            isOwner=True)
        return [acl.get_related_object() for acl in acls]
Beispiel #10
0
class Dataset(models.Model):
    """Class to link datasets to experiments

    :attribute experiment: a forign key to the
       :class:`tardis.tardis_portal.models.Experiment`
    :attribute description: description of this dataset
    """

    experiments = models.ManyToManyField(Experiment, related_name='datasets')
    description = models.TextField(blank=True)
    immutable = models.BooleanField(default=False)
    objects = OracleSafeManager()

    class Meta:
        app_label = 'tardis_portal'

    def getParameterSets(self, schemaType=None):
        """Return the dataset parametersets associated with this
        experiment.

        """
        from tardis.tardis_portal.models.parameters import Schema
        if schemaType == Schema.DATASET or schemaType is None:
            return self.datasetparameterset_set.filter(
                schema__type=Schema.DATASET)
        else:
            raise Schema.UnsupportedType

    def __unicode__(self):
        return self.description

    def get_first_experiment(self):
        return self.experiments.order_by('created_time')[:1].get()

    @models.permalink
    def get_absolute_url(self):
        """Return the absolute url to the current ``Dataset``"""
        return ('tardis.tardis_portal.views.view_dataset', (), {
            'dataset_id': self.id
        })

    @models.permalink
    def get_edit_url(self):
        """Return the absolute url to the edit view of the current
        ``Dataset``
        """
        return ('tardis.tardis_portal.views.edit_dataset', (self.id, ))

    def get_images(self):
        from .datafile import IMAGE_FILTER
        images = self.dataset_file_set.order_by('-modification_time',
                                               '-created_time')\
                                      .filter(IMAGE_FILTER)
        return images

    def _get_image(self):
        try:
            return self.get_images()[0]
        except IndexError:
            return None

    image = property(_get_image)

    def get_size(self):
        from .datafile import Dataset_File
        return Dataset_File.sum_sizes(self.dataset_file_set)
Beispiel #11
0
class Dataset(models.Model):
    """Class to link datasets to experiments

    :attribute experiment: a forign key to the
       :class:`tardis.tardis_portal.models.Experiment`
    :attribute facility: the foreign key to the facility that generated
        this data
    :attribute instrument: the foreign key to the instrument that generated
        this data
    :attribute description: description of this dataset
    """

    experiments = models.ManyToManyField(Experiment, related_name='datasets')
    description = models.TextField(blank=True)
    directory = models.CharField(blank=True, null=True, max_length=255)
    immutable = models.BooleanField(default=False)
    instrument = models.ForeignKey(Instrument, null=True, blank=True)
    objects = OracleSafeManager()

    class Meta:
        app_label = 'tardis_portal'
        ordering = ['-id']

    @property
    def is_online(self):
        return all(df.is_online for df in self.datafile_set.all())

    def getParameterSets(self, schemaType=None):
        """Return the dataset parametersets associated with this
        experiment.

        """
        from tardis.tardis_portal.models.parameters import Schema
        if schemaType == Schema.DATASET or schemaType is None:
            return self.datasetparameterset_set.filter(
                schema__type=Schema.DATASET)
        else:
            raise Schema.UnsupportedType

    def __unicode__(self):
        return self.description

    def get_first_experiment(self):
        return self.experiments.order_by('created_time')[:1].get()

    def get_path(self):
        return path.join(str(self.get_first_experiment().id), str(self.id))

    def get_datafiles(self):
        from .datafile import DataFile
        return DataFile.objects.filter(dataset=self)

    @models.permalink
    def get_absolute_url(self):
        """Return the absolute url to the current ``Dataset``"""
        return ('tardis_portal.view_dataset', (), {'dataset_id': self.id})

    def get_download_urls(self):
        view = 'tardis.tardis_portal.download.streaming_download_' \
               'dataset'
        urls = {}
        for comptype in getattr(settings, 'DEFAULT_ARCHIVE_FORMATS',
                                ['tgz', 'tar']):
            urls[comptype] = reverse(view,
                                     kwargs={
                                         'dataset_id': self.id,
                                         'comptype': comptype
                                     })

        return urls

    @models.permalink
    def get_edit_url(self):
        """Return the absolute url to the edit view of the current
        ``Dataset``
        """
        return ('tardis.tardis_portal.views.edit_dataset', (self.id, ))

    def get_images(self):
        from .datafile import IMAGE_FILTER
        return self.datafile_set.order_by('filename').filter(IMAGE_FILTER)

    def _get_image(self):
        try:
            return self.get_images()[0]
        except IndexError:
            return None

    image = property(_get_image)

    def get_thumbnail_url(self):
        if self.image is None:
            return None
        return reverse('tardis.tardis_portal.iiif.download_image',
                       kwargs={
                           'datafile_id': self.image.id,
                           'region': 'full',
                           'size': '100,',
                           'rotation': 0,
                           'quality': 'native',
                           'format': 'jpg'
                       })

    def get_size(self):
        from .datafile import DataFile
        return DataFile.sum_sizes(self.datafile_set)

    def _has_any_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False
        return self.experiments.all()

    def _has_view_perm(self, user_obj):
        return self._has_any_perm(user_obj)

    def _has_change_perm(self, user_obj):
        if self.immutable:
            return False
        return self._has_any_perm(user_obj)

    def _has_delete_perm(self, user_obj):
        if self.immutable:
            return False
        return self._has_any_perm(user_obj)

    def get_all_storage_boxes_used(self):
        boxes = StorageBox.objects.filter(file_objects__datafile__dataset=self)
        return boxes
Beispiel #12
0
class Experiment(models.Model):
    """The ``Experiment`` model inherits from :class:`django.db.models.Model`

    :attribute url: **Undocumented**
    :attribute approved: **Undocumented**
    :attribute title: the title of the experiment.
    :attribute institution_name: the name of the institution who created
       the dataset.
    :attribute start_time: **Undocumented**
    :attribute end_time: **Undocumented**
    :attribute created_time: **Undocumented**
    :attribute handle: **Undocumented**
    :attribute public: **Undocumented**
    :attribute objects: default model manager
    :attribute safe: ACL aware model manager

    """

    PUBLIC_ACCESS_NONE = 1
    PUBLIC_ACCESS_EMBARGO = 25
    PUBLIC_ACCESS_METADATA = 50
    PUBLIC_ACCESS_FULL = 100

    PUBLIC_ACCESS_CHOICES = (
        (PUBLIC_ACCESS_NONE, 'No public access (hidden)'),
        (PUBLIC_ACCESS_EMBARGO, 'Ready to be released pending embargo expiry'),
        (PUBLIC_ACCESS_METADATA, 'Public Metadata only (no data file access)'),
        (PUBLIC_ACCESS_FULL, 'Public'),
    )

    PUBLICATION_SCHEMA_ROOT = 'http://www.tardis.edu.au/schemas/publication/'
    PUBLICATION_DETAILS_SCHEMA = PUBLICATION_SCHEMA_ROOT + 'details/'
    PUBLICATION_DRAFT_SCHEMA = PUBLICATION_SCHEMA_ROOT + 'draft/'

    url = models.URLField(max_length=255, null=True, blank=True)
    approved = models.BooleanField(default=False)
    title = models.CharField(max_length=400)
    institution_name = models.CharField(max_length=400,
                                        default=settings.DEFAULT_INSTITUTION)
    description = models.TextField(blank=True)
    start_time = models.DateTimeField(null=True, blank=True)
    end_time = models.DateTimeField(null=True, blank=True)
    created_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
    created_by = models.ForeignKey(User)
    handle = models.TextField(null=True, blank=True)
    locked = models.BooleanField(default=False)
    public_access = \
        models.PositiveSmallIntegerField(choices=PUBLIC_ACCESS_CHOICES,
                                         null=False,
                                         default=PUBLIC_ACCESS_NONE)
    license = models.ForeignKey(
        License,  # @ReservedAssignment
        blank=True,
        null=True)
    objectacls = GenericRelation(ObjectACL)
    objects = OracleSafeManager()
    safe = ExperimentManager()  # The acl-aware specific manager.

    class Meta:
        app_label = 'tardis_portal'

    def save(self, *args, **kwargs):
        super(Experiment, self).save(*args, **kwargs)
        from .hooks import publish_public_expt_rifcs
        publish_public_expt_rifcs(self)

    def is_publication_draft(self):
        return self.experimentparameterset_set.filter(
            schema__namespace=getattr(
                settings, 'PUBLICATION_DRAFT_SCHEMA',
                self.PUBLICATION_DRAFT_SCHEMA)).count() > 0

    def is_publication(self):
        return self.experimentparameterset_set.filter(
            schema__namespace__startswith=getattr(
                settings, 'PUBLICATION_SCHEMA_ROOT',
                self.PUBLICATION_SCHEMA_ROOT)).count() > 0

    def getParameterSets(self, schemaType=None):
        """Return the experiment parametersets associated with this
        experiment.

        """
        from tardis.tardis_portal.models.parameters import Schema
        if schemaType == Schema.EXPERIMENT or schemaType is None:
            return self.experimentparameterset_set.filter(
                schema__type=Schema.EXPERIMENT)
        else:
            raise Schema.UnsupportedType

    def __unicode__(self):
        return self.title

    def get_or_create_directory(self):
        dirname = path.join(settings.FILE_STORE_PATH, str(self.id))
        if not path.exists(dirname):
            from os import chmod, mkdir
            try:
                mkdir(dirname)
                chmod(dirname, 0770)
            except:
                dirname = None
        return dirname

    @models.permalink
    def get_absolute_url(self):
        """Return the absolute url to the current ``Experiment``"""
        return ('tardis_portal.view_experiment', (), {
            'experiment_id': self.id
        })

    @models.permalink
    def get_edit_url(self):
        """Return the absolute url to the edit view of the current
        ``Experiment``

        """
        return ('tardis.tardis_portal.views.edit_experiment', (), {
            'experiment_id': self.id
        })

    @models.permalink
    def get_create_token_url(self):
        """Return the absolute url to the create token view of the current
        ``Experiment``
        """
        return ('tardis.tardis_portal.views.create_token', (), {
            'experiment_id': self.id
        })

    def get_datafiles(self):
        from .datafile import DataFile
        return DataFile.objects.filter(dataset__experiments=self)

    def get_download_urls(self):
        urls = {}
        view = 'tardis.tardis_portal.download.streaming_download_experiment'
        for comptype in getattr(settings, 'DEFAULT_ARCHIVE_FORMATS',
                                ['tgz', 'tar']):
            urls[comptype] = reverse(view,
                                     kwargs={
                                         'experiment_id': self.id,
                                         'comptype': comptype
                                     })

        return urls

    def get_images(self):
        from .datafile import IMAGE_FILTER
        return self.get_datafiles().order_by('-modification_time',
                                             '-created_time') \
            .filter(IMAGE_FILTER)

    def get_size(self):
        from .datafile import DataFile
        return DataFile.sum_sizes(self.get_datafiles())

    @classmethod
    def public_access_implies_distribution(cls, public_access_level):
        '''
        Determines if a level of public access implies that distribution should
        be allowed, or alternately if it should not be allowed. Used to
        prevent free-distribution licences for essentially private data, and
        overly-restrictive licences for public data.
        '''
        return public_access_level > cls.PUBLIC_ACCESS_METADATA

    def public_download_allowed(self):
        '''
        instance method version of 'public_access_implies_distribution'
        '''
        return self.public_access > Experiment.PUBLIC_ACCESS_METADATA

    def get_ct(self):
        return ContentType.objects.get_for_model(self)

    def get_owners(self):
        acls = ObjectACL.objects.filter(pluginId='django_user',
                                        content_type=self.get_ct(),
                                        object_id=self.id,
                                        isOwner=True)
        return [acl.get_related_object() for acl in acls]

    def get_groups(self):
        acls = ObjectACL.objects.filter(pluginId='django_group',
                                        content_type=self.get_ct(),
                                        object_id=self.id,
                                        canRead=True)
        return [acl.get_related_object() for acl in acls]

    def _has_view_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False

        if self.public_access >= self.PUBLIC_ACCESS_METADATA:
            return True

    def _has_change_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False

        if self.locked:
            return False

        return None

    def _has_delete_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False

        return None
Beispiel #13
0
class Parameter(models.Model):
    name = models.ForeignKey(ParameterName)
    # string_value has a custom index created via migrations (for Postgresql)
    string_value = models.TextField(null=True, blank=True)
    numerical_value = models.FloatField(null=True, blank=True, db_index=True)
    datetime_value = models.DateTimeField(null=True, blank=True, db_index=True)
    link_id = models.PositiveIntegerField(null=True, blank=True)
    link_ct = models.ForeignKey(ContentType, null=True, blank=True)
    link_gfk = GenericForeignKey('link_ct', 'link_id')
    objects = OracleSafeManager()
    parameter_type = 'Abstract'

    class Meta:
        abstract = True
        app_label = 'tardis_portal'
        ordering = ['name']

    def get(self):
        return _get_parameter(self)

    def __unicode__(self):
        try:
            return '%s Param: %s=%s' % (self.parameter_type, self.name.name,
                                        self.get())
        except:
            return 'Unitialised %sParameter' % self.parameter_type

    @property
    def link_url(self):
        if not self.name.isLink():
            return None
        if isinstance(self.link_gfk, DataFile):
            url = reverse('tardis_portal.view_dataset',
                          kwargs={'dataset_id': self.link_gfk.dataset.id})
        elif isinstance(self.link_gfk, Dataset):
            url = reverse('tardis_portal.view_dataset',
                          kwargs={'dataset_id': self.link_id})
        elif isinstance(self.link_gfk, Experiment):
            url = reverse('tardis_portal.view_experiment',
                          kwargs={'experiment_id': self.link_id})
        elif self.link_gfk is None and self.string_value:
            url = self.string_value
        else:
            raise NotImplementedError
        return url

    def set_value(self, value):
        """
        Sets the parameter value, converting into the appropriate data type.
        Deals with date/time strings that are timezone naive or aware, based
        on the USE_TZ setting.

        :param basestring value: a string (or string-like) repr of the value
        :raises SuspiciousOperation:
        """
        if self.name.isNumeric():
            self.numerical_value = float(value)
        elif self.name.isDateTime():
            # We convert the value string into datetime object.
            # dateutil.parser detects and converts many date formats and is
            # quite permissive in what it accepts (form validation and API
            # input validation happens elsewhere and may be less permissive)
            datevalue = dateutil.parser.parse(value)
            if settings.USE_TZ and is_naive(datevalue):
                datevalue = make_aware(datevalue, LOCAL_TZ)
            elif not settings.USE_TZ and is_aware(datevalue):
                datevalue = make_naive(datevalue, LOCAL_TZ)
            self.datetime_value = datevalue
        elif self.name.isLink():
            # Always store the raw value as a string, even if setting
            # the GenericForeignKey via link_id/link_ct
            if str(value) == '' or value is None:
                return
            self.string_value = unicode(value)

            try:
                # We detect experiment or dataset view URLs
                # (eg, /experiment/view/12345/ or /api/v1/dataset/456)
                # and extract values to populate link_ct and link_id. This
                # covers two common cases, allowing LINK Parameters to be
                # properly created via the REST API.

                match = resolve(value)
                if match.view_name == u'api_dispatch_detail':
                    model_name = match.kwargs.get(u'resource_name', None)
                    if model_name not in ('experiment', 'dataset'):
                        model_name, pk = None, None
                    else:
                        pk = match.kwargs.get('pk', None)
                elif match.view_name.endswith('view_experiment'):
                    model_name = 'experiment'
                    pk = match.kwargs.get('experiment_id')
                elif match.view_name.endswith('view_dataset'):
                    model_name = 'dataset'
                    pk = match.kwargs.get('dataset_id')
                else:
                    model_name, pk = None, None

                if pk is not None and model_name is not None:
                    self.link_id = pk
                    self.link_ct = ContentType.objects.get(
                        app_label='tardis_portal', model=model_name.lower())
            except (ValueError, IndexError, Resolver404):
                # If we were unable to successfully match the url to model
                # instance, return an error. For any URL the URL Parameter
                # type should be used.
                raise SuspiciousOperation('Link parameter could not be set '
                                          'from string: %s' % str(value))
        else:
            self.string_value = unicode(value)

    def _has_any_perm(self, user_obj):
        if not hasattr(self, 'id'):
            return False
        return self.parameterset

    def _has_view_perm(self, user_obj):
        return self._has_any_perm(user_obj)

    def _has_change_perm(self, user_obj):
        return self._has_any_perm(user_obj)

    def _has_delete_perm(self, user_obj):
        return self._has_any_perm(user_obj)