Example #1
0
def _validate_formats(data, schema):
    """Go through schema checking the formats date-time, time and base64"""
    if 'format' in schema:
        format_name = schema['format']
        if format_name == "date-time" and not validate_rfc3339(data):
            raise ForbiddenError("A date-time was not in the required format.")
        elif format_name == "time" and not _validate_timestr(data):
            raise ForbiddenError("A time was not in the required format.")
        elif format_name == "base64" and not _validate_base64(data):
            raise ForbiddenError("A string was not valid base64.")
        elif format_name == "timezone" and not _validate_timezone(data):
            raise ForbiddenError("A string was not a valid timezone.")
    if 'properties' in schema and isinstance(schema['properties'], dict):
        for key, value in data.items():
            try:
                _validate_formats(value, schema['properties'][key])
            except (TypeError, KeyError):
                pass
    if 'additionalProperties' in schema:
        if isinstance(schema['additionalProperties'], dict):
            for value in data.values():
                try:
                    _validate_formats(value, schema['additionalProperties'])
                except TypeError:
                    pass
    if 'items' in schema and isinstance(schema['items'], dict):
        for item in data:
            try:
                _validate_formats(item, schema['items'])
            except TypeError:
                pass
Example #2
0
def datetime_or_date(instance):
    if not instance:
        raise ValueError
    result = strict_rfc3339.validate_rfc3339(instance)
    if result:
        return result
    return datetime.datetime.strptime(instance, "%Y-%m-%d")
Example #3
0
def get_date(date):
    valid = strict_rfc3339.validate_rfc3339(date)
    if not valid:
        try:
            datetime.datetime.strptime(date, "%Y-%m-%d")
        except ValueError:
            return date
    return date_parser.parse(date).strftime("%d %b %Y")
Example #4
0
def get_year(date):
    valid = strict_rfc3339.validate_rfc3339(date)
    if not valid:
        try:
            datetime.datetime.strptime(date, "%Y-%m-%d")
        except ValueError:
            return date
    return date.split("-")[0]
Example #5
0
 def is_date(instance):
     print instance
     if not isinstance(instance, str_types):
         # return True
         raise FormatError(
             "%r is not a date-time format" % (instance)
         )
     return strict_rfc3339.validate_rfc3339(instance)
Example #6
0
def get_date(date):
    valid = strict_rfc3339.validate_rfc3339(date)
    if not valid:
        try:
            datetime.datetime.strptime(date, "%Y-%m-%d")
        except ValueError:
            return date
    return date_parser.parse(date).strftime("%d %b %Y")
def test_parse_string():
    for base, seconds_fraction, timezone in itertools.product(
            BASE_DATES, SECONDS_FRACTIONS, TIMEZONES):
        datetime_string = '{0}{1}{2}'.format(base, seconds_fraction, timezone)

        assert strict_rfc3339.validate_rfc3339(datetime_string), \
            'Not RFC3339: {}'.format(datetime_string)  # for sanity
        yield _assert_datetime_parse_equals, datetime_string, \
            EXPECTED[datetime_string]
Example #8
0
def validate_date(s):
    '''
    Validate date as defined by "full-date" on http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14

    >>> validate_date('foo')
    False

    >>> validate_date('2015-07-31')
    True
    '''
    return strict_rfc3339.validate_rfc3339(s + 'T00:00:00Z')
Example #9
0
def validate_date(s):
    '''
    Validate date as defined by "full-date" on http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14

    >>> validate_date('foo')
    False

    >>> validate_date('2015-07-31')
    True
    '''
    return strict_rfc3339.validate_rfc3339(s + 'T00:00:00Z')
Example #10
0
def is_datetime(instance):
    if not isinstance(instance, (binary_type, text_type)):
        return False

    if DATETIME_HAS_STRICT_RFC3339:
        return strict_rfc3339.validate_rfc3339(instance)

    if DATETIME_HAS_ISODATE:
        return isodate.parse_datetime(instance)

    return True
Example #11
0
def is_datetime(checker: TypeChecker, instance) -> bool:
    """
    Function to passed in TypeChecker for checking if property's type is custom type "interval"
    """
    if validate_rfc3339(instance):
        return True
    try:
        datetime.fromisoformat(instance)
    except ValueError:
        return False

    return True
Example #12
0
def is_datetime(instance):
    if not isinstance(instance, (bytes, str)):
        return False

    if DATETIME_HAS_RFC3339_VALIDATOR:
        return validate_rfc3339(instance)

    if DATETIME_HAS_STRICT_RFC3339:
        return strict_rfc3339.validate_rfc3339(instance)

    if DATETIME_HAS_ISODATE:
        return isodate.parse_datetime(instance)

    return True
Example #13
0
    def is_valid_datetime(json_post):
        """
        Determines if the datetime is strictly RFC3339

        Args:
            json_post: a json message as a python dict

        Returns:
            True if the value in key=datetime is RFC3339
        """
        try:
            if not strict_rfc3339.validate_rfc3339(json_post["datetime"]):
                return False
            else:
                return True
        except KeyError as e:
            print(e)
            return False
