예제 #1
0
def _build_dynamic_choice_list_filter(spec, report):
    wrapped = DynamicChoiceListFilterSpec.wrap(spec)
    choice_provider_spec = wrapped.get_choice_provider_spec()
    choice_provider = FilterChoiceProviderFactory.from_spec(
        choice_provider_spec)(report, wrapped.slug)
    choice_provider.configure(choice_provider_spec)

    invalid_spec = (wrapped.ancestor_expression and not set(
        wrapped.ancestor_expression.keys()) == set(['field', 'location_type']))
    if invalid_spec:
        raise BadSpecError(
            _("'ancestor_expression' must be empty dictionary or have 'field', 'location_type' keys"
              ))

    if wrapped.ancestor_expression and not isinstance(choice_provider,
                                                      LocationChoiceProvider):
        raise BadSpecError(
            _("'ancestor_expression' is applicable only for location choices"))

    return DynamicChoiceListFilter(
        name=wrapped.slug,
        datatype=wrapped.datatype,
        field=wrapped.field,
        label=wrapped.display,
        show_all=wrapped.show_all,
        url_generator=dynamic_choice_list_url,
        choice_provider=choice_provider,
        ancestor_expression=wrapped.ancestor_expression,
    )
예제 #2
0
 def validate_spec(self, spec):
     if 'type' not in spec:
         raise BadSpecError(
             _('Indicator specification must include a root level type field.'
               ))
     elif spec['type'] not in self.constructor_map:
         raise BadSpecError(
             _('Illegal indicator type: "{0}", must be one of the following choice: ({1})'
               .format(spec['type'], ', '.join(self.constructor_map))))
예제 #3
0
 def get_whens(self):
     whens = []
     for value, bounds in self.ranges.items():
         if len(bounds) != 2:
             raise BadSpecError('Range must contain 2 items, contains {}'.format(len(bounds)))
         try:
             bounds = [int(b) for b in bounds]
         except ValueError:
             raise BadSpecError('Invalid range: [{}, {}]'.format(bounds[0], bounds[1]))
         whens.append([self._base_expression(bounds), bindparam(None, value)])
     return whens
예제 #4
0
 def from_spec(cls, spec):
     if spec.get('type') not in cls.spec_map:
         raise BadSpecError(_('Illegal chart type: {0}, must be one of the following choice: ({1})').format(
             spec.get('type', _('(missing from spec)')),
             ', '.join(cls.spec_map)
         ))
     try:
         return cls.spec_map[spec['type']].wrap(spec)
     except BadValueError as e:
         raise BadSpecError(_('Problem creating chart from spec: {}, message is: {}').format(
             json.dumps(spec, indent=2),
             str(e),
         ))
예제 #5
0
 def from_spec(cls, spec, context=None):
     try:
         return cls.spec_map[spec['type']](spec, context)
     except KeyError:
         raise BadSpecError(_('Invalid or missing getter type: {}. Valid options are: {}').format(
             spec.get('type', '[missing]'),
             ', '.join(cls.spec_map.keys()),
         ))
     except BadValueError as e:
         raise BadSpecError(_('Problem creating getter: {}. Message is: {}').format(
             json.dumps(spec, indent=2),
             str(e),
         ))
예제 #6
0
 def get_transform(cls, spec):
     try:
         return cls.spec_map[spec['type']].wrap(spec)
     except KeyError:
         raise BadSpecError(_('Invalid or missing transform type: {}. Valid options are: {}').format(
             spec.get('type', None),
             ', '.join(cls.spec_map.keys()),
         ))
     except BadValueError as e:
         raise BadSpecError(_('Problem creating transform: {}. Message is: {}').format(
             json.dumps(spec, indent=2),
             str(e),
         ))
예제 #7
0
    def validate_db_config(self):
        mirrored_engine_ids = self.mirrored_engine_ids
        if not mirrored_engine_ids:
            return
        if self.engine_id in mirrored_engine_ids:
            raise BadSpecError("mirrored_engine_ids list should not contain engine_id")

        for engine_id in mirrored_engine_ids:
            if not connection_manager.engine_id_is_available(engine_id):
                raise BadSpecError(
                    "DB for engine_id {} is not availble".format(engine_id)
                )

        if not connection_manager.resolves_to_unique_dbs(mirrored_engine_ids + [self.engine_id]):
            raise BadSpecError("No two engine_ids should point to the same database")
예제 #8
0
 def from_spec(cls, spec):
     column_type = spec.get('type') or 'field'
     if column_type not in cls.class_map:
         raise BadSpecError(
             'Unknown or missing column type: {} must be in [{}]'.format(
                 column_type, ', '.join(cls.class_map)))
     try:
         return cls.class_map[column_type].wrap(spec)
     except BadValueError as e:
         raise BadSpecError(
             _('Problem creating column from spec: {}, message is: {}').
             format(
                 json.dumps(spec, indent=2),
                 str(e),
             ))
