Skip to content

Commit

Permalink
[#6] Initial importing of datapackage-py's Schema
Browse files Browse the repository at this point in the history
We still have to recreate the same API, but at least the tests are passing.
  • Loading branch information
vitorbaptista committed Jan 15, 2016
1 parent 67a07e2 commit 9baf726
Show file tree
Hide file tree
Showing 23 changed files with 396 additions and 637 deletions.
22 changes: 22 additions & 0 deletions .coveragerc
@@ -0,0 +1,22 @@
[run]
source =
datapackage_validate/*

[xml]
output = shippable/codecoverage/coverage.xml

[report]
# Regexes for lines to exclude from consideration
exclude_lines =
# Don't complain about missing debug-only code:
def __repr__
if self\.debug

# Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise NotImplementedError

# Don't complain if non-runnable code isn't run:
if 0:
if False:
if __name__ == .__main__.:
4 changes: 1 addition & 3 deletions datapackage_validate/__init__.py
Expand Up @@ -4,7 +4,5 @@
from __future__ import print_function
from __future__ import unicode_literals

from .validation import validate


__all__ = ['validate']
__all__ = ['schema']
32 changes: 0 additions & 32 deletions datapackage_validate/compat.py

This file was deleted.

18 changes: 11 additions & 7 deletions datapackage_validate/exceptions.py
@@ -1,16 +1,20 @@
class DataPackageValidateException(Exception):
def __init__(self, *args, **kwargs):
super(DataPackageValidateException, self).__init__(*args, **kwargs)
self.errors = []
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import jsonschema.exceptions

class SchemaError(DataPackageValidateException):

class DataPackageException(Exception):
pass


class ValidationError(DataPackageValidateException):
class SchemaError(DataPackageException,
jsonschema.exceptions.SchemaError):
pass


class RegistryError(DataPackageValidateException):
class ValidationError(DataPackageException,
jsonschema.exceptions.ValidationError):
pass
121 changes: 121 additions & 0 deletions datapackage_validate/schema.py
@@ -0,0 +1,121 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import os
import copy
import six
import requests
import json
import jsonschema
import datapackage_registry
from datapackage_registry.exceptions import DataPackageRegistryException
from .exceptions import (
SchemaError, ValidationError
)


class Schema(object):
'''Abstracts a JSON Schema and allows validation of data against it.
Args:
schema (str or dict): The JSON Schema itself as a dict, or a local path
or URL to it.
Raises:
SchemaError: If unable to load schema or it was invalid.
Warning:
The schema objects created with this class are read-only. You should
change any of its attributes after creation.
'''
def __init__(self, schema):
self._registry = self._load_registry()
self._schema = self._load_schema(schema, self._registry)
self._validator = self._load_validator(self._schema, self._registry)
self._check_schema()

def to_dict(self):
'''dict: Convert this :class:`.Schema` to dict.'''
return copy.deepcopy(self._schema)

def validate(self, data):
'''Validates a data dict against this schema.
Args:
data (dict): The data to be validated.
Raises:
ValidationError: If the data is invalid.
'''
try:
self._validator.validate(data)
except jsonschema.ValidationError as e:
six.raise_from(ValidationError.create_from(e), e)

def _load_registry(self):
try:
return datapackage_registry.Registry()
except DataPackageRegistryException as e:
six.raise_from(SchemaError(e), e)

def _load_schema(self, schema, registry):
the_schema = schema

if isinstance(schema, six.string_types):
try:
the_schema = registry.get(schema)
if not the_schema:
if os.path.isfile(schema):
with open(schema, 'r') as f:
the_schema = json.load(f)
else:
req = requests.get(schema)
req.raise_for_status()
the_schema = req.json()
except (IOError,
ValueError,
DataPackageRegistryException,
requests.exceptions.RequestException) as e:
msg = 'Unable to load schema at "{0}"'
six.raise_from(SchemaError(msg.format(schema)), e)
elif isinstance(the_schema, dict):
the_schema = copy.deepcopy(the_schema)
else:
msg = 'Schema must be a "dict", but was a "{0}"'
raise SchemaError(msg.format(type(the_schema).__name__))

return the_schema

def _load_validator(self, schema, registry):
resolver = None

if registry.base_path:
path = 'file://{base_path}/'.format(base_path=registry.base_path)
resolver = jsonschema.RefResolver(path, schema)

validator_class = jsonschema.validators.validator_for(schema)

return validator_class(schema, resolver=resolver)

def _check_schema(self):
try:
self._validator.check_schema(self._schema)
except jsonschema.exceptions.SchemaError as e:
six.raise_from(SchemaError.create_from(e), e)

def __getattr__(self, name):
if name in self.__dict__.get('_schema', {}):
return copy.deepcopy(self._schema[name])

msg = '\'{0}\' object has no attribute \'{1}\''
raise AttributeError(msg.format(self.__class__.__name__, name))

def __setattr__(self, name, value):
if name in self.__dict__.get('_schema', {}):
raise AttributeError('can\'t set attribute')
super(self.__class__, self).__setattr__(name, value)

def __dir__(self):
return list(self.__dict__.keys()) + list(self._schema.keys())
97 changes: 0 additions & 97 deletions datapackage_validate/validation.py

This file was deleted.

4 changes: 0 additions & 4 deletions dev-requirements.txt

This file was deleted.

11 changes: 11 additions & 0 deletions run_coveralls.py
@@ -0,0 +1,11 @@
#!/bin/env/python

import os

from subprocess import call


if __name__ == '__main__':
if 'TRAVIS' in os.environ:
rc = call('coveralls')
raise SystemExit(rc)
5 changes: 5 additions & 0 deletions tests/fixtures/datapackage_with_foo.txt_resource.json
@@ -0,0 +1,5 @@
{
"resources": [
{ "path": "foo.txt" }
]
}
1 change: 1 addition & 0 deletions tests/fixtures/empty_array.json
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions tests/fixtures/empty_datapackage.json
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions tests/fixtures/empty_schema.json
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions tests/fixtures/foo.txt
@@ -0,0 +1 @@
foo
2 changes: 2 additions & 0 deletions tests/fixtures/foo_newline_bar.txt
@@ -0,0 +1,2 @@
foo
bar
Binary file added tests/fixtures/image.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions tests/fixtures/not_a_json
@@ -0,0 +1 @@
I'm not a JSON
1 change: 1 addition & 0 deletions tests/fixtures/unicode.txt
@@ -0,0 +1 @@
万事开头难

0 comments on commit 9baf726

Please sign in to comment.