Example #14
0
def explore_ocds(request, pk):
    context, db_data, error = explore_data_context(request, pk)
    if error:
        return error

    lib_cove_ocds_config = LibCoveOCDSConfig()
    lib_cove_ocds_config.config["current_language"] = translation.get_language(
    )
    lib_cove_ocds_config.config[
        "schema_version_choices"] = settings.COVE_CONFIG[
            "schema_version_choices"]
    lib_cove_ocds_config.config["schema_codelists"] = settings.COVE_CONFIG[
        "schema_codelists"]

    upload_dir = db_data.upload_dir()
    upload_url = db_data.upload_url()
    file_name = db_data.original_file.file.name
    file_type = context["file_type"]

    post_version_choice = request.POST.get(
        "version", lib_cove_ocds_config.config["schema_version"])
    replace = False
    validation_errors_path = os.path.join(upload_dir,
                                          "validation_errors-3.json")

    if file_type == "json":
        # open the data first so we can inspect for record package
        with open(file_name, encoding="utf-8") as fp:
            try:
                json_data = json.load(fp,
                                      parse_float=Decimal,
                                      object_pairs_hook=OrderedDict)
            except ValueError as err:
                raise CoveInputDataError(
                    context={
                        "sub_title":
                        _("Sorry, we can't process that data"),
                        "link":
                        "index",
                        "link_text":
                        _("Try Again"),
                        "msg":
                        _(
                            format_html(
                                "We think you tried to upload a JSON file, but it is not well formed JSON."
                                '\n\n<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">'
                                "</span> <strong>Error message:</strong> {}",
                                err,
                            )),
                        "error":
                        format(err),
                    })

            if not isinstance(json_data, dict):
                raise CoveInputDataError(
                    context={
                        "sub_title":
                        _("Sorry, we can't process that data"),
                        "link":
                        "index",
                        "link_text":
                        _("Try Again"),
                        "msg":
                        _("OCDS JSON should have an object as the top level, the JSON you supplied does not."
                          ),
                    })

            version_in_data = json_data.get("version", "")
            db_data.data_schema_version = version_in_data
            select_version = post_version_choice or db_data.schema_version
            schema_ocds = SchemaOCDS(
                select_version=select_version,
                release_data=json_data,
                lib_cove_ocds_config=lib_cove_ocds_config,
            )

            if schema_ocds.missing_package:
                exceptions.raise_missing_package_error()
            if schema_ocds.invalid_version_argument:
                # This shouldn't happen unless the user sends random POST data.
                exceptions.raise_invalid_version_argument(post_version_choice)
            if schema_ocds.invalid_version_data:
                if isinstance(version_in_data, str) and re.compile(
                        "^\d+\.\d+\.\d+$").match(version_in_data):
                    exceptions.raise_invalid_version_data_with_patch(
                        version_in_data)
                else:
                    if not isinstance(version_in_data, str):
                        version_in_data = "{} (it must be a string)".format(
                            str(version_in_data))
                    context["unrecognized_version_data"] = version_in_data

            if schema_ocds.version != db_data.schema_version:
                replace = True
            if schema_ocds.extensions:
                schema_ocds.create_extended_release_schema_file(
                    upload_dir, upload_url)
            schema_url = schema_ocds.extended_schema_file or schema_ocds.release_schema_url

            if "records" in json_data:
                context["conversion"] = None
            else:
                # Replace the spreadsheet conversion only if it exists already.
                converted_path = os.path.join(upload_dir, "flattened")
                replace_converted = replace and os.path.exists(converted_path +
                                                               ".xlsx")

                with warnings.catch_warnings():
                    warnings.filterwarnings(
                        'ignore'
                    )  # flattentool uses UserWarning, so can't set a specific category

                    convert_json_context = convert_json(
                        upload_dir,
                        upload_url,
                        file_name,
                        lib_cove_ocds_config,
                        schema_url=schema_url,
                        replace=replace_converted,
                        request=request,
                        flatten=request.POST.get("flatten"),
                    )

                context.update(convert_json_context)

    else:
        # Use the lowest release pkg schema version accepting 'version' field
        metatab_schema_url = SchemaOCDS(
            select_version="1.1",
            lib_cove_ocds_config=lib_cove_ocds_config).release_pkg_schema_url
        metatab_data = get_spreadsheet_meta_data(upload_dir, file_name,
                                                 metatab_schema_url, file_type)
        if "version" not in metatab_data:
            metatab_data["version"] = "1.0"
        else:
            db_data.data_schema_version = metatab_data["version"]

        select_version = post_version_choice or db_data.schema_version
        schema_ocds = SchemaOCDS(
            select_version=select_version,
            release_data=metatab_data,
            lib_cove_ocds_config=lib_cove_ocds_config,
        )

        # Unlike for JSON data case above, do not check for missing data package
        if schema_ocds.invalid_version_argument:
            # This shouldn't happen unless the user sends random POST data.
            exceptions.raise_invalid_version_argument(post_version_choice)
        if schema_ocds.invalid_version_data:
            version_in_data = metatab_data.get("version")
            if re.compile("^\d+\.\d+\.\d+$").match(version_in_data):
                exceptions.raise_invalid_version_data_with_patch(
                    version_in_data)
            else:
                context["unrecognized_version_data"] = version_in_data

        # Replace json conversion when user chooses a different schema version.
        if db_data.schema_version and schema_ocds.version != db_data.schema_version:
            replace = True

        if schema_ocds.extensions:
            schema_ocds.create_extended_release_schema_file(
                upload_dir, upload_url)
        schema_url = schema_ocds.extended_schema_file or schema_ocds.release_schema_url
        pkg_url = schema_ocds.release_pkg_schema_url

        if file_type != "csv":
            # ORIGINAL UNFLATTEN
            conversion_context = convert_spreadsheet(
                upload_dir,
                upload_url,
                file_name,
                file_type,
                lib_cove_ocds_config,
                schema_url=schema_url,
                pkg_schema_url=pkg_url,
                replace=replace,
            )
        else:
            # Convert Simple CSV to flat OCDS and return context

            conversion_context = convert_simple_csv_submission(
                db_data,
                lib_cove_ocds_config,
                schema_url,
                replace=replace,
            )

        context.update(conversion_context)

        with open(context["converted_path"], encoding="utf-8") as fp:
            json_data = json.load(fp,
                                  parse_float=Decimal,
                                  object_pairs_hook=OrderedDict)

    if replace:
        if os.path.exists(validation_errors_path):
            os.remove(validation_errors_path)

    context = common_checks_ocds(context,
                                 upload_dir,
                                 json_data,
                                 schema_ocds,
                                 cache=settings.CACHE_VALIDATION_ERRORS)

    if schema_ocds.json_deref_error:
        exceptions.raise_json_deref_error(schema_ocds.json_deref_error)

    schema_version = getattr(schema_ocds, "version", None)
    if schema_version:
        db_data.schema_version = schema_version
    if not db_data.rendered:
        db_data.rendered = True

    db_data.save()

    context.update({
        "data_schema_version":
        db_data.schema_version,
        "first_render":
        not db_data.rendered,
        "validation_errors_grouped":
        group_validation_errors(context["validation_errors"]),
    })

    ocds_show_schema = SchemaOCDS()
    ocds_show_deref_schema = ocds_show_schema.get_release_schema_obj(
        deref=True)

    if "records" in json_data:
        template = "cove_ocds/explore_record.html"
        if hasattr(json_data, "get") and hasattr(json_data.get("records"),
                                                 "__iter__"):
            context["records"] = json_data["records"]
        else:
            context["records"] = []
        if isinstance(json_data["records"],
                      list) and len(json_data["records"]) < 100:
            context["ocds_show_data"] = ocds_show_data(json_data,
                                                       ocds_show_deref_schema)
    else:
        template = "silvereye/explore_release.html"
        if hasattr(json_data, "get") and hasattr(json_data.get("releases"),
                                                 "__iter__"):
            context["releases"] = json_data["releases"]
            if (isinstance(json_data["releases"], list)
                    and len(json_data["releases"]) < 100):
                context["ocds_show_data"] = ocds_show_data(
                    json_data, ocds_show_deref_schema)

            # Parse release dates into objects so the template can format them.
            for release in context["releases"]:
                if hasattr(release, "get") and release.get("date"):
                    if validate_rfc3339(release["date"]):
                        release["date"] = parser.parse(release["date"])
                    else:
                        release["date"] = None

                try:
                    trans_date = release["contracts"][0]["implementation"][
                        "transactions"][0]["date"]
                    parsed_trans_date = parser.parse(trans_date)
                    release["contracts"][0]["implementation"]["transactions"][
                        0]["date"] = parsed_trans_date
                except KeyError:
                    pass

            if context.get("releases_aggregates"):
                date_fields = [
                    "max_award_date",
                    "max_contract_date",
                    "max_release_date",
                    "max_tender_date",
                    "min_award_date",
                    "min_contract_date",
                    "min_release_date",
                    "min_tender_date",
                ]
                for field in date_fields:
                    if context["releases_aggregates"].get(field):
                        if validate_rfc3339(
                                context["releases_aggregates"][field]):
                            context["releases_aggregates"][
                                field] = parser.parse(
                                    context["releases_aggregates"][field])
                        else:
                            context["releases_aggregates"][field] = None
        else:
            context["releases"] = []

    # Include field coverage report
    original_file_path = context["original_file"]["path"]
    mapper = CSVMapper(csv_path=original_file_path)
    db_data.notice_type = mapper.release_type
    db_data.save()
    coverage_context = mapper.get_coverage_context()
    context.update({
        "field_coverage": coverage_context,
    })

    ocds_validation_errors, simple_csv_errors = prepare_simple_csv_validation_errors(
        context["validation_errors"], mapper,
        coverage_context["required_fields_missing"])

    context.update({
        "ocds_validation_errors": ocds_validation_errors,
        "simple_csv_errors": simple_csv_errors,
        "csv_mapper": mapper,
    })

    # Silvereye: Insert OCDS data
    releases = context.get("releases")
    if releases:
        # If we don't have validation errors
        validation_errors_grouped = context["validation_errors_grouped"]
        if not validation_errors_grouped:
            json_string = json.dumps(json_data,
                                     indent=2,
                                     sort_keys=True,
                                     cls=DjangoJSONEncoder)
            UpsertDataHelpers().upsert_ocds_data(json_string,
                                                 supplied_data=db_data)

            average_field_completion = coverage_context.get(
                "average_field_completion")
            inst, created = FieldCoverage.objects.update_or_create(
                file_submission=db_data,
                defaults={
                    "tenders_field_coverage":
                    average_field_completion
                    if mapper.release_type == "tender" else None,
                    "awards_field_coverage":
                    average_field_completion
                    if mapper.release_type == "award" else None,
                    "spend_field_coverage":
                    average_field_completion
                    if mapper.release_type == "spend" else None,
                })
            update_publisher_monthly_counts()

    return render(request, template, context)