예제 #9
0
def _build_compound_filter(spec, context):
    compound_type_map = {
        'or': ORFilter,
        'and': ANDFilter,
    }
    if spec['type'] not in compound_type_map:
        raise BadSpecError(_('Complex filter type {0} must be one of the following choices ({1})').format(
            spec['type'],
            ', '.join(compound_type_map)
        ))
    elif not isinstance(spec.get('filters'), list):
        raise BadSpecError(_('{0} filter type must include a "filters" list'.format(spec['type'])))

    filters = [FilterFactory.from_spec(subspec, context) for subspec in spec['filters']]
    return compound_type_map[spec['type']](filters)
예제 #10
0
    def by_id(cls, config_id, domain=None):
        """
        Returns a ReportConfiguration object, NOT StaticReportConfigurations.

        :param domain: Optionally specify domain name to validate access.
                       Raises ``DocumentNotFound`` if domains don't match.
        """
        mapping = cls.by_id_mapping()
        if config_id not in mapping:
            mapping = cls.by_id_mapping(rebuild=True)

        metadata = mapping.get(config_id, None)
        if not metadata:
            raise BadSpecError(
                _('The report configuration referenced by this report could '
                  'not be found.'))

        config = cls._get_from_metadata(metadata)
        if domain and config.domain != domain:
            raise DocumentNotFound(
                "Document {} of class {} not in domain {}!".format(
                    config_id,
                    config.__class__.__name__,
                    domain,
                ))
        return config
예제 #11
0
 def from_spec(cls, spec, context=None):
     cls.validate_spec(spec)
     try:
         return cls.constructor_map[spec['type']](spec, context)
     except BadValueError as e:
         # for now reraise jsonobject exceptions as BadSpecErrors
         raise BadSpecError(str(e))
예제 #12
0
 def wrap(self, obj):
     if 'constant' not in obj:
         raise BadSpecError(
             '"constant" property is required in object beginning with <pre>{}</pre>'
             .format(textwrap.shorten(str(obj), width=75,
                                      placeholder="...")))
     return super(ConstantGetterSpec, self).wrap(obj)
예제 #13
0
 def from_spec(cls, spec):
     column_type = spec.get('type') or 'field'
     if column_type not in cls.class_map:
         raise BadSpecError(
             'Unknown or missing column type: {} must be in [{}]'.format(
                 column_type, ', '.join(cls.class_map.keys())))
     return cls.class_map[column_type].wrap(spec)
예제 #14
0
파일: specs.py 프로젝트: ye-man/commcare-hq
 def configure(self, compiled_properties):
     for key in compiled_properties:
         if not isinstance(key, (six.text_type, bytes)):
             raise BadSpecError("Properties in a dict expression must be strings!")
         if six.PY3:
             soft_assert_type_text(key)
     self._compiled_properties = compiled_properties
예제 #15
0
 def validate_spec(cls, spec):
     if spec.get('type') not in cls.constructor_map:
         raise BadSpecError(
             _('Illegal report filter type: {0}, must be one of the following choice: ({1})').format(
                 spec.get('type', _('(missing from spec)')),
                 ', '.join(cls.constructor_map.keys())
             )
         )
예제 #16
0
 def from_spec(cls, spec, context=None):
     if _is_literal(spec):
         return cls.from_spec(_convert_constant_to_expression_spec(spec), context)
     try:
         return cls.spec_map[spec['type']](spec, context)
     except KeyError:
         raise BadSpecError(_('Invalid or missing getter type: {} for expression: {}. '
                              'Valid options are: {}').format(
             spec.get('type', '[missing]'),
             spec,
             ', '.join(cls.spec_map.keys()),
         ))
     except (TypeError, BadValueError) as e:
         raise BadSpecError(_('Problem creating getter: {}. Message is: {}').format(
             json.dumps(spec, indent=2, default=json_handler),
             str(e),
         ))
예제 #17
0
 def validate_spec(self, spec):
     if spec.get('type') not in self.constructor_map:
         raise BadSpecError(
             _('Illegal or missing filter type: "{0}", must be one of the following choice: ({1})'.format(
                 spec.get('type'),
                 ', '.join(self.constructor_map)
             ))
         )
예제 #18
0
 def report_class_by_domain_and_id(cls, domain, config_id):
     for wrapped, path in cls._all():
         if cls.get_doc_id(domain, wrapped.report_id,
                           wrapped.custom_configurable_report) == config_id:
             return wrapped.custom_configurable_report
     raise BadSpecError(
         _('The report configuration referenced by this report could '
           'not be found.'))
예제 #19
0
    def configure(self, doc_id_expression, value_expression):
        non_couch_doc_types = (LOCATION_DOC_TYPE,)
        if (self.related_doc_type not in non_couch_doc_types
                and get_db_by_doc_type(self.related_doc_type) is None):
            raise BadSpecError('Cannot determine database for document type {}!'.format(self.related_doc_type))

        self._doc_id_expression = doc_id_expression
        self._value_expression = value_expression
예제 #20
0
파일: models.py 프로젝트: ekush/commcare-hq
 def by_id(cls, config_id):
     """
     Returns a ReportConfiguration object, NOT CustomReportConfigurations.
     """
     for ds in cls.all():
         if ds.get_id == config_id:
             return ds
     raise BadSpecError(_('The report configuration referenced by this report could '
                          'not be found.'))
