trials 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0faac0139726fc3797359f6d89582fcc463721378f4614f711b97d4de0f7850b
4
+ data.tar.gz: bf7c8ad2165fb67eedaf1b0c5c78f15af345f17a4a064b36a452e850d672afe3
5
+ SHA512:
6
+ metadata.gz: b691fe13f902bc121b4ba85a0350d077682d73d3119beba04cc4a788a891c94eb9d208a76e5b9af8b59e880c421b51fd30b672bb7ed2845569e86ec938a2cef5
7
+ data.tar.gz: 80a851272d8ed0b997df0e3a5f10c257acf73fd2cf07c9373c0cc5c26dfb1d7d473a4a6da7f08ebcd72ddf475d4d011cf86f9937cdd477a27ccedf195e184c33
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/trials'
4
+
5
+ # env
6
+ START_TIME = Time.now
7
+ SCRIPT_NAME = ARGV[0].gsub('.rb', '')
8
+ RUN = "#{START_TIME.strftime("%Y%m%dT%H%M%S")}_#{SCRIPT_NAME}"
9
+ ROOT = Dir.pwd
10
+ SECRETS = OpenStruct.new
11
+
12
+ if File.exists?(File.expand_path('~/.trials/secrets.yml'))
13
+ JSON.parse(
14
+ YAML.load_file(File.expand_path('~/.trials/secrets.yml')).to_json,
15
+ object_class: OpenStruct,
16
+ )
17
+ end
18
+
19
+ # init standard dirs
20
+ FileUtils.mkdir_p("seeds")
21
+ FileUtils.mkdir_p("results/#{RUN}")
22
+ FileUtils.mkdir_p("tmp")
23
+
24
+ # log start
25
+ log "starting #{SCRIPT_NAME} at #{START_TIME.iso8601}"
26
+ log nil
27
+
28
+ # run script
29
+ load "#{SCRIPT_NAME}.rb"
30
+
31
+ # log end
32
+ END_TIME = Time.now
33
+ log nil
34
+ log "done at #{END_TIME.iso8601}, took #{(END_TIME - START_TIME).round(4)}s"
@@ -0,0 +1,36 @@
1
+ require 'active_support/all'
2
+ require 'aws-sdk-dynamodb'
3
+ require 'benchmark'
4
+ require 'csv'
5
+ require 'fileutils'
6
+ require 'fuzzy_match'
7
+ require 'google_drive'
8
+ require 'namae'
9
+ require 'nokogiri'
10
+ require 'ostruct'
11
+ require 'pp'
12
+ require 'pry'
13
+ require 'rest-client'
14
+ require 'set'
15
+ require 'smalltext'
16
+ require 'sqlite3'
17
+ require 'street_address'
18
+ require 'tty-table'
19
+ require 'yaml'
20
+
21
+ require_relative 'trials/utils/various'
22
+ require_relative 'trials/utils/csvs'
23
+ require_relative 'trials/utils/hashes'
24
+ require_relative 'trials/utils/logging'
25
+ require_relative 'trials/utils/strings'
26
+ require_relative 'trials/utils/files'
27
+ require_relative 'trials/utils/jsons'
28
+ require_relative 'trials/utils/sqls'
29
+ require_relative 'trials/utils/pdfs'
30
+ require_relative 'trials/utils/xmls'
31
+ require_relative 'trials/utils/benchmarking'
32
+ require_relative 'trials/utils/rollbar'
33
+ require_relative 'trials/utils/aws'
34
+ require_relative 'trials/utils/google_drive'
35
+ require_relative 'trials/data_handling/addresses'
36
+ require_relative 'trials/data_handling/names'
@@ -0,0 +1,37 @@
1
+ # normal format <number> <STREET NAME>, <CITY>, <STATE> <postal>
2
+
3
+ def normalize_address(address)
4
+ return if address.blank?
5
+
6
+ cleaner_string = if address.respond_to?(:address1)
7
+ "#{address.address1}, #{address.city}, #{address.state} #{address.postal_code}"
8
+ else
9
+ address
10
+ end
11
+
12
+ cleaner_string = cleaner_string.gsub('#', ' #').squish
13
+ parsed = StreetAddress::US.parse(cleaner_string)
14
+
15
+ return if parsed.blank?
16
+ return if parsed.number.blank?
17
+ return if parsed.street.blank?
18
+ return if parsed.city.blank?
19
+ return if parsed.state.blank?
20
+ return if parsed.postal_code.blank?
21
+
22
+ parsed.prefix = nil
23
+ parsed.suffix = nil
24
+ parsed.unit_prefix = nil
25
+ parsed.unit = nil
26
+ parsed.postal_code_ext = nil
27
+
28
+ parsed.to_s.upcase
29
+ end
30
+
31
+ def parse_address(address_string)
32
+ StreetAddress::US.parse(address_string)
33
+ end
34
+
35
+ def normalize_and_parse_address(address_string)
36
+ StreetAddress::US.parse(normalize_address(address_string))
37
+ end
@@ -0,0 +1,84 @@
1
+ # normal <FIRST> <LAST>
2
+
3
+ Name = Struct.new(:first_name, :middle_name, :last_name)
4
+
5
+ class NamePartsParser
6
+ def initialize(name_string)
7
+ @namae = Namae.parse((name_string || '').upcase).first
8
+ end
9
+
10
+ def first
11
+ normalize_name(split_first_and_middle(given).first)
12
+ end
13
+
14
+ def middle
15
+ normalize_name(split_first_and_middle(given).last)
16
+ end
17
+
18
+ def last
19
+ normalize_name(family)
20
+ end
21
+
22
+ private
23
+
24
+ def given
25
+ @namae&.given || ''
26
+ end
27
+
28
+ def family
29
+ @namae&.family || ''
30
+ end
31
+
32
+ def split_first_and_middle(first_and_middle)
33
+ names = first_and_middle.split(' ', 2)
34
+ names.length == 1 ? names + [''] : names
35
+ end
36
+ end
37
+
38
+ def normalize_name(name)
39
+ return if name.blank?
40
+
41
+ name = name_from_parts(name) if name.respond_to?(:first_name)
42
+
43
+ name.strip.upcase.delete('^A-Z\ \-').squeeze(" ")
44
+ end
45
+
46
+ def normalize_full_names(names)
47
+ Array.wrap(names)
48
+ .map { |n| normalize_full_name(n) }
49
+ .map(&:to_s)
50
+ .map(&:presence)
51
+ .compact
52
+ .uniq
53
+ end
54
+
55
+ def normalize_full_name(name)
56
+ return if name.blank?
57
+
58
+ name.strip.upcase.delete('^A-Z\ \-').squeeze(" ")
59
+ end
60
+
61
+ def parse_name(name)
62
+ NamePartsParser.new(name)
63
+ end
64
+
65
+ def normalize_and_parse_name(name)
66
+ NamePartsParser.new(normalize_name(name))
67
+ end
68
+
69
+ # private
70
+
71
+ def name_from_parts(name)
72
+ first = normalize_name_part(name.first_name)
73
+ last = normalize_name_part(name.last_name)
74
+
75
+ [first, last].join(' ')
76
+ end
77
+
78
+ def full_name_from_parts(name)
79
+ first = normalize_name_part(name.first_name)
80
+ middle = normalize_name_part(name.middle_name)
81
+ last = normalize_name_part(name.last_name)
82
+
83
+ [first, middle, last].join(' ')
84
+ end
@@ -0,0 +1,67 @@
1
+ def ddb_connection
2
+ @connection ||= Aws::DynamoDB::Client.new(
3
+ access_key_id: secrets.aws.key,
4
+ secret_access_key: secrets.aws.secret,
5
+ region: secrets.aws.region,
6
+ )
7
+ end
8
+
9
+ def cached_ddb_scan(query)
10
+ json_cache(query.dig(:table_name)) { ddb_scan(query) }
11
+ end
12
+
13
+ def ddb_scan(query)
14
+ segmentation = query.delete(:segmentation) || 4
15
+
16
+ threads = (0..segmentation - 1).map do |segment|
17
+ Thread.new do
18
+ Thread.current[:output] = ddb_scan_without_segmentation(
19
+ query.merge(
20
+ total_segments: segmentation,
21
+ segment: segment,
22
+ ),
23
+ )
24
+ end
25
+ end
26
+
27
+ threads.each(&:join)
28
+
29
+ threads.map { |t| t[:output] }.flatten
30
+ end
31
+
32
+ def ddb_scan_without_segmentation(query)
33
+ result = nil
34
+ requests = 0
35
+ items = []
36
+
37
+ loop do
38
+ break unless result.blank? || result.last_evaluated_key.present?
39
+
40
+ result = ddb_connection.scan(query.merge(exclusive_start_key: result&.last_evaluated_key))
41
+ items += result.items.compact.map(&:symbolize_keys)
42
+ end
43
+
44
+ items
45
+ end
46
+
47
+ def ddb_upload_items(table, all_items)
48
+ all_items.each_slice(25).with_index do |items, i|
49
+ next unless items.any?
50
+
51
+ begin
52
+ ddb_connection.batch_write_item(
53
+ request_items: {
54
+ table => items.compact.map do |item|
55
+ {
56
+ put_request: {
57
+ item: item
58
+ }
59
+ }
60
+ end
61
+ }
62
+ )
63
+ end
64
+
65
+ yield(items, i * 25) if block_given?
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ def timeit
2
+ log(Benchmark.measure { yield }.to_s)
3
+ end
@@ -0,0 +1,19 @@
1
+ def read_csv(filename)
2
+ CSV
3
+ .foreach(seeds_path(filename), headers: true)
4
+ .map(&:to_h)
5
+ .map(&:symbolize_keys)
6
+ .select { |i| i.values.any?(&:present?) }
7
+ end
8
+
9
+ def write_csv_from_hashes(file, hash_set, attrs: nil)
10
+ attrs ||= uniq_hash_keys(hash_set)
11
+
12
+ CSV.open(results_path(file), 'w') do |csv|
13
+ csv << attrs
14
+
15
+ hash_set.each do |c|
16
+ csv << attrs.map { |a| c.send(:dig, a) }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,110 @@
1
+ # paths
2
+
3
+ def seeds_path(name)
4
+ "#{ROOT}/seeds/#{name}"
5
+ end
6
+
7
+ alias seed_path seeds_path
8
+
9
+ def seed_exists?(name)
10
+ File.exist?(seed_path(name))
11
+ end
12
+
13
+ alias seeds_exist? seed_exists?
14
+
15
+ def results_path(name)
16
+ "#{ROOT}/results/#{RUN}/#{name}"
17
+ end
18
+
19
+ alias result_path results_path
20
+
21
+ def result_exists?(name)
22
+ File.exist?(result_path(name))
23
+ end
24
+
25
+ alias results_exist? result_exists?
26
+
27
+ def tmp_path(name)
28
+ "#{ROOT}/tmp/#{name}"
29
+ end
30
+
31
+ def tmp_exists?(name)
32
+ File.exist?(tmp_path(name))
33
+ end
34
+
35
+ def list_dir(dir)
36
+ Dir["#{seeds_path(dir)}/**/*"]
37
+ end
38
+
39
+ # reading
40
+
41
+ def read(file)
42
+ return unless seed_exists?(file)
43
+ File.read(seeds_path(file))
44
+ end
45
+
46
+ alias read_seed read
47
+ alias read_seeds read
48
+
49
+ def read_tmp(file)
50
+ return unless tmp_exists?(file)
51
+ File.read(tmp_path(file))
52
+ end
53
+
54
+ def readlines(file)
55
+ File.read(seeds_path(file)).split("\n")
56
+ end
57
+
58
+ # writing
59
+
60
+ def write(file, content)
61
+ FileUtils.mkdir_p(File.dirname(results_path(file)))
62
+ File.open(results_path(file), 'w') { |f| f << content }
63
+ end
64
+
65
+ alias write_result write
66
+ alias write_results write
67
+
68
+ def write_tmp(file, content)
69
+ FileUtils.mkdir_p(File.dirname(tmp_path(file)))
70
+ File.open(tmp_path(file), 'w') { |f| f << content }
71
+ end
72
+
73
+ def append(file, content)
74
+ File.open(results_path(file), 'a') { |f| f << content }
75
+ end
76
+
77
+ alias append_result append
78
+ alias append_results append
79
+
80
+ # deleting
81
+
82
+ def delete(file)
83
+ return unless result_exists?(file)
84
+ FileUtils.rm_r(results_path(file))
85
+ end
86
+
87
+ alias delete_result delete
88
+ alias delete_results delete
89
+
90
+ def delete_tmp(file)
91
+ return unless tmp_exists?(file)
92
+ FileUtils.rm_r(tmp_path(file))
93
+ end
94
+
95
+ def delete_seeds(file)
96
+ return unless seed_exists?(file)
97
+ FileUtils.rm_r(seeds_path(file))
98
+ end
99
+
100
+ alias delete_seed delete_seeds
101
+
102
+ # other
103
+
104
+ def make_seed(file)
105
+ FileUtils.cp(results_path(file), seeds_path(file))
106
+ end
107
+
108
+ def make_tmp(file)
109
+ FileUtils.cp(results_path(file), tmp_path(file))
110
+ end
@@ -0,0 +1,8 @@
1
+ def gd_session
2
+ @gd_session ||= begin
3
+ write('config.json', secrets.google.drive_config_json)
4
+ session = GoogleDrive::Session.from_config(results_path("config.json"))
5
+ delete('config.json')
6
+ session
7
+ end
8
+ end
@@ -0,0 +1,90 @@
1
+ def uniq_hash_keys(hashes)
2
+ hashes.flat_map(&:keys).uniq.compact
3
+ end
4
+
5
+ def sanitize_hash_value(hash, key:, type:, date_format: '%Y-%m-%d')
6
+ hash.merge(
7
+ key => or_nil do
8
+ case type
9
+ when :date
10
+ Date.strptime(hash.dig(key), date_format)
11
+ when :datetime
12
+ DateTime.parse(hash.dig(key))
13
+ when :integer, :int
14
+ hash.dig(key).to_i
15
+ when :float
16
+ hash.dig(key).to_f
17
+ when :string
18
+ hash.dig(key).to_s
19
+ when :alphanum
20
+ string_to_alphanum(hash.dig(key))
21
+ when :present?
22
+ hash.dig(key).present?
23
+ end
24
+ end
25
+ )
26
+ end
27
+
28
+ def sanitize_hash_values(hash, scheme = {})
29
+ scheme.each do |k, v|
30
+ hash = sanitize_hash_value(hash, key: k, type: v)
31
+ end
32
+
33
+ hash
34
+ end
35
+
36
+ def rename_hash_key(hash, from:, to:)
37
+ hash[to] = hash.delete(from)
38
+ hash
39
+ end
40
+
41
+ def rename_hash_keys(hash, scheme = {})
42
+ scheme.each do |k, v|
43
+ hash = rename_hash_key(hash, from: k, to: v)
44
+ end
45
+
46
+ hash
47
+ end
48
+
49
+ def merge_hash_groups(*groups, key:, join_type: :inner)
50
+ groups = groups.map { |group| group.map { |g| [g.dig(key), g] }.to_h }
51
+
52
+ keys = begin
53
+ case join_type
54
+ when :inner
55
+ groups.map(&:keys).reduce(&:&)
56
+ when :all
57
+ groups.flat_map(&:keys).uniq
58
+ when :first
59
+ groups.first.keys
60
+ end
61
+ end
62
+
63
+ keys.map { |key| groups.map { |g| g.dig(key) }.compact.reduce(&:merge) }
64
+ end
65
+
66
+ def count_for_group_by(batch, &block)
67
+ batch
68
+ .group_by(&block)
69
+ .map { |k, v| [k, v.length] }
70
+ .to_h
71
+ end
72
+
73
+ def array_to_count_hash(list)
74
+ list.uniq.reduce({}) do |h, i|
75
+ h[i] = list.count(i)
76
+ h
77
+ end
78
+ end
79
+
80
+ def update_counts_hash(counts, update)
81
+ update.each do |k, v|
82
+ if counts.key?(k)
83
+ counts[k] += v
84
+ else
85
+ counts[k] = v
86
+ end
87
+ end
88
+
89
+ counts
90
+ end
@@ -0,0 +1,22 @@
1
+ def read_json(filename)
2
+ result = JSON.parse(read(filename))
3
+
4
+ aggressive_deep_symbolize_keys(result)
5
+ end
6
+
7
+ def write_hashes_to_json(file, hashes)
8
+ write(file, hashes.to_json)
9
+ end
10
+
11
+ def json_cache(key)
12
+ name = "json/#{key}.json"
13
+
14
+ return aggressive_deep_symbolize_keys(JSON.parse(read_tmp(name))) if tmp_exists?(name)
15
+
16
+ write_tmp(name, yield.to_json)
17
+ json_cache(key)
18
+ end
19
+
20
+ def invalidate_json_cache
21
+ delete_tmp("json")
22
+ end
@@ -0,0 +1,42 @@
1
+ def render_table_from_hashes(hash_set, sort: true, headers: nil)
2
+ return 'no data' if hash_set.blank?
3
+
4
+ headers = headers || uniq_hash_keys(hash_set)
5
+
6
+ headers.sort! if sort
7
+
8
+ content = hash_set
9
+ .map { |h| h.select { |k, v| v.present? }.to_h }
10
+ .map { |hash| headers.map { |h| hash.dig(h) } }
11
+ .map { |r| r.map(&:to_s) }
12
+
13
+ TTY::Table.new(header: headers, rows: content).render(:unicode).to_s
14
+ end
15
+
16
+ def log(item, nl: true, quiet: false, each: true)
17
+ item ||= ''
18
+
19
+ if each && item.is_a?(Array)
20
+ item.each { |i| log(i, nl: nl, quiet: quiet, each: false) }
21
+ return
22
+ end
23
+
24
+ File.open(results_path('log.txt'), 'a') do |f|
25
+ f << begin
26
+ if item.is_a?(String) || item.is_a?(Numeric)
27
+ item.to_s
28
+ else
29
+ PP.pp(item, '').chomp
30
+ end
31
+ end
32
+
33
+ f << "\n" if nl
34
+ end
35
+
36
+ print item unless quiet
37
+ puts '' if nl
38
+ end
39
+
40
+ def l(item, nl: true, quiet: false)
41
+ log(item, nl: nl, quiet: quiet, each: false)
42
+ end
@@ -0,0 +1,4 @@
1
+ def pdf_to_text(path)
2
+ `pdftotext "#{seeds_path(path)}" #{tmp_path('tmp_pdf.txt')}; \
3
+ cat #{tmp_path('tmp_pdf.txt')}`
4
+ end
@@ -0,0 +1,26 @@
1
+ def get_single_rollbar_items_page(token:, page:, status: 'active')
2
+ url = URI("https://api.rollbar.com/api/1/instances/?access_token=#{token}&page=#{page}&status=#{status}")
3
+ http = Net::HTTP.new(url.host, url.port)
4
+ http.use_ssl = true
5
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
6
+ request = Net::HTTP::Get.new(url)
7
+ JSON.parse(http.request(request).body).deep_symbolize_keys.dig(:result, :instances)
8
+ end
9
+
10
+ def get_rollbar_items(token:, status: 'active')
11
+ current_page = 0
12
+ items = []
13
+
14
+ loop do
15
+ single_page_of_items = get_single_rollbar_items_page(token: token, page: current_page, status: status)
16
+
17
+ items += single_page_of_items
18
+
19
+ break if single_page_of_items.empty?
20
+ break if yield(current_page, items)
21
+
22
+ current_page += 1
23
+ end
24
+
25
+ items.compact.uniq
26
+ end
@@ -0,0 +1,70 @@
1
+ def hashes_to_sql_temp_table(hashes)
2
+ attrs = uniq_hash_keys(hashes)
3
+
4
+ attr_chars = attrs
5
+ .map { |a| "#{a} varchar" }
6
+ .join(', ')
7
+
8
+ value_tuples = hashes
9
+ .map { |s| '(' + attrs.map { |a| "'#{s.dig(a) }'" }.join(', ') + ')' }
10
+ .join(",\n")
11
+
12
+ <<~SQL
13
+ create temp table seed_data (
14
+ #{attr_chars}
15
+ );
16
+
17
+ insert into seed_data values
18
+ #{value_tuples};
19
+ SQL
20
+ end
21
+
22
+ def create_db(name)
23
+ db_loc = results_path("#{name}.db")
24
+
25
+ raise 'db already exists' if File.exist?(db_loc)
26
+
27
+ db = SQLite3::Database.new(db_loc)
28
+ db.results_as_hash = true
29
+ db
30
+ end
31
+
32
+ def use_db(name)
33
+ db_loc = seeds_path("#{name}.db")
34
+
35
+ raise 'no db exists' unless File.exist?(db_loc)
36
+
37
+ db = SQLite3::Database.new(db_loc)
38
+ db.results_as_hash = true
39
+ db
40
+ end
41
+
42
+ def create_table(db, table, **attrs)
43
+ should_log = attrs.delete(:log)
44
+ attrs = attrs.map { |k, v| " #{k} #{v}" }.join(",\n")
45
+ sql = <<~SQL
46
+ create table #{table} (
47
+ #{attrs}
48
+ );
49
+ SQL
50
+
51
+ log sql if should_log
52
+ db.execute sql
53
+ end
54
+
55
+ def insert_into_db(db, table, **attrs)
56
+ should_log = attrs.delete(:log)
57
+ keys_group = "(#{attrs.keys.join(', ')})"
58
+ values_group = "(#{(['?'] * attrs.values.length).join(', ')})"
59
+ sql = <<~SQL
60
+ insert into #{table} #{keys_group}
61
+ values #{values_group}
62
+ SQL
63
+
64
+ log sql if should_log
65
+ db.execute sql, attrs.values
66
+ end
67
+
68
+ def query_db(db, query)
69
+ db.execute(query)
70
+ end
@@ -0,0 +1,11 @@
1
+ def normalize_string(string)
2
+ string.chomp.strip.squish
3
+ end
4
+
5
+ def string_to_alphanum(string)
6
+ string.gsub(/[^A-Za-z0-9]/, '')
7
+ end
8
+
9
+ def string_encode_utf_8(string)
10
+ string.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
11
+ end
@@ -0,0 +1,21 @@
1
+ def secrets
2
+ SECRETS
3
+ end
4
+
5
+ def or_nil
6
+ val = yield
7
+ raise if val.blank? || val == 0
8
+ val
9
+ rescue StandardError
10
+ end
11
+
12
+ def float?(string)
13
+ true if Float(string) rescue false
14
+ end
15
+
16
+ def aggressive_deep_symbolize_keys(maybe)
17
+ return maybe.deep_symbolize_keys if maybe.respond_to?(:deep_symbolize_keys)
18
+ return maybe.map { |i| aggressive_deep_symbolize_keys(i) } if maybe.respond_to?(:each)
19
+
20
+ maybe
21
+ end
@@ -0,0 +1,11 @@
1
+ def hash_from_xml(str)
2
+ Hash.from_xml(clean_xml(str)).deep_symbolize_keys
3
+ end
4
+
5
+ def prettify_xml(str)
6
+ Nokogiri::XML(str) { |c| c.default_xml.noblanks }.to_xml(indent: 2)
7
+ end
8
+
9
+ def clean_xml(str)
10
+ Nokogiri::XML(str.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')).to_xml
11
+ end
metadata ADDED
@@ -0,0 +1,327 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trials
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - grahamotte
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk-dynamodb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: benchmark
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: csv
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fileutils
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fuzzy_match
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: google_drive
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: json
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: minitest
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: namae
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: nokogiri
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: ostruct
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: pry
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rake
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rest-client
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: smalltext
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: sqlite3
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: street_address
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ type: :runtime
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
265
+ - !ruby/object:Gem::Dependency
266
+ name: tty-table
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ type: :runtime
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - ">="
277
+ - !ruby/object:Gem::Version
278
+ version: '0'
279
+ description:
280
+ email:
281
+ executables:
282
+ - trial
283
+ extensions: []
284
+ extra_rdoc_files: []
285
+ files:
286
+ - bin/trial
287
+ - lib/trials.rb
288
+ - lib/trials/data_handling/addresses.rb
289
+ - lib/trials/data_handling/names.rb
290
+ - lib/trials/utils/aws.rb
291
+ - lib/trials/utils/benchmarking.rb
292
+ - lib/trials/utils/csvs.rb
293
+ - lib/trials/utils/files.rb
294
+ - lib/trials/utils/google_drive.rb
295
+ - lib/trials/utils/hashes.rb
296
+ - lib/trials/utils/jsons.rb
297
+ - lib/trials/utils/logging.rb
298
+ - lib/trials/utils/pdfs.rb
299
+ - lib/trials/utils/rollbar.rb
300
+ - lib/trials/utils/sqls.rb
301
+ - lib/trials/utils/strings.rb
302
+ - lib/trials/utils/various.rb
303
+ - lib/trials/utils/xmls.rb
304
+ homepage:
305
+ licenses:
306
+ - MIT
307
+ metadata: {}
308
+ post_install_message:
309
+ rdoc_options: []
310
+ require_paths:
311
+ - lib
312
+ required_ruby_version: !ruby/object:Gem::Requirement
313
+ requirements:
314
+ - - ">="
315
+ - !ruby/object:Gem::Version
316
+ version: '0'
317
+ required_rubygems_version: !ruby/object:Gem::Requirement
318
+ requirements:
319
+ - - ">="
320
+ - !ruby/object:Gem::Version
321
+ version: '0'
322
+ requirements: []
323
+ rubygems_version: 3.0.3
324
+ signing_key:
325
+ specification_version: 4
326
+ summary: gem for testing out ideas quickly
327
+ test_files: []