diff --git a/.travis.yml b/.travis.yml index 3a1eb50..83a126b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,16 @@ language: ruby -bundler_args: --without debug script: "bundle exec rspec spec" -before_install: - - 'gem update --system --conservative || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems)' - - 'gem update bundler --conservative' env: - CI=true rvm: - - 2.2.2 - - 2.3 - 2.4 - 2.5 - 2.6 - - jruby-9 - - rbx-3 + - 2.7 + - jruby cache: bundler sudo: false matrix: allow_failures: - - rvm: jruby-9 - - rvm: rbx-3 + - rvm: jruby dist: trusty diff --git a/Gemfile b/Gemfile index cb88497..26e1cd1 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem 'rdf-xsd', github: "ruby-rdf/rdf-xsd", branch: "develop" group :development, :test do gem 'ebnf', github: "dryruby/ebnf", branch: "develop" gem 'json-ld', github: "ruby-rdf/json-ld", branch: "develop" + gem "rdf-aggregate-repo", git: "https://github.com/ruby-rdf/rdf-aggregate-repo", branch: "develop" gem 'rdf-isomorphic', github: "ruby-rdf/rdf-isomorphic", branch: "develop" gem "rdf-rdfa", github: "ruby-rdf/rdf-rdfa", branch: "develop" gem "rdf-spec", github: "ruby-rdf/rdf-spec", branch: "develop" diff --git a/README.md b/README.md index 1aac24d..1996c10 100644 --- a/README.md +++ b/README.md @@ -104,8 +104,8 @@ The `rdf` command-line interface is extended with `entail` and `lint` commands. ## Dependencies -* [Ruby](https://ruby-lang.org/) (>= 2.2.2) -* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.0) +* [Ruby](https://ruby-lang.org/) (>= 2.4) +* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.1) ## Mailing List diff --git a/VERSION b/VERSION index be14282..a918a2a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.3 +0.6.0 diff --git a/lib/rdf/reasoner/extensions.rb b/lib/rdf/reasoner/extensions.rb index cd74cb6..1641940 100644 --- a/lib/rdf/reasoner/extensions.rb +++ b/lib/rdf/reasoner/extensions.rb @@ -34,9 +34,9 @@ def entail(method, &block) # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def domain_compatible?(resource, queryable, options = {}) + def domain_compatible?(resource, queryable, **options) %w(owl rdfs schema).map {|r| "domain_compatible_#{r}?".to_sym}.all? do |meth| - !self.respond_to?(meth) || self.send(meth, resource, queryable, options) + !self.respond_to?(meth) || self.send(meth, resource, queryable, **options) end end @@ -50,9 +50,9 @@ def domain_compatible?(resource, queryable, options = {}) # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def range_compatible?(resource, queryable, options = {}) + def range_compatible?(resource, queryable, **options) %w(owl rdfs schema).map {|r| "range_compatible_#{r}?".to_sym}.all? do |meth| - !self.respond_to?(meth) || self.send(meth, resource, queryable, options) + !self.respond_to?(meth) || self.send(meth, resource, queryable, **options) end end end @@ -89,9 +89,9 @@ def entail(method, &block) # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def domain_compatible?(resource, queryable, options = {}) + def domain_compatible?(resource, queryable, **options) %w(owl rdfs schema).map {|r| "domain_compatible_#{r}?".to_sym}.all? do |meth| - !self.respond_to?(meth) || self.send(meth, resource, queryable, options) + !self.respond_to?(meth) || self.send(meth, resource, queryable, **options) end end @@ -105,9 +105,9 @@ def domain_compatible?(resource, queryable, options = {}) # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def range_compatible?(resource, queryable, options = {}) + def range_compatible?(resource, queryable, **options) %w(owl rdfs schema).map {|r| "range_compatible_#{r}?".to_sym}.all? do |meth| - !self.respond_to?(meth) || self.send(meth, resource, queryable, options) + !self.respond_to?(meth) || self.send(meth, resource, queryable, **options) end end end @@ -233,7 +233,7 @@ def lint messages = {} # Check for defined classes in known vocabularies - self.query(predicate: RDF.type) do |stmt| + self.query({predicate: RDF.type}) do |stmt| vocab = RDF::Vocabulary.find(stmt.object) term = (RDF::Vocabulary.find_term(stmt.object) rescue nil) if vocab pname = term ? term.pname : stmt.object.pname @@ -275,7 +275,7 @@ def lint end # See if type of the subject is in the domain of this predicate - resource_types[stmt.subject] ||= self.query(subject: stmt.subject, predicate: RDF.type). + resource_types[stmt.subject] ||= self.query({subject: stmt.subject, predicate: RDF.type}). map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}. flatten. uniq. @@ -290,7 +290,7 @@ def lint end # Make sure that if ranges are defined, the object has an appropriate type - resource_types[stmt.object] ||= self.query(subject: stmt.object, predicate: RDF.type). + resource_types[stmt.object] ||= self.query({subject: stmt.object, predicate: RDF.type}). map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}. flatten. uniq. @@ -316,7 +316,7 @@ def lint def show_resource(resource) if resource.node? resource.to_ntriples + '(' + - self.query(subject: resource, predicate: RDF.type). + self.query({subject: resource, predicate: RDF.type}). map {|s| s.object.uri? ? s.object.pname : s.object.to_ntriples} .join(',') + ')' diff --git a/lib/rdf/reasoner/owl.rb b/lib/rdf/reasoner/owl.rb index 5222a21..a633efb 100644 --- a/lib/rdf/reasoner/owl.rb +++ b/lib/rdf/reasoner/owl.rb @@ -50,7 +50,7 @@ def _entail_equivalentClass if self.predicate == RDF.type if term = (RDF::Vocabulary.find_term(self.object) rescue nil) term._entail_equivalentClass do |t| - statements << RDF::Statement(self.to_h.merge(object: t, inferred: true)) + statements << RDF::Statement(**self.to_h.merge(object: t, inferred: true)) end end end @@ -89,7 +89,7 @@ def _entail_equivalentProperty statements = [] if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil) term._entail_equivalentProperty do |t| - statements << RDF::Statement(self.to_h.merge(predicate: t, inferred: true)) + statements << RDF::Statement(**self.to_h.merge(predicate: t, inferred: true)) end end statements.each {|s| yield s} if block_given? diff --git a/lib/rdf/reasoner/rdfs.rb b/lib/rdf/reasoner/rdfs.rb index 359ac1f..bfa8b69 100644 --- a/lib/rdf/reasoner/rdfs.rb +++ b/lib/rdf/reasoner/rdfs.rb @@ -74,7 +74,7 @@ def _entail_subClassOf if term = (RDF::Vocabulary.find_term(self.object) rescue nil) term._entail_subClassOf do |t| next if t.node? # Don't entail BNodes - statements << RDF::Statement(self.to_h.merge(object: t, inferred: true)) + statements << RDF::Statement(**self.to_h.merge(object: t, inferred: true)) end end #$stderr.puts("subClassf(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}") @@ -143,7 +143,7 @@ def _entail_subPropertyOf statements = [] if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil) term._entail_subPropertyOf do |t| - statements << RDF::Statement(self.to_h.merge(predicate: t, inferred: true)) + statements << RDF::Statement(**self.to_h.merge(predicate: t, inferred: true)) end #$stderr.puts("subPropertyOf(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}") end @@ -208,7 +208,7 @@ def _entail_domain if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil) term.domain.each do |t| next if t.node? # Don't entail BNodes - statements << RDF::Statement(self.to_h.merge(predicate: RDF.type, object: t, inferred: true)) + statements << RDF::Statement(**self.to_h.merge(predicate: RDF.type, object: t, inferred: true)) end end #$stderr.puts("domain(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}") @@ -229,7 +229,7 @@ def _entail_range if object.resource? && term = (RDF::Vocabulary.find_term(self.predicate) rescue nil) term.range.each do |t| next if t.node? # Don't entail BNodes - statements << RDF::Statement(self.to_h.merge(subject: self.object, predicate: RDF.type, object: t, inferred: true)) + statements << RDF::Statement(**self.to_h.merge(subject: self.object, predicate: RDF.type, object: t, inferred: true)) end end #$stderr.puts("range(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}") @@ -249,13 +249,13 @@ def _entail_range # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def domain_compatible_rdfs?(resource, queryable, options = {}) + def domain_compatible_rdfs?(resource, queryable, **options) raise RDF::Reasoner::Error, "#{self} can't get domains" unless property? domains = Array(self.domain).reject(&:node?) - [RDF::OWL.Thing, RDF::RDFS.Resource] # Fully entailed types of the resource types = options.fetch(:types) do - queryable.query(subject: resource, predicate: RDF.type). + queryable.query({subject: resource, predicate: RDF.type}). map {|s| (t = (RDF::Vocabulary.find_term(s.object)) rescue nil) && t.entail(:subClassOf)}. flatten. uniq. @@ -276,7 +276,7 @@ def domain_compatible_rdfs?(resource, queryable, options = {}) # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def range_compatible_rdfs?(resource, queryable, options = {}) + def range_compatible_rdfs?(resource, queryable, **options) raise RDF::Reasoner::Error, "#{self} can't get ranges" unless property? if !(ranges = Array(self.range).reject(&:node?) - [RDF::OWL.Thing, RDF::RDFS.Resource]).empty? if resource.literal? @@ -337,7 +337,7 @@ def range_compatible_rdfs?(resource, queryable, options = {}) else # Fully entailed types of the resource types = options.fetch(:types) do - queryable.query(subject: resource, predicate: RDF.type). + queryable.query({subject: resource, predicate: RDF.type}). map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}. flatten. uniq. diff --git a/lib/rdf/reasoner/schema.rb b/lib/rdf/reasoner/schema.rb index e785bc8..da16039 100644 --- a/lib/rdf/reasoner/schema.rb +++ b/lib/rdf/reasoner/schema.rb @@ -22,12 +22,12 @@ module Schema # @param [Hash{Symbol => Object}] options # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def domain_compatible_schema?(resource, queryable, options = {}) + def domain_compatible_schema?(resource, queryable, **options) raise RDF::Reasoner::Error, "#{self} can't get domains" unless property? domains = Array(self.domainIncludes) - [RDF::OWL.Thing] # Fully entailed types of the resource - types = entailed_types(resource, queryable, options) unless domains.empty? + types = entailed_types(resource, queryable, **options) unless domains.empty? # Every domain must match some entailed type resource_acceptable = Array(types).empty? || domains.any? {|d| types.include?(d)} @@ -35,7 +35,7 @@ def domain_compatible_schema?(resource, queryable, options = {}) # Resource may still be acceptable if types include schema:Role, and any any other resource references `resource` using this property resource_acceptable || types.include?(RDF::Vocab::SCHEMA.Role) && - !queryable.query(predicate: self, object: resource).empty? + !queryable.query({predicate: self, object: resource}).empty? end ## @@ -52,7 +52,7 @@ def domain_compatible_schema?(resource, queryable, options = {}) # @param [Hash{Symbol => Object}] options ({}) # @option options [Array] :types # Fully entailed types of resource, if not provided, they are queried - def range_compatible_schema?(resource, queryable, options = {}) + def range_compatible_schema?(resource, queryable, **options) raise RDF::Reasoner::Error, "#{self} can't get ranges" unless property? if !(ranges = Array(self.rangeIncludes) - [RDF::OWL.Thing]).empty? if resource.literal? @@ -123,12 +123,12 @@ def range_compatible_schema?(resource, queryable, options = {}) true # schema:URL matches URI resources elsif ranges == [RDF::Vocab::SCHEMA.Text] && resource.uri? # Allowed if resource is untyped - entailed_types(resource, queryable, options).empty? + entailed_types(resource, queryable, **options).empty? elsif literal_range?(ranges) false # If resource isn't literal, this is a range violation else # Fully entailed types of the resource - types = entailed_types(resource, queryable, options) + types = entailed_types(resource, queryable, **options) # Every range must match some entailed type resource_acceptable = Array(types).empty? || ranges.any? {|d| types.include?(d)} @@ -138,7 +138,7 @@ def range_compatible_schema?(resource, queryable, options = {}) # Resource also acceptable if it is a Role, and the Role object contains the same predicate having a compatible object types.include?(RDF::Vocab::SCHEMA.Role) && - queryable.query(subject: resource, predicate: self).any? do |stmt| + queryable.query({subject: resource, predicate: self}).any? do |stmt| acc = self.range_compatible_schema?(stmt.object, queryable) acc end || @@ -174,9 +174,9 @@ def self.included(mod) private # Fully entailed types - def entailed_types(resource, queryable, options = {}) + def entailed_types(resource, queryable, **options) options.fetch(:types) do - queryable.query(subject: resource, predicate: RDF.type). + queryable.query({subject: resource, predicate: RDF.type}). map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}. flatten. uniq. diff --git a/rdf-reasoner.gemspec b/rdf-reasoner.gemspec index 26e9c83..c958a91 100755 --- a/rdf-reasoner.gemspec +++ b/rdf-reasoner.gemspec @@ -23,17 +23,17 @@ Gem::Specification.new do |gem| the vocabulary ruleset. This can be used to implement SPARQL Entailment Regimes.).gsub(/\s+/m, ' ') - gem.required_ruby_version = '>= 2.2.2' + gem.required_ruby_version = '>= 2.4' gem.requirements = [] - gem.add_runtime_dependency 'rdf', '~> 3.0' - gem.add_runtime_dependency 'rdf-vocab', '~> 3.0' - gem.add_runtime_dependency 'rdf-xsd', '~> 3.0' + gem.add_runtime_dependency 'rdf', '~> 3.1' + gem.add_runtime_dependency 'rdf-vocab', '~> 3.1' + gem.add_runtime_dependency 'rdf-xsd', '~> 3.1' - gem.add_development_dependency 'rdf-spec', '~> 3.0' - gem.add_development_dependency 'rdf-turtle', '~> 3.0' - gem.add_development_dependency 'json-ld', '~> 3.0' + gem.add_development_dependency 'rdf-spec', '~> 3.1' + gem.add_development_dependency 'rdf-turtle', '~> 3.1' + gem.add_development_dependency 'json-ld', '~> 3.1' gem.add_development_dependency 'equivalent-xml', '~> 0.6' - gem.add_development_dependency 'rspec', '~> 3.8' - gem.add_development_dependency 'yard' , '~> 0.9.19' + gem.add_development_dependency 'rspec', '~> 3.9' + gem.add_development_dependency 'yard' , '~> 0.9.20' gem.post_install_message = nil end diff --git a/script/reason b/script/reason index 9ee3b0f..61a2f66 100755 --- a/script/reason +++ b/script/reason @@ -11,7 +11,7 @@ end require 'getoptlong' -def run(reader, options) +def run(reader, **options) repo = RDF::Repository.new << reader stmt_cnt = repo.count prefixes = reader.prefixes @@ -96,13 +96,13 @@ end if ARGV.empty? s = input ? input : $stdin.read - RDF::Reader.for(options[:input_format] || :ntriples).new(input, options) do |reader| - run(reader, options) + RDF::Reader.for(options[:input_format] || :ntriples).new(input, **options) do |reader| + run(reader, **options) end else ARGV.each do |file| RDF::Reader.open(file, parser_options) do |reader| - run(reader, options) + run(reader, **options) end end end diff --git a/spec/suite_helper.rb b/spec/suite_helper.rb index 548fd27..226022d 100644 --- a/spec/suite_helper.rb +++ b/spec/suite_helper.rb @@ -22,7 +22,7 @@ class << self # HTTP Request headers. # @return [IO] File stream # @yield [IO] File stream - def self.open_file(filename_or_url, options = {}, &block) + def self.open_file(filename_or_url, **options, &block) case when filename_or_url.to_s =~ /^file:/ path = filename_or_url[5..-1]