parliamentarian 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9cd38f5cb99774b5aacfa8074a76cace5f9e68e1fca7939242fdccdea7dac42e
4
+ data.tar.gz: 1c8ebbec3a095b89f0250ba39620ef1fc2c7f0878aecb235dd867853983bf35d
5
+ SHA512:
6
+ metadata.gz: f5e3702bec1c772317f3fd86a1893b964ba3ea5dbf00ff24ff61d240719b2c8ced76f4dbc1b8e35f5821f4a3612f42dc990c4613366fff915a2f73ad57bea971
7
+ data.tar.gz: b1bb5f7dc7ccca8ab0a898057df147573e4d4540acec4ec6821713f5565997733673cc783a0fe225b8d166e983784fbeee10d43cfb770d8ff333d001ecb3b716
@@ -0,0 +1,13 @@
1
+ # Array#blank?
2
+ # Array#blankQ
3
+
4
+ # 20100308
5
+ # 0.0.0
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ class Array
10
+
11
+ alias_method :blank?, :empty?
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ # Array#extract_options!
2
+
3
+ # 20090123
4
+ # 0.0.0
5
+
6
+ # History: Stolen wholesale from ActiveSupport.
7
+
8
+ class Array
9
+
10
+ def extract_options!
11
+ last.is_a?(::Hash) ? pop : {}
12
+ end
13
+
14
+ end
@@ -0,0 +1,14 @@
1
+ # Array#peek_options
2
+
3
+ # 20100308
4
+ # 0.1.0
5
+
6
+ # History: Originally called #extract_options (no exclamation mark), but written again a few days ago for Switches as #peek_options. #extract_options has been moved to #extract_options! as an alias for it.
7
+
8
+ class Array
9
+
10
+ def peek_options
11
+ last.is_a?(::Hash) ? last : {}
12
+ end
13
+
14
+ end
@@ -0,0 +1,41 @@
1
+ # Array#to_csv
2
+
3
+ # 20111211
4
+ # 0.9.9
5
+
6
+ # Todo:
7
+ # 1. Split all these up and move each method into Array... Done as of 0.9.0.
8
+ # 2. ~ Array#to_csv, massive refactor, including getting rid of a lot of aliases for now at least. Done as of 0.9.0.
9
+
10
+ # Changes since 0.8:
11
+ # 1. Has it's own file now.
12
+ # 0/1
13
+ # 2. Removed all the require lines for the array methods since these are simple operations. So, I am now doing the quoting directly, since quote_each() which calls wrap_each() which in turn calls wrap() is lots of extra method calls.
14
+ # 2/3
15
+ # 3. + require '_meta/default_to' && making use of it in the case test, since if I explicitly supply nil, then the quote is not set to double in the argument definition.
16
+ # 3/9
17
+ # 4. Version number bump to 0.9.9.
18
+ # 5. /+ e +/+ e.to_s +/.
19
+
20
+ require '_meta/default_to'
21
+
22
+ class Array
23
+
24
+ def to_csv(quote = :double)
25
+ case quote.default_to(:double).to_sym
26
+ when :double
27
+ self.collect{|e| '"' + e.to_s + '"'}.join(',')
28
+ when :spacey_double
29
+ self.collect{|e| '"' + e.to_s + '"'}.join(', ')
30
+ when :single
31
+ self.collect{|e| "'" + e.to_s + "'"}.join(',')
32
+ when :spacey_single
33
+ self.collect{|e| "'" + e.to_s + "'"}.join(', ')
34
+ when :none, :unquoted
35
+ self.join(',')
36
+ when :spacey_none, :spacey_unquoted
37
+ self.join(', ')
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,15 @@
1
+ # FalseClass#blank?
2
+ # FalseClass#blankQ
3
+
4
+ # 20100308
5
+ # 0.0.0
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ class FalseClass
10
+
11
+ def blank?
12
+ true
13
+ end
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+ # Hash#blank?
2
+ # Hash#blankQ
3
+
4
+ # 20100308
5
+ # 0.0.0
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ class Hash
10
+
11
+ alias_method :blank?, :empty?
12
+
13
+ end
@@ -0,0 +1,34 @@
1
+ # Hash#to_csv
2
+
3
+ # 2010.05.21
4
+ # 0.9.1
5
+
6
+ # Changes:
7
+ # 1. - Hash#write.
8
+ # 2. ~ Hash#to_csv, a significant reduction in complexity.
9
+ # 0/1
10
+ # 3. /desired_columns/selected_columns/.
11
+
12
+ # Todo:
13
+ # 1. Split all these up and move each method into Array... Done as of 0.9.0.
14
+ # 2. Tidy the splat stuff with that technique from recently!?... Done/made redundant as of 0.9.0.
15
+
16
+ require 'Array/extract_optionsX'
17
+ require 'Array/to_csv'
18
+
19
+ class Hash
20
+
21
+ def to_csv(*args)
22
+ options = args.extract_options!
23
+ quote = options[:quote]
24
+ selected_columns = options[:selected_columns]
25
+ collector = []
26
+ if selected_columns
27
+ selected_columns.each{|column| collector << self[column]}
28
+ else
29
+ self.each{|k,v| collector << self[v]}
30
+ end
31
+ collector.to_csv(quote)
32
+ end
33
+
34
+ end
@@ -0,0 +1,15 @@
1
+ # NilClass#blank?
2
+ # NilClass#blankQ
3
+
4
+ # 20100308
5
+ # 0.0.0
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ class NilClass
10
+
11
+ def blank?
12
+ true
13
+ end
14
+
15
+ end
@@ -0,0 +1,25 @@
1
+ # NilClass/default_to.rb
2
+ # NilClass#default_to
3
+
4
+ # 20140524
5
+ # 0.2.0
6
+
7
+ # Description: Used in concert with Object#default_to, NilClass#default_to will assign a default value to a variable if that variable is nil, or if it isn't nil Object#default_to will return the value of the variable already set.
8
+
9
+ # History: Taken from Switches 0.9.9.
10
+
11
+ # Changes:
12
+ # 1. - alias_method :default, since the complement, Object#default_to, was clashing with the ruby mail gem.
13
+ # 2. + require 'Object/default_to', since these two are supposed to work together.
14
+
15
+ require 'Object/default_to'
16
+
17
+ class NilClass
18
+
19
+ def default_to(o)
20
+ o
21
+ end
22
+ alias_method :defaults_to, :default_to
23
+ alias_method :default_is, :default_to
24
+
25
+ end
@@ -0,0 +1,15 @@
1
+ # Numeric#blank?
2
+ # Numeric#blankQ
3
+
4
+ # 20100308
5
+ # 0.0.0
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ class Numeric
10
+
11
+ def blank?
12
+ false
13
+ end
14
+
15
+ end
@@ -0,0 +1,18 @@
1
+ # Object#blankQ
2
+ # Object#blank?
3
+
4
+ # 2010.04.04
5
+ # 0.0.1
6
+
7
+ # History: Stolen wholesale from a recent version of ActiveSupport.
8
+
9
+ # Changes:
10
+ # 1. Now using a more recent version from ActiveSupport. This more recent version from ActiveSupport is likely more efficient and slightly more succinct.
11
+
12
+ class Object
13
+
14
+ def blank?
15
+ respond_to?(:empty?) ? empty? : !self
16
+ end
17
+
18
+ end
@@ -0,0 +1,25 @@
1
+ # Object/default_to.rb
2
+ # Object#default_to
3
+
4
+ # 20140524
5
+ # 0.2.0
6
+
7
+ # Description: Enables a slightly more powerful assignment mechanism than does ||=, such that it will assign a default value to a variable if the parameterized source is nil, whereas ||= will only assign to the paramterized source if the variable is not already set.
8
+
9
+ # History: Taken from Switches 0.9.9.
10
+
11
+ # Changes:
12
+ # 1. - alias_method :default, since it was clashing with the ruby mail gem.
13
+ # 2. + require 'NilClass/default_to', since these two are supposed to work together.
14
+
15
+ require 'NilClass/default_to'
16
+
17
+ class Object
18
+
19
+ def default_to(o)
20
+ self
21
+ end
22
+ alias_method :defaults_to, :default_to
23
+ alias_method :default_is, :default_to
24
+
25
+ end
@@ -0,0 +1,31 @@
1
+ # Parliamentarian.rb
2
+ # Parliamentarian
3
+
4
+ # 20210408
5
+ # 0.8.5
6
+
7
+ # Changes since 0.7:
8
+ # 0: Paramterised the location of the CSV files so that it can be a local file or the original URL by default with a view to making use of those files as fixtures for tests.
9
+ # 1. ~ Australia::Federal.fetch, .senators, .members, so that one is able to supply a csv file location.
10
+ # 2. ~ Australia::Victoria.fetch, .legislative_councillors, .legislative_assemblymen, so that one is able to supply a csv file location.
11
+ # 3. Removed the self-run sections from Australia::Federal and Australia::Victoria with proper tests in their stead.
12
+ # 4. + ./test
13
+ # 0/1
14
+ # 5. /require 'SimpleCSV.rbd'/SimpleCSV/require 'SimpleCSV'/
15
+ # 1/2
16
+ # 6. Swapped Victorian councillors and assemblymen URLs as they were the reverse of what they should be.
17
+ # 7. /legislative_assemblymen/legislative_assemblymembers/, so as to be consistent with the CSV filename being downloaded.
18
+ # 2/3
19
+ # 8. Underscored all the dynamically created methods for each of the column names in the CSV files.
20
+ # 3/4
21
+ # 9. Missed some aliases when underscoring in the previous version.
22
+ # 4/5
23
+ # 10. + VERSION file
24
+ # 11. + parliamentarian.gemspec
25
+ # 12. ~ Gemfile to include webmock.
26
+ # 13. + required lib files (to be broken out later.)
27
+
28
+ lib_dir = File.dirname(File.expand_path(__FILE__))
29
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
30
+
31
+ require_relative 'Parliamentarian/Australia'
@@ -0,0 +1,4 @@
1
+ # Parliamentarian/Australia.rb
2
+
3
+ require_relative 'Australia/Federal'
4
+ require_relative 'Australia/Victoria'
@@ -0,0 +1,95 @@
1
+ # Parliamentarian/Australia/Federal.rb
2
+ # Parliamentarian::Australia::Federal
3
+
4
+ require 'open-uri'
5
+ require 'SimpleCSV'
6
+ require 'String/underscore'
7
+
8
+ module Parliamentarian
9
+ module Australia
10
+ class Federal
11
+
12
+ SENATE_URL = 'https://www.aph.gov.au/~/media/03%20Senators%20and%20Members/Address%20Labels%20and%20CSV%20files/Senators/allsenel.csv?la=en'
13
+ HOUSE_OF_REPRESENTATIVES_URL = 'https://www.aph.gov.au/~/media/03%20Senators%20and%20Members/Address%20Labels%20and%20CSV%20files/SurnameRepsCSV.csv?la=en'
14
+
15
+ class << self
16
+
17
+ def fetch(csv_file_location)
18
+ raw_csv = if ['http', 'https'].include?(URI.parse(csv_file_location).scheme)
19
+ URI.open(csv_file_location)
20
+ else
21
+ File.read(csv_file_location)
22
+ end
23
+ SimpleCSV.read(raw_csv, headers: true)
24
+ end
25
+
26
+ def all(senators_csv_file_location = nil, members_csv_file_location = nil)
27
+ @all ||= (senators(senators_csv_file_location) + house_of_representatives(members_csv_file_location)).flatten
28
+ end
29
+
30
+ def senators(csv_file_location = nil)
31
+ @senators ||= (
32
+ csv_file_location = csv_file_location || SENATE_URL
33
+ fetch(csv_file_location).collect{|row| self.new(row)}
34
+ )
35
+ end
36
+ alias_method :senate, :senators
37
+
38
+ def members(csv_file_location = nil)
39
+ @members ||= (
40
+ csv_file_location = csv_file_location || HOUSE_OF_REPRESENTATIVES_URL
41
+ fetch(csv_file_location).collect{|row| self.new(row)}
42
+ )
43
+ end
44
+ alias_method :house_of_representatives, :members
45
+
46
+ end # class << self
47
+
48
+ def initialize(row)
49
+ row.keys.each do |header|
50
+ attr_name = self.attr_name(header)
51
+ self.class.send(:attr_accessor, attr_name)
52
+ self.send("#{attr_name}=", row[header])
53
+ end
54
+ synthesize_email_address
55
+ end
56
+
57
+ # For consistency with Australia::Victoria and vice-versa...
58
+ def firstname; first_name; end
59
+ def lastname; surname; end
60
+ def last_name; surname; end
61
+
62
+ def postcode
63
+ @electorate_postcode
64
+ end
65
+
66
+ # predicate methods
67
+
68
+ def senator?
69
+ salutation == 'Senator'
70
+ end
71
+
72
+ def member?
73
+ !senator?
74
+ end
75
+
76
+ private
77
+
78
+ def attr_name(header)
79
+ header.underscore
80
+ end
81
+
82
+ def synthesize_email_address
83
+ self.class.send(:attr_accessor, 'email')
84
+ self.email = (
85
+ if senator?
86
+ "senator.#{surname.downcase}@aph.gov.au"
87
+ else
88
+ "#{first_name}.#{surname}.MP@aph.gov.au"
89
+ end
90
+ )
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,74 @@
1
+ # Parliamentarian/Australia/Victoria.rb
2
+ # Parliamentarian::Australia::Victoria
3
+
4
+ require 'open-uri'
5
+ require 'SimpleCSV'
6
+ require 'String/underscore'
7
+
8
+ module Parliamentarian
9
+ module Australia
10
+ class Victoria
11
+
12
+ LEGISLATIVE_COUNCIL_URL = 'https://www.parliament.vic.gov.au/images/members/councilmembers.csv'
13
+ LEGISLATIVE_ASSEMBLY_URL = 'https://www.parliament.vic.gov.au/images/members/assemblymembers.csv'
14
+
15
+ class << self
16
+
17
+ def fetch(csv_file_location)
18
+ raw_csv = if ['http', 'https'].include?(URI.parse(csv_file_location).scheme)
19
+ URI.open(csv_file_location)
20
+ else
21
+ File.read(csv_file_location)
22
+ end
23
+ SimpleCSV.read(raw_csv, headers: true)
24
+ end
25
+
26
+ def all(legislative_councillors_csv_file_location = nil, legislative_assemblymembers_csv_file_location = nil)
27
+ @all ||= (legislative_councillors(legislative_councillors_csv_file_location) + legislative_assemblymembers(legislative_assemblymembers_csv_file_location)).flatten
28
+ end
29
+
30
+ def legislative_councillors(csv_file_location = nil)
31
+ @legislative_council ||= (
32
+ csv_file_location = csv_file_location || LEGISLATIVE_COUNCIL_URL
33
+ fetch(csv_file_location).collect{|row| self.new(row)}
34
+ )
35
+ end
36
+
37
+ def legislative_assemblymembers(csv_file_location = nil)
38
+ @legislative_assembly ||= (
39
+ csv_file_location = csv_file_location || LEGISLATIVE_ASSEMBLY_URL
40
+ fetch(csv_file_location).collect{|row| self.new(row)}
41
+ )
42
+ end
43
+
44
+ end # class << self
45
+
46
+ def initialize(row)
47
+ row.keys.each do |header|
48
+ attr_name = self.attr_name(header)
49
+ self.class.send(:attr_accessor, attr_name)
50
+ self.send("#{attr_name}=", row[header])
51
+ end
52
+ extract_postcode_from_electorate_office_address
53
+ end
54
+
55
+ # For consistency with Australia::Federal and vice-versa...
56
+ def firstname; preferred_name; end
57
+ def first_name; preferred_name; end
58
+ def surname; last_name; end
59
+ def lastname; last_name; end
60
+
61
+ private
62
+
63
+ def attr_name(header)
64
+ header.underscore
65
+ end
66
+
67
+ def extract_postcode_from_electorate_office_address
68
+ self.class.send(:attr_accessor, 'postcode')
69
+ self.postcode = eo_address.split.last
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,5 @@
1
+ class Parliamentarian
2
+
3
+ VERSION = '0.8.5'
4
+
5
+ end
data/lib/SimpleCSV.rb ADDED
@@ -0,0 +1,389 @@
1
+ # SimpleCSV.rb
2
+ # SimpleCSV
3
+
4
+ # 20200606
5
+ # 0.10.3
6
+
7
+ # Description: A CSV object for reading and writing CSV (and similar) text files with tabulated data to and from files and strings.
8
+
9
+ # Todo:
10
+ # 1. Have it be able to read mixed CSV files. Done as of 0.9.0.
11
+ # 2. Have it be able to read escaped and quoted delimeters.
12
+ # 3. Separate out the different classes into separate files. Done as of 0.8 I think, but taken further with 0.9.
13
+ # 4. Create a gem and/or Rubylibify and/or
14
+ # 5. Optionally do line counts.
15
+ # 6. Optionally do column count checks.
16
+ # 7. Optionally do data consistency checks for column length, type, and anything else that makes sense.
17
+ # 8. Put the option to specify quoting into to_csv and possibly remove it from #init. Done as of at least 0.8.
18
+ # 9. Remove underscores when outputting the header line, but only if they were added---and only if they're wanting to be removed?... As of 0.9.0, I just use strings anyway.
19
+ # 10. Reorder the conditionals in #write_line and #write_header. Done as of 0.9.0.
20
+ # 11. Simplify some more! Done as of 0.9.1.
21
+
22
+ # Ideas:
23
+ # 1. Standardize on either symbols or strings for column names, since presently one has to be consistent. It would be nicer to be able to mix and match---if possible.
24
+ # 2. Automatically detect as to whether there is a header line by taking the first line and comparing the types (alpha, numeric, alpha-numeric, etcetera) with each of the column values with those of the subsequent 2 or 3 or so lines and if there is a correspondence, then assume that there is a header line. This would mean that the assumption that there is would change and that if the guess was wrong that it would need to be made explict.
25
+ # 3. Have it #read a file automatically if any of 'r' or 'r+' or 'w+' is given as the mode.
26
+ # 4. Finally try to make use of Index instead of Hash, since that library file is still hanging around. Using this class may be simpler but not faster than using Hash and Array.
27
+
28
+ # Bugs:
29
+ # 1. This did cope with commas within a quoted CSV file, however while I think I broke this again with 0.9.0, I'm not sure that I ever had it working properly. It works properly as of 0.9.3 at least.
30
+ # 2. Does SimpleCSV#write_row handle it if there are no attributes/columns defined? It needs to work with CSV files with no column names.
31
+
32
+ # Changes since 0.9:
33
+ # 1. - SimpleCSV.rbd directory, moving everything up a directory, and SimpleCSV.rb inside the lib directory, so it now adheres to a more conventional Ruby library structure. May re-introduce .rbd, self-contained Ruby libraries one day, but will need to have the require overload work correctly and be able to load .rbd files correctly when presented. This may have changed sometime in the past quite a few years...
34
+ # 2. + ./Kernel/silently.rb which was used in the speed testing file, but had never been incorporated into the lib directory as it should.
35
+ # 0/1
36
+ # 3. - ./test until such time as they are half-decent, which they have never been!
37
+ # 1/2
38
+ # 4. Separated CSVFile and CSVString into their own files.
39
+ # 5. require 'stringio' --> CSVString.rb
40
+ # 2/3
41
+ # 6. /CSVFile/SimpleCSV::File/
42
+ # 7. /CSVString/SimpleCSV::String/
43
+ # 8. Ensured that there are a number of leading class colon separators (::) in strategic places!
44
+
45
+ $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
46
+
47
+ require '_meta/blankQ'
48
+ require 'Array/extract_optionsX'
49
+ require 'Array/peek_options'
50
+ require 'Array/to_csv'
51
+ require 'Hash/to_csv'
52
+ require 'String/split_csv'
53
+
54
+ require 'SimpleCSV/File'
55
+ require 'SimpleCSV/String'
56
+
57
+ class SimpleCSV
58
+
59
+ class << self
60
+
61
+ def source_type(source)
62
+ if ::File.exist?(source)
63
+ SimpleCSV::File
64
+ else
65
+ SimpleCSV::String
66
+ end
67
+ end
68
+
69
+ def open(source, *args, &block)
70
+ @csv_file = new(source, *args)
71
+ if block
72
+ begin
73
+ yield @csv_file
74
+ @csv_file
75
+ ensure
76
+ @csv_file.close
77
+ end
78
+ else
79
+ @csv_file
80
+ end
81
+ end
82
+
83
+ def each(source, *args, &block)
84
+ new(source, *args).each(&block)
85
+ end
86
+ alias_method :foreach, :each
87
+
88
+ def collect(source, *args, &block)
89
+ new_collection = []
90
+ each(source, *args){|row| new_collection << block.call(row)}
91
+ new_collection
92
+ end
93
+ alias_method :map, :collect
94
+
95
+ def select(source, *args, &block)
96
+ new_collection = []
97
+ each(source, *args){|row| new_collection << row if block.call(row)}
98
+ new_collection
99
+ end
100
+ alias_method :find_all, :select
101
+
102
+ def reject(source, *args, &block)
103
+ new_collection = []
104
+ each(source, *args){|row| new_collection << row unless block.call(row)}
105
+ new_collection
106
+ end
107
+
108
+ def detect(source, *args, &block)
109
+ each(source, *args){|row| return row if block.call(row)}
110
+ end
111
+ alias_method :find, :detect
112
+
113
+ def read(source, *args, &block)
114
+ if block
115
+ parse(source, *args, &block)
116
+ else
117
+ new(source, *args).read_csv
118
+ end
119
+ end
120
+ alias_method :read_csv, :read
121
+
122
+ def parse(source, *args, &block)
123
+ if block
124
+ each(source, *args, &block)
125
+ else
126
+ read(source, *args)
127
+ end
128
+ end
129
+ alias_method :parse_csv, :parse
130
+
131
+ def write(source, *args)
132
+ new(source, *args).write_csv
133
+ end
134
+ alias_method :write_csv, :write
135
+
136
+ def header_row(source, *args)
137
+ new(source, *args).header_row
138
+ end
139
+
140
+ def first_row(source, *args)
141
+ new(source, *args).first_row
142
+ end
143
+
144
+ def attributes(source, *args)
145
+ new(source, *args).attributes
146
+ end
147
+
148
+ def columns(source, *args)
149
+ new(source, *args).columns
150
+ end
151
+
152
+ def parse_line(raw_row, *args) # For FasterCSV compatibility.
153
+ options = args.extract_options!
154
+ row_separator = options[:row_separator] || options[:row_sep] || "\n"
155
+ column_separator = options[:column_separator] || options[:col_sep] || ','
156
+ sc = SimpleCSV.new(raw_row, :quote => nil, :as_array => true, :row_separator => row_separator, :column_separator => column_separator)
157
+ sc.parse_row(raw_row)
158
+ end
159
+
160
+ end # class << self
161
+
162
+ include Enumerable
163
+
164
+ attr_accessor :header_row, :mode, :quote, :row_separator, :selected_columns, :as_array, :rows
165
+
166
+ def initialize(source, *args)
167
+ @source = (
168
+ if source.is_a?(::String)
169
+ SimpleCSV.source_type(source).new(source, *args).source
170
+ else
171
+ source
172
+ end
173
+ )
174
+ options = args.extract_options!
175
+ @header_row = options[:header_row] || options[:headers] || options[:header] || false
176
+ @mode = options[:mode] || 'r'
177
+ @quote = options[:quote] || nil
178
+ @row_separator = options[:row_separator] || options[:row_sep] || "\n"
179
+ @column_separator = options[:column_separator] || options[:col_sep] || ','
180
+ @selected_columns = options[:selected_columns]
181
+ @as_array = options[:as_array] || false
182
+ if options[:columns]
183
+ self.columns = options[:columns]
184
+ else
185
+ self.columns
186
+ end
187
+ @rows = []
188
+ end
189
+
190
+ def close
191
+ @source.close
192
+ end
193
+
194
+ def read(*selected_columns, &block)
195
+ if block
196
+ parse(*selected_columns, &block)
197
+ else
198
+ read_header
199
+ @source.each(@row_separator){|raw_row| @rows << parse_row(raw_row, *selected_columns)}
200
+ (@source.rewind; @source.truncate(0)) if @mode == 'r+'
201
+ @rows
202
+ end
203
+ end
204
+ alias_method :read_csv, :read
205
+
206
+ def read_header
207
+ columns
208
+ if header_row?
209
+ (@source.rewind; @source.gets(@row_separator))
210
+ else
211
+ @source.rewind
212
+ end
213
+ end
214
+ alias_method :read_csv_header, :read_header
215
+
216
+ def parse(*selected_columns, &block)
217
+ if block
218
+ each(*selected_columns, &block)
219
+ else
220
+ read(*selected_columns)
221
+ end
222
+ end
223
+ alias_method :parse_csv, :parse
224
+
225
+ def columns
226
+ @columns ||= (
227
+ if header_row? && ['r', 'r+', 'a+'].include?(@mode) && (first_row = first_row?)
228
+ columns, i = {}, -1
229
+ first_row.split_csv(@quote, @column_separator, @row_separator).each do |column_name|
230
+ if column_name.empty?
231
+ columns[column_name].blank? ? columns[column_name] = [i += 1] : columns[column_name] << (i += 1)
232
+ else
233
+ columns[column_name] = (i += 1)
234
+ end
235
+ end
236
+ columns
237
+ else
238
+ nil
239
+ end
240
+ )
241
+ end
242
+
243
+ def columns=(*column_order)
244
+ @columns = {}
245
+ column_order.flatten!
246
+ if column_order[0].is_a?(Hash)
247
+ column_order[0].each{|column_name, column_position| @columns[column_name.to_s] = column_position}
248
+ else
249
+ i = -1
250
+ column_order.each{|column| @columns[column.to_s] = (i += 1)}
251
+ end
252
+ end
253
+
254
+ def parse_row(raw_row, *selected_columns)
255
+ parsed_row = {}
256
+ i = -1
257
+ if selected_columns.empty?
258
+ if @columns.blank?
259
+ raw_row.split_csv(@quote, @column_separator, @row_separator).each{|column_value| parsed_row[i += 1] = column_value}
260
+ else
261
+ raw_row.split_csv(@quote, @column_separator, @row_separator).each{|column_value| parsed_row[attributes[i += 1]] = column_value}
262
+ end
263
+ else
264
+ selected_columns.flatten!
265
+ case selected_columns[0]
266
+ when Integer
267
+ raw_row.split_csv(@quote, @column_separator, @row_separator).each{|column_value| parsed_row[i] = column_value unless !selected_columns.include?(i += 1)}
268
+ else
269
+ raw_row.split_csv(@quote, @column_separator, @row_separator).each{|column_value| parsed_row[attributes[i]] = column_value unless !selected_columns.include?(attributes[i += 1])}
270
+ end
271
+ end
272
+ if @as_array
273
+ if @columns.blank?
274
+ (0..(parsed_row.size - 1)).inject([]){|a,i| a << parsed_row[i]}
275
+ else
276
+ attributes.collect{|attribute| parsed_row[attribute]}
277
+ end
278
+ else
279
+ parsed_row
280
+ end
281
+ end
282
+
283
+ def write(*selected_columns)
284
+ write_header(*selected_columns) if header_row?
285
+ each{|row| write_row(row, *selected_columns)}
286
+ end
287
+ alias_method :write_csv, :write
288
+
289
+ def write_header(*selected_columns)
290
+ selected_columns.flatten!
291
+ if selected_columns.empty?
292
+ write_row(attributes.to_csv)
293
+ else
294
+ write_row(columns.to_csv)
295
+ end
296
+ end
297
+ alias_method :write_csv_header, :write_header
298
+
299
+ def write_row(row, *selected_columns)
300
+ collector = []
301
+ selected_columns.flatten!
302
+ unless attributes.blank?
303
+ if selected_columns.blank?
304
+ attributes.each{|attribute| collector << row[attribute] unless row[attribute].nil?}
305
+ else
306
+ selected_columns.each{|column| collector << row[column] unless row[column].nil?}
307
+ end
308
+ @source.puts(collector.to_csv(@quote))
309
+ end
310
+ end
311
+ alias_method :write_csv_row, :write_row
312
+
313
+ def each(*selected_columns)
314
+ selected_columns.flatten!
315
+ if @rows[0]
316
+ if selected_columns.empty?
317
+ @rows.each{|row| yield row}
318
+ else
319
+ @rows.each do |row|
320
+ yield selected_columns.inject({}){|hash, column_name| hash[column_name] = row[column_name]; hash}
321
+ end
322
+ end
323
+ else
324
+ if selected_columns.empty?
325
+ read_csv.each{|row| yield row}
326
+ else
327
+ read_csv(selected_columns).each do |row|
328
+ yield selected_columns.inject({}){|hash, column_name| hash[column_name] = row[column_name]; hash}
329
+ end
330
+ end
331
+ end
332
+ end
333
+ alias_method :each_row, :each
334
+
335
+ def attributes
336
+ @attributes ||= (
337
+ if columns.blank?
338
+ nil
339
+ else
340
+ a = []
341
+ columns.each do |k,v|
342
+ case v
343
+ when Array
344
+ v.each{|e| a << ['', e]}
345
+ else
346
+ a << [k, v]
347
+ end
348
+ end
349
+ a.sort{|a,b| a[1] <=> b[1]}.collect{|a| a[0]}
350
+ end
351
+ )
352
+ end
353
+
354
+ def attributes=(attributes)
355
+ @attributes = attributes
356
+ end
357
+
358
+ def header_row?
359
+ @header_row
360
+ end
361
+
362
+ def first_row
363
+ @source.rewind
364
+ return_value = @source.gets(@row_separator)
365
+ @source.rewind
366
+ return_value
367
+ end
368
+ alias_method :first_row?, :first_row
369
+
370
+ def to_a
371
+ read_csv unless @rows[0]
372
+ if @as_array
373
+ @rows
374
+ elsif @columns.blank?
375
+ result = []
376
+ @rows.each do |row|
377
+ a = []
378
+ (0..(row.size - 1)).inject([]){|a,i| a << row[i]}
379
+ result << a
380
+ end
381
+ result
382
+ else
383
+ @rows.collect do |row|
384
+ attributes.collect{|attribute| row[attribute]}
385
+ end
386
+ end
387
+ end
388
+
389
+ end # class SimpleCSV
@@ -0,0 +1,50 @@
1
+ # SimpleCSV/File.rb
2
+ # SimpleCSV::File
3
+
4
+ require_relative File.join('..', 'SimpleCSV')
5
+
6
+ class SimpleCSV
7
+ class File < SimpleCSV
8
+
9
+ class << self
10
+
11
+ def open(source, *args, &block)
12
+ @csv_file = new(source, *args)
13
+ super(source, *args, &block)
14
+ end
15
+
16
+ end # class << self
17
+
18
+ def initialize(filename, *args)
19
+ @filename = filename
20
+ @args = args
21
+ super(source, *args)
22
+ end
23
+
24
+ def source
25
+ @source ||= ::File.new(filename, mode, permissions)
26
+ end
27
+
28
+ def mode
29
+ @mode ||= (
30
+ case @args.peek_options[:mode].to_s
31
+ when 'r', 'r+', 'w', 'w+', 'a', 'a+'; @args.peek_options[:mode].to_s
32
+ when 'read_only', 'read-only', 'readonly'; 'r'
33
+ when 'rw', 'read_write', 'read-write', 'readwrite'; 'r+'
34
+ when 'write_only', 'write-only', 'writeonly'; 'w'
35
+ when 'append'; 'a'
36
+ else 'r'
37
+ end
38
+ )
39
+ end
40
+
41
+ def permissions
42
+ @permissions ||= @args.peek_options[:permissions]
43
+ end
44
+
45
+ def filename
46
+ @filename ||= File.expand_path(@filename)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,30 @@
1
+ # SimpleCSV/String.rb
2
+ # SimpleCSV::String
3
+
4
+ require 'stringio'
5
+
6
+ require_relative File.join('..', 'SimpleCSV')
7
+
8
+ class SimpleCSV
9
+ class String < SimpleCSV
10
+
11
+ class << self
12
+
13
+ def open(source, *args, &block)
14
+ @csv_file = new(source, *args)
15
+ super(source, *args, &block)
16
+ end
17
+
18
+ end # class << self
19
+
20
+ def initialize(string, *args)
21
+ @string = string
22
+ super(source, *args)
23
+ end
24
+
25
+ def source
26
+ @source ||= StringIO.new(@string)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ # String#blank?
2
+ # String#blankQ
3
+
4
+ # 2010.04.04
5
+ # 0.0.1
6
+
7
+ # History: Stolen wholesale from a recent version of ActiveSupport.
8
+
9
+ # Changes:
10
+ # 1. Now using a more recent version from ActiveSupport. This more recent version from ActiveSupport is likely more efficient and slightly more succinct.
11
+
12
+ class String
13
+
14
+ def blank?
15
+ self !~ /\S/
16
+ end
17
+
18
+ end
@@ -0,0 +1,66 @@
1
+ # String/split_csv
2
+ # String#split_csv
3
+
4
+ # 20111110
5
+ # 0.7.0
6
+
7
+ # History: Written for SimpleCSV.
8
+
9
+ # Todo:
10
+ # 1. Consider having a mode which splits up strings as if they were unquoted, but retains quotes (which contain commas) as per 0.4.0. I think that is what I had in mind when I thought that the other two libraries weren't handling it correctly. It should really be optional as to how quotes are handled.
11
+
12
+ # Notes:
13
+ # 1. I reckon both CSV and FasterCSV handle doubly-quoted quotes incorrectly. If I am wanting everything between the commas, then that means *everything*, including any quote marks regardless of where they are. If additionally, I am wanting to selectively choose only that which is between, then I can do this too by specifying that the data contained therein is mixed and so I dispense with the outer-most quote marks. CSV and FasterCSV presume to know what I want and dispense with the outer quote marks even though the rest of a line is being parsed as if there are none. This is inconsistent.
14
+
15
+ # Changes since 0.6:
16
+ # 1. + row_separator.
17
+
18
+ class String
19
+
20
+ def split_csv(quote = nil, column_separator = ',', row_separator = nil)
21
+ case quote
22
+ when :none, :unquoted
23
+ if row_separator
24
+ self.chomp(row_separator).split(column_separator)
25
+ else
26
+ self.chomp.split(column_separator)
27
+ end
28
+ when :double, :double_quoted, :double_quotes
29
+ if row_separator
30
+ self.chomp(row_separator).split(column_separator).collect{|e| e.sub(/^"/, '').sub(/"$/, '')}
31
+ else
32
+ self.chomp.split(column_separator).collect{|e| e.sub(/^"/, '').sub(/"$/, '')}
33
+ end
34
+ else
35
+ split_row = []
36
+ assembling_column = false
37
+ buffer = ''
38
+ if row_separator
39
+ self.chomp!(row_separator)
40
+ else
41
+ self.chomp!
42
+ end
43
+ self.split(column_separator).each do |e|
44
+ if assembling_column && !(e =~ /"$/) # e.not_closing_quotes?
45
+ buffer << e
46
+ elsif assembling_column && e =~ /"$/ # e.closing_quotes?
47
+ buffer << e.sub(/"$/, '') # remove the trailing quote
48
+ split_row << buffer
49
+ assembling_column = false
50
+ elsif (e =~ /^"/) && !(e =~ /"$/) # e.opening_quotes_but_not_closing_quotes?
51
+ buffer = ''
52
+ buffer << e.sub(/^"/, '') + column_separator # remove leading quote and replace the column_separator
53
+ assembling_column = true
54
+ else
55
+ if (e =~ /^"/) && (e =~ /"$/) # e.both_opening_and_closing_quotes?
56
+ split_row << e.sub(/^"/, '').sub(/"$/, '')
57
+ else
58
+ split_row << e
59
+ end
60
+ end
61
+ end
62
+ split_row
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,32 @@
1
+ # String#underscore
2
+
3
+ # 2010.10.15
4
+ # 0.1.0
5
+
6
+ # Description: The compliment of camelize. This takes a camel-case word and converts any capitals into lowercase and excepting for a leading capital letter, prepends each with an underscore. It also converts namespaces to paths, ie. '::' to '/'.
7
+
8
+ # History: Almost stolen wholesale from ActiveSupport::Inflector::Inflections#underscore 3.0.0.beta3.
9
+
10
+ # Examples:
11
+ # "ActiveRecord".underscore
12
+ # => "active_record"
13
+ # "ActiveRecord::Errors".underscore
14
+ # => active_record/errors
15
+
16
+ # Changes since 0.0
17
+ # 1. Updated with changes from active_support 3.0.0.
18
+ # 2. Will now successfully handle strings with spaces.
19
+ # 3. Removed the dup'ed word since once the transformational methods were chained this became unnecessary.
20
+
21
+ class String
22
+
23
+ def underscore
24
+ gsub(' ', '_').
25
+ gsub(/::/, '/').
26
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
27
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
28
+ tr("-", "_").
29
+ downcase
30
+ end
31
+
32
+ end
@@ -0,0 +1,15 @@
1
+ # TrueClass#blank?
2
+ # TrueClass#blankQ
3
+
4
+ # 20100308
5
+ # 0.0.0
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ class TrueClass
10
+
11
+ def blank?
12
+ false
13
+ end
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+ # _meta/blankQ
2
+
3
+ # 2010.04.04
4
+ # 0.0.0
5
+
6
+ require 'Array/blankQ'
7
+ require 'FalseClass/blankQ'
8
+ require 'Hash/blankQ'
9
+ require 'NilClass/blankQ'
10
+ require 'Numeric/blankQ'
11
+ require 'Object/blankQ'
12
+ require 'String/blankQ'
13
+ require 'TrueClass/blankQ'
@@ -0,0 +1,7 @@
1
+ # _meta/default_to
2
+
3
+ # 0.0.0
4
+ # 20100316
5
+
6
+ require 'Object/default_to'
7
+ require 'NilClass/default_to'
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parliamentarian
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.5
5
+ platform: ruby
6
+ authors:
7
+ - thoran
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
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: minitest-spec-context
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
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: webmock
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: This will download and parse the lastest list of members and their contact
56
+ details for the alleged parliament of the State of Victoria and the alleged federal
57
+ parliament for Australia so far.
58
+ email: code@thoran.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - lib/Array/blankQ.rb
64
+ - lib/Array/extract_optionsX.rb
65
+ - lib/Array/peek_options.rb
66
+ - lib/Array/to_csv.rb
67
+ - lib/FalseClass/blankQ.rb
68
+ - lib/Hash/blankQ.rb
69
+ - lib/Hash/to_csv.rb
70
+ - lib/NilClass/blankQ.rb
71
+ - lib/NilClass/default_to.rb
72
+ - lib/Numeric/blankQ.rb
73
+ - lib/Object/blankQ.rb
74
+ - lib/Object/default_to.rb
75
+ - lib/Parliamentarian.rb
76
+ - lib/Parliamentarian/Australia.rb
77
+ - lib/Parliamentarian/Australia/Federal.rb
78
+ - lib/Parliamentarian/Australia/Victoria.rb
79
+ - lib/Parliamentarian/VERSION.rb
80
+ - lib/SimpleCSV.rb
81
+ - lib/SimpleCSV/File.rb
82
+ - lib/SimpleCSV/String.rb
83
+ - lib/String/blankQ.rb
84
+ - lib/String/split_csv.rb
85
+ - lib/String/underscore.rb
86
+ - lib/TrueClass/blankQ.rb
87
+ - lib/_meta/blankQ.rb
88
+ - lib/_meta/default_to.rb
89
+ homepage: http://github.com/thoran/Parliamentarian
90
+ licenses:
91
+ - Ruby
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '2.5'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.2.3
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Download and parse details for members of parliament.
112
+ test_files: []