Example #15
0
def explore_ocds(request, pk):
    context, db_data, error = explore_data_context(request, pk)
    if error:
        return error

    lib_cove_ocds_config = LibCoveOCDSConfig()
    lib_cove_ocds_config.config["current_language"] = translation.get_language(
    )
    lib_cove_ocds_config.config[
        "schema_version_choices"] = settings.COVE_CONFIG[
            "schema_version_choices"]
    lib_cove_ocds_config.config["schema_codelists"] = settings.COVE_CONFIG[
        "schema_codelists"]

    upload_dir = db_data.upload_dir()
    upload_url = db_data.upload_url()
    file_name = db_data.original_file.file.name
    file_type = context["file_type"]

    post_version_choice = request.POST.get("version")
    replace = False
    validation_errors_path = os.path.join(upload_dir,
                                          "validation_errors-3.json")

    if file_type == "json":
        # open the data first so we can inspect for record package
        with open(file_name, encoding="utf-8") as fp:
            try:
                json_data = json.load(fp,
                                      parse_float=Decimal,
                                      object_pairs_hook=OrderedDict)
            except UnicodeError as err:
                raise CoveInputDataError(
                    context={
                        'sub_title':
                        _("Sorry, we can't process that data"),
                        'link':
                        'index',
                        'link_text':
                        _('Try Again'),
                        'msg':
                        format_html(
                            _("The file that you uploaded doesn't appear to be well formed JSON. OCDS JSON follows the I-JSON format, which requires UTF-8 encoding. Ensure that your file uses UTF-8 encoding, then try uploading again."
                              '\n\n<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">'
                              '</span> <strong>Error message:</strong> {}'),
                            err),
                        'error':
                        format(err)
                    })
            except ValueError as err:
                raise CoveInputDataError(
                    context={
                        "sub_title":
                        _("Sorry, we can't process that data"),
                        "link":
                        "index",
                        "link_text":
                        _("Try Again"),
                        "msg":
                        format_html(
                            _(
                                "We think you tried to upload a JSON file, but it is not well formed JSON."
                                '\n\n<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">'
                                "</span> <strong>Error message:</strong> {}",
                            ),
                            err,
                        ),
                        "error":
                        format(err),
                    })

            if not isinstance(json_data, dict):
                raise CoveInputDataError(
                    context={
                        "sub_title":
                        _("Sorry, we can't process that data"),
                        "link":
                        "index",
                        "link_text":
                        _("Try Again"),
                        "msg":
                        _("OCDS JSON should have an object as the top level, the JSON you supplied does not."
                          ),
                    })

            version_in_data = json_data.get("version", "")
            db_data.data_schema_version = version_in_data
            select_version = post_version_choice or db_data.schema_version
            schema_ocds = SchemaOCDS(select_version=select_version,
                                     release_data=json_data,
                                     lib_cove_ocds_config=lib_cove_ocds_config,
                                     record_pkg="records" in json_data)

            if schema_ocds.missing_package:
                exceptions.raise_missing_package_error()
            if schema_ocds.invalid_version_argument:
                # This shouldn't happen unless the user sends random POST data.
                exceptions.raise_invalid_version_argument(post_version_choice)
            if schema_ocds.invalid_version_data:
                if isinstance(version_in_data, str) and re.compile(
                        "^\d+\.\d+\.\d+$").match(version_in_data):
                    exceptions.raise_invalid_version_data_with_patch(
                        version_in_data)
                else:
                    if not isinstance(version_in_data, str):
                        version_in_data = "{} (it must be a string)".format(
                            str(version_in_data))
                    context["unrecognized_version_data"] = version_in_data

            if schema_ocds.version != db_data.schema_version:
                replace = True
            if schema_ocds.extensions:
                schema_ocds.create_extended_schema_file(upload_dir, upload_url)
            url = schema_ocds.extended_schema_file or schema_ocds.schema_url

            if "records" in json_data:
                context["conversion"] = None
            else:
                # Replace the spreadsheet conversion only if it exists already.
                converted_path = os.path.join(upload_dir, "flattened")
                replace_converted = replace and os.path.exists(converted_path +
                                                               ".xlsx")

                with warnings.catch_warnings():
                    warnings.filterwarnings(
                        'ignore'
                    )  # flattentool uses UserWarning, so can't set a specific category

                    convert_json_context = convert_json(
                        upload_dir,
                        upload_url,
                        file_name,
                        lib_cove_ocds_config,
                        schema_url=url,
                        replace=replace_converted,
                        request=request,
                        flatten=request.POST.get("flatten"),
                    )

                context.update(convert_json_context)

    else:
        # Use the lowest release pkg schema version accepting 'version' field
        metatab_schema_url = SchemaOCDS(
            select_version="1.1",
            lib_cove_ocds_config=lib_cove_ocds_config).pkg_schema_url
        metatab_data = get_spreadsheet_meta_data(upload_dir, file_name,
                                                 metatab_schema_url, file_type)
        if "version" not in metatab_data:
            metatab_data["version"] = "1.0"
        else:
            db_data.data_schema_version = metatab_data["version"]

        select_version = post_version_choice or db_data.schema_version
        schema_ocds = SchemaOCDS(
            select_version=select_version,
            release_data=metatab_data,
            lib_cove_ocds_config=lib_cove_ocds_config,
        )

        # Unlike for JSON data case above, do not check for missing data package
        if schema_ocds.invalid_version_argument:
            # This shouldn't happen unless the user sends random POST data.
            exceptions.raise_invalid_version_argument(post_version_choice)
        if schema_ocds.invalid_version_data:
            version_in_data = metatab_data.get("version")
            if re.compile("^\d+\.\d+\.\d+$").match(version_in_data):
                exceptions.raise_invalid_version_data_with_patch(
                    version_in_data)
            else:
                context["unrecognized_version_data"] = version_in_data

        # Replace json conversion when user chooses a different schema version.
        if db_data.schema_version and schema_ocds.version != db_data.schema_version:
            replace = True

        if schema_ocds.extensions:
            schema_ocds.create_extended_schema_file(upload_dir, upload_url)
        url = schema_ocds.extended_schema_file or schema_ocds.schema_url
        pkg_url = schema_ocds.pkg_schema_url

        context.update(
            convert_spreadsheet(
                upload_dir,
                upload_url,
                file_name,
                file_type,
                lib_cove_ocds_config,
                schema_url=url,
                pkg_schema_url=pkg_url,
                replace=replace,
            ))

        with open(context["converted_path"], encoding="utf-8") as fp:
            json_data = json.load(fp,
                                  parse_float=Decimal,
                                  object_pairs_hook=OrderedDict)

    if replace:
        if os.path.exists(validation_errors_path):
            os.remove(validation_errors_path)

    context = common_checks_ocds(context, upload_dir, json_data, schema_ocds)

    if schema_ocds.json_deref_error:
        exceptions.raise_json_deref_error(schema_ocds.json_deref_error)

    context.update({
        "data_schema_version":
        db_data.data_schema_version,
        "first_render":
        not db_data.rendered,
        "validation_errors_grouped":
        group_validation_errors(context["validation_errors"]),
    })

    schema_version = getattr(schema_ocds, "version", None)
    if schema_version:
        db_data.schema_version = schema_version
    if not db_data.rendered:
        db_data.rendered = True

    db_data.save()

    if "records" in json_data:
        ocds_show_schema = SchemaOCDS(record_pkg=True)
        ocds_show_deref_schema = ocds_show_schema.get_schema_obj(deref=True)
        template = "cove_ocds/explore_record.html"
        if hasattr(json_data, "get") and hasattr(json_data.get("records"),
                                                 "__iter__"):
            context["records"] = json_data["records"]
        else:
            context["records"] = []
        if isinstance(json_data["records"],
                      list) and len(json_data["records"]) < 100:
            context["ocds_show_data"] = ocds_show_data(json_data,
                                                       ocds_show_deref_schema)
    else:
        ocds_show_schema = SchemaOCDS(record_pkg=False)
        ocds_show_deref_schema = ocds_show_schema.get_schema_obj(deref=True)
        template = "cove_ocds/explore_release.html"
        if hasattr(json_data, "get") and hasattr(json_data.get("releases"),
                                                 "__iter__"):
            context["releases"] = json_data["releases"]
            if (isinstance(json_data["releases"], list)
                    and len(json_data["releases"]) < 100):
                context["ocds_show_data"] = ocds_show_data(
                    json_data, ocds_show_deref_schema)

            # Parse release dates into objects so the template can format them.
            for release in context["releases"]:
                if hasattr(release, "get") and release.get("date"):
                    if validate_rfc3339(release["date"]):
                        release["date"] = parser.parse(release["date"])
                    else:
                        release["date"] = None
            if context.get("releases_aggregates"):
                date_fields = [
                    "max_award_date",
                    "max_contract_date",
                    "max_release_date",
                    "max_tender_date",
                    "min_award_date",
                    "min_contract_date",
                    "min_release_date",
                    "min_tender_date",
                ]
                for field in date_fields:
                    if context["releases_aggregates"].get(field):
                        if validate_rfc3339(
                                context["releases_aggregates"][field]):
                            context["releases_aggregates"][
                                field] = parser.parse(
                                    context["releases_aggregates"][field])
                        else:
                            context["releases_aggregates"][field] = None
        else:
            context["releases"] = []

    return render(request, template, context)