예제 #21
0
def get_operator(slug):
    try:
        return OPERATORS[slug.lower()]
    except KeyError:
        raise BadSpecError(
            '{0} is not a valid operator. Choices are {1}'.format(
                slug,
                ', '.join(OPERATORS.keys()),
            ))
예제 #22
0
 def _check_for_duplicates(supposedly_unique_list, error_msg):
     # http://stackoverflow.com/questions/9835762/find-and-list-duplicates-in-python-list
     duplicate_items = set([
         item for item in supposedly_unique_list
         if supposedly_unique_list.count(item) > 1
     ])
     if len(duplicate_items) > 0:
         raise BadSpecError(
             _(error_msg).format(', '.join(sorted(duplicate_items))))
예제 #23
0
 def from_spec(cls, spec, report=None):
     cls.validate_spec(spec)
     try:
         return cls.constructor_map[spec['type']](spec, report)
     except (AssertionError, BadValueError) as e:
         raise BadSpecError(_('Problem creating report filter from spec: {}, message is: {}').format(
             json.dumps(spec, indent=2),
             str(e),
         ))
예제 #24
0
    def configure(self, doc_id_expression, value_expression):
        if get_db_by_doc_type(self.related_doc_type) is None:
            raise BadSpecError(
                u'Cannot determine database for document type {}!'.format(
                    self.related_doc_type))

        self._doc_id_expression = doc_id_expression
        self._value_expression = value_expression
        # used in caching
        self._vary_on = json.dumps(self.value_expression, sort_keys=True)
예제 #25
0
    def validate(self, required=True):
        super(DataSourceConfiguration, self).validate(required)
        # these two properties implicitly call other validation
        self._get_main_filter()
        self._get_deleted_filter()

        # validate indicators and column uniqueness
        columns = [c.id for c in self.indicators.get_columns()]
        unique_columns = set(columns)
        if len(columns) != len(unique_columns):
            for column in set(columns):
                columns.remove(column)
            raise BadSpecError(_('Report contains duplicate column ids: {}').format(', '.join(set(columns))))

        if self.referenced_doc_type not in VALID_REFERENCED_DOC_TYPES:
            raise BadSpecError(
                _('Report contains invalid referenced_doc_type: {}').format(self.referenced_doc_type))

        self.parsed_expression
예제 #26
0
파일: models.py 프로젝트: ekush/commcare-hq
 def by_id(cls, config_id):
     """
     Returns a DataSourceConfiguration object,
     NOT a CustomDataSourceConfiguration.
     """
     for ds in cls.all():
         if ds.get_id == config_id:
             return ds
     raise BadSpecError(_('The data source referenced by this report could '
                          'not be found.'))
예제 #27
0
 def pk_columns(self):
     columns = []
     for col in self.get_columns():
         if col.is_primary_key:
             column_name = decode_column_name(col)
             columns.append(column_name)
     if self.sql_settings.primary_key:
         if set(columns) != set(self.sql_settings.primary_key):
             raise BadSpecError("Primary key columns must have is_primary_key set to true", self.data_source_id)
         columns = self.sql_settings.primary_key
     return columns
예제 #28
0
 def from_spec(cls, spec, is_static, domain=None):
     column_type = spec.get('type') or 'field'
     if column_type not in cls.class_map:
         raise BadSpecError(
             'Unknown or missing column type: {} must be in [{}]'.format(
                 column_type, ', '.join(cls.class_map)))
     column_class = cls.class_map[column_type]
     if column_class.restricted_to_static(domain) and not (
             is_static or settings.UNIT_TESTING):
         raise BadSpecError(
             "{} columns are only available to static report configs".
             format(column_type))
     try:
         return column_class.wrap(spec)
     except BadValueError as e:
         raise BadSpecError(
             _('Problem creating column from spec: {}, message is: {}').
             format(
                 json.dumps(spec, indent=2),
                 str(e),
             ))
예제 #29
0
    def make_template(cls, spec):
        if spec.get('type') not in cls.spec_map:
            raise BadSpecError(
                _('Illegal sum_when_template type: "{0}", must be in: ({1})').
                format(spec.get('type'), ', '.join(cls.spec_map)))
        try:
            template = cls.spec_map[spec['type']].wrap(spec)
        except BadValueError as e:
            raise BadSpecError(
                _('Problem creating template: {}, message is: {}').format(
                    json.dumps(spec, indent=2),
                    str(e),
                ))

        expected = template.bind_count()
        actual = len(template.binds)
        if expected != actual:
            raise BadSpecError(
                _('Expected {} binds in sum_when_template {}, found {}').
                format(expected, spec['type'], actual))

        return template
예제 #30
0
 def report_class_by_domain_and_id(cls, domain, config_id):
     try:
         report_domain, wrapped = cls.by_id_mapping()[config_id]
     except KeyError:
         raise BadSpecError(
             _('The report configuration referenced by this report could not be found.')
         )
     if report_domain != domain:
         raise DocumentNotFound("Document {} of class {} not in domain {}!".format(
             config_id,
             ReportConfiguration.__class__.__name__,
             domain,
         ))
     return wrapped.custom_configurable_report