Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
from __future__ import unicode_literals
from .util import Specification, is_url, is_email
from . import compat
class Source(Specification):
"""
Source object which can be added to a DataPackage object or a Resource
object to represent where the data comes from.
From the specification:
Each source hash may have name, web and email fields.
"""
SPECIFICATION = {'name': compat.str,
'web': compat.str,
'email': compat.str}
@property
def web(self):
"""
Link to the source of the data on the web
"""
return self['web']
@web.setter
def web(self, value):
if not value:
if 'web' in self:
del self['web']
return
class License(Specification):
"""
License object which can be added to a DataPackage's license or licenses
array or a Resource's licensese array.
From the specification:
"[E]ntry MUST be a hash with a type. The type SHOULD be an
**Open Definition license** ID if an ID exists for the license.
If another license name or identifier is used as type then the
url property MUST link to the actual license text. The url
property MAY be specified when used in combination with an
**Open Definition license ID**.
"""
SPECIFICATION = {'type': compat.str,
'url': compat.str}
def __init__(self, *args, **kwargs):
# We need to pick them out in a specific order to make sure that
# the url is set when type is not an Open Definition license id
self.url = kwargs.pop('url', None)
self.type = kwargs.pop('type', None)
super(License, self).__init__(*args, **kwargs)
@property
def type(self):
"""
The type should be an **Open Definition license** ID but
can be any string which then has to be combined with a
link
"""
dict.__delitem__(self, attribute)
return
# Attribute must exist in the specification keys
if attribute in self.SPECIFICATION.keys():
spec_type = self.SPECIFICATION[attribute]
# If spec_type is None we don't do any validation of type
if spec_type is not None:
# To accommodate for multiple types we cast non-tuples into
# a tuple to make later processing easier
if type(spec_type) != tuple:
spec_type = (spec_type,)
if not isinstance(value, spec_type):
raise TypeError(
"Attribute '{0}' ({1}) should be {2}".format(
attribute, type(value),
' or '.join([compat.str(s) for s in spec_type])))
elif not self.EXTENDABLE:
raise AttributeError(
"Attribute '{0}' is not allowed in a '{1}' object".format(
attribute, self.__class__.__name__))
dict.__setitem__(self, attribute, value)
def email(self, value):
if not value:
if 'email' in self:
del self['email']
return
if not is_email(value):
raise ValueError("not an email address: {0}".format(value))
self['email'] = compat.str(value)
SPECIFICATION = {'required': bool,
'minLength': int,
'maxLength': int,
'unique': bool,
'pattern': compat.str,
'minimum': None,
'maximum': None}
class Reference(Specification):
"""
Reference object which can be added to a ForeignKey object to represent
the reference to the other datapackage.
"""
SPECIFICATION = {'datapackage': compat.str,
'resource': compat.str,
'fields': (compat.str, list)}
REQUIRED = ('fields',)
def __setattr__(self, attribute, value):
if attribute == 'fields':
# We need to make sure all fields are represented with by their
# names if it is a list
if type(value) == list:
modified_value = []
for single_value in value:
if type(single_value) == compat.str:
modified_value.append(single_value)
elif isinstance(single_value, Field):
modified_value.append(single_value.name)
else:
def web(self, value):
if not value:
if 'web' in self:
del self['web']
return
if not is_url(value):
raise ValueError("not a url: {0}".format(value))
self['web'] = compat.str(value)
def name(self, value):
if not value:
raise ValueError('A person must have a name')
self['name'] = compat.str(value)