Example #16
0
 def is_datetime(instance):
     if not isinstance(instance, str_types):
         return True
     return strict_rfc3339.validate_rfc3339(instance)
Example #17
0
    def validate(self, raw_value: Union[None, str, bytes, _MissingType],
                 raw: bool) -> Union[None, str, bytes, _MissingType]:
        if isinstance(raw_value, (str, bytes)):
            value = raw_value
        elif raw_value is None:
            if self.nullable:
                return None
            raise ValidatorError("value should be type of str")
        elif isinstance(raw_value, _MissingType):
            if self.default is None:
                return raw_value
            value = self.default
        else:
            raise ValidatorError("value should be type of str")

        if self.minLength is not None and len(value) < self.minLength:
            raise ValidatorError(
                f"value length should be more than {self.minLength}")
        if self.maxLength is not None and len(value) > self.maxLength:
            raise ValidatorError(
                f"value length should be less than {self.maxLength}")
        if self.enum is not None and value not in self.enum:
            raise ValidatorError(f"value should be one of {self.enum}")

        if self.format not in (
                StringFormat.Default,
                StringFormat.Password,
                StringFormat.Binary,
        ):
            assert isinstance(value, str)
            if self.format == StringFormat.Uuid:
                try:
                    uuid.UUID(value)
                except ValueError:
                    raise ValidatorError("value should be uuid")
            elif self.format == StringFormat.Datetime:
                if not strict_rfc3339.validate_rfc3339(value):
                    raise ValidatorError("value should be datetime format")
            elif self.format == StringFormat.Date:
                if not strict_rfc3339.validate_rfc3339(f"{value}T00:00:00Z"):
                    raise ValidatorError("value should be date format")
            elif self.format == StringFormat.Email:
                if not _EMAIL_REGEX.match(value):
                    raise ValidatorError("value should be valid email")
            elif self.format == StringFormat.Byte:
                try:
                    base64.b64decode(value)
                except ValueError:
                    raise ValidatorError(
                        "value should be base64-encoded string")
            elif self.format == StringFormat.IPv4:
                try:
                    ipaddress.IPv4Address(value)
                except ValueError:
                    raise ValidatorError("value should be valid ipv4 address")
            elif self.format == StringFormat.IPv6:
                try:
                    ipaddress.IPv6Address(value)
                except ValueError:
                    raise ValidatorError("value should be valid ipv6 address")
            elif self.format == StringFormat.Hostname:
                hostname = value[:-1] if value[-1] == "." else value
                if len(hostname) > 255 or not all(
                        _HOSTNAME_REGEX.match(x) for x in hostname.split(".")):
                    raise ValidatorError("value should be valid hostname")

        if (self.format != StringFormat.Binary and self.pattern
                and not self.pattern.search(value)):
            raise ValidatorError(
                f"value should match regex pattern '{self.pattern.pattern}'")

        return value
Example #18
0
def _rfc3339_datetime(s):
    if validate_rfc3339(s):
        return s
    raise ValueError
