Class: DataPackage::Package

Inherits:
Hash
  • Object
show all
Includes:
Helpers
Defined in:
lib/datapackage/package.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#base_path, #dereference_descriptor, #is_fully_qualified_url?, #is_safe_path?, #join_paths, #load_json, #resolve_json_reference

Constructor Details

#initialize(descriptor = nil, opts: {}) ⇒ Package

Parse or create a data package Supports reading data from JSON file, directory, and a URL

descriptor

Hash or String

opts

Options used to customize reading and parsing



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/datapackage/package.rb', line 15

def initialize(descriptor = nil, opts: {})
  @opts = opts
  @dead_resources = []
  self.merge! parse_package(descriptor)
  @profile = DataPackage::Profile.new(self.fetch('profile', DataPackage::DEFAULTS[:package][:profile]))
  self['profile'] = @profile.name
  define_properties!
  load_resources!
rescue OpenURI::HTTPError, SocketError => e
  raise PackageException.new "Package URL returned #{e.message}"
rescue JSON::ParserError
  raise PackageException.new 'Package descriptor is not valid JSON'
end

Instance Attribute Details

#errorsObject (readonly)

Public



9
10
11
# File 'lib/datapackage/package.rb', line 9

def errors
  @errors
end

#profileObject (readonly)

Public



9
10
11
# File 'lib/datapackage/package.rb', line 9

def profile
  @profile
end

Instance Method Details

#add_resource(resource) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/datapackage/package.rb', line 70

def add_resource(resource)
  resource = load_resource(resource)
  self['resources'].push(resource)
  begin
    self.validate
    resource
  rescue DataPackage::ValidationError
    self['resources'].pop
    nil
  end
end

#baseObject

Returns the directory for a local file package or base url for a remote Returns nil for an in-memory object (because it has no base as yet)



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/datapackage/package.rb', line 99

def base
  # user can override base
  return @opts[:base] if @opts[:base]
  return '' unless @location
  # work out base directory or uri
  if local?
      return File.dirname(@location)
  else
      return @location.split('/')[0..-2].join('/')
  end
end

#descriptorObject



51
52
53
# File 'lib/datapackage/package.rb', line 51

def descriptor
  self.to_h
end

#get_resource(resource_name) ⇒ Object



65
66
67
68
# File 'lib/datapackage/package.rb', line 65

def get_resource(resource_name)
  update_resources!
  self['resources'].find{ |resource| resource.name == resource_name }
end

#infer(base_path: nil, directory: nil) ⇒ Object

Raises:



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/datapackage/package.rb', line 122

def infer(base_path: nil, directory: nil)
  raise PackageException.new('Base path is required for infer') unless base_path
  raise PackageException.new('Directory is required for infer') unless directory

  dir_path = File.join(base_path, directory)
  Dir.glob("#{dir_path}/*.csv") do |filename|
    resource = Resource.infer(filename)
    add_resource(resource)
  end

  # If there were CSVs, this is a tabular data package
  if resources.count > 0
    self['profile'] = 'tabular-data-package'
  end

  descriptor
end

#iter_errorsObject



43
44
45
46
47
48
49
# File 'lib/datapackage/package.rb', line 43

def iter_errors
  errors = @profile.iter_errors(self){ |err| err }
  self['resources'].each do |resource|
    resource.iter_errors{ |err| errors << err }
  end
  errors.each{ |error| yield error }
end

#local?Boolean

Is this a local package? Returns true if created from an in-memory object or a file/directory reference

Returns:

  • (Boolean)


112
113
114
115
116
# File 'lib/datapackage/package.rb', line 112

def local?
  return @local if @local
  return false if @location =~ /\A#{URI::regexp}\z/
  true
end

#property(property, default = nil) ⇒ Object



118
119
120
# File 'lib/datapackage/package.rb', line 118

def property(property, default = nil)
  self[property] || default
end

#remove_resource(resource_name) ⇒ Object



82
83
84
85
86
87
# File 'lib/datapackage/package.rb', line 82

def remove_resource(resource_name)
  update_resources!
  resource = get_resource(resource_name)
  self['resources'].reject!{ |resource| resource.name == resource_name }
  resource
end

#resource_namesObject



60
61
62
63
# File 'lib/datapackage/package.rb', line 60

def resource_names
  update_resources!
  self['resources'].map{|res| res.name}
end

#resourcesObject



55
56
57
58
# File 'lib/datapackage/package.rb', line 55

def resources
  update_resources!
  self['resources']
end

#save(target = @location) ⇒ Object



89
90
91
92
93
# File 'lib/datapackage/package.rb', line 89

def save(target=@location)
  update_resources!
  File.open(target, "w") { |file| file << JSON.pretty_generate(self) }
  true
end

#valid?Boolean Also known as: valid

Returns:

  • (Boolean)


29
30
31
32
33
# File 'lib/datapackage/package.rb', line 29

def valid?
  return false unless @profile.valid?(self)
  return false if self['resources'].map{ |resource| resource.valid? }.include?(false)
  true
end

#validateObject



37
38
39
40
41
# File 'lib/datapackage/package.rb', line 37

def validate
  @profile.validate(self)
  self['resources'].each { |resource| resource.validate }
  true
end