configparser 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in configparser.gemspec
4
+ gemspec
@@ -1,4 +1,6 @@
1
- Copyright (c) 2011 Chris Lee, PhD
1
+ Copyright (c) 2013 chrislee35
2
+
3
+ MIT License
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
@@ -0,0 +1,79 @@
1
+ # Configparser
2
+
3
+ Configparser parses configuration files compatible with Python's ConfigParser
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'configparser'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install configparser
18
+
19
+ ## Usage
20
+
21
+ $ cat test/simple.cfg
22
+ test1=hi
23
+ test2 = hello
24
+
25
+ [first_section]
26
+ mytest=55
27
+ yourtest = 99
28
+ #nothere=notthere
29
+ myboolean
30
+
31
+ [second section]
32
+ myway=or the
33
+ highway
34
+
35
+ cp = ConfigParser.new('test/simple.cfg')
36
+ puts cp.to_s
37
+
38
+ test1: hi
39
+ test2: hello
40
+ [first_section]
41
+ myboolean
42
+ mytest: 55
43
+ yourtest: 99
44
+ [second section]
45
+ myway: or the highway
46
+
47
+ $ cat test/complex.cfg
48
+ global1=default-$(global3)
49
+ global2=strange-$(global1)
50
+ global3=whatever
51
+
52
+ [section1]
53
+ local1=$(global2)-$(local2)-local
54
+ local2=yodel
55
+
56
+ [section2]
57
+ local1=hotel
58
+ local2=recent $(local1)
59
+ local3=un$(resolvable)
60
+
61
+ cp = ConfigParser.new('test/complex.cfg')
62
+ puts cp['global2']
63
+ puts cp['section1']['local1']
64
+ puts cp['section2']['local2']
65
+ puts cp['section2']['local3']
66
+
67
+ strange-default-whatever
68
+ strange-default-whatever-yodel-local
69
+ recent hotel
70
+ un$(resolvable)
71
+
72
+
73
+ ## Contributing
74
+
75
+ 1. Fork it
76
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
77
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
78
+ 4. Push to the branch (`git push origin my-new-feature`)
79
+ 5. Create new Pull Request
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib'
8
+ t.test_files = FileList['test/test_*.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'configparser/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "configparser"
8
+ spec.version = Configparser::VERSION
9
+ spec.authors = ["chrislee35"]
10
+ spec.email = ["rubygems@chrislee.dhs.org"]
11
+ spec.description = %q{parses configuration files compatable with Python's ConfigParser}
12
+ spec.summary = %q{parses configuration files compatable with Python's ConfigParser}
13
+ spec.homepage = "https://github.com/chrislee35/configparser"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.signing_key = "#{File.dirname(__FILE__)}/../gem-private_key.pem"
25
+ spec.cert_chain = ["#{File.dirname(__FILE__)}/../gem-public_cert.pem"]
26
+
27
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ end
@@ -1 +1,99 @@
1
- require 'configparser/base'
1
+ require "configparser/version"
2
+
3
+ # DESCRIPTION: parses configuration files compatible with Python's ConfigParser
4
+
5
+ class ConfigParser < Hash
6
+ def initialize(fname)
7
+ section = nil
8
+ key = nil
9
+ File.open(fname,"r").each_line do |line|
10
+ next if (line =~ /^(#|;)/)
11
+
12
+ # parse out the lines of the config
13
+ if line =~ /^(.+?)\s*[=:]\s*(.+)$/ # handle key=value lines
14
+ if section
15
+ self[section] = {} unless self[section]
16
+ key = $1
17
+ self[section][key] = $2
18
+ else
19
+ key = $1
20
+ self[key] = $2
21
+ end
22
+ elsif line =~ /^\[(.+?)\]/ # handle new sections
23
+ section = $1
24
+ elsif line =~ /^\s+(.+?)$/ # handle continued lines
25
+ if section
26
+ self[section][key] += " #{$1}";
27
+ else
28
+ self[key] += " #{$1}"
29
+ end
30
+ elsif line =~ /^([\w\d\_\-]+)$/
31
+ if section
32
+ self[section] = {} unless self[section]
33
+ key = $1
34
+ self[section][key] = true
35
+ else
36
+ key = $1
37
+ self[key] = true
38
+ end
39
+ end
40
+ end
41
+
42
+ # handle substitutions (globals first)
43
+ changes = true
44
+ while changes do
45
+ changes = false
46
+ self.each_key do |k|
47
+ next if self[k].is_a? Hash
48
+ next unless self[k].is_a? String
49
+ self[k].gsub!(/\$\((.+?)\)/) {|x|
50
+ changes = true if self[$1]
51
+ self[$1] || "$(#{$1})"
52
+ }
53
+ end
54
+ end
55
+
56
+ # handle substitutions within the sections
57
+ changes = true
58
+ while changes do
59
+ changes = false
60
+ self.each_key do |k|
61
+ next unless self[k].is_a? Hash
62
+ self[k].each_key do |j|
63
+ next unless self[k][j].is_a? String
64
+ self[k][j].gsub!(/\$\((.+?)\)/) {|x|
65
+ changes = true if self[k][$1] || self[$1]
66
+ self[k][$1] || self[$1] || "$(#{$1})"
67
+ }
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def to_s
74
+ str = ""
75
+ # print globals first
76
+ self.keys.sort.each do |k|
77
+ next if self[k].is_a? Hash
78
+ if self[k] === true
79
+ str << "#{k}\n"
80
+ else
81
+ str << "#{k}: #{self[k]}\n"
82
+ end
83
+ end
84
+
85
+ # now print the sections
86
+ self.keys.sort.each do |k|
87
+ next unless self[k].is_a? Hash
88
+ str << "[#{k}]\n"
89
+ self[k].keys.sort.each do |j|
90
+ if self[k][j] === true
91
+ str << "#{j}\n"
92
+ else
93
+ str << "#{j}: #{self[k][j]}\n"
94
+ end
95
+ end
96
+ end
97
+ str
98
+ end
99
+ end
@@ -0,0 +1,3 @@
1
+ class Configparser
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ global1=default-$(global3)
2
+ global2=strange-$(global1)
3
+ global3=whatever
4
+
5
+ [section1]
6
+ local1=$(global2)-$(local2)-local
7
+ local2=yodel
8
+
9
+ [section2]
10
+ local1=hotel
11
+ local2=recent $(local1)
12
+ local3=un$(resolvable)
@@ -1,18 +1,2 @@
1
- require 'rubygems'
2
- require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
1
  require 'test/unit'
11
- require 'shoulda'
12
-
13
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
- $LOAD_PATH.unshift(File.dirname(__FILE__))
15
- require 'configparser'
16
-
17
- class Test::Unit::TestCase
18
- end
2
+ require File.expand_path('../../lib/configparser.rb', __FILE__)
@@ -0,0 +1,12 @@
1
+ test1=hi
2
+ test2 = hello
3
+
4
+ [first_section]
5
+ mytest=55
6
+ yourtest = 99
7
+ #nothere=notthere
8
+ myboolean
9
+
10
+ [second section]
11
+ myway=or the
12
+ highway
@@ -1,7 +1,15 @@
1
- require 'helper'
1
+ unless Kernel.respond_to?(:require_relative)
2
+ module Kernel
3
+ def require_relative(path)
4
+ require File.join(File.dirname(caller[0]), path.to_str)
5
+ end
6
+ end
7
+ end
8
+
9
+ require_relative 'helper'
2
10
 
3
11
  class TestConfigparser < Test::Unit::TestCase
4
- should "parse a simple config" do
12
+ def test_parse_a_simple_config
5
13
  cp = ConfigParser.new('test/simple.cfg')
6
14
  assert_not_nil(cp)
7
15
  assert_equal('hi',cp['test1'])
@@ -12,7 +20,7 @@ class TestConfigparser < Test::Unit::TestCase
12
20
  assert_equal('or the highway',cp['second section']['myway'])
13
21
  end
14
22
 
15
- should "convert a simple config to a string" do
23
+ def test_convert_a_simple_config_to_a_string
16
24
  cp = ConfigParser.new('test/simple.cfg')
17
25
  doc = "test1: hi
18
26
  test2: hello
@@ -26,7 +34,7 @@ myway: or the highway
26
34
  assert_equal(doc,cp.to_s)
27
35
  end
28
36
 
29
- should "parse a config with substitutions" do
37
+ def test_parse_a_config_with_substitutions
30
38
  cp = ConfigParser.new('test/complex.cfg')
31
39
  assert_not_nil(cp)
32
40
  assert_equal('strange-default-whatever',cp['global2'])
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configparser
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
- - Chris Lee
13
+ - chrislee35
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain:
@@ -18,76 +18,45 @@ cert_chain:
18
18
  -----BEGIN CERTIFICATE-----
19
19
  MIIDYjCCAkqgAwIBAgIBADANBgkqhkiG9w0BAQUFADBXMREwDwYDVQQDDAhydWJ5
20
20
  Z2VtczEYMBYGCgmSJomT8ixkARkWCGNocmlzbGVlMRMwEQYKCZImiZPyLGQBGRYD
21
- ZGhzMRMwEQYKCZImiZPyLGQBGRYDb3JnMB4XDTExMDIyNzE1MzAxOVoXDTEyMDIy
22
- NzE1MzAxOVowVzERMA8GA1UEAwwIcnVieWdlbXMxGDAWBgoJkiaJk/IsZAEZFghj
21
+ ZGhzMRMwEQYKCZImiZPyLGQBGRYDb3JnMB4XDTEzMDUyMjEyNTk0N1oXDTE0MDUy
22
+ MjEyNTk0N1owVzERMA8GA1UEAwwIcnVieWdlbXMxGDAWBgoJkiaJk/IsZAEZFghj
23
23
  aHJpc2xlZTETMBEGCgmSJomT8ixkARkWA2RoczETMBEGCgmSJomT8ixkARkWA29y
24
- ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNM1Hjs6q58sf7Jp64A
25
- vEY2cnRWDdFpD8UWpwaJK5kgSHOVgs+0mtszn+YlYjmx8kpmuYpyU4g9mNMImMQe
26
- ow8pVsL4QBBK/1Ozgdxrsptk3IiTozMYA+g2I/+WvZSEDu9uHkKe8pvMBEMrg7RJ
27
- IN7+jWaPnSzg3DbFwxwOdi+QRw33DjK7oFWcOaaBqWTUpI4epdi/c/FE1I6UWULJ
28
- ZF/Uso0Sc2Pp/YuVhuMHGrUbn7zrWWo76nnK4DTLfXFDbZF5lIXT1w6BtIiN6Ho9
29
- Rdr/W6663hYUo3WMsUSa3I5+PJXEBKmGHIZ2TNFnoFIRHha2fmm1HC9+BTaKwcO9
30
- PLcCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQURzsNkZo2rv86Ftc+hVww
31
- RNICMrwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQBRRw/iNA/PdnvW
32
- OBoNCSr/IiHOGZqMHgPJwyWs68FhThnLc2EyIkuLTQf98ms1/D3p0XX9JsxazvKT
33
- W/in8Mm/R2fkVziSdzqChtw/4Z4bW3c+RF7TgX6SP5cKxNAfKmAPuItcs2Y+7bdS
34
- hr/FktVtT2iAmISRnlEbdaTpfl6N2ZWNT83khV6iOs5xRkX/+0e+GgAv9mE6nqr1
35
- AkuDXMhposxcnFZUrZ3UtMPEe/JnyP7Vv6pvr3qtZm8FidFZU91+rX/fwdyBU8RP
36
- /5l8uLWXXNt1wEbtu4N1I66LwTK2iRrQZE8XtlgZGbxYDFUkiurq3OafF2YwRs6W
37
- 6yhklP75
24
+ ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANcPrx8BZiWIR9xWWG8I
25
+ tqR538tS1t+UJ4FZFl+1vrtU9TiuWX3Vj37TwUpa2fFkziK0n5KupVThyEhcem5m
26
+ OGRjvgrRFbWQJSSscIKOpwqURHVKRpV9gVz/Hnzk8S+xotUR1Buo3Ugr+I1jHewD
27
+ Cgr+y+zgZbtjtHsJtsuujkOcPhEjjUinj68L9Fz9BdeJQt+IacjwAzULix6jWCht
28
+ Uc+g+0z8Esryca2G6I1GsrgX6WHw8dykyQDT9dCtS2flCOwSC1R0K5T/xHW54f+5
29
+ wcw8mm53KLNe+tmgVC6ZHyME+qJsBnP6uxF0aTEnGA/jDBQDhQNTF0ZP/abzyTsL
30
+ zjUCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFO8w
31
+ +aeP7T6kVJblCg6eusOII9DfMA0GCSqGSIb3DQEBBQUAA4IBAQBCQyRJLXsBo2Fy
32
+ 8W6e/W4RemQRrlAw9DK5O6U71JtedVob2oq+Ob+zmS+PifE2+L+3RiJ2H6VTlOzi
33
+ x+A061MUXhGraqVq4J2FC8kt4EQywAD0P0Ta5GU24CGSF08Y3GkJy1Sa4XqTC2YC
34
+ o51s7JP+tkCCtpVYSdzJhTllieRAWBpGV1dtaoeUKE6tYPMBkosxSRcVGczk/Sc3
35
+ 7eQCpexYy9JlUBI9u3BqIY9E+l+MSn8ihXSPmyK0DgrhaCu+voaSFVOX6Y+B5qbo
36
+ jLXMQu2ZgISYwXNjNbGVHehut82U7U9oiHoWcrOGazaRUmGO9TXP+aJLH0gw2dcK
37
+ AfMglXPi
38
38
  -----END CERTIFICATE-----
39
39
 
40
- date: 2011-03-11 00:00:00 -05:00
41
- default_executable:
40
+ date: 2013-06-02 00:00:00 Z
42
41
  dependencies:
43
42
  - !ruby/object:Gem::Dependency
44
- version_requirements: &id001 !ruby/object:Gem::Requirement
45
- none: false
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- hash: 3
50
- segments:
51
- - 0
52
- version: "0"
53
- requirement: *id001
54
- prerelease: false
55
- name: shoulda
56
- type: :development
57
- - !ruby/object:Gem::Dependency
58
- version_requirements: &id002 !ruby/object:Gem::Requirement
59
- none: false
60
- requirements:
61
- - - ~>
62
- - !ruby/object:Gem::Version
63
- hash: 23
64
- segments:
65
- - 1
66
- - 0
67
- - 0
68
- version: 1.0.0
69
- requirement: *id002
70
- prerelease: false
71
43
  name: bundler
72
- type: :development
73
- - !ruby/object:Gem::Dependency
74
- version_requirements: &id003 !ruby/object:Gem::Requirement
44
+ version_requirements: &id001 !ruby/object:Gem::Requirement
75
45
  none: false
76
46
  requirements:
77
47
  - - ~>
78
48
  - !ruby/object:Gem::Version
79
- hash: 7
49
+ hash: 9
80
50
  segments:
81
51
  - 1
82
- - 5
83
- - 2
84
- version: 1.5.2
85
- requirement: *id003
52
+ - 3
53
+ version: "1.3"
86
54
  prerelease: false
87
- name: jeweler
88
55
  type: :development
56
+ requirement: *id001
89
57
  - !ruby/object:Gem::Dependency
90
- version_requirements: &id004 !ruby/object:Gem::Requirement
58
+ name: rake
59
+ version_requirements: &id002 !ruby/object:Gem::Requirement
91
60
  none: false
92
61
  requirements:
93
62
  - - ">="
@@ -96,28 +65,32 @@ dependencies:
96
65
  segments:
97
66
  - 0
98
67
  version: "0"
99
- requirement: *id004
100
68
  prerelease: false
101
- name: rcov
102
69
  type: :development
70
+ requirement: *id002
103
71
  description: parses configuration files compatable with Python's ConfigParser
104
- email: rubygems@chrislee.dhs.org
72
+ email:
73
+ - rubygems@chrislee.dhs.org
105
74
  executables: []
106
75
 
107
76
  extensions: []
108
77
 
109
- extra_rdoc_files:
110
- - LICENSE.txt
111
- - README.rdoc
78
+ extra_rdoc_files: []
79
+
112
80
  files:
113
- - lib/configparser.rb
114
- - lib/configparser/base.rb
81
+ - .gitignore
82
+ - Gemfile
115
83
  - LICENSE.txt
116
- - README.rdoc
84
+ - README.md
85
+ - Rakefile
86
+ - configparser.gemspec
87
+ - lib/configparser.rb
88
+ - lib/configparser/version.rb
89
+ - test/complex.cfg
117
90
  - test/helper.rb
91
+ - test/simple.cfg
118
92
  - test/test_configparser.rb
119
- has_rdoc: true
120
- homepage: https://rubygems.org/gems/configparser
93
+ homepage: https://github.com/chrislee35/configparser
121
94
  licenses:
122
95
  - MIT
123
96
  post_install_message:
@@ -146,10 +119,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
119
  requirements: []
147
120
 
148
121
  rubyforge_project:
149
- rubygems_version: 1.6.1
122
+ rubygems_version: 1.8.25
150
123
  signing_key:
151
124
  specification_version: 3
152
125
  summary: parses configuration files compatable with Python's ConfigParser
153
126
  test_files:
127
+ - test/complex.cfg
154
128
  - test/helper.rb
129
+ - test/simple.cfg
155
130
  - test/test_configparser.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,19 +0,0 @@
1
- = configparser
2
-
3
- Description goes here.
4
-
5
- == Contributing to configparser
6
-
7
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
- * Fork the project
10
- * Start a feature/bugfix branch
11
- * Commit and push until you are happy with your contribution
12
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2011 Chris Lee, PhD. See LICENSE.txt for
18
- further details.
19
-
@@ -1,84 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # DESCRIPTION: parses configuration files compatable with Python's ConfigParser
3
-
4
- class ConfigParser < Hash
5
- def initialize(fname)
6
- section = nil
7
- key = nil
8
- File.open(fname,"r").each_line do |line|
9
- next if (line =~ /^(#|;)/)
10
-
11
- # parse out the lines of the config
12
- if line =~ /^(.+?)\s*[=:]\s*(.+)$/ # handle key=value lines
13
- if section
14
- self[section] = {} unless self[section]
15
- key = $1
16
- self[section][key] = $2
17
- else
18
- key = $1
19
- self[key] = $2
20
- end
21
- elsif line =~ /^\[(.+?)\]/ # handle new sections
22
- section = $1
23
- elsif line =~ /^\s+(.+?)$/ # handle continued lines
24
- if section
25
- self[section][key] += " #{$1}";
26
- else
27
- self[key] += " #{$1}"
28
- end
29
- elsif line =~ /^([\w\d\_\-]+)$/
30
- if section
31
- self[section] = {} unless self[section]
32
- key = $1
33
- self[section][key] = true
34
- else
35
- key = $1
36
- self[key] = true
37
- end
38
- end
39
- end
40
-
41
- # handle substitutions (globals first)
42
- self.each_key do |k|
43
- next if self[k].is_a? Hash
44
- next unless self[k].is_a? String
45
- self[k].gsub!(/\$\((.+?)\)/) {|x| self[$1] || "$(#{$1})"}
46
- end
47
-
48
- # handle substitutions within the sections
49
- self.each_key do |k|
50
- next unless self[k].is_a? Hash
51
- self[k].each_key do |j|
52
- next unless self[k][j].is_a? String
53
- self[k][j].gsub!(/\$\((.+?)\)/) {|x| self[k][$1] || self[$1] || "$(#{$1})"}
54
- end
55
- end
56
- end
57
-
58
- def to_s
59
- str = ""
60
- # print globals first
61
- self.keys.sort.each do |k|
62
- next if self[k].is_a? Hash
63
- if self[k] === true
64
- str << "#{k}\n"
65
- else
66
- str << "#{k}: #{self[k]}\n"
67
- end
68
- end
69
-
70
- # now print the sections
71
- self.keys.sort.each do |k|
72
- next unless self[k].is_a? Hash
73
- str << "[#{k}]\n"
74
- self[k].keys.sort.each do |j|
75
- if self[k][j] === true
76
- str << "#{j}\n"
77
- else
78
- str << "#{j}: #{self[k][j]}\n"
79
- end
80
- end
81
- end
82
- str
83
- end
84
- end