Example #19
0
def get_post(start_time, end_time):
    """
    Get a single post and convert to json.

    Args:
        start_time: Beginning time of window of data being queried
        end_time: End time of window of data being queried

    Returns:
        Data for a specific period of time. It will output a list of jsons,
        outputting the data if found and outputting 'data not found' if
        that time was not found in database.


    .. :quickref: Data Window; Get window of data

    **Example request**:

    Shell command:

    *with email/password:*

    .. sourcecode:: shell

        curl --user <email>:<password> -X GET https://localhost/api/v0.1/posts/2017-09-13T13:01:57Z/2017-09-13T13:01:59Z

    *or with token:*

    .. sourcecode:: shell

        curl --user <token>: -X GET https://localhost/api/v0.1/posts/2017-09-13T13:01:57Z/2017-09-13T13:01:59Z

    Command response:

    .. sourcecode:: http

        GET /api/v0.1/posts/2017-09-13T13:01:57Z/2017-09-13T13:01:59Z HTTP/1.1
        localhost
        Authorization: Basic <b64 encoded email:password or token:>

    **Example response**:

    .. sourcecode:: http

        HTTP/1.1 200 OK
        Content-Type: application/json

        [
            {
                "JSON_message":"goes_here"
                },
            {
                "next_JSON_message":"goes_here"
                }
        ]

    *(JSON cut for length)*

   :query start_time: Beginning time of window of data being queried
   :query end_time: End time of window of data being queried
   :reqheader Authorization: use cURL tag with <email>:<psswrd>, or <token>:
   :resheader Content-Type: application/json
   :statuscode 200: Successfully retrieved data
   :statuscode 401: Invalid credentials
   :statuscode 403: Not signed in

    """
    time_format = '%Y-%m-%dT%H:%M:%SZ'
    start_time_stripped = datetime.strptime(start_time, time_format)
    end = datetime.strptime(end_time, time_format)
    time_delta = datetime.strptime(end_time, time_format) \
        - datetime.strptime(start_time, time_format)

    if not (strict_rfc3339.validate_rfc3339(start_time) and
            strict_rfc3339.validate_rfc3339(end_time)):
        print("Error: datetimes are not RFC 3339")
        return bad_request('Error: Datetimes are not RFC 3339')

    start_time_epoch = strict_rfc3339.rfc3339_to_timestamp(start_time)
    end_time_epoch = strict_rfc3339.rfc3339_to_timestamp(end_time)
    # print("start_time_epoch: {} end_time_epoch: {}".format(start_time_epoch,
    # end_time_epoch))
    if (end_time_epoch < start_time_epoch):
        print("Error: end time is before start time")
        return bad_request('Error: End time is before start time')

    MAX_API_DATA_S = current_app.config['MAX_API_DATA_PER_REQUEST']

    if time_delta > timedelta(seconds=MAX_API_DATA_S):
        return too_many_requests(
            'Request is above {} seconds of data.'.format(MAX_API_DATA_S))

    end = start_time_stripped + time_delta
    data = []
    while start_time_stripped <= end:
        # Until we change to 24hr time
        strtime = start_time_stripped.strftime(time_format)
        try:
            cache.get(strtime)
            no_redis_connection = False
        except RedisError:
            no_redis_connection = True

        if not no_redis_connection:
            if cache.get(strtime) is None:
                data_query = Machine.query.filter_by(
                    datetime=strtime).first()
                if data_query is not None:
                    try:
                        raw_data = data_query.to_json()
                        data.append(raw_data)
                        cache.set(strtime, raw_data, timeout=0)
                    except BaseException:
                        data.append({"Error": "Could not find data."})
            else:
                data.append(cache.get(strtime))
        else:
            data_query = Machine.query.filter_by(datetime=strtime).first()
            if data_query is not None:
                try:
                    raw_data = data_query.to_json()
                    data.append(raw_data)
                except BaseException:
                    data.append({"Error": "Could not find data."})
        start_time_stripped += timedelta(seconds=1)

    return jsonify(data)
    def test_catalog(self):

        singer.write_message = singer_write_message
        log_miner.UPDATE_BOOKMARK_PERIOD = 1

        with get_test_connection() as conn:
            conn.autocommit = True

            catalog = tap_oracle.do_discovery(get_test_conn_config(), [])
            chicken_stream = [
                s for s in catalog.streams if s.table == 'CHICKEN'
            ][0]
            chicken_stream = select_all_of_stream(chicken_stream)

            chicken_stream = set_replication_method_for_stream(
                chicken_stream, 'LOG_BASED')

            cur = conn.cursor()

            prev_scn = cur.execute(
                "SELECT current_scn FROM V$DATABASE").fetchall()[0][0]

            our_date = datetime.date(1996, 6, 6)
            our_ts = datetime.datetime(1997, 2, 2, 2, 2, 2, 722184)
            nyc_tz = pytz.timezone('America/New_York')
            our_ts_tz_edt = nyc_tz.localize(
                datetime.datetime(1997, 3, 3, 3, 3, 3, 722184))
            our_ts_tz_utc = datetime.datetime(1997, 3, 3, 3, 3, 3, 722184,
                                              pytz.UTC)
            auckland_tz = pytz.timezone('Pacific/Auckland')
            our_ts_local = auckland_tz.localize(
                datetime.datetime(1997, 3, 3, 18, 3, 3, 722184))

            crud_up_log_miner_fixtures(
                cur, 'CHICKEN', {
                    '"our_date"': our_date,
                    '"our_ts"': our_ts,
                    '"our_ts_tz_edt"': our_ts_tz_edt,
                    '"our_ts_tz_utc"': our_ts_tz_utc,
                    '"our_ts_tz_local"': our_ts_local
                }, self.update_add_1_day)

            post_scn = cur.execute(
                "SELECT current_scn FROM V$DATABASE").fetchall()[0][0]
            LOGGER.info("post SCN: {}".format(post_scn))

            state = write_bookmark({}, chicken_stream.tap_stream_id, 'scn',
                                   prev_scn)
            state = write_bookmark(state, chicken_stream.tap_stream_id,
                                   'version', 1)
            tap_oracle.do_sync(get_test_conn_config(), catalog, None, state)

            verify_crud_messages(self, CAUGHT_MESSAGES, ['ID'])

            #verify message 1 - first insert
            insert_rec_1 = CAUGHT_MESSAGES[1].record
            self.assertIsNotNone(insert_rec_1.get('scn'))
            insert_rec_1.pop('scn')
            self.assertIsNone(insert_rec_1.get('_sdc_deleted_at'))
            self.assertEqual(insert_rec_1.get('ID'), 1)
            insert_rec_1.pop('_sdc_deleted_at')
            insert_rec_1.pop('ID')

            self.assertEqual(
                insert_rec_1, {
                    'our_ts': '1997-02-02T02:02:02.722184+00:00',
                    'our_ts_tz_edt': '1997-03-03T03:03:03.722184-05:00',
                    'our_ts_tz_utc': '1997-03-03T03:03:03.722184+00:00',
                    'our_date': '1996-06-06T00:00:00.00+00:00',
                    'our_ts_tz_local': '1997-03-03T05:03:03.722184+00:00'
                })

            for v in insert_rec_1.values():
                self.assertTrue(strict_rfc3339.validate_rfc3339(v))

            #verify UPDATE
            update_rec = CAUGHT_MESSAGES[5].record
            self.assertIsNotNone(update_rec.get('scn'))
            update_rec.pop('scn')

            self.assertEqual(
                update_rec, {
                    'our_ts': '1997-02-03T02:02:02.722184+00:00',
                    'our_ts_tz_edt': '1997-03-04T03:03:03.722184-05:00',
                    'our_ts_tz_utc': '1997-03-04T03:03:03.722184+00:00',
                    'our_date': '1996-06-07T00:00:00.00+00:00',
                    '_sdc_deleted_at': None,
                    'our_ts_tz_local': '1997-03-04T05:03:03.722184+00:00',
                    'ID': 1
                })

            #verify first DELETE message
            delete_rec = CAUGHT_MESSAGES[9].record
            self.assertIsNotNone(delete_rec.get('scn'))
            self.assertIsNotNone(delete_rec.get('_sdc_deleted_at'))
            delete_rec.pop('scn')
            delete_rec.pop('_sdc_deleted_at')
            self.assertEqual(
                delete_rec, {
                    'our_ts': '1997-02-03T02:02:02.722184+00:00',
                    'our_ts_tz_edt': '1997-03-04T03:03:03.722184-05:00',
                    'our_ts_tz_utc': '1997-03-04T03:03:03.722184+00:00',
                    'our_date': '1996-06-07T00:00:00.00+00:00',
                    'our_ts_tz_local': '1997-03-04T05:03:03.722184+00:00',
                    'ID': 1
                })

            #verify second DELETE message
            delete_rec_2 = CAUGHT_MESSAGES[11].record

            self.assertIsNotNone(delete_rec_2.get('scn'))
            self.assertIsNotNone(delete_rec_2.get('_sdc_deleted_at'))
            delete_rec_2.pop('scn')
            delete_rec_2.pop('_sdc_deleted_at')
            self.assertEqual(
                delete_rec_2, {
                    'our_ts': '1997-02-03T02:02:02.722184+00:00',
                    'our_ts_tz_edt': '1997-03-04T03:03:03.722184-05:00',
                    'our_ts_tz_utc': '1997-03-04T03:03:03.722184+00:00',
                    'our_date': '1996-06-07T00:00:00.00+00:00',
                    'our_ts_tz_local': '1997-03-04T05:03:03.722184+00:00',
                    'ID': 2
                })
