From 407eda2a2de647d952f5957f46d992d89fd53c10 Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Thu, 29 Dec 2016 23:03:11 -0800 Subject: [PATCH] A number of compatible keyword arguments changes, Methods that can take a Statement must wait for `Statement#to_hash` to be completely removed. Logger level can be an integer in some existing calls. Map those to symbols. --- lib/rdf/cli.rb | 25 ++++++----- lib/rdf/mixin/enumerable.rb | 5 +-- lib/rdf/model/graph.rb | 6 +-- lib/rdf/model/literal.rb | 40 +++++++++-------- lib/rdf/model/literal/boolean.rb | 11 +++-- lib/rdf/model/literal/date.rb | 11 +++-- lib/rdf/model/literal/datetime.rb | 7 ++- lib/rdf/model/literal/decimal.rb | 11 +++-- lib/rdf/model/literal/double.rb | 11 +++-- lib/rdf/model/literal/integer.rb | 13 +++--- lib/rdf/model/literal/time.rb | 11 +++-- lib/rdf/model/literal/token.rb | 13 +++--- lib/rdf/model/statement.rb | 23 ++++++---- lib/rdf/model/uri.rb | 2 +- lib/rdf/ntriples/reader.rb | 11 +++-- lib/rdf/ntriples/writer.rb | 29 ++++++------ lib/rdf/query.rb | 14 +++--- lib/rdf/query/pattern.rb | 5 ++- lib/rdf/query/solution.rb | 5 ++- lib/rdf/reader.rb | 55 ++++++++++++++--------- lib/rdf/transaction.rb | 2 +- lib/rdf/util/file.rb | 75 ++++++++++++++----------------- lib/rdf/util/logger.rb | 52 ++++++++++----------- lib/rdf/util/uuid.rb | 5 ++- lib/rdf/vocab/writer.rb | 8 ++-- lib/rdf/vocabulary.rb | 18 ++++---- lib/rdf/writer.rb | 42 ++++++++++------- spec/util_logger_spec.rb | 43 ++++++++++++++++++ 28 files changed, 311 insertions(+), 242 deletions(-) diff --git a/lib/rdf/cli.rb b/lib/rdf/cli.rb index 955628f0..845342cf 100644 --- a/lib/rdf/cli.rb +++ b/lib/rdf/cli.rb @@ -338,23 +338,24 @@ def self.usage(options, banner: nil) # Execute one or more commands, parsing input as necessary # # @param [Array] args + # @param [IO] output + # @param [Hash{Symbol => Object}] options # @return [Boolean] - def self.exec(args, **options) - out = options[:output] || $stdout - out.set_encoding(Encoding::UTF_8) if out.respond_to?(:set_encoding) && RUBY_PLATFORM == "java" + def self.exec(args, output: $stdout, option_parser: self.options, **options) + output.set_encoding(Encoding::UTF_8) if output.respond_to?(:set_encoding) && RUBY_PLATFORM == "java" cmds, args = args.partition {|e| commands.include?(e.to_s)} if cmds.empty? - usage(options.fetch(:option_parser, self.options)) + usage(option_parser) abort "No command given" end if cmds.first == 'help' on_cmd = cmds[1] if on_cmd && COMMANDS.fetch(on_cmd.to_sym, {})[:help] - usage(options.fetch(:option_parser, self.options), banner: "Usage: #{self.basename.split('/').last} #{COMMANDS[on_cmd.to_sym][:help]}") + usage(option_parser, banner: "Usage: #{self.basename.split('/').last} #{COMMANDS[on_cmd.to_sym][:help]}") else - usage(options.fetch(:option_parser, self.options)) + usage(option_parser) end return end @@ -431,15 +432,19 @@ def self.formats(reader: false, writer: false) # yielding a reader # # @param [Array] files + # @param [String] evaluate from command-line, rather than referenced file + # @param [Symbol] format (:ntriples) Reader symbol for finding reader + # @param [Encoding] encoding set on the input + # @param [Hash{Symbol => Object}] options sent to reader # @yield [reader] # @yieldparam [RDF::Reader] # @return [nil] - def self.parse(files, **options, &block) + def self.parse(files, evaluate: nil, format: :ntriples, encoding: Encoding::UTF_8, **options, &block) if files.empty? # If files are empty, either use options[:execute] - input = options[:evaluate] ? StringIO.new(options[:evaluate]) : $stdin - input.set_encoding(options.fetch(:encoding, Encoding::UTF_8)) - r = RDF::Reader.for(options[:format] || :ntriples) + input = evaluate ? StringIO.new(evaluate) : $stdin + input.set_encoding(encoding) + r = RDF::Reader.for(format) (@readers ||= []) << r r.new(input, options) do |reader| yield(reader) diff --git a/lib/rdf/mixin/enumerable.rb b/lib/rdf/mixin/enumerable.rb index f4053c86..7ad2093e 100644 --- a/lib/rdf/mixin/enumerable.rb +++ b/lib/rdf/mixin/enumerable.rb @@ -738,11 +738,10 @@ def to_h # @see RDF::Writer.dump # @raise [RDF::WriterError] if no writer found # @since 0.2.0 - def dump(*args) - options = args.last.is_a?(Hash) ? args.pop : {} + def dump(*args, **options) writer = RDF::Writer.for(*args) raise RDF::WriterError, "No writer found using #{args.inspect}" unless writer - writer.dump(self, nil, options) + writer.dump(self, nil, **options) end protected diff --git a/lib/rdf/model/graph.rb b/lib/rdf/model/graph.rb index 82266649..a7c7c5af 100644 --- a/lib/rdf/model/graph.rb +++ b/lib/rdf/model/graph.rb @@ -87,12 +87,12 @@ def self.load(url, graph_name: nil, **options, &block) end ## - # @param [RDF::Resource] graph_name + # @param [RDF::Resource] graph_name # The graph_name from the associated {RDF::Queryable} associated # with this graph as provided with the `:data` option # (only for {RDF::Queryable} instances supporting # named graphs). - # @param [RDF::Queryable] :data (RDF::Repository.new) + # @param [RDF::Queryable] data (RDF::Repository.new) # Storage behind this graph. # # @raise [ArgumentError] if a `data` does not support named graphs. @@ -294,7 +294,7 @@ def insert_statement(statement) def insert_statements(statements) enum = Enumerable::Enumerator.new do |yielder| - statements.send(method = statements.respond_to?(:each_statement) ? :each_statement : :each) do |s| + statements.send(statements.respond_to?(:each_statement) ? :each_statement : :each) do |s| s = s.dup s.graph_name = graph_name yielder << s diff --git a/lib/rdf/model/literal.rb b/lib/rdf/model/literal.rb index 2885532a..a379f3af 100644 --- a/lib/rdf/model/literal.rb +++ b/lib/rdf/model/literal.rb @@ -104,13 +104,13 @@ def self.datatyped_class(uri) ## # @private - def self.new(value, **options) - raise ArgumentError, "datatype with language must be rdf:langString" if options[:language] && (options[:datatype] || RDF.langString).to_s != RDF.langString.to_s + def self.new(value, language: nil, datatype: nil, lexical: nil, validate: false, canonicalize: false, **options) + raise ArgumentError, "datatype with language must be rdf:langString" if language && (datatype || RDF.langString).to_s != RDF.langString.to_s klass = case when !self.equal?(RDF::Literal) self # subclasses can be directly constructed without type dispatch - when typed_literal = datatyped_class(options[:datatype].to_s) + when typed_literal = datatyped_class(datatype.to_s) typed_literal else case value when ::TrueClass then RDF::Literal::Boolean @@ -126,9 +126,13 @@ def self.new(value, **options) end end literal = klass.allocate - literal.send(:initialize, value, options) - literal.validate! if options[:validate] - literal.canonicalize! if options[:canonicalize] + if klass.equal?(RDF::Literal) + literal.send(:initialize, value, language: language, datatype: datatype) + else + literal.send(:initialize, value, datatype: datatype) + end + literal.validate! if validate + literal.canonicalize! if canonicalize literal end @@ -147,28 +151,28 @@ def self.new(value, **options) # depending on if there is language # # @param [Object] value - # @option options [Symbol] :language (nil) + # @param [Symbol] language (nil) # Language is downcased to ensure proper matching - # @option options [String] :lexical (nil) + # @param [String] lexical (nil) # Supplied lexical representation of this literal, - # otherwise it comes from transforming `value` to a string form - # See {#to_s}. - # @option options [URI] :datatype (nil) - # @option options [Boolean] :validate (false) - # @option options [Boolean] :canonicalize (false) + # otherwise it comes from transforming `value` to a string form.. + # @param [URI] datatype (nil) + # @param [Boolean] validate (false) + # @param [Boolean] canonicalize (false) # @raise [ArgumentError] # if there is a language and datatype is no rdf:langString # or datatype is rdf:langString and there is no language # @see http://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal # @see http://www.w3.org/TR/rdf11-concepts/#section-Datatypes - def initialize(value, **options) + # @see #to_s + def initialize(value, language: nil, datatype: nil, lexical: nil, validate: false, canonicalize: false) @object = value.freeze - @string = options[:lexical] if options[:lexical] + @string = lexical if lexical @string = value if !defined?(@string) && value.is_a?(String) @string = @string.encode(Encoding::UTF_8).freeze if @string @object = @string if @string && @object.is_a?(String) - @language = options[:language].to_s.downcase.to_sym if options[:language] - @datatype = RDF::URI(options[:datatype]).freeze if options[:datatype] + @language = language.to_s.downcase.to_sym if language + @datatype = RDF::URI(datatype).freeze if datatype @datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE) @datatype ||= @language ? RDF.langString : RDF::XSD.string raise ArgumentError, "datatype of rdf:langString requires a language" if !@language && @datatype == RDF::langString @@ -441,7 +445,7 @@ def squish! # # @param [String] string # @return [String] - # @see {RDF::Term#escape} + # @see RDF::Term#escape def escape(string) string.gsub('\\', '\\\\'). gsub("\t", '\\t'). diff --git a/lib/rdf/model/literal/boolean.rb b/lib/rdf/model/literal/boolean.rb index dab8967c..24ba9d2c 100644 --- a/lib/rdf/model/literal/boolean.rb +++ b/lib/rdf/model/literal/boolean.rb @@ -11,12 +11,11 @@ class Boolean < Literal FALSES = %w(false 0).freeze ## - # @param [Boolean] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + # @param [String, Boolean] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case when true.equal?(value) then true when false.equal?(value) then false diff --git a/lib/rdf/model/literal/date.rb b/lib/rdf/model/literal/date.rb index 7b35249a..706db0b6 100644 --- a/lib/rdf/model/literal/date.rb +++ b/lib/rdf/model/literal/date.rb @@ -10,12 +10,11 @@ class Date < Literal FORMAT = '%Y-%m-%d'.freeze ## - # @param [Date] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + # @param [String, Date, #to_date] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case when value.is_a?(::Date) then value when value.respond_to?(:to_date) then value.to_date diff --git a/lib/rdf/model/literal/datetime.rb b/lib/rdf/model/literal/datetime.rb index c641e386..d62df5f8 100644 --- a/lib/rdf/model/literal/datetime.rb +++ b/lib/rdf/model/literal/datetime.rb @@ -12,10 +12,9 @@ class DateTime < Literal ## # @param [DateTime] value # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case when value.is_a?(::DateTime) then value when value.respond_to?(:to_datetime) then value.to_datetime diff --git a/lib/rdf/model/literal/decimal.rb b/lib/rdf/model/literal/decimal.rb index a6155091..f52a9c59 100644 --- a/lib/rdf/model/literal/decimal.rb +++ b/lib/rdf/model/literal/decimal.rb @@ -15,12 +15,11 @@ class Decimal < Numeric GRAMMAR = /^[\+\-]?\d+(\.\d*)?$/.freeze ## - # @param [BigDecimal] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + # @param [String, BidDecimal, Numeric] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case when value.is_a?(BigDecimal) then value when value.is_a?(Numeric) then BigDecimal(value) diff --git a/lib/rdf/model/literal/double.rb b/lib/rdf/model/literal/double.rb index e6835257..ff17b4a6 100644 --- a/lib/rdf/model/literal/double.rb +++ b/lib/rdf/model/literal/double.rb @@ -15,12 +15,11 @@ class Double < Numeric GRAMMAR = /^(?:NaN|(?:[\+\-]?(?:INF|(?:\d+(\.\d*)?(e[\+\-]?\d+)?))))$/i.freeze ## - # @param [Float, #to_f] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + # @param [String, Float, #to_f] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case when value.is_a?(::String) then case value when '+INF' then 1/0.0 diff --git a/lib/rdf/model/literal/integer.rb b/lib/rdf/model/literal/integer.rb index c0d81d68..f089c34e 100644 --- a/lib/rdf/model/literal/integer.rb +++ b/lib/rdf/model/literal/integer.rb @@ -16,15 +16,14 @@ class Integer < Decimal GRAMMAR = /^[\+\-]?\d+$/.freeze ## - # @param [Integer, #to_i] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + # @param [String, Integer, #to_i] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case + when value.is_a?(::Integer) then value when value.respond_to?(:to_i) then value.to_i - when value.is_a?(::Integer) then value else Integer(value.to_s) rescue nil end end diff --git a/lib/rdf/model/literal/time.rb b/lib/rdf/model/literal/time.rb index 7a33f49e..faf52c02 100644 --- a/lib/rdf/model/literal/time.rb +++ b/lib/rdf/model/literal/time.rb @@ -15,12 +15,11 @@ class Time < Literal FORMAT = '%H:%M:%S%:z'.freeze ## - # @param [Time] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) + # @param [String, DateTime, #to_datetime] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) @object = case when value.is_a?(::DateTime) then value when value.respond_to?(:to_datetime) then value.to_datetime rescue ::DateTime.parse(value.to_s) diff --git a/lib/rdf/model/literal/token.rb b/lib/rdf/model/literal/token.rb index bbf08800..8310a9c8 100644 --- a/lib/rdf/model/literal/token.rb +++ b/lib/rdf/model/literal/token.rb @@ -9,13 +9,12 @@ class Token < Literal GRAMMAR = /\A[^\x0D\x0A\x09]+\z/i.freeze # FIXME ## - # @param [Symbol, #to_s] value - # @option options [String] :lexical (nil) - def initialize(value, **options) - @datatype = RDF::URI(options[:datatype] || self.class.const_get(:DATATYPE)) - @string = options[:lexical] if options.has_key?(:lexical) - @string ||= value if value.is_a?(String) - @object = value.is_a?(Symbol) ? value : value.to_s + # @param [String, Symbol, #to_sym] value + # @param (see Literal#initialize) + def initialize(value, datatype: nil, lexical: nil) + @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE)) + @string = lexical || (value if value.is_a?(String)) + @object = value.is_a?(Symbol) ? value : value.to_sym end ## diff --git a/lib/rdf/model/statement.rb b/lib/rdf/model/statement.rb index 2be97cf0..6a51ad4a 100644 --- a/lib/rdf/model/statement.rb +++ b/lib/rdf/model/statement.rb @@ -31,11 +31,11 @@ class Statement ## # @private # @since 0.2.2 - def self.from(statement, **options) + def self.from(statement, graph_name: nil, **options) case statement when Array, Query::Pattern - graph_name = statement[3] == false ? nil : statement[3] - self.new(statement[0], statement[1], statement[2], options.merge(graph_name: graph_name)) + graph_name ||= statement[3] == false ? nil : statement[3] + self.new(statement[0], statement[1], statement[2], graph_name: graph_name, **options) when Statement then statement when Hash then self.new(options.merge(statement)) else raise ArgumentError, "expected RDF::Statement, Hash, or Array, but got #{statement.inspect}" @@ -73,8 +73,8 @@ def self.from(statement, **options) # @overload initialize(subject, predicate, object, **options) # @param [RDF::Term] subject # A symbol is converted to an interned {Node}. - # @param [RDF::URI] predicate - # @param [RDF::Resource] object + # @param [RDF::URI] predicate + # @param [RDF::Resource] object # if not a {Resource}, it is coerced to {Literal} or {Node} depending on if it is a symbol or something other than a {Term}. # @param [Hash{Symbol => Object}] options # @option options [RDF::Term] :graph_name (nil) @@ -397,12 +397,17 @@ def to_s ## # Returns a graph containing this statement in reified form. # - # @param [Hash{Symbol => Object}] options + # @param [RDF::Term] subject (nil) + # Subject of reification. + # @param [RDF::Term] id (nil) + # Node identifier, when subject is anonymous + # @param [RDF::Term] graph_name (nil) + # Note, in RDF 1.1, a graph name MUST be an {Resource}. # @return [RDF::Graph] # @see http://www.w3.org/TR/rdf-primer/#reification - def reified(**options) - RDF::Graph.new(graph_name: options[:graph_name]) do |graph| - subject = options[:subject] || RDF::Node.new(options[:id]) + def reified(subject: nil, id: nil, graph_name: nil) + RDF::Graph.new(graph_name: graph_name) do |graph| + subject = subject || RDF::Node.new(id) graph << [subject, RDF.type, RDF[:Statement]] graph << [subject, RDF.subject, self.subject] graph << [subject, RDF.predicate, self.predicate] diff --git a/lib/rdf/model/uri.rb b/lib/rdf/model/uri.rb index 88caa16b..aa1b1c65 100644 --- a/lib/rdf/model/uri.rb +++ b/lib/rdf/model/uri.rb @@ -281,7 +281,7 @@ def urn? # # @return [Boolean] `true` or `false` # @see http://en.wikipedia.org/wiki/URI_scheme - # @see {NON_HIER_SCHEMES} + # @see NON_HIER_SCHEMES # @since 1.0.10 def hier? !NON_HIER_SCHEMES.include?(scheme) diff --git a/lib/rdf/ntriples/reader.rb b/lib/rdf/ntriples/reader.rb index bbbdd1fa..f2a32a49 100644 --- a/lib/rdf/ntriples/reader.rb +++ b/lib/rdf/ntriples/reader.rb @@ -91,6 +91,7 @@ class Reader < RDF::Reader # @param [String] input # @param [{Symbol => Object}] options # From {RDF::Reader#initialize} + # @option options [RDF::Util::Logger] :logger ([]) # @return [RDF::Term] def self.unserialize(input, **options) case input @@ -130,11 +131,12 @@ def self.parse_node(input, **options) ## # (see unserialize) + # @param [Boolean] intern (false) Use Interned URI # @return [RDF::URI] - def self.parse_uri(input, **options) + def self.parse_uri(input, intern: false, **options) if input =~ URIREF uri_str = unescape($1) - RDF::URI.send(options[:intern] ? :intern : :new, unescape($1)) + RDF::URI.send(intern ? :intern : :new, unescape($1)) end end @@ -218,12 +220,13 @@ def read_comment end ## + # @param [Boolean] intern (false) Use Interned Node # @return [RDF::URI] # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (uriref) - def read_uriref(**options) + def read_uriref(intern: false, **options) if uri_str = match(URIREF) uri_str = self.class.unescape(uri_str) - uri = RDF::URI.send(intern? && options[:intern] ? :intern : :new, uri_str) + uri = RDF::URI.send(intern? && intern ? :intern : :new, uri_str) uri.validate! if validate? uri.canonicalize! if canonicalize? uri diff --git a/lib/rdf/ntriples/writer.rb b/lib/rdf/ntriples/writer.rb index 953a2d0a..fa677d40 100644 --- a/lib/rdf/ntriples/writer.rb +++ b/lib/rdf/ntriples/writer.rb @@ -182,15 +182,14 @@ def self.serialize(value) # # @param [IO, File] output # the output stream - # @param [Hash{Symbol => Object}] options = ({}) - # any additional options. See {RDF::Writer#initialize} - # @option options [Boolean] :validate (true) + # @param [Boolean] validate (true) # whether to validate terms when serializing + # @param [Hash{Symbol => Object}] options ({}) + # any additional options. See {RDF::Writer#initialize} # @yield [writer] `self` # @yieldparam [RDF::Writer] writer # @yieldreturn [void] - def initialize(output = $stdout, **options, &block) - options = {validate: true}.merge(options) + def initialize(output = $stdout, validate: true, **options, &block) super end @@ -218,10 +217,10 @@ def write_triple(subject, predicate, object) # Returns the N-Triples representation of a statement. # # @param [RDF::Statement] statement - # @param [Hash{Symbol => Object}] options = ({}) + # @param [Hash{Symbol => Object}] options ({}) # @return [String] def format_statement(statement, **options) - format_triple(*statement.to_triple, options) + format_triple(*statement.to_triple, **options) end ## @@ -230,29 +229,29 @@ def format_statement(statement, **options) # @param [RDF::Resource] subject # @param [RDF::URI] predicate # @param [RDF::Term] object - # @param [Hash{Symbol => Object}] options = ({}) + # @param [Hash{Symbol => Object}] options ({}) # @return [String] def format_triple(subject, predicate, object, **options) - "%s %s %s ." % [subject, predicate, object].map { |value| format_term(value, options) } + "%s %s %s ." % [subject, predicate, object].map { |value| format_term(value, **options) } end ## # Returns the N-Triples representation of a blank node. # # @param [RDF::Node] node - # @param [Hash{Symbol => Object}] options = ({}) - # @option options [Boolean] :unique_bnodes (false) + # @param [Boolean] unique_bnodes (false) # Serialize node using unique identifier, rather than any used to create the node. + # @param [Hash{Symbol => Object}] options ({}) # @return [String] - def format_node(node, **options) - options[:unique_bnodes] ? node.to_unique_base : node.to_s + def format_node(node, unique_bnodes: false, **options) + unique_bnodes ? node.to_unique_base : node.to_s end ## # Returns the N-Triples representation of a URI reference using write encoding. # # @param [RDF::URI] uri - # @param [Hash{Symbol => Object}] options = ({}) + # @param [Hash{Symbol => Object}] options ({}) # @return [String] def format_uri(uri, **options) string = uri.to_s @@ -296,7 +295,7 @@ def format_uri(uri, **options) # Returns the N-Triples representation of a literal. # # @param [RDF::Literal, String, #to_s] literal - # @param [Hash{Symbol => Object}] options = ({}) + # @param [Hash{Symbol => Object}] options ({}) # @return [String] def format_literal(literal, **options) case literal diff --git a/lib/rdf/query.rb b/lib/rdf/query.rb index 58f940ac..82d9ad0f 100644 --- a/lib/rdf/query.rb +++ b/lib/rdf/query.rb @@ -165,21 +165,25 @@ def self.Solutions(*args) # @overload initialize(patterns, **options) # @param [Hash{Object => Object}] patterns # ... - # @param [Hash{Symbol => Object}] options - # any additional keyword options - # @option options [RDF::Query::Solutions] :solutions (Solutions.new) - # @option options [RDF::Resource, RDF::Query::Variable, false] :graph_name (nil) + # @param [RDF::Query::Solutions] :solutions (Solutions.new) + # @param [RDF::Resource, RDF::Query::Variable, false] :graph_name (nil) # Default graph name for matching against queryable. # Named queries either match against a specifically named # graphs if the name is an {RDF::Resource} or bound {RDF::Query::Variable}. # Names that are against unbound variables match either default # or named graphs. # The name of `false` will only match against the default graph. - # @option options [RDF::Resource, RDF::Query::Variable, false] :name (nil) + # @param [RDF::Resource, RDF::Query::Variable, false] :name (nil) # Alias for `:graph_name`. + # @param [Hash{Symbol => Object}] options + # any additional keyword options # @yield [query] # @yieldparam [RDF::Query] query # @yieldreturn [void] ignored + # + # FIXME: Once `Statement#to_hash` has been removed completely, this can change to: + # def initialize(*patterns, solutions: nil, graph_name: nil, name: nil, **options, &block) + def initialize(*patterns, &block) @options = patterns.last.is_a?(Hash) ? patterns.pop.dup : {} patterns << @options if patterns.empty? diff --git a/lib/rdf/query/pattern.rb b/lib/rdf/query/pattern.rb index 978474b5..a86a2fa6 100644 --- a/lib/rdf/query/pattern.rb +++ b/lib/rdf/query/pattern.rb @@ -5,11 +5,12 @@ class Pattern < RDF::Statement ## # @private # @since 0.2.2 - def self.from(pattern, **options) + def self.from(pattern, graph_name: nil, **options) case pattern when Pattern then pattern when Array, Statement - self.new(pattern[0], pattern[1], pattern[2], options.merge(graph_name: pattern[3])) + graph_name ||= pattern[3] + self.new(pattern[0], pattern[1], pattern[2], graph_name: graph_name, **options) when Hash then self.new(options.merge(pattern)) else raise ArgumentError, "expected RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}" end diff --git a/lib/rdf/query/solution.rb b/lib/rdf/query/solution.rb index e1c91c96..c98594a4 100644 --- a/lib/rdf/query/solution.rb +++ b/lib/rdf/query/solution.rb @@ -35,7 +35,7 @@ class Solution # # @param [Hash{Symbol => RDF::Term}] bindings # @yield [solution] - def initialize(**bindings, &block) + def initialize(bindings = {}, &block) @bindings = bindings.to_hash if block_given? @@ -269,7 +269,8 @@ def inspect # # @return (see #to_h) # @deprecated Use {#to_h} instead. - # @overload + # + # @overload binding(name) # Return the binding for this name # # @param [Symbol] name diff --git a/lib/rdf/reader.rb b/lib/rdf/reader.rb index cbb8905d..f88528b6 100644 --- a/lib/rdf/reader.rb +++ b/lib/rdf/reader.rb @@ -219,31 +219,43 @@ def to_sym # # @param [IO, File, String] input # the input stream to read - # @param [Hash{Symbol => Object}] options - # any additional options - # @option options [Encoding] :encoding (Encoding::UTF_8) + # @param [Encoding] encoding (Encoding::UTF_8) # the encoding of the input stream - # @option options [Boolean] :validate (false) + # @param [Boolean] validate (false) # whether to validate the parsed statements and values - # @option options [Boolean] :canonicalize (false) + # @param [Boolean] canonicalize (false) # whether to canonicalize parsed literals - # @option options [Boolean] :intern (true) + # @param [Boolean] intern (true) # whether to intern all parsed URIs - # @option options [Hash] :prefixes (Hash.new) + # @param [Hash] prefixes (Hash.new) # the prefix mappings to use (not supported by all readers) - # @option options [#to_s] :base_uri (nil) + # @param [#to_s] base_uri (nil) # the base URI to use when resolving relative URIs (not supported by # all readers) + # @param [Hash{Symbol => Object}] options + # any additional options # @yield [reader] `self` # @yieldparam [RDF::Reader] reader # @yieldreturn [void] ignored - def initialize(input = $stdin, **options, &block) - @options = options.dup - @options[:validate] ||= false - @options[:canonicalize] ||= false - @options[:intern] ||= true - @options[:prefixes] ||= Hash.new - @options[:base_uri] ||= input.base_uri if input.respond_to?(:base_uri) + def initialize(input = $stdin, + encoding: Encoding::UTF_8, + validate: false, + canonicalize: false, + intern: true, + prefixes: Hash.new, + base_uri: nil, + **options, + &block) + + base_uri ||= input.base_uri if input.respond_to?(:base_uri) + @options = options.merge({ + encoding: encoding, + validate: validate, + canonicalize: canonicalize, + intern: intern, + prefixes: prefixes, + base_uri: base_uri + }) @input = case input when String then StringIO.new(input) @@ -619,13 +631,12 @@ class ReaderError < IOError ## # Initializes a new lexer error instance. # - # @param [String, #to_s] message - # @param [Hash{Symbol => Object}] options - # @option options [String] :token (nil) - # @option options [Integer] :lineno (nil) - def initialize(message, **options) - @token = options[:token] - @lineno = options[:lineno] || (@token.lineno if @token.respond_to?(:lineno)) + # @param [String, #to_s] message + # @param [String] token (nil) + # @param [Integer] lineno (nil) + def initialize(message, token: nil, lineno: nil) + @token = token + @lineno = lineno || (token.lineno if token.respond_to?(:lineno)) super(message.to_s) end end # ReaderError diff --git a/lib/rdf/transaction.rb b/lib/rdf/transaction.rb index 8b1fa50e..a71704bb 100644 --- a/lib/rdf/transaction.rb +++ b/lib/rdf/transaction.rb @@ -88,7 +88,7 @@ def each(*args, &block) # @yieldparam [RDF::Transaction] tx # @return [void] def self.begin(repository, mutable: false, **options, &block) - self.new(repository, options.merge(mutable: mutable), &block) + self.new(repository, mutable: mutable, **options, &block) end ## diff --git a/lib/rdf/util/file.rb b/lib/rdf/util/file.rb index 9b8bd7a9..9b30e10a 100644 --- a/lib/rdf/util/file.rb +++ b/lib/rdf/util/file.rb @@ -30,8 +30,7 @@ class HttpAdapter # @option options [Array, String] :headers # HTTP Request headers # @return [Hash] A hash of HTTP request headers - def self.headers options - headers = options.fetch(:headers, {}) + def self.headers headers: {} headers['Accept'] ||= default_accept_header headers end @@ -45,19 +44,19 @@ def self.default_accept_header ## # @abstract # @param [String] base_uri to open + # @param [String] proxy + # HTTP Proxy to use for requests. + # @param [Array, String] headers ({}) + # HTTP Request headers + # @param [Boolean] verify_none (false) + # Don't verify SSL certificates # @param [Hash{Symbol => Object}] options # options are ignored in this implementation. Applications are encouraged # to override this implementation to provide more control over HTTP # headers and redirect following. - # @option options [String] :proxy - # HTTP Proxy to use for requests. - # @option options [Array, String] :headers - # HTTP Request headers - # @option options [Boolean] :verify_none (false) - # Don't verify SSL certificates # @return [RemoteDocument, Object] A {RemoteDocument}. If a block is given, the result of evaluating the block is returned. # @raise [IOError] if not found - def self.open_url(base_uri, **options) + def self.open_url(base_uri, proxy: nil, headers: {}, verify_none: false, **options) raise NoMethodError.new("#{self.inspect} does not implement required method `open_url` for ", "open_url") end end @@ -69,18 +68,14 @@ def self.open_url(base_uri, **options) # allowing the use of `Rack::Cache` to avoid network access. # @since 1.2 class RestClientAdapter < HttpAdapter - # @see HttpAdapter.open_url - # @param [String] base_uri to open - # @param [Hash{Symbol => Object}] options - # @return [RemoteDocument, Object] A {RemoteDocument}. If a block is given, the result of evaluating the block is returned. - # @raise [IOError] if not found - def self.open_url(base_uri, **options) - ssl_verify = options[:verify_none] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER + # (see HttpAdapter.open_url) + def self.open_url(base_uri, proxy: nil, headers: {}, verify_none: false, **options) + ssl_verify = verify_none ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER # If RestClient is loaded, prefer it - RestClient.proxy = options[:proxy].to_s if options[:proxy] + RestClient.proxy = proxy.to_s if proxy client = RestClient::Resource.new(base_uri, verify_ssl: ssl_verify) - client.get(headers(options)) do |response, request, res, &blk| + client.get(headers(headers: headers)) do |response, request, res, &blk| case response.code when 200..299 # found object @@ -109,18 +104,14 @@ def self.open_url(base_uri, **options) # Net::HTTP adapter to retrieve resources without additional dependencies # @since 1.2 class NetHttpAdapter < HttpAdapter - # @see HttpAdapter.open_url - # @param [String] base_uri to open - # @param [Hash{Symbol => Object}] options - # @return [RemoteDocument, Object] A {RemoteDocument}. If a block is given, the result of evaluating the block is returned. - # @raise [IOError] if not found - def self.open_url(base_uri, **options) - ssl_verify = options[:verify_none] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER + # (see HttpAdapter.open_url) + def self.open_url(base_uri, proxy: nil, headers: {}, verify_none: false, **options) + ssl_verify = verify_none ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER redirect_count = 0 max_redirects = 5 parsed_url = ::URI.parse(base_uri) - parsed_proxy = ::URI.parse(options[:proxy].to_s) + parsed_proxy = ::URI.parse(proxy.to_s) base_uri = parsed_url.to_s remote_document = nil @@ -131,7 +122,7 @@ def self.open_url(base_uri, **options) use_ssl: parsed_url.scheme == 'https', verify_mode: ssl_verify ) do |http| - request = Net::HTTP::Get.new(parsed_url.request_uri, headers(options)) + request = Net::HTTP::Get.new(parsed_url.request_uri, headers(headers: headers)) http.request(request) do |response| case response when Net::HTTPSuccess @@ -193,14 +184,11 @@ def conn end end - # @see HttpAdapter.open_url - # @param [String] base_uri to open - # @param [Hash{Symbol => Object}] options - # @return [RemoteDocument, Object] A {RemoteDocument}. - def self.open_url(base_uri, **options) + # (see HttpAdapter.open_url) + def self.open_url(base_uri, proxy: nil, headers: {}, verify_none: false, **options) response = conn.get do |req| req.url base_uri - headers(options).each do |k,v| + headers(headers: headers).each do |k,v| req.headers[k] = v end end @@ -283,29 +271,34 @@ def http_adapter(use_net_http = false) # # => Cached resource if current, otherwise returned resource # # @param [String] filename_or_url to open + # @param [String] proxy + # HTTP Proxy to use for requests. + # @param [Array, String] headers ({}) + # HTTP Request headers + # @param [Boolean] verify_none (false) + # Don't verify SSL certificates # @param [Hash{Symbol => Object}] options # options are ignored in this implementation. Applications are encouraged # to override this implementation to provide more control over HTTP # headers and redirect following. If opening as a file, # options are passed to `Kernel.open`. - # @option options [String] :proxy - # HTTP Proxy to use for requests. - # @option options [Array, String] :headers - # HTTP Request headers, passed to Kernel.open. - # @option options [Boolean] :verify_none (false) - # Don't verify SSL certificates # @return [RemoteDocument, Object] A {RemoteDocument}. If a block is given, the result of evaluating the block is returned. # @yield [ RemoteDocument] A {RemoteDocument} for local files # @yieldreturn [Object] returned from open_file # @raise [IOError] if not found - def self.open_file(filename_or_url, **options, &block) + def self.open_file(filename_or_url, proxy: nil, headers: {}, verify_none: false, **options, &block) filename_or_url = $1 if filename_or_url.to_s.match(/^file:(.*)$/) remote_document = nil if filename_or_url.to_s =~ /^https?/ base_uri = filename_or_url.to_s - remote_document = self.http_adapter(!!options[:use_net_http]).open_url(base_uri, options) + remote_document = self.http_adapter(!!options[:use_net_http]). + open_url(base_uri, + proxy: proxy, + headers: headers, + verify_none: verify_none, + **options) else # Fake content type based on found format format = RDF::Format.for(filename_or_url.to_s) diff --git a/lib/rdf/util/logger.rb b/lib/rdf/util/logger.rb index 01c07ab3..b5615d29 100644 --- a/lib/rdf/util/logger.rb +++ b/lib/rdf/util/logger.rb @@ -43,10 +43,10 @@ def log_statistics(**options) # @overload log_fatal(*args, **options, &block) # @param [Array] args # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level (:fatal) # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output - # @option options [:fatal, :error, :warn, :info, :debug] level (:<<) # @option options [Integer] :lineno associated with message # @option options [Logger, #<<] :logger # @option options [Class] :exception, (StandardError) @@ -54,9 +54,8 @@ def log_statistics(**options) # @yieldreturn [String] added to message # @return [void] # @raise Raises the provided exception class using the first element from args as the message component. - def log_fatal(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} - logger_common(*args, "Called from #{Gem.location_of_caller.join(':')}", options.merge(level: :fatal), &block) + def log_fatal(*args, level: :fatal, **options, &block) + logger_common(*args, "Called from #{Gem.location_of_caller.join(':')}", level: level, **options, &block) raise options.fetch(:exception, StandardError), args.first end @@ -68,6 +67,7 @@ def log_fatal(*args, &block) # @overload log_error(*args, **options, &block) # @param [Array] args # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level (:error) # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output @@ -79,12 +79,11 @@ def log_fatal(*args, &block) # @yieldreturn [String] added to message # @return [void] # @raise Raises the provided exception class using the first element from args as the message component, if `:exception` option is provided. - def log_error(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} + def log_error(*args, level: :error, **options, &block) logger = self.logger(options) return if logger.recovering logger.recovering = true - logger_common(*args, options.merge(level: :error), &block) + logger_common(*args, level: level, **options, &block) raise options[:exception], args.first if options[:exception] end @@ -102,6 +101,7 @@ def log_recovering?(**options) # @overload log_warn(*args, **options, &block) # @param [Array] args # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level (:warn) # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output @@ -110,9 +110,8 @@ def log_recovering?(**options) # @option options [Logger, #<<] :logger # @yieldreturn [String] added to message # @return [void] - def log_warn(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} - logger_common(*args, options.merge(level: :warn), &block) + def log_warn(*args, level: :warn, **options, &block) + logger_common(*args, level: level, **options, &block) end ## @@ -123,6 +122,7 @@ def log_warn(*args, &block) # @overload log_recover(*args, **options, &block) # @param [Array] args # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level (:info) # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output @@ -130,12 +130,11 @@ def log_warn(*args, &block) # @option options [Logger, #<<] :logger # @yieldreturn [String] added to message # @return [void] - def log_recover(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} + def log_recover(*args, level: :info, **options, &block) logger = self.logger(options) logger.recovering = false return if args.empty? && !block_given? - logger_common(*args, options.merge(level: :info), &block) + logger_common(*args, level: level, **options, &block) end ## @@ -144,6 +143,7 @@ def log_recover(*args, &block) # @overload log_info(*args, **options, &block) # @param [Array] args # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level (:info) # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output @@ -151,9 +151,8 @@ def log_recover(*args, &block) # @option options [Logger, #<<] :logger # @yieldreturn [String] added to message # @return [void] - def log_info(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} - logger_common(*args, options.merge(level: :info), &block) + def log_info(*args, level: :info, **options, &block) + logger_common(*args, level: level, **options, &block) end ## @@ -162,6 +161,7 @@ def log_info(*args, &block) # @overload log_debug(*args, **options, &block) # @param [Array] args # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level (:debug) # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output @@ -169,9 +169,8 @@ def log_info(*args, &block) # @option options [Logger, #<<] :logger # @yieldreturn [String] added to message # @return [void] - def log_debug(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} - logger_common(*args, options.merge(level: :debug), &block) + def log_debug(*args, level: :debug, **options, &block) + logger_common(*args, level: level, **options, &block) end ## @@ -200,6 +199,7 @@ def log_depth(**options, &block) # # @overload logger_common(args, options) # @param [Array] args Messages + # @param [:fatal, :error, :warn, :info, :debug] level # @param [Hash{Symbol => Object}] options # @option options [Integer] :depth # Recursion depth for indenting output @@ -208,11 +208,11 @@ def log_depth(**options, &block) # @option options [Logger, #<<] :logger # @yieldreturn [String] added to message # @return [void] - def logger_common(*args) - options = args.last.is_a?(Hash) ? args.pop : {} - level = options[:level] + def logger_common(*args, level:, **options) logger = self.logger(options) logger.log_statistics[level] = logger.log_statistics[level].to_i + 1 + # Some older code uses integer level numbers + level = [:debug, :info, :warn, :error, :fatal][level] if level.is_a?(Integer) return if logger.level > {fatal: 4, error: 3, warn: 2, info: 1, debug: 0}[level] depth = options.fetch(:depth, logger.log_depth) @@ -234,8 +234,8 @@ def log_statistics ## # @overload log_depth(options, &block) # Increase depth around a method invocation + # @param [Integer] depth (1) recursion depth # @param [Hash{Symbol}] options (@options || {}) - # @option options [Integer] :depth (1) recursion depth # @option options [Logger, #<<] :logger # @yield # Yields with no arguments @@ -245,16 +245,16 @@ def log_statistics # @overload log_depth # # Return the current log depth # @return [Integer] - def log_depth(**options) + def log_depth(depth: 1, **options) @log_depth ||= 0 if block_given? - @log_depth += options.fetch(:depth, 1) + @log_depth += depth yield else @log_depth end ensure - @log_depth -= options.fetch(:depth, 1) if block_given? + @log_depth -= depth if block_given? end # Give Logger like behavior to non-logger objects diff --git a/lib/rdf/util/uuid.rb b/lib/rdf/util/uuid.rb index 1573d0fa..ebeefa11 100644 --- a/lib/rdf/util/uuid.rb +++ b/lib/rdf/util/uuid.rb @@ -13,16 +13,17 @@ module UUID # [UUID]: http://rubygems.org/gems/uuid # [UUIDTools]: http://rubygems.org/gems/uuidtools # + # @param [:default, :compact, :urn] format (:default) # @param [Hash{Symbol => Object}] options # any options to pass through to the underlying UUID library # @return [String] a UUID string # @raise [LoadError] if no UUID library is available # @see http://rubygems.org/gems/uuid # @see http://rubygems.org/gems/uuidtools - def self.generate(**options) + def self.generate(format: :default, **options) begin require 'uuid' - ::UUID.generate(options[:format] || :default) + ::UUID.generate(format) rescue LoadError => e begin require 'uuidtools' diff --git a/lib/rdf/vocab/writer.rb b/lib/rdf/vocab/writer.rb index 75c73553..d45313db 100644 --- a/lib/rdf/vocab/writer.rb +++ b/lib/rdf/vocab/writer.rb @@ -54,10 +54,10 @@ def self.options # # @param [IO, File] output # the output stream + # @param [RDF::URI] base_uri + # URI of this vocabulary # @param [Hash{Symbol => Object}] options = ({}) # any additional options. See {RDF::Writer#initialize} - # @option options [RDF::URI] :base_uri - # URI of this vocabulary # @option options [String] :class_name # Class name for this vocabulary # @option options [String] :module_name ("RDF") @@ -71,9 +71,9 @@ def self.options # @yield [writer] `self` # @yieldparam [RDF::Writer] writer # @yieldreturn [void] - def initialize(output = $stdout, **options, &block) - options.fetch(:base_uri) {raise ArgumentError, "base_uri option required"} + def initialize(output = $stdout, base_uri:, **options, &block) @graph = RDF::Repository.new + options.merge(base_uri: base_uri) super end diff --git a/lib/rdf/vocabulary.rb b/lib/rdf/vocabulary.rb index 83c17cba..2a0d9abd 100644 --- a/lib/rdf/vocabulary.rb +++ b/lib/rdf/vocabulary.rb @@ -154,7 +154,7 @@ def property(*args) # Shortcut for `rdf:type`, values are String interpreted as a {URI}. # @return [RDF::Vocabulary::Term] # - # @note If the ontology URI has the vocabulary namespace URI as a prefix, it may also be defined using {#property} or {#term} + # @note If the ontology URI has the vocabulary namespace URI as a prefix, it may also be defined using `#property` or `#term` def ontology(*args) case args.length when 0 @@ -566,14 +566,16 @@ class Term < RDF::URI ## # @overload URI(uri, **options) # @param [URI, String, #to_s] uri + # @param [Hash{Symbol,Resource => Term, #to_s}] attributes + # Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF # @param [Hash{Symbol => Object}] options # @option options [Boolean] :validate (false) # @option options [Boolean] :canonicalize (false) - # @option options [Hash{Symbol,Resource => Term, #to_s}] :attributes - # Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF # # @overload URI(**options) # @param [Hash{Symbol => Object}] options + # @param [Hash{Symbol,Resource => Term, #to_s}] attributes + # Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF # @option options options [Boolean] :validate (false) # @option options options [Boolean] :canonicalize (false) # @option options [Vocabulary] :vocab The {Vocabulary} associated with this term. @@ -591,14 +593,10 @@ class Term < RDF::URI # @option options [String, #to_s] :path The path component. # @option options [String, #to_s] :query The query component. # @option options [String, #to_s] :fragment The fragment component. - # @option options [Hash{Symbol,Resource => Term, #to_s}] :attributes - # Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF - def initialize(*args, **options) - @attributes = options.fetch(:attributes) + def initialize(*args, attributes:, **options) + @attributes = attributes if RUBY_ENGINE == "rbx" - # FIXME: Somehow, this gets messed up in Rubinius - args << options - super(*args) + super(*args, **options) else super end diff --git a/lib/rdf/writer.rb b/lib/rdf/writer.rb index 3cae0345..dc2f790e 100644 --- a/lib/rdf/writer.rb +++ b/lib/rdf/writer.rb @@ -79,7 +79,7 @@ def self.each(&block) # @param [String] filename # @return [Class] # - # @overload for(options = {}) + # @overload for(**options) # Finds an RDF writer class based on various options. # # @param [Hash{Symbol => Object}] options @@ -154,26 +154,29 @@ class << self # the graph or repository to dump # @param [IO, File, String] io # the output stream or file to write to + # @param [Encoding, String, Symbol] encoding + # the encoding to use on the output stream. + # Defaults to the format associated with `content_encoding`. # @param [Hash{Symbol => Object}] options # passed to {RDF::Writer#initialize} or {RDF::Writer.buffer} # @return [void] - def self.dump(data, io = nil, **options) + def self.dump(data, io = nil, encoding: nil, **options) if io.is_a?(String) io = File.open(io, 'w') elsif io.respond_to?(:external_encoding) && io.external_encoding - options = {encoding: io.external_encoding}.merge(options) + encoding ||= io.external_encoding end - io.set_encoding(options[:encoding]) if io.respond_to?(:set_encoding) && options[:encoding] + io.set_encoding(encoding) if io.respond_to?(:set_encoding) && encoding method = data.respond_to?(:each_statement) ? :each_statement : :each if io - new(io, options) do |writer| + new(io, encoding: encoding, **options) do |writer| data.send(method) do |statement| writer << statement end writer.flush end else - buffer(options) do |writer| + buffer(encoding: encoding, **options) do |writer| data.send(method) do |statement| writer << statement end @@ -184,19 +187,23 @@ def self.dump(data, io = nil, **options) ## # Buffers output into a string buffer. # + # @param [Encoding, String, Symbol] encoding + # the encoding to use on the output stream. + # Defaults to the format associated with `content_encoding`. + # @param [Hash{Symbol => Object}] options + # passed to {RDF::Writer#initialize} # @yield [writer] # @yieldparam [RDF::Writer] writer # @yieldreturn [void] # @return [String] # @raise [ArgumentError] if no block is provided - def self.buffer(*args, &block) - options = args.last.is_a?(Hash) ? args.last : {} - options[:encoding] ||= Encoding::UTF_8 if RUBY_PLATFORM == "java" + def self.buffer(*args, encoding: nil, **options, &block) + encoding ||= Encoding::UTF_8 if RUBY_PLATFORM == "java" raise ArgumentError, "block expected" unless block_given? StringIO.open do |buffer| - buffer.set_encoding(options[:encoding]) if options[:encoding] - self.new(buffer, *args) { |writer| block.call(writer) } + buffer.set_encoding(encoding) if encoding + self.new(buffer, *args, encoding: encoding, **options) { |writer| block.call(writer) } buffer.string end end @@ -205,16 +212,19 @@ def self.buffer(*args, &block) # Writes output to the given `filename`. # # @param [String, #to_s] filename + # @param [Encoding, String, Symbol] encoding + # the encoding to use on the output stream. + # Defaults to the format associated with `content_encoding`. + # @param [Symbol] format (nil) # @param [Hash{Symbol => Object}] options # any additional options (see {RDF::Writer#initialize} and {RDF::Format.for}) - # @option options [Symbol] :format (nil) # @return [RDF::Writer] - def self.open(filename, **options, &block) + def self.open(filename, encoding: nil, format: nil, **options, &block) File.open(filename, 'wb') do |file| - file.set_encoding(options[:encoding]) if options[:encoding] + file.set_encoding(encoding) if encoding format_options = options.dup format_options[:file_name] ||= filename - self.for(options[:format] || format_options).new(file, options, &block) + self.for(format || format_options).new(file, encoding: encoding, **options, &block) end end @@ -421,7 +431,7 @@ def write_statement(statement) # Make sure BNodes in statement use unique identifiers if statement.node? - terms = statement.to_quad.map do |term| + statement.to_quad.map do |term| if term.is_a?(RDF::Node) term = term.original while term.original @nodes[term] ||= begin diff --git a/spec/util_logger_spec.rb b/spec/util_logger_spec.rb index 40aa3573..d462d41e 100644 --- a/spec/util_logger_spec.rb +++ b/spec/util_logger_spec.rb @@ -140,6 +140,49 @@ def initialize(logger = nil) end end + describe "#log_debug" do + it "Logs messages, and yield return" do + subject.log_debug("a", "b") {"c"} + expect(subject.logger.to_s).to eql "DEBUG a: b: c\n" + end + + it "adds lineno" do + subject.log_debug("a", lineno: 10) + expect(subject.logger.to_s).to eql "DEBUG [line 10] a\n" + end + + it "adds depth with option" do + subject.log_debug("a", depth: 2) + expect(subject.logger.to_s).to eql "DEBUG a\n" + end + + it "adds depth with option" do + subject.log_debug("a", depth: 2) + expect(subject.logger.to_s).to eql "DEBUG a\n" + end + + it "uses logger from @options" do + logger = LogTester.new + logger.options[:logger] = RDF::Spec.logger + logger.log_debug("a") + expect(logger.instance_variable_get(:@logger).to_s).to be_empty + expect(logger.options[:logger].to_s).to eql "DEBUG a\n" + end + + it "uses logger from options" do + logger = LogTester.new + l = RDF::Spec.logger + logger.log_debug("a", logger: l) + expect(logger.instance_variable_get(:@logger).to_s).to be_empty + expect(l.to_s).to eql "DEBUG a\n" + end + + it "increments log_statistics" do + subject.log_debug("foo") rescue nil + expect(subject.log_statistics[:debug]).to eql 1 + end + end + describe "#log_depth" do specify {expect {|b| subject.log_depth(&b)}.to yield_with_no_args}