cocos 0.2.0 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed017038dd37ce27a71bb2835900c893dc916643e1f07e3809a18eca3f626265
4
- data.tar.gz: 77f8a74da6add1f4af968364c3eecfbae7cb1dfd88bce89bb04490ad3932df44
3
+ metadata.gz: 38e913cc7ec8d6951edd7bb59ac80626aadf3a3fbd7b13f82ccc123dffc6a7b1
4
+ data.tar.gz: 8883a9656f7aa48b6c778e9786966f507a80dbd13be670ca69ff9ed5b20656a8
5
5
  SHA512:
6
- metadata.gz: c74889afd4f26afd75e8bcd306920f916646787cf3a85e3d94e2e67b0aed81bea4747c7e924d0dde40c2aa22661a61eed59c656ca1f57842ffd4d6f9099ae00b
7
- data.tar.gz: f25f050d937978cf344530b6f347716f79f137b1e467518be2c5d506a39eedbe7f5bf16163047685cf18d4e34d7cf501cc200db6b1c876e0406b35f4d0968edc
6
+ metadata.gz: 1b9e85de98ce029a384d0ce1fa2e09905d3d7eeee956d59ab090c0eb9300b1de121ecc1bfeaaacdebdca7dd66227f7a9fefce1ef397d1d97fa5123cac32609c8
7
+ data.tar.gz: ba6fc944c1dc724c131c0f32390349140c3d658a4db80d876a421704eea1d13ac78ecedc3da6141ba7116367270e836d8aafcb420b12bd664ae604ac557af8a4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,4 @@
1
+ ### 0.3.0
1
2
  ### 0.0.1 / 2022-08-01
2
3
 
3
4
  * Everything is new. First release.
data/Manifest.txt CHANGED
@@ -4,4 +4,5 @@ Manifest.txt
4
4
  README.md
5
5
  Rakefile
6
6
  lib/cocos.rb
7
+ lib/cocos/env.rb
7
8
  lib/cocos/version.rb