Example #21
0
def async_statistics(self, start_time, end_time):
    """
    Gets a specific set of statistically analyzed data from the database to be used in Statistical Analysis.

    Args:
        start_time: Beginning time of window of data being queried
        end_time: End time of window of data being queried

    Returns:
        response: the trimmed blower data, or a status report
        This async function will output a primitive dict of shape:
            {
                result:
                status:
            }
        Where, if successful, 'result' is also a primitive dict containing
        start_time, end_time, and a list of trimmed json blower data (or an
        empty dict if blower wasn't on). If not successful, 'result' will be a
        string containing a status message. 'status' will always be an int,
        referring to an HTTP status code.

        When returned, the statistics_status endpoint handles the primitive result,
        and returns a jsonified output to the user.

    **Example request**:

    Shell command:

    *with email/password:*

    .. sourcecode:: shell

        curl --user <email>:<password> -X GET https://localhost/api/v0.1/statistics/2017-09-13T13:01:57Z/2017-09-13T13:01:59Z

    *or with token:*

    .. sourcecode:: shell

        curl --user <token>: -X GET https://localhost/api/v0.1/statistics/2017-09-13T13:01:57Z/2017-09-13T13:01:59Z

    Command response:

    .. sourcecode:: http

        GET /api/v0.1/statistics/2017-09-13T13:01:57Z/2017-09-13T13:01:59Z HTTP/1.1
        localhost
        Authorization: Basic <b64 encoded email:password or token:>


   :query start_time: Beginning time of window of data being queried
   :query end_time: End time of window of data being queried
   :reqheader Authorization: use cURL tag with <email>:<psswrd>, or <token>:
   :resheader Content-Type: application/json
   :statuscode 200: Successfully retrieved data
   :statuscode 204: No content
   :statuscode 401: Invalid credentials
   :statuscode 403: Not signed in
   """
    #pr = cProfile.Profile()
    #pr.enable()

    self.update_state(state='STARTED',
                        meta={'result': "Gathering data for statistical analysis.",
                              'status': 202})

    # TODO We should define that you cannot run statistics over a super long
    # period since this is not an asynchronous request.
    MAX_API_DATA_S = current_app.config['MAX_API_DATA_PER_REQUEST']
    # issue with collecting more than a half hour at a time
    delta_t_chunk_size = MAX_API_DATA_S
    # Checking and setting up the start and end times

    if not (strict_rfc3339.validate_rfc3339(start_time) and
            strict_rfc3339.validate_rfc3339(end_time)):
        print("Error: datetimes are not RFC 3339")
        response = {'result': "Bad request; datetimes are not RFC 3339.",
                    'status': 400}
        # API will return bad_request
        return response

    start_time_epoch = strict_rfc3339.rfc3339_to_timestamp(start_time)
    end_time_epoch = strict_rfc3339.rfc3339_to_timestamp(end_time)
    if (end_time_epoch < start_time_epoch):
        print("Error: end time is before start time")
        response = {'result': "Bad request; end time is before start time",
                    'status': 400}
        # API will return bad_request
        return response

    temp_start_time_epoch = start_time_epoch
    # Add chunk time to temp time values only if request time exceeds 30 min
    if end_time_epoch - start_time_epoch >= 1800:
        temp_end_time_epoch = start_time_epoch + delta_t_chunk_size
    else:
        temp_end_time_epoch = end_time_epoch

    # Do stuff

    self.update_state(state='PROGRESS',
                        meta={'result': "Finished gathering data, running stats.",
                              'status': 202})

    # @TODO update whatever the actual response is
    response = {'result': {'start_time' : start_time, 'end_time' : end_time,
                           'data': 'here is data'},
                'status': '200'}

    #pr.disable()
    #s = io.StringIO()
    #ps = pstats.Stats(pr, stream=s).sort_stats('tottime')
    #ps.print_stats()
    #print(s.getvalue())

    if response is None:
        # An error occured in Statistics.py, couldn't process request
        response = {'result': "Processing Failure; Statistics returned nothing.",
                    'status': 500}
        return response
    else:
        # successfully returned data
        return response
Example #22
0
def datetime_or_date(instance):
    result = strict_rfc3339.validate_rfc3339(instance)
    if result:
        return result
    return datetime.datetime.strptime(instance, "%Y-%m-%d")
def sf_date_time_validator(value: str) -> None:
    if not strict_rfc3339.validate_rfc3339(value):
        raise ValidatorError("value should be datetime format")
