humanname 0.4.4-x86_64-linux → 0.8.0-x86_64-linux
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +8 -39
- data/humanname.gemspec +5 -5
- data/lib/humanname/version.rb +1 -1
- data/lib/humanname.rb +131 -10
- data/lib/native/arm64/libhuman_name.dylib +0 -0
- data/lib/native/arm64/libhuman_name.so +0 -0
- data/lib/native/x86_64/human_name.dll +0 -0
- data/lib/native/x86_64/libhuman_name.dylib +0 -0
- data/lib/native/x86_64/libhuman_name.so +0 -0
- data/spec/humanname_spec.rb +12 -14
- metadata +18 -16
- data/lib/humanname/native.bundle +0 -0
- data/lib/humanname/native.so +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4f09cc8706ffe6d100443c3b1424e268559eb5ad95816cf8db9a49d92f247c41
|
4
|
+
data.tar.gz: 318f6bf3ea00aa09f7c6a503182351ea491ae7854a26b96a0ac8ea9386cca4e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9c480c75130da9fbd194d500407fb5855344d4989157f133483045b461a3a1c84586217bd4242b07a8d04219f51300917b25741e2013986cf4f551158e8f036
|
7
|
+
data.tar.gz: 675a2825eaf398d8ea6dde01e8bf8d6c80b3a596e5423552720a56da1065e548bbd4f44652b246455b720e059f320990665c3eab4c49dc85e7da95dad1f62f93
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# human-name-rb
|
2
2
|
Ruby bindings for the Rust crate [`human_name`](https://github.com/djudd/human-name), a library for parsing and comparing human names.
|
3
3
|
|
4
|
-
[![Build Status](https://travis-ci.org/djudd/human-name-rb.svg?branch=master)](https://travis-ci.org/djudd/human-name-rb)
|
5
|
-
|
6
4
|
See the [`human_name` docs](http://djudd.github.io/human-name) for details.
|
7
5
|
|
8
6
|
# Examples
|
@@ -36,41 +34,12 @@ See the [`human_name` docs](http://djudd.github.io/human-name) for details.
|
|
36
34
|
|
37
35
|
# Supported environments
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
If you're willing to do a little more work, anywhere supported by [Helix](https://github.com/tildeio/helix)
|
42
|
-
and the nightly Rust compiler:
|
43
|
-
```bash
|
44
|
-
curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly
|
45
|
-
git clone git@github.com:djudd/human-name-rb.git
|
46
|
-
cd human-name-rb
|
47
|
-
bundle exec rake
|
48
|
-
```
|
49
|
-
|
50
|
-
That will give you a .gem file in pkg/ which should work in environments similar
|
51
|
-
to the one in which it was built.
|
52
|
-
|
53
|
-
# Benchmark results
|
54
|
-
|
55
|
-
Comparing to [`people`](https://github.com/academia-edu/people), [`namae`](https://github.com/berkmancenter/namae), and [`human_name_parser`](https://github.com/abachman/human_name_parser),
|
56
|
-
on 16k real examples taken mostly from PubMed author fields:
|
57
|
-
|
58
|
-
```
|
59
|
-
$ bundle exec rake benchmark
|
60
|
-
people gem:
|
61
|
-
3.010000 0.030000 3.040000 ( 3.032075)
|
62
|
-
namae gem:
|
63
|
-
3.550000 0.080000 3.630000 ( 3.630643)
|
64
|
-
human_name_parser gem:
|
65
|
-
1.960000 0.030000 1.990000 ( 1.991358)
|
66
|
-
this gem:
|
67
|
-
0.100000 0.000000 0.100000 ( 0.107794)
|
68
|
-
```
|
69
|
-
|
70
|
-
Our implementation uses a similar strategy to `people` and `human_name_parser`
|
71
|
-
but covers significantly more edge cases, and also supports comparison.
|
72
|
-
(`human_name_parser` also covers fewer edge cases than `people`, as of December
|
73
|
-
2015, which probably explains its speed advantage.)
|
37
|
+
Linux, MacOS, and Windows, as of the versions currently supported by GitHub Actions.
|
38
|
+
x86-64 or Apple Silicon. Ruby 2.7 or later.
|
74
39
|
|
75
|
-
|
76
|
-
|
40
|
+
If you have access to another environment which is supported by the Rust compiler,
|
41
|
+
it should be relatively straightforward to fork the library and add support. You'll need
|
42
|
+
to build [`human_name`](http://github.com/djudd/human-name), copy the resulting library
|
43
|
+
from `target/release/` in that repository to `lib/native/<arch>/` in this one,
|
44
|
+
and modify `native_lib_path` appropriately. If this environment is additionally supported
|
45
|
+
by GitHub Actions, I'm also happy to accept a PR.
|
data/humanname.gemspec
CHANGED
@@ -11,10 +11,10 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = 'https://github.com/djudd/human-name-rb'
|
12
12
|
s.license = 'Apache-2.0'
|
13
13
|
s.platform = Gem::Platform::CURRENT
|
14
|
-
s.required_ruby_version = '>= 2.
|
15
|
-
s.add_runtime_dependency '
|
16
|
-
s.add_development_dependency 'rake', '~>
|
14
|
+
s.required_ruby_version = '>= 2.7.0'
|
15
|
+
s.add_runtime_dependency 'ffi', '~> 1.15.1'
|
16
|
+
s.add_development_dependency 'rake', '~> 13.0.6'
|
17
17
|
s.add_development_dependency 'rspec', '~> 3.4.0'
|
18
|
-
s.add_development_dependency 'rubygems-tasks', '~> 0.2.
|
19
|
-
s.add_development_dependency 'pry', '~> 0.
|
18
|
+
s.add_development_dependency 'rubygems-tasks', '~> 0.2.5'
|
19
|
+
s.add_development_dependency 'pry', '~> 0.14.2'
|
20
20
|
end
|
data/lib/humanname/version.rb
CHANGED
data/lib/humanname.rb
CHANGED
@@ -1,24 +1,136 @@
|
|
1
|
-
require '
|
1
|
+
require 'ffi'
|
2
2
|
require 'humanname/version'
|
3
|
-
require 'humanname/native'
|
4
3
|
|
5
4
|
module HumanName
|
6
|
-
Name = RustHumanName
|
7
|
-
|
8
5
|
UTF8 = 'UTF-8'.freeze
|
6
|
+
NAME_PARTS = %w(
|
7
|
+
surname
|
8
|
+
given_name
|
9
|
+
initials
|
10
|
+
first_initial
|
11
|
+
middle_initials
|
12
|
+
middle_names
|
13
|
+
generational_suffix
|
14
|
+
display_first_last
|
15
|
+
display_full
|
16
|
+
display_initial_surname
|
17
|
+
).freeze
|
18
|
+
|
19
|
+
class UnsupportedPlatform < StandardError
|
20
|
+
def initialize
|
21
|
+
platform = Gem::Platform.local
|
22
|
+
super("Unsupported platform: #{platform.os}-#{platform.cpu}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Native
|
27
|
+
extend FFI::Library
|
28
|
+
|
29
|
+
def self.init!
|
30
|
+
path = native_lib_path
|
31
|
+
if File.exist?(path)
|
32
|
+
ffi_lib path
|
33
|
+
else
|
34
|
+
raise UnsupportedPlatform.new
|
35
|
+
end
|
36
|
+
|
37
|
+
attach_function :human_name_parse, [:string], :pointer
|
38
|
+
attach_function :human_name_consistent_with, [:pointer, :pointer], :bool
|
39
|
+
attach_function :human_name_hash, [:pointer], :uint64
|
40
|
+
|
41
|
+
NAME_PARTS.each do |part|
|
42
|
+
attach_function "human_name_#{part}".to_sym, [:pointer], :pointer
|
43
|
+
end
|
44
|
+
|
45
|
+
attach_function :human_name_goes_by_middle_name, [:pointer], :bool
|
46
|
+
attach_function :human_name_byte_len, [:pointer], :uint32
|
47
|
+
|
48
|
+
attach_function :human_name_free_name, [:pointer], :void
|
49
|
+
attach_function :human_name_free_string, [:pointer], :void
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.native_lib_path
|
53
|
+
platform = Gem::Platform.local
|
54
|
+
|
55
|
+
filename = case platform.os
|
56
|
+
when 'darwin'
|
57
|
+
'libhuman_name.dylib'
|
58
|
+
when 'linux'
|
59
|
+
'libhuman_name.so'
|
60
|
+
when /mswin|mingw/
|
61
|
+
'human_name.dll'
|
62
|
+
else
|
63
|
+
raise UnsupportedPlatform.new
|
64
|
+
end
|
65
|
+
|
66
|
+
cpu = platform.cpu
|
67
|
+
cpu = 'x86_64' if cpu == 'x64'
|
68
|
+
|
69
|
+
File.expand_path(
|
70
|
+
File.join('../native/', cpu, filename),
|
71
|
+
__FILE__,
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
Native.init!
|
77
|
+
private_constant :Native
|
78
|
+
|
79
|
+
class NativeString < String
|
80
|
+
DESTRUCTOR = Native.method(:human_name_free_string)
|
81
|
+
|
82
|
+
def self.wrap(pointer)
|
83
|
+
new(pointer) unless pointer.null?
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize(pointer)
|
87
|
+
@pointer = FFI::AutoPointer.new(pointer, DESTRUCTOR)
|
88
|
+
super(@pointer.read_string.force_encoding(UTF8))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private_constant :NativeString
|
93
|
+
|
94
|
+
class Name < FFI::AutoPointer
|
95
|
+
DESTRUCTOR = Native.method(:human_name_free_name)
|
9
96
|
|
10
|
-
class Name
|
11
97
|
def self.parse(string)
|
12
98
|
string = string.encode(UTF8) unless string.encoding == UTF8
|
13
|
-
|
99
|
+
pointer = Native.human_name_parse(string)
|
100
|
+
new(pointer) unless pointer.null?
|
14
101
|
end
|
15
102
|
|
16
|
-
def
|
17
|
-
|
18
|
-
matches_slug_or_localpart_utf8(string)
|
103
|
+
def initialize(pointer)
|
104
|
+
super(pointer, DESTRUCTOR)
|
19
105
|
end
|
20
106
|
|
21
|
-
|
107
|
+
def ==(other)
|
108
|
+
other.is_a?(Name) && Native.human_name_consistent_with(self, other)
|
109
|
+
end
|
110
|
+
alias_method :eql?, :==
|
111
|
+
|
112
|
+
def hash
|
113
|
+
Native.human_name_hash(self)
|
114
|
+
end
|
115
|
+
|
116
|
+
NAME_PARTS.each do |part|
|
117
|
+
native_method = "human_name_#{part}".to_sym
|
118
|
+
|
119
|
+
define_method part do
|
120
|
+
pointer = Native.send(native_method, self)
|
121
|
+
NativeString.wrap(pointer)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def goes_by_middle_name
|
126
|
+
Native.human_name_goes_by_middle_name(self)
|
127
|
+
end
|
128
|
+
|
129
|
+
def length
|
130
|
+
Native.human_name_byte_len(self)
|
131
|
+
end
|
132
|
+
|
133
|
+
JSON_PARTS = %w( surname given_name first_initial middle_initials middle_names generational_suffix ).map(&:to_sym)
|
22
134
|
|
23
135
|
def as_json(options = {})
|
24
136
|
# We take an "options" argument for minimal compatibility with ActiveSupport,
|
@@ -27,11 +139,20 @@ module HumanName
|
|
27
139
|
raise ArgumentError.new("Unsupported option: #{opt}") if options[opt]
|
28
140
|
end
|
29
141
|
|
142
|
+
to_h
|
143
|
+
end
|
144
|
+
|
145
|
+
def to_h
|
30
146
|
JSON_PARTS.inject({}) do |memo, part|
|
31
147
|
memo[part] = send(part)
|
32
148
|
memo
|
33
149
|
end
|
34
150
|
end
|
151
|
+
|
152
|
+
def inspect
|
153
|
+
"HumanName::Name(#{display_full})"
|
154
|
+
end
|
155
|
+
|
35
156
|
end
|
36
157
|
|
37
158
|
def self.parse(string)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/spec/humanname_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe HumanName do
|
|
9
9
|
expect(n.given_name).to eq('Jane')
|
10
10
|
expect(n.surname).to eq('Doe')
|
11
11
|
expect(n.middle_names).to be_nil
|
12
|
-
expect(n.
|
12
|
+
expect(n.generational_suffix).to be_nil
|
13
13
|
expect(n.display_full).to eq('Jane Doe')
|
14
14
|
expect(n.display_first_last).to eq('Jane Doe')
|
15
15
|
expect(n.display_initial_surname).to eq('J. Doe')
|
@@ -22,7 +22,7 @@ describe HumanName do
|
|
22
22
|
expect(n.given_name).to eq('John')
|
23
23
|
expect(n.surname).to eq('de la MacDonald')
|
24
24
|
expect(n.middle_names).to eq('Allen')
|
25
|
-
expect(n.
|
25
|
+
expect(n.generational_suffix).to eq('Jr.')
|
26
26
|
expect(n.display_full).to eq('John Allen Q. de la MacDonald, Jr.')
|
27
27
|
expect(n.display_first_last).to eq('John de la MacDonald')
|
28
28
|
expect(n.display_initial_surname).to eq('J. de la MacDonald')
|
@@ -69,16 +69,6 @@ describe HumanName do
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
describe 'matches_slug_or_localpart' do
|
73
|
-
it 'is true given match' do
|
74
|
-
expect(HumanName.parse("Jane Doe").matches_slug_or_localpart('janexdoe')).to be_truthy
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'is false given non-match' do
|
78
|
-
expect(HumanName.parse("Jane Doe").matches_slug_or_localpart('johnxdoe')).to be_falsey
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
72
|
it 'implements as_json' do
|
83
73
|
n = HumanName.parse("JOHN ALLEN Q DE LA MACDONALD JR")
|
84
74
|
expect(n.as_json).to eq({
|
@@ -87,11 +77,19 @@ describe HumanName do
|
|
87
77
|
middle_names: 'Allen',
|
88
78
|
first_initial: 'J',
|
89
79
|
middle_initials: 'AQ',
|
90
|
-
|
80
|
+
generational_suffix: 'Jr.',
|
91
81
|
})
|
92
82
|
end
|
93
83
|
|
94
84
|
it 'does not leak memory' do
|
85
|
+
skip unless ['linux', 'darwin'].include?(Gem::Platform.local.os)
|
86
|
+
|
87
|
+
# This is fishy but we either have a memory leak with 3.3 or something has changed
|
88
|
+
# with memory management such that it's harder to write a clean test for one.
|
89
|
+
# I suspect the latter because it's easier to understand why that would change
|
90
|
+
# between Ruby versions, but I'm not sure...
|
91
|
+
skip if RUBY_VERSION >= "3.3"
|
92
|
+
|
95
93
|
def rss
|
96
94
|
GC.start
|
97
95
|
`ps -o rss= -p #{Process.pid}`.chomp.to_i
|
@@ -106,7 +104,7 @@ describe HumanName do
|
|
106
104
|
first_initial
|
107
105
|
middle_initials
|
108
106
|
middle_names
|
109
|
-
|
107
|
+
generational_suffix
|
110
108
|
display_first_last
|
111
109
|
display_full
|
112
110
|
display_initial_surname
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: humanname
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: x86_64-linux
|
6
6
|
authors:
|
7
7
|
- David Judd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: ffi
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.15.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.15.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 13.0.6
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 13.0.6
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,28 +58,28 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.2.
|
61
|
+
version: 0.2.5
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.2.
|
68
|
+
version: 0.2.5
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 0.14.2
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 0.14.2
|
83
83
|
description: A library for parsing and comparing human names. Wraps the Rust crate
|
84
84
|
`human_name`.
|
85
85
|
email: david.a.judd@gmail.com
|
@@ -92,9 +92,12 @@ files:
|
|
92
92
|
- README.md
|
93
93
|
- humanname.gemspec
|
94
94
|
- lib/humanname.rb
|
95
|
-
- lib/humanname/native.bundle
|
96
|
-
- lib/humanname/native.so
|
97
95
|
- lib/humanname/version.rb
|
96
|
+
- lib/native/arm64/libhuman_name.dylib
|
97
|
+
- lib/native/arm64/libhuman_name.so
|
98
|
+
- lib/native/x86_64/human_name.dll
|
99
|
+
- lib/native/x86_64/libhuman_name.dylib
|
100
|
+
- lib/native/x86_64/libhuman_name.so
|
98
101
|
- spec/humanname_spec.rb
|
99
102
|
- spec/spec_helper.rb
|
100
103
|
homepage: https://github.com/djudd/human-name-rb
|
@@ -109,15 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
112
|
requirements:
|
110
113
|
- - ">="
|
111
114
|
- !ruby/object:Gem::Version
|
112
|
-
version: 2.
|
115
|
+
version: 2.7.0
|
113
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
117
|
requirements:
|
115
118
|
- - ">="
|
116
119
|
- !ruby/object:Gem::Version
|
117
120
|
version: '0'
|
118
121
|
requirements: []
|
119
|
-
|
120
|
-
rubygems_version: 2.5.2
|
122
|
+
rubygems_version: 3.5.9
|
121
123
|
signing_key:
|
122
124
|
specification_version: 4
|
123
125
|
summary: A library for parsing and comparing human names
|
data/lib/humanname/native.bundle
DELETED
Binary file
|
data/lib/humanname/native.so
DELETED
Binary file
|