# HG changeset patch # User Michael Granger # Date 1506462656 25200 # Tue Sep 26 14:50:56 2017 -0700 # Node ID 211f70b5a215c9526c423bcdfb5eb778ea660be3 # Parent 67dd02fdd447522c442e9d8499e3fefaec9e89f1 Update to WordNet 3.1, Sequel 5.0. - Made tests run under both Sqlite and PG. - Removed deprecated syntax/conventions from Sequel < 5 - Move to Ruby 2.4 as primary tested version, though 2.3 is still supported - Made fetching Synset by ordinal deterministic diff --git a/.gems b/.gems --- a/.gems +++ b/.gems @@ -1,5 +1,6 @@ -hoe-deveiate -v0.8.0 -sequel -v4.38.0 -sqlite3 -v1.3.11 -loggability -v0.11.0 -simplecov -v0.12.0 +hoe-deveiate +loggability +pg +sequel +simplecov +sqlite3 diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -5,11 +5,13 @@ ^data/wordnet\-defaultdb/wordnet30\.sqlite$ ^commit\-msg\.txt$ ^wordnet-defaultdb/pkg/ -^wordnet-defaultdb/data/wordnet\-defaultdb/wordnet30\.sqlite$ +^wordnet-defaultdb/data/wordnet\-defaultdb/wordnet31\.sqlite$ ^wordnet-defaultdb/commit\-msg\.txt$ ^wordnet-defaultdb/LICENSE-WORDNET.txt$ -^wordnet-defaultdb/wordnet30-sqlite-1.0.1.zip$ +^wordnet-defaultdb/sqlunet-sqlite-4\.0\.0-31-all\.zip$ ^ChangeLog$ ^doc/ \.(pdf|svg)$ coverage/ +spec/.state + diff --git a/.hoerc b/.hoerc --- a/.hoerc +++ b/.hoerc @@ -1,2 +1,2 @@ --- -exclude: !ruby/regexp /\.(hg|hoerc|DS_Store|rvm(rc|\.gems)|irbrc|pryrc|tm_.*)|(experiments\x2f|wordnet-defaultdb\x2f|doc\x2f|Manifest-data\.txt)|\.(svg)$/ +exclude: !ruby/regexp /\.(hg|hoerc|DS_Store|rvm(rc|\.gems)|irbrc|pryrc|tm_.*)|(experiments\x2f|wordnet-defaultdb\x2f|doc\x2f|Manifest-data\.txt|spec\x2f\.state)|\.(svg)$/ diff --git a/.pryrc b/.pryrc --- a/.pryrc +++ b/.pryrc @@ -17,8 +17,13 @@ Loggability.level = :debug if $DEBUG - puts "Instantiating the lexicon as $lex" - $lex = WordNet::Lexicon.new + if Gem::Specification.find_all_by_name( 'pg' ).any? + puts "Instantiating the lexicon against the PostgreSQL (wordnet31) DB as $lex" + $lex = WordNet::Lexicon.new( 'postgres:/wordnet31' ) + else + puts "Instantiating the lexicon against the default DB as $lex" + $lex = WordNet::Lexicon.new + end rescue Exception => e $stderr.puts "Ack! WordNet failed to load: #{e.message}\n\t" + e.backtrace.join( "\n\t" ) diff --git a/.ruby-version b/.ruby-version --- a/.ruby-version +++ b/.ruby-version @@ -1,1 +1,1 @@ -2.3 \ No newline at end of file +2.4 diff --git a/README.rdoc b/README.rdoc --- a/README.rdoc +++ b/README.rdoc @@ -60,8 +60,8 @@ == Requirements -* Ruby >= 2.2 -* Sequel >= 4.38 +* Ruby >= 2.3 +* Sequel >= 5.0 == Authors @@ -71,7 +71,7 @@ == License -Copyright (c) 2002-2016, The FaerieMUD Consortium +Copyright (c) 2002-2017, The FaerieMUD Consortium All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Rakefile b/Rakefile --- a/Rakefile +++ b/Rakefile @@ -29,12 +29,12 @@ self.developer 'Michael Granger', 'ged@FaerieMUD.org' - self.dependency 'sequel', '~> 4.38' - self.dependency 'loggability', '~> 0.11' + self.dependency 'sequel', '~> 5.0' + self.dependency 'loggability', '~> 0.11' - self.dependency 'sqlite3', '~> 1.3', :developer - self.dependency 'rspec', '~> 3.5', :developer - self.dependency 'simplecov', '~> 0.12', :developer + self.dependency 'sqlite3', '~> 1.3', :developer + self.dependency 'rspec', '~> 3.5', :developer + self.dependency 'simplecov', '~> 0.12', :developer self.spec_extras[:post_install_message] = %{ If you don't already have a WordNet database installed somewhere, diff --git a/lib/wordnet.rb b/lib/wordnet.rb --- a/lib/wordnet.rb +++ b/lib/wordnet.rb @@ -47,15 +47,15 @@ require 'wordnet/lexicon' + require 'wordnet/model' - require 'wordnet/model' - require 'wordnet/sense' - require 'wordnet/synset' - require 'wordnet/semanticlink' - require 'wordnet/lexicallink' - require 'wordnet/word' - require 'wordnet/morph' - require 'wordnet/sumoterm' + WordNet::Model.register_model( 'wordnet/sense' ) + WordNet::Model.register_model( 'wordnet/synset' ) + WordNet::Model.register_model( 'wordnet/semanticlink' ) + WordNet::Model.register_model( 'wordnet/lexicallink' ) + WordNet::Model.register_model( 'wordnet/word' ) + WordNet::Model.register_model( 'wordnet/morph' ) + WordNet::Model.register_model( 'wordnet/sumoterm' ) # # Backward-compatibility stuff diff --git a/lib/wordnet/lexicon.rb b/lib/wordnet/lexicon.rb --- a/lib/wordnet/lexicon.rb +++ b/lib/wordnet/lexicon.rb @@ -7,8 +7,7 @@ require 'wordnet' unless defined?( WordNet ) require 'wordnet/constants' -require 'wordnet/synset' -require 'wordnet/word' +require 'wordnet/model' # WordNet lexicon class - provides access to the WordNet lexical @@ -20,11 +19,11 @@ # To create a Lexicon, point it at a database using {Sequel database connection # criteria}[http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html]: # -# lex = WordNet::Lexicon.new( 'postgres://localhost/wordnet30' ) -# # => # +# lex = WordNet::Lexicon.new( 'postgres://localhost/wordnet31' ) +# # => # # # # Another way of doing the same thing: -# lex = WordNet::Lexicon.new( adapter: 'postgres', database: 'wordnet30', host: 'localhost' ) +# lex = WordNet::Lexicon.new( adapter: 'postgres', database: 'wordnet31', host: 'localhost' ) # # => # # # Alternatively, if you have the 'wordnet-defaultdb' gem (which includes an @@ -33,7 +32,7 @@ # # lex = WordNet::Lexicon.new # # => # +# # /data/wordnet-defaultdb/wordnet31.sqlite> # # == Looking Up Synsets # @@ -128,10 +127,6 @@ log_to :wordnet - # Add the logger device to the default options after it's been loaded - WordNet::DEFAULT_DB_OPTIONS.merge!( :logger => [Loggability[WordNet]] ) - - ### Get the Sequel URI of the default database, if it's installed. def self::default_db_uri self.log.debug "Fetching the default db URI" @@ -153,7 +148,7 @@ 'wordnet-defaultdb/data/wordnet-defaultdb' end - dbfile = datadir + 'wordnet30.sqlite' + dbfile = datadir + 'wordnet31.sqlite' self.log.debug " dbfile is: %s" % [ dbfile ] if dbfile.exist? @@ -181,6 +176,13 @@ @db.sql_log_level = :debug WordNet::Model.db = @db + WordNet::Model.descendents.each do |subclass| + self.log.debug "Switching DB for %p to %p" % [ subclass, @db ] + subclass.dataset = @db[ subclass.table_name ] + end + + # Add the logger device after it's been loaded + @db.logger = Loggability[ self.class ] end @@ -189,7 +191,7 @@ uri = WordNet::Lexicon.default_db_uri or raise WordNet::LexiconError, "No default WordNetSQL database! You can install it via the " + "wordnet-defaultdb gem, or download a version yourself from " + - "http://sourceforge.net/projects/wnsql/" + "http://sqlunet.sourceforge.net/" @db = self.connect( uri, options ) end @@ -287,11 +289,11 @@ when Integer self.log.debug " limiting to sense %d" % [ arg ] - dataset = dataset.limit( 1, arg-1 ) + dataset = dataset.order( :synsetid ).limit( 1, arg-1 ) when Range self.log.debug " limiting to range of senses: %p" % [ arg ] - dataset = dataset.limit( arg.entries.length, arg.begin - 1 ) + dataset = dataset.order( :synsetid ).limit( arg.entries.length, arg.begin - 1 ) when Regexp self.log.debug " filter: definition =~ %p" % [ arg ] diff --git a/lib/wordnet/model.rb b/lib/wordnet/model.rb --- a/lib/wordnet/model.rb +++ b/lib/wordnet/model.rb @@ -4,17 +4,21 @@ require 'loggability' require 'sequel' -# Use a mock database until the real one is provided by the user -Sequel::Model.db = Sequel.mock if Sequel::DATABASES.empty? - require 'wordnet' unless defined?( WordNet ) + module WordNet + Model = Class.new( Sequel::Model ) + Model.def_Model( WordNet ) + + Model.require_valid_table = false + + # The base WordNet database-backed domain class. It's a subclass of Sequel::Model, so # you'll first need to be familiar with Sequel (http://sequel.rubyforge.org/) and # especially its Sequel::Model ORM. - class Model < Sequel::Model + class Model extend Loggability # Loggability API -- log to the WordNet module's logger @@ -22,58 +26,46 @@ # Sequel plugins plugin :validation_helpers - plugin :schema plugin :subclasses - ### Execute a block after removing all loggers from the current database handle, then - ### restore them before returning. - def self::without_sql_logging( logged_db=nil ) - logged_db ||= self.db - - loggers_to_restore = logged_db.loggers.dup - logged_db.loggers.clear - yield - ensure - logged_db.loggers.replace( loggers_to_restore ) + # Allow registration of subclasses to load once the db is connected + class << self + attr_reader :registered_models end + @registered_models = [] ### Reset the database connection that all model objects will use. ### @param [Sequel::Database] newdb the new database object. def self::db=( newdb ) - self.without_sql_logging( newdb ) do + Loggability.with_level( :fatal ) do super end - self.descendents.each do |subclass| - self.log.debug "Resetting database connection for: %p to: %p" % [ subclass, newdb ] - subclass.db = newdb + self.load_registered_models if self == WordNet::Model + end + + + ### Register a model subclass path to load when the database is connected. If + ### there's already a database connection, just `require` it immediately. + def self::register_model( name ) + if @db + require( name ) + else + self.registered_models << name + end + end + + + ### Load any models which have been registered. + def self::load_registered_models + self.registered_models.each do |path| + require( path ) end end end # class Model - ### Overridden version of Sequel.Model() that creates subclasses of WordNet::Model instead - ### of Sequel::Model. - ### @see Sequel.Model() - def self::Model( source ) - unless Sequel::Model::ANONYMOUS_MODEL_CLASSES.key?( source ) - anonclass = nil - WordNet::Model.without_sql_logging do - if source.is_a?( Sequel::Database ) - anonclass = Class.new( WordNet::Model ) - anonclass.db = source - else - anonclass = Class.new( WordNet::Model ).set_dataset( source ) - end - end - - Sequel::Model::ANONYMOUS_MODEL_CLASSES[ source ] = anonclass - end - - return Sequel::Model::ANONYMOUS_MODEL_CLASSES[ source ] - end - end # module WordNet diff --git a/lib/wordnet/sumoterm.rb b/lib/wordnet/sumoterm.rb --- a/lib/wordnet/sumoterm.rb +++ b/lib/wordnet/sumoterm.rb @@ -13,6 +13,7 @@ class WordNet::SumoTerm < WordNet::Model( :sumoterms ) include WordNet::Constants + # Table "public.sumoterms" # Column | Type | Modifiers # -----------------------+------------------------+-------------------- diff --git a/lib/wordnet/synset.rb b/lib/wordnet/synset.rb --- a/lib/wordnet/synset.rb +++ b/lib/wordnet/synset.rb @@ -14,7 +14,7 @@ # # We can either fetch the synset from a connected Lexicon: # -# lexicon = WordNet::Lexicon.new( 'postgres://localhost/wordnet30' ) +# lexicon = WordNet::Lexicon.new( 'postgres://localhost/wordnet31' ) # ss = lexicon[ :first, 'time' ] # # => #] # - ## - # :singleton-method: nouns - # Dataset method: filtered by part of speech: nouns. - def_dataset_method( :nouns ) { filter(pos: 'n') } + dataset_module do + + ### :singleton-method: nouns + ### Limit results to nouns. + def nouns + return self.where( pos: 'n' ) + end - ## - # :singleton-method: verbs - # Dataset method: filtered by part of speech: verbs. - def_dataset_method( :verbs ) { filter(pos: 'v') } + + ### :singleton-method: verbs + ### Limit results to verbs. + def verbs + return self.where( pos: 'v' ) + end + - ## - # :singleton-method: adjectives - # Dataset method: filtered by part of speech: adjectives. - def_dataset_method( :adjectives ) { filter(pos: 'a') } + ### :singleton-method: adjectives + ### Limit results to adjectives. + def adjectives + return self.where( pos: 'a' ) + end + - ## - # :singleton-method: adverbs - # Dataset method: filtered by part of speech: adverbs. - def_dataset_method( :adverbs ) { filter(pos: 'r') } + ### :singleton-method: adverbs + ### Limit results to adverbs. + def adverbs + return self.where( pos: 'r' ) + end + - ## - # :singleton-method: adjective_satellites - # Dataset method: filtered by part of speech: adjective satellites. - def_dataset_method( :adjective_satellites ) { filter(pos: 's') } + ### :singleton-method: adjective_satellites + ### Limit results to adjective satellites. + def adjective_satellites + return self.where( pos: 's' ) + end + + end # :section: diff --git a/lib/wordnet/word.rb b/lib/wordnet/word.rb --- a/lib/wordnet/word.rb +++ b/lib/wordnet/word.rb @@ -88,9 +88,14 @@ # Dataset methods # - ## - # Return a dataset for words matching the given +lemma+. - def_dataset_method( :by_lemma ) {|lemma| filter( lemma: lemma ) } + dataset_module do + + ### Limit the dataset to words matching the given +lemma+. + def by_lemma( lemma ) + return where( lemma: lemma ) + end + + end # diff --git a/spec/helpers.rb b/spec/helpers.rb --- a/spec/helpers.rb +++ b/spec/helpers.rb @@ -23,17 +23,18 @@ config.mock_with( :rspec ) do |mock| mock.syntax = :expect end + config.example_status_persistence_file_path = "spec/.state" - if Gem::Specification.find_all_by_name( 'pg' ).empty? + if Gem::Specification.find_all_by_name( 'pg' ).any? + $dburi = 'postgres:/wordnet31' + else config.filter_run_excluding( :requires_pg ) + unless (( $dburi = WordNet::Lexicon.default_db_uri )) + config.filter_run_excluding( :requires_database ) + end end - begin - uri = WordNet::Lexicon.default_db_uri - WordNet.log.info "Database tests will use: #{uri}" - rescue WordNet::LexiconError - config.filter_run_excluding( :requires_database ) - end + $stderr.puts "Using database: %p" % [ $dburi ] config.include( WordNet::SpecHelpers ) config.include( Loggability::SpecHelpers ) diff --git a/spec/wordnet/lexicon_spec.rb b/spec/wordnet/lexicon_spec.rb --- a/spec/wordnet/lexicon_spec.rb +++ b/spec/wordnet/lexicon_spec.rb @@ -11,9 +11,8 @@ describe WordNet::Lexicon do - before( :all ) do - @devdb = Pathname( 'wordnet-defaultdb/data/wordnet-defaultdb/wordnet30.sqlite' ). - expand_path + let( :devdb ) do + Pathname( 'wordnet-defaultdb/data/wordnet-defaultdb/wordnet31.sqlite' ).expand_path end @@ -22,26 +21,26 @@ it "uses the wordnet-defaultdb database gem (if available)" do expect( Gem ).to receive( :datadir ).with( 'wordnet-defaultdb' ).at_least( :once ). and_return( '/tmp/foo' ) - expect( FileTest ).to receive( :exist? ).with( '/tmp/foo/wordnet30.sqlite' ). + expect( FileTest ).to receive( :exist? ).with( '/tmp/foo/wordnet31.sqlite' ). and_return( true ) - expect( WordNet::Lexicon.default_db_uri ).to eq( "sqlite:/tmp/foo/wordnet30.sqlite" ) + expect( WordNet::Lexicon.default_db_uri ).to eq( "sqlite:/tmp/foo/wordnet31.sqlite" ) end it "uses the development version of the wordnet-defaultdb database gem if it's " + "not installed" do expect( Gem ).to receive( :datadir ).with( 'wordnet-defaultdb' ). and_return( nil ) - expect( FileTest ).to receive( :exist? ).with( @devdb.to_s ). + expect( FileTest ).to receive( :exist? ).with( devdb.to_s ). and_return( true ) - expect( WordNet::Lexicon.default_db_uri ).to eq( "sqlite:#{@devdb}" ) + expect( WordNet::Lexicon.default_db_uri ).to eq( "sqlite:#{devdb}" ) end it "returns nil if there is no default database" do expect( Gem ).to receive( :datadir ).with( 'wordnet-defaultdb' ). and_return( nil ) - expect( FileTest ).to receive( :exist? ).with( @devdb.to_s ). + expect( FileTest ).to receive( :exist? ).with( devdb.to_s ). and_return( false ) expect( WordNet::Lexicon.default_db_uri ).to be_nil() @@ -53,7 +52,7 @@ it "raises an exception if created with no arguments and no defaultdb is available" do expect( Gem ).to receive( :datadir ).with( 'wordnet-defaultdb' ).at_least( :once ). and_return( nil ) - expect( FileTest ).to receive( :exist? ).with( @devdb.to_s ). + expect( FileTest ).to receive( :exist? ).with( devdb.to_s ). and_return( false ) expect { @@ -62,130 +61,98 @@ end - context "with the default database", :requires_database => true do + context "via its index operator" do + + let( :lexicon ) { WordNet::Lexicon.new($dburi) } + - let( :lexicon ) { WordNet::Lexicon.new } + it "can look up a Synset by ID" do + rval = lexicon[ 101222212 ] + # Can't use "be_a", as on failure it does Array(WordNet::Synset), which explodes to + # all synsets in the database + expect( rval.class ).to eq( WordNet::Synset ) + expect( rval.words.map( &:to_s ) ).to include( 'carrot' ) + end - context "via its index operator" do + it "can look up a Word by ID" do + rval = lexicon[ 21346 ] + expect( rval.class ).to eq( WordNet::Word ) + expect( rval.lemma ).to eq( 'carrot' ) + end - it "can look up a Synset by ID" do - rval = lexicon[ 101219722 ] - expect( rval ).to be_a( WordNet::Synset ) - expect( rval.words.map( &:to_s ) ).to include( 'carrot' ) - end + it "can look up the synset for a word and a sense" do + ss = lexicon[ :boot, 3 ] + expect( ss.class ).to eq( WordNet::Synset ) + expect( ss.definition ).to eq( 'footwear that covers the whole foot and lower leg' ) + end - it "can look up a Word by ID" do - rval = lexicon[ 21338 ] - expect( rval ).to be_a( WordNet::Word ) - expect( rval.lemma ).to eq( 'carrot' ) - end + it "can look up all synsets for a particular word" do + sss = lexicon.lookup_synsets( :tree ) + expect( sss.size ).to eq( 7 ) + expect( sss ).to all( be_a(WordNet::Synset) ) + end + + it "can constrain fetched synsets to a certain range of results" do + sss = lexicon.lookup_synsets( :tree, 1..4 ) + expect( sss.size ).to eq( 4 ) + end + + it "can constrain fetched synsets to a certain (exclusive) range of results" do + sss = lexicon.lookup_synsets( :tree, 1...4 ) + expect( sss.size ).to eq( 3 ) + end - it "can look up the synset for a word and a sense" do - ss = lexicon[ :boot, 3 ] - expect( ss ).to be_a( WordNet::Synset ) - expect( ss.definition ).to eq( 'footwear that covers the whole foot and lower leg' ) - end + it "can look up a synset for a word and a substring of its definition" do + ss = lexicon[ :boot, 'kick' ] + expect( ss.class ).to eq( WordNet::Synset ) + expect( ss.definition ).to match( /kick/i ) + end + + it "can look up a synset for a word and a part of speech" do + ss = lexicon[ :boot, :verb ] + expect( ss.class ).to eq( WordNet::Synset ) + expect( ss.definition ).to match( /cause to load/i ) + end + + it "can look up a synset for a word and an abbreviated part of speech" do + ss = lexicon[ :boot, :n ] + expect( ss.class ).to eq( WordNet::Synset ) + expect( ss.definition ).to match( /delivering a blow with the foot/i ) + end + + it "can constrain fetched synsets with a Regexp match against its definition", :requires_pg do + sss = lexicon.lookup_synsets( :tree, /plant/ ) + expect( sss.size ).to eq( 2 ) + end - it "can look up all synsets for a particular word" do - sss = lexicon.lookup_synsets( :tree ) - expect( sss.size ).to eq( 7 ) - expect( sss ).to all( be_a(WordNet::Synset) ) - end + it "can constrain fetched synsets via lexical domain" do + sss = lexicon.lookup_synsets( :tree, 'noun.shape' ) + expect( sss.size ).to eq( 1 ) + expect( sss.first ).to eq( WordNet::Synset[113935275 ] ) + end - it "can constrain fetched synsets to a certain range of results" do - sss = lexicon.lookup_synsets( :tree, 1..4 ) - expect( sss.size ).to eq( 4 ) - end + it "can constrain fetched synsets via part of speech as a single-letter Symbol" do + sss = lexicon.lookup_synsets( :tree, :n ) + expect( sss.size ).to eq( 3 ) + expect( sss ).to include( + lexicon[ :tree, 'actor' ], + lexicon[ :tree, 'figure' ], + lexicon[ :tree, 'plant' ] + ) + end - it "can constrain fetched synsets to a certain (exclusive) range of results" do - sss = lexicon.lookup_synsets( :tree, 1...4 ) - expect( sss.size ).to eq( 3 ) - end - + it "can constrain fetched synsets via part of speech as a Symbol word" do + sss = lexicon.lookup_synsets( :tree, :verb ) + expect( sss.size ).to eq( 4 ) + expect( sss ).to include( + WordNet::Synset[ 201938064 ], + WordNet::Synset[ 201147629 ], + WordNet::Synset[ 201619197 ], + WordNet::Synset[ 200319912 ] + ) end end - context "with a PostgreSQL database", :requires_pg do - - let( :lexicon ) { WordNet::Lexicon.new('postgres:/wordnet30') } - - context "via its index operator" do - - it "can look up a Synset by ID" do - rval = lexicon[ 101219722 ] - expect( rval ).to be_a( WordNet::Synset ) - expect( rval.words.map(&:to_s) ).to include( 'carrot' ) - end - - it "can look up a Word by ID" do - rval = lexicon[ 21338 ] - expect( rval ).to be_a( WordNet::Word ) - expect( rval.lemma ).to eq( 'carrot' ) - end - - it "can look up the synset for a word and a sense" do - ss = lexicon[ :boot, 3 ] - expect( ss ).to be_a( WordNet::Synset ) - expect( ss.definition ).to eq( 'footwear that covers the whole foot and lower leg' ) - end - - it "can look up a synset for a word and a substring of its definition" do - ss = lexicon[ :boot, 'kick' ] - expect( ss ).to be_a( WordNet::Synset ) - expect( ss.definition ).to match( /kick/i ) - end - - it "can look up a synset for a word and a part of speech" do - ss = lexicon[ :boot, :verb ] - expect( ss ).to be_a( WordNet::Synset ) - expect( ss.definition ).to match( /cause to load/i ) - end - - it "can look up a synset for a word and an abbreviated part of speech" do - ss = lexicon[ :boot, :n ] - expect( ss ).to be_a( WordNet::Synset ) - expect( ss.definition ).to match( /act of delivering/i ) - end - - it "can constrain fetched synsets with a Regexp match against its definition" do - sss = lexicon.lookup_synsets( :tree, /plant/ ) - expect( sss.size ).to eq( 2 ) - end - - it "can constrain fetched synsets via lexical domain" do - sss = lexicon.lookup_synsets( :tree, 'noun.shape' ) - expect( sss.size ).to eq( 1 ) - expect( sss.first ).to eq( WordNet::Synset[ 113912260 ] ) - end - - it "can constrain fetched synsets via part of speech as a single-letter Symbol" do - sss = lexicon.lookup_synsets( :tree, :n ) - expect( sss.size ).to eq( 3 ) - expect( sss ).to include( - WordNet::Synset[ 113912260 ], - WordNet::Synset[ 111348160 ], - WordNet::Synset[ 113104059 ] - ) - end - - it "can constrain fetched synsets via part of speech as a Symbol word" do - sss = lexicon.lookup_synsets( :tree, :verb ) - expect( sss.size ).to eq( 4 ) - expect( sss ).to include( - WordNet::Synset[ 200319111 ], - WordNet::Synset[ 201145163 ], - WordNet::Synset[ 201616293 ], - WordNet::Synset[ 201934205 ] - ) - end - - it "includes the database adapter name in its inspect output" do - expect( lexicon.inspect ).to include( "postgres" ) - end - - end - end - end diff --git a/spec/wordnet/model_spec.rb b/spec/wordnet/model_spec.rb --- a/spec/wordnet/model_spec.rb +++ b/spec/wordnet/model_spec.rb @@ -16,12 +16,5 @@ describe WordNet::Model do - it "propagates database handle changes to all of its subclasses" do - subclass = WordNet::Model( :tests ) - newdb = Sequel.mock - WordNet::Model.db = newdb - expect( subclass.db ).to equal( newdb ) - end - end diff --git a/spec/wordnet/semanticlink_spec.rb b/spec/wordnet/semanticlink_spec.rb --- a/spec/wordnet/semanticlink_spec.rb +++ b/spec/wordnet/semanticlink_spec.rb @@ -2,16 +2,18 @@ require_relative '../helpers' require 'rspec' -require 'wordnet/semanticlink' +require 'wordnet' ##################################################################### ### C O N T E X T S ##################################################################### -describe WordNet::SemanticLink, :requires_database => true do +describe 'WordNet::SemanticLink', :requires_database do - let( :lexicon ) { WordNet::Lexicon.new } + let( :described_class ) { WordNet::SemanticLink } + + let( :lexicon ) { WordNet::Lexicon.new($dburi) } let( :word ) { lexicon[96814] } # 'parody' let( :synset ) { word.synsets.first } let( :semlink ) { synset.semlinks.first } diff --git a/spec/wordnet/sense_spec.rb b/spec/wordnet/sense_spec.rb --- a/spec/wordnet/sense_spec.rb +++ b/spec/wordnet/sense_spec.rb @@ -2,16 +2,18 @@ require_relative '../helpers' -require 'wordnet/sense' +require 'wordnet' -describe WordNet::Sense, :requires_database => true do +describe 'WordNet::Sense', :requires_database do before( :all ) do - @lexicon = WordNet::Lexicon.new + @lexicon = WordNet::Lexicon.new( $dburi ) end + let( :described_class ) { WordNet::Sense } + let( :sense ) do WordNet::Word[ 79712 ].senses.first end diff --git a/spec/wordnet/synset_spec.rb b/spec/wordnet/synset_spec.rb --- a/spec/wordnet/synset_spec.rb +++ b/spec/wordnet/synset_spec.rb @@ -2,20 +2,22 @@ require_relative '../helpers' require 'rspec' -require 'wordnet/synset' ##################################################################### ### C O N T E X T S ##################################################################### -describe WordNet::Synset, :requires_database => true do +describe 'WordNet::Synset', :requires_database do before( :all ) do - @lexicon = WordNet::Lexicon.new + @lexicon = WordNet::Lexicon.new( $dburi ) end + let( :described_class ) { WordNet::Synset } + + it "knows what kinds of lexical domains are available" do expect( described_class.lexdomains ).to be_a( Hash ) expect( described_class.lexdomains ).to include( 'noun.cognition' ) @@ -42,7 +44,7 @@ # floor, level, storey, story (noun): [noun.artifact] a structure # consisting of a room or set of rooms at a single position along a # vertical scale (hypernym: 1, hyponym: 5, part meronym: 1) - let( :synset ) { WordNet::Synset[103365991] } + let( :synset ) { @lexicon['story', :n] } it "knows what lexical domain it's from" do @@ -60,31 +62,17 @@ expect( enum ).to be_a( Enumerator ) end - it "can recursively traverse its semantic links" do - res = synset.traverse( :hypernyms ).to_a - expect( res.size ).to eq( 6 ) - expect( res ).to eq([ - WordNet::Synset[ 104341686 ], - WordNet::Synset[ 100021939 ], - WordNet::Synset[ 100003553 ], - WordNet::Synset[ 100002684 ], - WordNet::Synset[ 100001930 ], - WordNet::Synset[ 100001740 ], - ]) - end - it "can return an Enumerator for recursively traversing its semantic links" do enum = synset.traverse( :hypernyms ) - expect( enum.next ).to eq( WordNet::Synset[ 104341686 ] ) - expect( enum.next ).to eq( WordNet::Synset[ 100021939 ] ) - expect( enum.next ).to eq( WordNet::Synset[ 100003553 ] ) - expect( enum.next ).to eq( WordNet::Synset[ 100002684 ] ) - expect( enum.next ).to eq( WordNet::Synset[ 100001930 ] ) - expect( enum.next ).to eq( WordNet::Synset[ 100001740 ] ) - expect { - enum.next - }.to raise_error( StopIteration ) + expect( enum ).to be_a( Enumerator ).and( contain_exactly( + @lexicon['artifact', :n], + @lexicon['unit', :n], + @lexicon['object', :n], + @lexicon['physical entity', :n], + @lexicon['entity', :n], + @lexicon['structure', :n], + ) ) end end diff --git a/spec/wordnet/word_spec.rb b/spec/wordnet/word_spec.rb --- a/spec/wordnet/word_spec.rb +++ b/spec/wordnet/word_spec.rb @@ -3,21 +3,23 @@ require 'rspec' require 'wordnet' -require 'wordnet/word' ##################################################################### ### C O N T E X T S ##################################################################### -describe WordNet::Word, :requires_database => true do +describe 'WordNet::Word', :requires_database do - let( :lexicon ) { WordNet::Lexicon.new } + let( :described_class ) { WordNet::Word } + + let!( :lexicon ) { WordNet::Lexicon.new($dburi) } context "the Word for 'run'" do - let( :word ) { lexicon[113377] } + let( :word ) { described_class.by_lemma('run').first } + it "knows what senses it has" do senses = word.senses @@ -26,6 +28,7 @@ expect( senses.first ).to be_a( WordNet::Sense ) end + it "knows what synsets it has" do synsets = word.synsets @@ -34,6 +37,7 @@ expect( synsets.first.senses ).to include( word.senses.first ) end + it "has a dataset for selecting noun synsets" do expect( word.nouns ).to be_a( Sequel::Dataset ) expect( word.nouns.count ).to eq( 16 ) @@ -46,6 +50,7 @@ ) end + it "has a dataset for selecting verb synsets" do expect( word.verbs ).to be_a( Sequel::Dataset ) expect( word.verbs.count ).to eq( 41 ) @@ -63,7 +68,8 @@ context "the Word for 'light'" do - let( :word ) { lexicon[77458] } + let( :word ) { described_class.by_lemma('light').first } + it "has a dataset for selecting adjective synsets" do expect( word.adjectives ).to be_a( Sequel::Dataset ) @@ -76,6 +82,7 @@ ) end + it "has a dataset for selecting adjective-satellite synsets" do expect( word.adjective_satellites ).to be_a( Sequel::Dataset ) expect( word.adjective_satellites.count ).to eq( 17 ) @@ -92,7 +99,8 @@ context "the Word for 'lightly'" do - let( :word ) { lexicon[77549] } + let( :word ) { described_class.by_lemma('lightly').first } + it "has a dataset for selecting adverb synsets" do expect( word.adverbs ).to be_a( Sequel::Dataset ) diff --git a/wordnet-defaultdb/Manifest.txt b/wordnet-defaultdb/Manifest.txt --- a/wordnet-defaultdb/Manifest.txt +++ b/wordnet-defaultdb/Manifest.txt @@ -3,5 +3,5 @@ Manifest.txt README.rdoc Rakefile -data/wordnet-defaultdb/wordnet30.sqlite +data/wordnet-defaultdb/wordnet31.sqlite lib/wordnet-defaultdb.rb diff --git a/wordnet-defaultdb/README.rdoc b/wordnet-defaultdb/README.rdoc --- a/wordnet-defaultdb/README.rdoc +++ b/wordnet-defaultdb/README.rdoc @@ -1,9 +1,9 @@ -# wordnet_defaultdb += wordnet_defaultdb * http://deveiate.org/projects/Ruby-WordNet/wiki/Databases -## Description +== Description This gem is a container for the default WordNetSQL database files loaded by the 'wordnet' gem if you don't have your own installation of the WordNet @@ -15,12 +15,12 @@ no arguments. -## Installation +== Installation gem install wordnet-defaultdb -## License +== License WordNet Release 3.0 diff --git a/wordnet-defaultdb/lib/wordnet-defaultdb.rb b/wordnet-defaultdb/lib/wordnet-defaultdb.rb --- a/wordnet-defaultdb/lib/wordnet-defaultdb.rb +++ b/wordnet-defaultdb/lib/wordnet-defaultdb.rb @@ -3,7 +3,7 @@ # This gem is a container for the default WordNetSQL database files required for # the 'wordnet' gem. It's mostly just a wrapper around the Sqlite database from: # -# http://sourceforge.net/projects/wnsql/ +# http://sqlunet.sourceforge.net/ # # == Author/s # @@ -13,7 +13,7 @@ module DefaultDB # Library version constant - VERSION = '0.99.0' + VERSION = '1.0.0' # Version-control revision constant REVISION = %q$Revision$ diff --git a/wordnet.gemspec b/wordnet.gemspec --- a/wordnet.gemspec +++ b/wordnet.gemspec @@ -1,63 +1,63 @@ # -*- encoding: utf-8 -*- -# stub: wordnet 1.1.0.pre20160918161825 ruby lib +# stub: wordnet 1.1.0.pre20170926144654 ruby lib Gem::Specification.new do |s| - s.name = "wordnet" - s.version = "1.1.0.pre20160918161825" + s.name = "wordnet".freeze + s.version = "1.1.0.pre20170926144654" - s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= - s.require_paths = ["lib"] - s.authors = ["Michael Granger"] - s.cert_chain = ["certs/ged.pem"] - s.date = "2016-09-18" - s.description = "This library is a Ruby interface to WordNet\u{ae}[http://wordnet.princeton.edu/].\nWordNet\u{ae} is an online lexical reference system whose design is inspired\nby current psycholinguistic theories of human lexical memory. English\nnouns, verbs, adjectives and adverbs are organized into synonym sets, each\nrepresenting one underlying lexical concept. Different relations link\nthe synonym sets.\n\nThis library uses WordNet-SQL[http://wnsql.sourceforge.net/], which is a\nconversion of the lexicon flatfiles into a relational database format. You\ncan either install the 'wordnet-defaultdb' gem, which packages up the\nSQLite3 version of WordNet-SQL, or install your own and point the lexicon\nat it by passing \n{Sequel connection parameters}[http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html]\nto the constructor." - s.email = ["ged@FaerieMUD.org"] - s.extra_rdoc_files = ["History.rdoc", "Manifest.txt", "README.rdoc", "WordNet30-license.txt", "History.rdoc", "README.rdoc"] - s.files = [".simplecov", "ChangeLog", "History.rdoc", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "TODO", "WordNet30-license.txt", "examples/gcs.rb", "examples/hypernym_tree.rb", "lib/wordnet.rb", "lib/wordnet/constants.rb", "lib/wordnet/lexicallink.rb", "lib/wordnet/lexicon.rb", "lib/wordnet/model.rb", "lib/wordnet/morph.rb", "lib/wordnet/semanticlink.rb", "lib/wordnet/sense.rb", "lib/wordnet/sumoterm.rb", "lib/wordnet/synset.rb", "lib/wordnet/word.rb", "spec/helpers.rb", "spec/wordnet/lexicon_spec.rb", "spec/wordnet/model_spec.rb", "spec/wordnet/semanticlink_spec.rb", "spec/wordnet/synset_spec.rb", "spec/wordnet/word_spec.rb", "spec/wordnet_spec.rb"] - s.homepage = "http://deveiate.org/projects/Ruby-WordNet" - s.licenses = ["BSD-3-Clause"] - s.post_install_message = "\nIf you don't already have a WordNet database installed somewhere,\nyou'll need to either download and install one from:\n\n http://wnsql.sourceforge.net/\n\nor just install the 'wordnet-defaultdb' gem, which will install\nthe SQLite version for you.\n\n" - s.rdoc_options = ["--main", "README.rdoc"] - s.required_ruby_version = Gem::Requirement.new(">= 2.2.0") - s.rubygems_version = "2.5.1" - s.summary = "This library is a Ruby interface to WordNet\u{ae}[http://wordnet.princeton.edu/]" + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version= + s.require_paths = ["lib".freeze] + s.authors = ["Michael Granger".freeze] + s.cert_chain = ["certs/ged.pem".freeze] + s.date = "2017-09-26" + s.description = "This library is a Ruby interface to WordNet\u00AE[http://wordnet.princeton.edu/].\nWordNet\u00AE is an online lexical reference system whose design is inspired\nby current psycholinguistic theories of human lexical memory. English\nnouns, verbs, adjectives and adverbs are organized into synonym sets, each\nrepresenting one underlying lexical concept. Different relations link\nthe synonym sets.\n\nThis library uses WordNet-SQL[http://wnsql.sourceforge.net/], which is a\nconversion of the lexicon flatfiles into a relational database format. You\ncan either install the 'wordnet-defaultdb' gem, which packages up the\nSQLite3 version of WordNet-SQL, or install your own and point the lexicon\nat it by passing \n{Sequel connection parameters}[http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html]\nto the constructor.".freeze + s.email = ["ged@FaerieMUD.org".freeze] + s.extra_rdoc_files = ["History.rdoc".freeze, "Manifest.txt".freeze, "README.md".freeze, "README.rdoc".freeze, "WordNet30-license.txt".freeze, "History.rdoc".freeze, "README.rdoc".freeze] + s.files = [".gems".freeze, ".ruby-gemset".freeze, ".ruby-version".freeze, ".simplecov".freeze, "ChangeLog".freeze, "Gemfile".freeze, "History.rdoc".freeze, "LICENSE".freeze, "Manifest.txt".freeze, "README.md".freeze, "README.rdoc".freeze, "Rakefile".freeze, "TODO".freeze, "WordNet30-license.txt".freeze, "certs/ged.pem".freeze, "examples/gcs.rb".freeze, "examples/hypernym_tree.rb".freeze, "lib/wordnet.rb".freeze, "lib/wordnet/constants.rb".freeze, "lib/wordnet/lexicallink.rb".freeze, "lib/wordnet/lexicon.rb".freeze, "lib/wordnet/model.rb".freeze, "lib/wordnet/morph.rb".freeze, "lib/wordnet/semanticlink.rb".freeze, "lib/wordnet/sense.rb".freeze, "lib/wordnet/sumoterm.rb".freeze, "lib/wordnet/synset.rb".freeze, "lib/wordnet/word.rb".freeze, "spec/helpers.rb".freeze, "spec/wordnet/lexicon_spec.rb".freeze, "spec/wordnet/model_spec.rb".freeze, "spec/wordnet/semanticlink_spec.rb".freeze, "spec/wordnet/sense_spec.rb".freeze, "spec/wordnet/synset_spec.rb".freeze, "spec/wordnet/word_spec.rb".freeze, "spec/wordnet_spec.rb".freeze, "wordnet.gemspec".freeze] + s.homepage = "http://deveiate.org/projects/Ruby-WordNet".freeze + s.licenses = ["BSD-3-Clause".freeze] + s.post_install_message = "\nIf you don't already have a WordNet database installed somewhere,\nyou'll need to either download and install one from:\n\n http://wnsql.sourceforge.net/\n\nor just install the 'wordnet-defaultdb' gem, which will install\nthe SQLite version for you.\n\n".freeze + s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] + s.required_ruby_version = Gem::Requirement.new(">= 2.2.0".freeze) + s.rubygems_version = "2.6.13".freeze + s.summary = "This library is a Ruby interface to WordNet\u00AE[http://wordnet.princeton.edu/]".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_runtime_dependency(%q, ["~> 4.38"]) - s.add_runtime_dependency(%q, ["~> 0.11"]) - s.add_development_dependency(%q, ["~> 1.4"]) - s.add_development_dependency(%q, ["~> 0.8"]) - s.add_development_dependency(%q, ["~> 0.2"]) - s.add_development_dependency(%q, ["~> 4.0"]) - s.add_development_dependency(%q, ["~> 1.3"]) - s.add_development_dependency(%q, ["~> 3.5"]) - s.add_development_dependency(%q, ["~> 0.12"]) - s.add_development_dependency(%q, ["~> 3.15"]) + s.add_runtime_dependency(%q.freeze, ["~> 5.0"]) + s.add_runtime_dependency(%q.freeze, ["~> 0.11"]) + s.add_development_dependency(%q.freeze, ["~> 1.4"]) + s.add_development_dependency(%q.freeze, ["~> 0.9"]) + s.add_development_dependency(%q.freeze, ["~> 0.2"]) + s.add_development_dependency(%q.freeze, ["~> 1.3"]) + s.add_development_dependency(%q.freeze, ["~> 3.5"]) + s.add_development_dependency(%q.freeze, ["~> 0.12"]) + s.add_development_dependency(%q.freeze, ["~> 4.0"]) + s.add_development_dependency(%q.freeze, ["~> 3.16"]) else - s.add_dependency(%q, ["~> 4.38"]) - s.add_dependency(%q, ["~> 0.11"]) - s.add_dependency(%q, ["~> 1.4"]) - s.add_dependency(%q, ["~> 0.8"]) - s.add_dependency(%q, ["~> 0.2"]) - s.add_dependency(%q, ["~> 4.0"]) - s.add_dependency(%q, ["~> 1.3"]) - s.add_dependency(%q, ["~> 3.5"]) - s.add_dependency(%q, ["~> 0.12"]) - s.add_dependency(%q, ["~> 3.15"]) + s.add_dependency(%q.freeze, ["~> 5.0"]) + s.add_dependency(%q.freeze, ["~> 0.11"]) + s.add_dependency(%q.freeze, ["~> 1.4"]) + s.add_dependency(%q.freeze, ["~> 0.9"]) + s.add_dependency(%q.freeze, ["~> 0.2"]) + s.add_dependency(%q.freeze, ["~> 1.3"]) + s.add_dependency(%q.freeze, ["~> 3.5"]) + s.add_dependency(%q.freeze, ["~> 0.12"]) + s.add_dependency(%q.freeze, ["~> 4.0"]) + s.add_dependency(%q.freeze, ["~> 3.16"]) end else - s.add_dependency(%q, ["~> 4.38"]) - s.add_dependency(%q, ["~> 0.11"]) - s.add_dependency(%q, ["~> 1.4"]) - s.add_dependency(%q, ["~> 0.8"]) - s.add_dependency(%q, ["~> 0.2"]) - s.add_dependency(%q, ["~> 4.0"]) - s.add_dependency(%q, ["~> 1.3"]) - s.add_dependency(%q, ["~> 3.5"]) - s.add_dependency(%q, ["~> 0.12"]) - s.add_dependency(%q, ["~> 3.15"]) + s.add_dependency(%q.freeze, ["~> 5.0"]) + s.add_dependency(%q.freeze, ["~> 0.11"]) + s.add_dependency(%q.freeze, ["~> 1.4"]) + s.add_dependency(%q.freeze, ["~> 0.9"]) + s.add_dependency(%q.freeze, ["~> 0.2"]) + s.add_dependency(%q.freeze, ["~> 1.3"]) + s.add_dependency(%q.freeze, ["~> 3.5"]) + s.add_dependency(%q.freeze, ["~> 0.12"]) + s.add_dependency(%q.freeze, ["~> 4.0"]) + s.add_dependency(%q.freeze, ["~> 3.16"]) end end