Example #24
0
def explore_ocds(request, pk):
    context, db_data, error = explore_data_context(request, pk)
    if error:
        return error

    upload_dir = db_data.upload_dir()
    upload_url = db_data.upload_url()
    file_name = db_data.original_file.file.name
    file_type = context['file_type']

    post_version_choice = request.POST.get('version')
    replace = False
    validation_errors_path = os.path.join(upload_dir,
                                          'validation_errors-3.json')

    if file_type == 'json':
        # open the data first so we can inspect for record package
        with open(file_name, encoding='utf-8') as fp:
            try:
                json_data = json.load(fp, parse_float=Decimal)
            except ValueError as err:
                raise CoveInputDataError(
                    context={
                        'sub_title':
                        _("Sorry, we can't process that data"),
                        'link':
                        'index',
                        'link_text':
                        _('Try Again'),
                        'msg':
                        _(
                            format_html(
                                'We think you tried to upload a JSON file, but it is not well formed JSON.'
                                '\n\n<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">'
                                '</span> <strong>Error message:</strong> {}',
                                err)),
                        'error':
                        format(err)
                    })

            if not isinstance(json_data, dict):
                raise CoveInputDataError(
                    context={
                        'sub_title':
                        _("Sorry, we can't process that data"),
                        'link':
                        'index',
                        'link_text':
                        _('Try Again'),
                        'msg':
                        _('OCDS JSON should have an object as the top level, the JSON you supplied does not.'
                          ),
                    })

            version_in_data = json_data.get('version', '')
            db_data.data_schema_version = version_in_data
            select_version = post_version_choice or db_data.schema_version
            schema_ocds = SchemaOCDS(select_version=select_version,
                                     release_data=json_data)

            if schema_ocds.missing_package:
                exceptions.raise_missing_package_error()
            if schema_ocds.invalid_version_argument:
                # This shouldn't happen unless the user sends random POST data.
                exceptions.raise_invalid_version_argument(post_version_choice)
            if schema_ocds.invalid_version_data:
                if isinstance(version_in_data, str) and re.compile(
                        '^\d+\.\d+\.\d+$').match(version_in_data):
                    exceptions.raise_invalid_version_data_with_patch(
                        version_in_data)
                else:
                    if not isinstance(version_in_data, str):
                        version_in_data = '{} (it must be a string)'.format(
                            str(version_in_data))
                    context['unrecognized_version_data'] = version_in_data

            if schema_ocds.version != db_data.schema_version:
                replace = True
            if schema_ocds.extensions:
                schema_ocds.create_extended_release_schema_file(
                    upload_dir, upload_url)
            url = schema_ocds.extended_schema_file or schema_ocds.release_schema_url

            if 'records' in json_data:
                context['conversion'] = None
            else:

                # Replace the spreadsheet conversion only if it exists already.
                converted_path = os.path.join(upload_dir, 'flattened')
                replace_converted = replace and os.path.exists(converted_path +
                                                               '.xlsx')
                context.update(
                    convert_json(upload_dir,
                                 upload_url,
                                 file_name,
                                 schema_url=url,
                                 replace=replace_converted,
                                 request=request,
                                 flatten=request.POST.get('flatten')))

    else:
        # Use the lowest release pkg schema version accepting 'version' field
        metatab_schema_url = SchemaOCDS(
            select_version='1.1').release_pkg_schema_url
        metatab_data = get_spreadsheet_meta_data(upload_dir, file_name,
                                                 metatab_schema_url, file_type)
        if 'version' not in metatab_data:
            metatab_data['version'] = '1.0'
        else:
            db_data.data_schema_version = metatab_data['version']

        select_version = post_version_choice or db_data.schema_version
        schema_ocds = SchemaOCDS(select_version=select_version,
                                 release_data=metatab_data)

        # Unlike for JSON data case above, do not check for missing data package
        if schema_ocds.invalid_version_argument:
            # This shouldn't happen unless the user sends random POST data.
            exceptions.raise_invalid_version_argument(post_version_choice)
        if schema_ocds.invalid_version_data:
            version_in_data = metatab_data.get('version')
            if re.compile('^\d+\.\d+\.\d+$').match(version_in_data):
                exceptions.raise_invalid_version_data_with_patch(
                    version_in_data)
            else:
                context['unrecognized_version_data'] = version_in_data

        # Replace json conversion when user chooses a different schema version.
        if db_data.schema_version and schema_ocds.version != db_data.schema_version:
            replace = True

        if schema_ocds.extensions:
            schema_ocds.create_extended_release_schema_file(
                upload_dir, upload_url)
        url = schema_ocds.extended_schema_file or schema_ocds.release_schema_url
        pkg_url = schema_ocds.release_pkg_schema_url

        context.update(
            convert_spreadsheet(upload_dir,
                                upload_url,
                                file_name,
                                file_type,
                                schema_url=url,
                                pkg_schema_url=pkg_url,
                                replace=replace))

        with open(context['converted_path'], encoding='utf-8') as fp:
            json_data = json.load(fp, parse_float=Decimal)

    if replace:
        if os.path.exists(validation_errors_path):
            os.remove(validation_errors_path)

    context = common_checks_ocds(context, upload_dir, json_data, schema_ocds)

    if schema_ocds.json_deref_error:
        exceptions.raise_json_deref_error(schema_ocds.json_deref_error)

    context.update({
        'data_schema_version': db_data.data_schema_version,
        'first_render': not db_data.rendered
    })

    schema_version = getattr(schema_ocds, 'version', None)
    if schema_version:
        db_data.schema_version = schema_version
    if not db_data.rendered:
        db_data.rendered = True

    db_data.save()

    if 'records' in json_data:
        template = 'cove_ocds/explore_record.html'
        if hasattr(json_data, 'get') and hasattr(json_data.get('records'),
                                                 '__iter__'):
            context['records'] = json_data['records']
        else:
            context['records'] = []
    else:
        template = 'cove_ocds/explore_release.html'
        if hasattr(json_data, 'get') and hasattr(json_data.get('releases'),
                                                 '__iter__'):
            context['releases'] = json_data['releases']

            # Parse release dates into objects so the template can format them.
            for release in context['releases']:
                if hasattr(release, 'get') and release.get('date'):
                    if validate_rfc3339(release['date']):
                        release['date'] = parser.parse(release['date'])
                    else:
                        release['date'] = None
            if context.get('releases_aggregates'):
                date_fields = [
                    'max_award_date', 'max_contract_date', 'max_release_date',
                    'max_tender_date', 'min_award_date', 'min_contract_date',
                    'min_release_date', 'min_tender_date'
                ]
                for field in date_fields:
                    if context['releases_aggregates'].get(field):
                        if (validate_rfc3339(
                                context['releases_aggregates'][field])):
                            context['releases_aggregates'][
                                field] = parser.parse(
                                    context['releases_aggregates'][field])
                        else:
                            context['releases_aggregates'][field] = None
        else:
            context['releases'] = []

    return render(request, template, context)
Example #25
0
 def is_datetime(instance):
     if not isinstance(instance, str):
         return True
     return validate_rfc3339(instance)