data/lib/cocos/env.rb ADDED
@@ -0,0 +1,91 @@
1
+ ###
2
+ # simple read_env, load_env machinery
3
+ ## inspired by
4
+ ## dotenv gem -> https://github.com/bkeepers/dotenv
5
+ ## figaro -> https://github.com/laserlemon/figaro
6
+ ## and others
7
+
8
+
9
+ ## todo/check:
10
+ ## move to its own (standandaloen) envparser gem - why? why not?
11
+
12
+ module EnvParser
13
+ # returns a hash
14
+ # (compatible structure - works like YAML.load_file)
15
+ #
16
+ # change to .read(path) and parse( text) - why? why not?
17
+ def self.load_file( path )
18
+ text = File.open( path, 'r:utf-8' ) { |f| f.read }
19
+ parse( text )
20
+ end
21
+ def self.load( text ) parse( text ); end
22
+
23
+
24
+ class Error < StandardError; end
25
+
26
+ ## todo/check - what is JSON and YAML returning Parser/ParseError something else?
27
+ ## YAML uses ParseError and JSON uses ParserError
28
+ class ParseError < Error; end
29
+
30
+
31
+ ## todo/check - if support for empty values e.g. abc= is required/possible???
32
+ ## todo/ addd support for quoted values - why? why not?
33
+ ## add support for "inline" end of line comments - why? why not?
34
+ ## add support for escapes and multi-line values - why? why not?
35
+ LINE_RX = /\A(?<key>[A-Za-z][A-Za-z0-9_-]*)
36
+ [ ]*
37
+ =
38
+ [ ]*
39
+ (?<value>.+?) ## non-greedy
40
+ \z
41
+ /x
42
+
43
+ ## use a parser class - why? why not?
44
+ def self.parse( text )
45
+ h = {}
46
+
47
+ lineno = 0
48
+ text.each_line do |line|
49
+ lineno += 1 ## track line numbers for (parse) error reporting
50
+
51
+ line = line.strip ## check: use strip (or be more strict) - why? why not?
52
+ ## skip empty and comment lines
53
+ next if line.empty? || line.start_with?( '#' )
54
+
55
+ if m=LINE_RX.match(line)
56
+ key = m[:key]
57
+ value = m[:value]
58
+
59
+ ## todo/check - check/warn about duplicates - why? why not?
60
+ h[key] = value
61
+ else
62
+ raise ParseError, "line #{lineno} - unknown line type; cannot parse >#{line}<"
63
+ end
64
+ end
65
+ h
66
+ end # methdod self.parse
67
+ end # module EnvParser
68
+
69
+
70
+
71
+ __END__
72
+
73
+ # parser regex from dotenv
74
+
75
+ LINE = /
76
+ (?:^|\A) # beginning of line
77
+ \s* # leading whitespace
78
+ (?:export\s+)? # optional export
79
+ ([\w.]+) # key
80
+ (?:\s*=\s*?|:\s+?) # separator
81
+ ( # optional value begin
82
+ \s*'(?:\\'|[^'])*' # single quoted value
83
+ | # or
84
+ \s*"(?:\\"|[^"])*" # double quoted value
85
+ | # or
86
+ [^\#\r\n]+ # unquoted value
87
+ )? # value end
88
+ \s* # trailing whitespace
89
+ (?:\#.*)? # optional comment
90
+ (?:$|\z) # end of line
91
+ /x
data/lib/cocos/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Cocos
3
3
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
4
- MINOR = 2
4
+ MINOR = 3
5
5
  PATCH = 0
6
6
  VERSION = [MAJOR,MINOR,PATCH].join('.')
7
7
 
data/lib/cocos.rb CHANGED
@@ -30,7 +30,7 @@ require 'webclient'
30
30
  #####################
31
31
  # our own code
32
32
  require 'cocos/version' # note: let version always go first
33
-
33
+ require 'cocos/env' ## e.g. EnvParser
34
34
 
35
35
  ###
36
36
  ## read/parse convenience/helper shortcuts
@@ -40,14 +40,35 @@ module Kernel
40
40
 
41
41
 
42
42
 
43
+ ################
44
+ # private helpers - keep along here - why? why not?
45
+
46
+ ##### check if path starts with http:// or https://
47
+ ## if yes, assume it's a download
48
+ DOWNLOAD_RX = %r{^https?://}i
49
+
50
+ ## note: hack - use !! to force nil (no match) to false
51
+ ## and matchdata to true
52
+ def _download?( path )
53
+ !! DOWNLOAD_RX.match( path )
54
+ end
55
+
56
+
57
+
43
58
  ## todo: add symbolize options a la read_json
44
59
  ## add sep options
45
60
  def read_csv( path, headers: true )
46
- if headers
47
- CsvHash.read( path )
61
+
62
+ if _download?( path )
63
+ parse_csv( _wget!( path ).text,
64
+ headers: headers )
48
65
  else
49
- Csv.read( path )
50
- end
66
+ if headers
67
+ CsvHash.read( path )
68
+ else
69
+ Csv.read( path )
70
+ end
71
+ end
51
72
  end
52
73
 
53
74
  def parse_csv( str, headers: true )
@@ -63,7 +84,11 @@ end
63
84
  ## for alternate shortcut for read_csv / parse_csv w/ headers: false
64
85
  ## returning arrays of strings
65
86
  def read_data( path )
66
- Csv.read( path )
87
+ if _download?( path )
88
+ read_data( _wget!( path ).text )
89
+ else
90
+ Csv.read( path )
91
+ end
67
92
  end
68
93
 
69
94
  def parse_data( str )
@@ -73,7 +98,11 @@ end
73
98
 
74
99
 
75
100
  def read_tab( path )
76
- Tab.read( path )
101
+ if _download?( path )
102
+ parse_tab( _wget!( path ).text )
103
+ else
104
+ Tab.read( path )
105
+ end
77
106
  end
78
107
 
79
108
  def parse_tab( str )
@@ -83,16 +112,17 @@ end
83
112
 
84
113
  ## todo: add symbolize options ???
85
114
  def read_json( path )
86
- JSON.parse( read_text( path ))
115
+ JSON.parse( read_text( path ))
87
116
  end
88
117
 
89
118
  def parse_json( str )
90
119
  JSON.parse( str )
91
120
  end
92
121
 
122
+
93
123
  ### todo/check: use parse_safeyaml or such? (is default anyway?) - why? why not?
94
124
  def read_yaml( path )
95
- YAML.load( read_text( path ))
125
+ YAML.load( read_text( path ))
96
126
  end
97
127
 
98
128
  def parse_yaml( str )
@@ -101,7 +131,7 @@ end
101
131
 
102
132
 
103
133
  def read_ini( path )
104
- INI.load( read_text( path ))
134
+ INI.load( read_text( path ))
105
135
  end
106
136
 
107
137
  def parse_ini( str )
@@ -115,22 +145,32 @@ alias_method :parse_conf, :parse_ini
115
145
 
116
146
 
117
147
  def read_text( path )
148
+ if _download?( path )
149
+ _wget!( path ).text
150
+ else
118
151
  ## todo/check: add universal newline mode or such?
119
152
  ## e.g. will always convert all
120
153
  ## newline variants (\n|\r|\n\r) to "universal" \n only
154
+ ##
155
+ ## add r:bom - why? why not?
121
156
  txt = File.open( path, 'r:utf-8' ) do |f|
122
157
  f.read
123
158
  end
124
159
  txt
160
+ end
125
161
  end
126
162
  alias_method :read_txt, :read_text
127
163
 
128
164
 
129
165
  def read_blob( path )
130
- blob = File.open( path, 'rb' ) do |f|
131
- f.read
132
- end
133
- blob
166
+ if _download?( path )
167
+ _wget!( path ).blob
168
+ else
169
+ blob = File.open( path, 'rb' ) do |f|
170
+ f.read
171
+ end
172
+ blob
173
+ end
134
174
  end
135
175
  alias_method :read_binary, :read_blob
136
176
  alias_method :read_bin, :read_blob
@@ -140,12 +180,42 @@ alias_method :read_bin, :read_blob
140
180
 
141
181
  ## todo/check: remove \n (or\r or \r\n) from line
142
182
  ## ruby (by default) keeps the newline - follow tradition? why? why not?
183
+ ## add/offer chomp: true/false option or such - why? why not?
184
+ ## see String.lines in rdoc
143
185
  ##
144
186
  def read_lines( path )
145
- lines = File.open( path, 'r:utf-8' ) do |f|
146
- f.readlines
147
- end
148
- lines
187
+ read_text( path ).lines
188
+ end
189
+
190
+ def parse_lines( str )
191
+ str.lines
192
+ end
193
+
194
+
195
+
196
+ def read_env( path )
197
+ EnvParser.load( read_text( path ))
198
+ end
199
+
200
+ def parse_env( str )
201
+ EnvParser.load( str )
202
+ end
203
+
204
+
205
+ ##
206
+ ## todo/check - change path to *paths=['./.env']
207
+ ## and support more files - why? why not?
208
+ def load_env( path='./.env' )
209
+ if File.exist?( path )
210
+ puts "==> loading .env settings..."
211
+ env = read_env( path )
212
+ puts " applying .env settings... (merging into ENV)"
213
+ pp env
214
+ ## note: will only add .env setting if NOT present in ENV!!!
215
+ env.each do |k,v|
216
+ ENV[k] ||= v
217
+ end
218
+ end
149
219
  end
150
220
 
151
221
 
@@ -163,7 +233,7 @@ def write_json( path, data )
163
233
  FileUtils.mkdir_p( dirname ) unless Dir.exist?( dirname )
164
234
 
165
235
  ## note: pretty print/reformat json
166
- File.open( path, "w:utf-8" ) do |f|
236
+ File.open( path, 'w:utf-8' ) do |f|
167
237
  f.write( JSON.pretty_generate( data ))
168
238
  end
169
239
  end
@@ -177,7 +247,7 @@ def write_blob( path, blob )
177
247
  dirname = File.dirname( path )
178
248
  FileUtils.mkdir_p( dirname ) unless Dir.exist?( dirname )
179
249
 
180
- File.open( path, "wb" ) do |f|
250
+ File.open( path, 'wb' ) do |f|
181
251
  f.write( blob )
182
252
  end
183
253
  end
@@ -193,7 +263,7 @@ def write_text( path, text )
193
263
  dirname = File.dirname( path )
194
264
  FileUtils.mkdir_p( dirname ) unless Dir.exist?( dirname )
195
265
 
196
- File.open( path, "w:utf-8" ) do |f|
266
+ File.open( path, 'w:utf-8' ) do |f|
197
267
  f.write( text )
198
268
  end
199
269
  end
@@ -211,6 +281,17 @@ end
211
281
 
212
282
 
213
283
 
284
+ ## private helper - make public -why? why not?
285
+ def _wget!( url, **kwargs )
286
+ res = Webclient.get( url, **kwargs )
287
+
288
+ ## check/todo - use a different exception/error - keep RuntimeError - why? why not?
289
+ raise RuntimeError, "HTTP #{res.status.code} - #{res.status.message}" if res.status.nok?
290
+
291
+ res
292
+ end
293
+
294
+
214
295
  end # module Kernel
215
296
 
216
297
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-22 00:00:00.000000000 Z
11
+ date: 2023-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: csvreader
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '3.23'
95
+ version: '4.0'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '3.23'
102
+ version: '4.0'
103
103
  description: cocos (code commons) - auto-include quick-starter prelude & prolog
104
104
  email: opensport@googlegroups.com
105
105
  executables: []
@@ -116,6 +116,7 @@ files:
116
116
  - README.md
117
117
  - Rakefile
118
118
  - lib/cocos.rb
119
+ - lib/cocos/env.rb
119
120
  - lib/cocos/version.rb
120
121
  homepage: https://github.com/rubycocos/cocos
121
122
  licenses:
@@ -138,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
139
  - !ruby/object:Gem::Version
139
140
  version: '0'
140
141
  requirements: []
141
- rubygems_version: 3.3.7
142
+ rubygems_version: 3.4.10
142
143
  signing_key:
143
144
  specification_version: 4
144
145
  summary: cocos (code commons) - auto-include quick-starter prelude & prolog