diff --git a/VERSION b/VERSION index 0aec50e6..3ad0595a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.4 +3.1.5 diff --git a/bin/rdf b/bin/rdf index edfddfb2..7ba1e94a 100755 --- a/bin/rdf +++ b/bin/rdf @@ -1,7 +1,7 @@ #!/usr/bin/env ruby -$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))) +$:.unshift(File.expand_path("../../lib", __FILE__)) require 'rubygems' -require 'rdf/cli' +require 'rdf' options = RDF::CLI.options(ARGV) diff --git a/lib/rdf.rb b/lib/rdf.rb index 57d21fa5..227e77e9 100644 --- a/lib/rdf.rb +++ b/lib/rdf.rb @@ -76,6 +76,9 @@ module RDF # Utilities autoload :Util, 'rdf/util' + # CLI + autoload :CLI, 'rdf/cli' + ## # Alias for `RDF::Resource.new`. # diff --git a/lib/rdf/cli.rb b/lib/rdf/cli.rb index ff1988f7..a1a3e29e 100644 --- a/lib/rdf/cli.rb +++ b/lib/rdf/cli.rb @@ -8,7 +8,7 @@ require 'linkeddata' rescue LoadError # Silently load without linkeddata, but try some others - %w(reasoner rdfa rdfxml turtle vocab json/ld ld/patch).each do |ser| + %w(microdata n3 rdfa rdfxml reasoner tabular trig trix turtle vocab xsd json/ld ld/patch).each do |ser| begin require ser.include?('/') ? ser : "rdf/#{ser}" rescue LoadError @@ -296,6 +296,12 @@ def to_hash control: :none, on: ["-o", "--output FILE"], description: "File to write output, defaults to STDOUT") {|arg| File.open(arg, "w")}, + RDF::CLI::Option.new( + symbol: :ordered, + control: :checkbox, + datatype: TrueClass, + on: ["--ordered"], + description: "Use order preserving repository"), RDF::CLI::Option.new( symbol: :format, control: :select, @@ -495,14 +501,16 @@ def self.exec(args, output: $stdout, option_parser: nil, messages: {}, **options options[:format] = options[:format].to_sym if options[:format] options[:output_format] = options[:output_format].to_sym if options[:output_format] - @repository = RDF::Repository.new + @repository = options[:ordered] ? + [].extend(RDF::Enumerable, RDF::Queryable) : + RDF::Repository.new # Parse input files if any command requires it if cmds.any? {|c| COMMANDS[c.to_sym][:parse]} start = Time.new count = 0 self.parse(args, **options) do |reader| - @repository << reader + reader.each_statement {|st| @repository << st} end secs = Time.new - start options[:logger].info "Parsed #{repository.count} statements with #{@readers.join(', ')} in #{secs} seconds @ #{count/secs} statements/second." diff --git a/lib/rdf/model/uri.rb b/lib/rdf/model/uri.rb index 84b0d877..5dedfc6b 100644 --- a/lib/rdf/model/uri.rb +++ b/lib/rdf/model/uri.rb @@ -902,7 +902,7 @@ def user=(value) # Normalized version of user # @return [String] def normalized_user - URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if user + URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if user end ## @@ -928,7 +928,7 @@ def password=(value) # Normalized version of password # @return [String] def normalized_password - URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if password + URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if password end HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze @@ -1295,7 +1295,7 @@ def normalize_segment(value, expr, downcase = false) value = value.dup.force_encoding(Encoding::UTF_8) decoded = CGI.unescape(value) decoded.downcase! if downcase - URI.encode(decoded, /[^(?:#{expr})]/) + URI.encode(decoded, /[^(?:#{expr})]/).force_encoding(Encoding::UTF_8) end end diff --git a/lib/rdf/util/file.rb b/lib/rdf/util/file.rb index 543d853c..7f91f7fd 100644 --- a/lib/rdf/util/file.rb +++ b/lib/rdf/util/file.rb @@ -14,7 +14,7 @@ module RDF; module Util # allowing the use of `Rack::Cache` to avoid network access. # # To use other HTTP clients, consumers can subclass - # {RDF::Util::File::HttpAdapter} and set the {RDF::Util::File.http_adapter}. + # {RDF::Util::File::HttpAdapter} and set the {RDF::Util::File.}. # # Also supports the file: scheme for access to local files. # @@ -121,8 +121,8 @@ def self.open_url(base_uri, proxy: nil, headers: {}, verify_none: false, **optio redirect_count = 0 max_redirects = 5 - parsed_url = ::URI.parse(base_uri) - parsed_proxy = ::URI.parse(proxy.to_s) + parsed_url = RDF::URI.parse(base_uri) + parsed_proxy = RDF::URI.parse(proxy.to_s) base_uri = parsed_url.to_s remote_document = nil diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 75ee3517..d431fca0 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -76,9 +76,16 @@ end end + describe "--ordered" do + it "sets :ordered" do + options = RDF::CLI.options(%w(help --ordered) << triple) + expect(options.options[:ordered]).to be_truthy + end + end + describe "--evaluate" do it "sets :evaluate" do - options = RDF::CLI.options(%w(helpcount --format ntriples --evaluate) << triple) + options = RDF::CLI.options(%w(help count --format ntriples --evaluate) << triple) expect(options.options[:evaluate]).to eql triple end end diff --git a/spec/model_uri_spec.rb b/spec/model_uri_spec.rb index 0a32c3d2..3273c410 100644 --- a/spec/model_uri_spec.rb +++ b/spec/model_uri_spec.rb @@ -470,6 +470,10 @@ "urn" => [ "urn:ex:s001", "urn:ex:s001" + ], + "utf-8" => [ + "Dürst", + "Dürst" ] }.each do |name, (input, output)| it "#canonicalize #{name}" do @@ -477,7 +481,7 @@ u2 = RDF::URI(output) expect(u1.canonicalize.hash).to eq u2.hash expect(u1.canonicalize.to_s).to eq u2.to_s - expect(u1).to eq u1 + expect(u1.canonicalize).to eq u1.canonicalize end end it "#canonicalize! alters resource" do @@ -486,11 +490,6 @@ expect(u1.canonicalize!.to_s).to eq u2.to_s expect(u1).to eq u2 end - it "#canonicalize does not fail with Encoding::CompatibilityError on weird IRIs" do - u1 = RDF::URI "htЫtp://user:passoЫd@exaЫmple.com:8080/path ПУТЬ?queЫry=valЫue#fragmeЫnt" - u2 = RDF::URI "ht%D0%ABtp://user:passoЫd@exaЫmple.com:8080/path%20ПУТЬ?queЫry=valЫue#fragmeЫnt" - expect {u1.canonicalize.to_s.dup.force_encoding(u2.to_s.encoding)}.not_to raise_error - end end describe "#/" do diff --git a/spec/util_logger_spec.rb b/spec/util_logger_spec.rb index 8a30ffa9..50e4ee28 100644 --- a/spec/util_logger_spec.rb +++ b/spec/util_logger_spec.rb @@ -100,22 +100,22 @@ def initialize(logger = nil) describe "#log_info" do it "Logs messages, and yield return" do subject.log_info("a", "b") {"c"} - expect(subject.logger.to_s).to eql "INFO a: b: c\n" + expect(subject.logger.to_s).to eql " INFO a: b: c\n" end it "adds lineno" do subject.log_info("a", lineno: 10) - expect(subject.logger.to_s).to eql "INFO [line 10] a\n" + expect(subject.logger.to_s).to eql " INFO [line 10] a\n" end it "adds depth with option" do subject.log_info("a", depth: 2) - expect(subject.logger.to_s).to eql "INFO a\n" + expect(subject.logger.to_s).to eql " INFO a\n" end it "adds depth with option" do subject.log_info("a", depth: 2) - expect(subject.logger.to_s).to eql "INFO a\n" + expect(subject.logger.to_s).to eql " INFO a\n" end it "uses logger from @options" do @@ -123,7 +123,7 @@ def initialize(logger = nil) logger.options[:logger] = RDF::Spec.logger logger.log_info("a") expect(logger.instance_variable_get(:@logger).to_s).to be_empty - expect(logger.options[:logger].to_s).to eql "INFO a\n" + expect(logger.options[:logger].to_s).to eql " INFO a\n" end it "uses logger from options" do @@ -131,7 +131,7 @@ def initialize(logger = nil) l = RDF::Spec.logger logger.log_info("a", logger: l) expect(logger.instance_variable_get(:@logger).to_s).to be_empty - expect(l.to_s).to eql "INFO a\n" + expect(l.to_s).to eql " INFO a\n" end it "increments log_statistics" do