Example #26
0
def explore_ocds(request, pk):
    context, db_data, error = explore_data_context(request, pk)
    if error:
        return error

    lib_cove_ocds_config = LibCoveOCDSConfig()
    lib_cove_ocds_config.config['current_language'] = translation.get_language()

    upload_dir = db_data.upload_dir()
    upload_url = db_data.upload_url()
    file_name = db_data.original_file.file.name
    file_type = context['file_type']

    post_version_choice = request.POST.get('version')
    replace = False
    validation_errors_path = os.path.join(upload_dir, 'validation_errors-3.json')

    if file_type == 'json':
        # open the data first so we can inspect for record package
        with open(file_name, encoding='utf-8') as fp:
            try:
                json_data = json.load(fp, parse_float=Decimal)
            except ValueError as err:
                raise CoveInputDataError(context={
                    'sub_title': _("Sorry, we can't process that data"),
                    'link': 'index',
                    'link_text': _('Try Again'),
                    'msg': _(format_html('We think you tried to upload a JSON file, but it is not well formed JSON.'
                             '\n\n<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">'
                             '</span> <strong>Error message:</strong> {}', err)),
                    'error': format(err)
                })

            if not isinstance(json_data, dict):
                raise CoveInputDataError(context={
                    'sub_title': _("Sorry, we can't process that data"),
                    'link': 'index',
                    'link_text': _('Try Again'),
                    'msg': _('OCDS JSON should have an object as the top level, the JSON you supplied does not.'),
                })

            version_in_data = json_data.get('version', '')
            db_data.data_schema_version = version_in_data
            select_version = post_version_choice or db_data.schema_version
            schema_ocds = SchemaOCDS(select_version=select_version, release_data=json_data, lib_cove_ocds_config=lib_cove_ocds_config)

            if schema_ocds.missing_package:
                exceptions.raise_missing_package_error()
            if schema_ocds.invalid_version_argument:
                # This shouldn't happen unless the user sends random POST data.
                exceptions.raise_invalid_version_argument(post_version_choice)
            if schema_ocds.invalid_version_data:
                if isinstance(version_in_data, str) and re.compile('^\d+\.\d+\.\d+$').match(version_in_data):
                    exceptions.raise_invalid_version_data_with_patch(version_in_data)
                else:
                    if not isinstance(version_in_data, str):
                        version_in_data = '{} (it must be a string)'.format(str(version_in_data))
                    context['unrecognized_version_data'] = version_in_data

            if schema_ocds.version != db_data.schema_version:
                replace = True
            if schema_ocds.extensions:
                schema_ocds.create_extended_release_schema_file(upload_dir, upload_url)
            url = schema_ocds.extended_schema_file or schema_ocds.release_schema_url

            if 'records' in json_data:
                context['conversion'] = None
            else:

                # Replace the spreadsheet conversion only if it exists already.
                converted_path = os.path.join(upload_dir, 'flattened')
                replace_converted = replace and os.path.exists(converted_path + '.xlsx')
                context.update(convert_json(upload_dir, upload_url, file_name, lib_cove_ocds_config,
                                            schema_url=url, replace=replace_converted,
                                            request=request, flatten=request.POST.get('flatten')))

    else:
        # Use the lowest release pkg schema version accepting 'version' field
        metatab_schema_url = SchemaOCDS(select_version='1.1', lib_cove_ocds_config=lib_cove_ocds_config).release_pkg_schema_url
        metatab_data = get_spreadsheet_meta_data(upload_dir, file_name, metatab_schema_url, file_type)
        if 'version' not in metatab_data:
            metatab_data['version'] = '1.0'
        else:
            db_data.data_schema_version = metatab_data['version']

        select_version = post_version_choice or db_data.schema_version
        schema_ocds = SchemaOCDS(select_version=select_version, release_data=metatab_data, lib_cove_ocds_config=lib_cove_ocds_config)

        # Unlike for JSON data case above, do not check for missing data package
        if schema_ocds.invalid_version_argument:
            # This shouldn't happen unless the user sends random POST data.
            exceptions.raise_invalid_version_argument(post_version_choice)
        if schema_ocds.invalid_version_data:
            version_in_data = metatab_data.get('version')
            if re.compile('^\d+\.\d+\.\d+$').match(version_in_data):
                exceptions.raise_invalid_version_data_with_patch(version_in_data)
            else:
                context['unrecognized_version_data'] = version_in_data

        # Replace json conversion when user chooses a different schema version.
        if db_data.schema_version and schema_ocds.version != db_data.schema_version:
            replace = True

        if schema_ocds.extensions:
            schema_ocds.create_extended_release_schema_file(upload_dir, upload_url)
        url = schema_ocds.extended_schema_file or schema_ocds.release_schema_url
        pkg_url = schema_ocds.release_pkg_schema_url

        context.update(convert_spreadsheet(upload_dir, upload_url, file_name, file_type, lib_cove_ocds_config,
                                           schema_url=url,
                                           pkg_schema_url=pkg_url, replace=replace))

        with open(context['converted_path'], encoding='utf-8') as fp:
            json_data = json.load(fp, parse_float=Decimal)

    if replace:
        if os.path.exists(validation_errors_path):
            os.remove(validation_errors_path)

    context = common_checks_ocds(context, upload_dir, json_data, schema_ocds)

    if schema_ocds.json_deref_error:
        exceptions.raise_json_deref_error(schema_ocds.json_deref_error)

    context.update({
        'data_schema_version': db_data.data_schema_version,
        'first_render': not db_data.rendered,
        'validation_errors_grouped': group_validation_errors(context['validation_errors']),
    })

    schema_version = getattr(schema_ocds, 'version', None)
    if schema_version:
        db_data.schema_version = schema_version
    if not db_data.rendered:
        db_data.rendered = True

    db_data.save()

    ocds_show_schema = SchemaOCDS()
    ocds_show_deref_schema = ocds_show_schema.get_release_schema_obj(deref=True)

    if 'records' in json_data:
        template = 'cove_ocds/explore_record.html'
        if hasattr(json_data, 'get') and hasattr(json_data.get('records'), '__iter__'):
            context['records'] = json_data['records']
        else:
            context['records'] = []
        if isinstance(json_data['records'], list) and len(json_data['records']) < 100:
            context['ocds_show_data'] = ocds_show_data(json_data, ocds_show_deref_schema)
    else:
        template = 'cove_ocds/explore_release.html'
        if hasattr(json_data, 'get') and hasattr(json_data.get('releases'), '__iter__'):
            context['releases'] = json_data['releases']
            if isinstance(json_data['releases'], list) and len(json_data['releases']) < 100:
                context['ocds_show_data'] = ocds_show_data(json_data, ocds_show_deref_schema)

            # Parse release dates into objects so the template can format them.
            for release in context['releases']:
                if hasattr(release, 'get') and release.get('date'):
                    if validate_rfc3339(release['date']):
                        release['date'] = parser.parse(release['date'])
                    else:
                        release['date'] = None
            if context.get('releases_aggregates'):
                date_fields = ['max_award_date', 'max_contract_date', 'max_release_date', 'max_tender_date', 'min_award_date', 'min_contract_date', 'min_release_date', 'min_tender_date']
                for field in date_fields:
                    if context['releases_aggregates'].get(field):
                        if(validate_rfc3339(context['releases_aggregates'][field])):
                            context['releases_aggregates'][field] = parser.parse(context['releases_aggregates'][field])
                        else:
                            context['releases_aggregates'][field] = None
        else:
            context['releases'] = []

    return render(request, template, context)
def sf_date_validator(value: str) -> None:
    if not strict_rfc3339.validate_rfc3339(f"{value}T00:00:00Z"):
        raise ValidatorError("value should be date format")
Example #28
0
def test_against_legacy(datetime_str):
    legacy_result = strict_rfc3339.validate_rfc3339(datetime_str)
    new_result = validate_rfc3339(datetime_str)
    assert legacy_result == new_result
def test_generated_rfc3339_datetime_strings_are_valid(datetime_string):
    assert strict_rfc3339.validate_rfc3339(datetime_string)
Example #30
0
def date_time_format_validator(value, **kwargs):
    if not strict_rfc3339.validate_rfc3339(value):
        raise ValidationError(MESSAGES['format']['invalid_datetime'].format(value))
Example #31
0
 def is_datetime(instance):
     if not isinstance(instance, str_types):
         return True
     return strict_rfc3339.validate_rfc3339(instance)
Example #32
0
def _rfc3339_datetime(s):
    if validate_rfc3339(s):
        return s
    raise ValueError