hocon 0.9.5 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -2
  3. data/README.md +22 -10
  4. data/lib/hocon.rb +9 -3
  5. data/lib/hocon/config_factory.rb +4 -0
  6. data/lib/hocon/config_value_factory.rb +13 -2
  7. data/lib/hocon/impl/config_reference.rb +5 -2
  8. data/lib/hocon/impl/simple_config_origin.rb +1 -1
  9. data/spec/fixtures/parse_render/example1/input.conf +21 -0
  10. data/spec/fixtures/parse_render/example1/output.conf +26 -0
  11. data/spec/fixtures/parse_render/example1/output_nocomments.conf +17 -0
  12. data/spec/fixtures/parse_render/example2/input.conf +10 -0
  13. data/spec/fixtures/parse_render/example2/output.conf +17 -0
  14. data/spec/fixtures/parse_render/example2/output_nocomments.conf +17 -0
  15. data/spec/fixtures/parse_render/example3/input.conf +2 -0
  16. data/spec/fixtures/parse_render/example3/output.conf +2 -0
  17. data/spec/fixtures/parse_render/example4/input.json +6 -0
  18. data/spec/fixtures/parse_render/example4/output.conf +6 -0
  19. data/spec/fixtures/test_utils/resources/bom.conf +2 -0
  20. data/spec/fixtures/test_utils/resources/cycle.conf +1 -0
  21. data/spec/fixtures/test_utils/resources/file-include.conf +5 -0
  22. data/spec/fixtures/test_utils/resources/include-from-list.conf +4 -0
  23. data/spec/fixtures/test_utils/resources/subdir/bar.conf +1 -0
  24. data/spec/fixtures/test_utils/resources/subdir/baz.conf +1 -0
  25. data/spec/fixtures/test_utils/resources/subdir/foo.conf +5 -0
  26. data/spec/fixtures/test_utils/resources/test01.conf +80 -0
  27. data/spec/fixtures/test_utils/resources/test01.json +4 -0
  28. data/spec/fixtures/test_utils/resources/test03.conf +36 -0
  29. data/spec/spec_helper.rb +43 -0
  30. data/spec/test_utils.rb +757 -0
  31. data/spec/unit/typesafe/config/concatenation_spec.rb +417 -0
  32. data/spec/unit/typesafe/config/conf_parser_spec.rb +822 -0
  33. data/spec/unit/typesafe/config/config_document_parser_spec.rb +494 -0
  34. data/spec/unit/typesafe/config/config_document_spec.rb +576 -0
  35. data/spec/unit/typesafe/config/config_factory_spec.rb +120 -0
  36. data/spec/unit/typesafe/config/config_node_spec.rb +552 -0
  37. data/spec/unit/typesafe/config/config_value_factory_spec.rb +85 -0
  38. data/spec/unit/typesafe/config/config_value_spec.rb +935 -0
  39. data/spec/unit/typesafe/config/hocon_spec.rb +54 -0
  40. data/spec/unit/typesafe/config/path_spec.rb +261 -0
  41. data/spec/unit/typesafe/config/public_api_spec.rb +520 -0
  42. data/spec/unit/typesafe/config/simple_config_spec.rb +112 -0
  43. data/spec/unit/typesafe/config/token_spec.rb +188 -0
  44. data/spec/unit/typesafe/config/tokenizer_spec.rb +801 -0
  45. metadata +39 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d586be6e36bce66c74d12ea9406b9b6d844394ae
4
- data.tar.gz: dafe13b0402fc522a2eb8b1048c9c9adcedc4aaf
3
+ metadata.gz: f53bd3b94192eb5515fdd8dee18a31f1b7ec3301
4
+ data.tar.gz: 9528170c7011011e68058de66b134240b6aaba5b
5
5
  SHA512:
6
- metadata.gz: 07793700cdc1f874d77686530ec13610197e91f9d2cd8b39cede3a8d01f36002ff1faa7e3a7c7c12b3109f96a80f71291248ff7bb3e7f91cca86111692d52b00
7
- data.tar.gz: 268a221b935ee64a080d0f4466914ca0652e02ce1405aec1d957d42d4169a0f391e25570564ab26070416cd712fa5ab5bb3164c9c4d43f18ba925c3afb6e77b2
6
+ metadata.gz: 692390bfc06e62f8674b9a45ac76777df321738ccb647180cff3378e69ff489a182f1a91573243da0703586709fcb4d02ae874ce2f7f2674770485b0b14afa18
7
+ data.tar.gz: e4f43e24a79072d8964fd3ee89dab2e9daa2e96dd1a9afd1b2db0ae97b5249f16d49a67617fa20272ef023b9c1836e502c9d9f0885c49d463ff45c01a0606f2f
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
- ## 0.9.5
1
+ ## 1.0.1
2
2
 
3
- This is a re-release of 0.9.3 to revert changes made in 0.9.4
3
+ This is a bugfix release.
4
+ The API is stable enough and the code is being used in production, so the version is also being bumped to 1.0.0
5
+
6
+ * Fixed a bug wherein calling "Hocon.load" would not
7
+ resolve substitutions.
8
+ * Fixed a circular dependency between the Hocon and Hocon::ConfigFactory
9
+ namespaces. Using the Hocon::ConfigFactory class now requires you to
10
+ use a `require 'hocon/config_factory'` instead of `require hocon`
11
+ * Add support for hashes with keyword keys
12
+
13
+ ## 1.0.0
14
+
15
+ This version number was burned.
4
16
 
5
17
  ## 0.9.3
6
18
 
data/README.md CHANGED
@@ -8,12 +8,16 @@ This is a port of the [Typesafe Config](https://github.com/typesafehub/config) l
8
8
  The library provides Ruby support for the [HOCON](https://github.com/typesafehub/config/blob/master/HOCON.md) configuration file format.
9
9
 
10
10
 
11
- At present, it supports supports parsing and modification of existing HOCON/JSON files via the `ConfigFactory` class and the `ConfigValueFactory` class, and rendering parsed config objects back to a String.
12
- It also supports the parsing and modification of HOCON/JSON files via `ConfigDocumentFactory`.
13
- PLEASE NOTE this project is in an experimental state, and in some cases may not work properly, so
14
- please be wary when using it. If you find a problem, feel free to open a github issue.
11
+ At present, it supports supports parsing and modification of existing HOCON/JSON files via the `ConfigFactory`
12
+ class and the `ConfigValueFactory` class, and rendering parsed config objects back to a String
13
+ ([see examples below](#basic-usage)). It also supports the parsing and modification of HOCON/JSON files via
14
+ `ConfigDocumentFactory`.
15
15
 
16
- The implementation is intended to be as close to a line-for-line port as the two languages allow, in hopes of making it fairly easy to port over new changesets from the Java code base over time.
16
+ **Note:** While the project is production ready, since not all features in the Typesafe library are supported,
17
+ you may still run into some issues. If you find a problem, feel free to open a github issue.
18
+
19
+ The implementation is intended to be as close to a line-for-line port as the two languages allow,
20
+ in hopes of making it fairly easy to port over new changesets from the Java code base over time.
17
21
 
18
22
  Basic Usage
19
23
  ===========
@@ -22,15 +26,18 @@ Basic Usage
22
26
  gem install hocon
23
27
  ```
24
28
 
29
+ To use the simple API, for reading config values:
25
30
 
26
31
  ```rb
27
- require 'hocon/config_factory'
32
+ require 'hocon'
28
33
 
29
- conf = Hocon::ConfigFactory.parse_file("myapp.conf")
30
- conf_map = conf.root.unwrapped
34
+ conf = Hocon.load("myapp.conf")
35
+ puts "Here's a setting: #{conf["foo"]["bar"]["baz"]}"
31
36
  ```
32
37
 
33
- To use the ConfigDocument API
38
+ To use the ConfigDocument API, if you need both read/write capability for
39
+ modifying settings in a config file, or if you want to retain access to
40
+ things like comments and line numbers:
34
41
 
35
42
  ```rb
36
43
  require 'hocon/parser/config_document_factory'
@@ -46,6 +53,10 @@ doc_has_value = doc.has_value?("a") # returns boolean
46
53
  orig_doc_text = doc.render # returns string
47
54
  ```
48
55
 
56
+ Note that a `ConfigDocument` is used primarily for simple configuration manipulation while preserving
57
+ whitespace and comments. As such, it is not powerful as the regular `Config` API, and will not resolve
58
+ substitutions.
59
+
49
60
  Testing
50
61
  =======
51
62
 
@@ -57,7 +68,8 @@ bundle exec rspec spec
57
68
  Unsupported Features
58
69
  ====================
59
70
 
60
- This supports many of the same things as the Java library, but there are some notable exceptions. Unsupported features include:
71
+ This supports many of the same things as the Java library, but there are some notable exceptions.
72
+ Unsupported features include:
61
73
 
62
74
  * Non file includes
63
75
  * Loading resources from the class path or URLs
data/lib/hocon.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Hocon
4
- require 'hocon/config_factory'
5
-
6
4
  def self.load(file)
7
- config = Hocon::ConfigFactory.parse_file(file)
5
+ # doing this require lazily, because otherwise, classes that need to
6
+ # `require 'hocon'` to get the module into scope will end up recursing
7
+ # through this require and probably ending up with circular dependencies.
8
+ require 'hocon/config_factory'
9
+ config = Hocon::ConfigFactory.load_file(file)
8
10
  return config.root.unwrapped
9
11
  end
10
12
 
11
13
  def self.parse(string)
14
+ # doing this require lazily, because otherwise, classes that need to
15
+ # `require 'hocon'` to get the module into scope will end up recursing
16
+ # through this require and probably ending up with circular dependencies.
17
+ require 'hocon/config_factory'
12
18
  config = Hocon::ConfigFactory.parse_string(string)
13
19
  return config.root.unwrapped
14
20
  end
@@ -6,6 +6,10 @@ require 'hocon/config_parse_options'
6
6
  require 'hocon/impl/config_impl'
7
7
  require 'hocon/config_factory'
8
8
 
9
+ ## Please note that the `parse` operations will simply create a ConfigValue
10
+ ## and do nothing else, whereas the `load` operations will perform a higher-level
11
+ ## operation and will resolve substitutions. If you have substitutions in your
12
+ ## configuration, use a `load` function
9
13
  class Hocon::ConfigFactory
10
14
  def self.parse_file(file_path, options = Hocon::ConfigParseOptions.defaults)
11
15
  Hocon::Impl::Parseable.new_file(file_path, options).parse.to_config
@@ -55,7 +55,11 @@ class Hocon::ConfigValueFactory
55
55
  # @return a new value
56
56
  #
57
57
  def self.from_any_ref(object, origin_description = nil)
58
- ConfigImpl.from_any_ref(object, origin_description)
58
+ if object.is_a?(Hash)
59
+ from_map(object, origin_description)
60
+ else
61
+ ConfigImpl.from_any_ref(object, origin_description)
62
+ end
59
63
  end
60
64
 
61
65
  #
@@ -69,6 +73,13 @@ class Hocon::ConfigValueFactory
69
73
  # @return a new {@link ConfigObject}
70
74
  #
71
75
  def self.from_map(values, origin_description = nil)
72
- ConfigImpl.from_any_ref(values, origin_description)
76
+ ConfigImpl.from_any_ref(process_hash(values), origin_description)
73
77
  end
78
+
79
+ private
80
+
81
+ def self.process_hash(hash)
82
+ Hash[hash.map {|k, v| [k.is_a?(Symbol) ? k.to_s : k, v.is_a?(Hash) ? process_hash(v) : v]}]
83
+ end
84
+
74
85
  end
@@ -3,13 +3,16 @@
3
3
  require 'hocon'
4
4
  require 'hocon/impl'
5
5
  require 'hocon/impl/abstract_config_value'
6
- require 'hocon/impl/resolve_source'
7
- require 'hocon/impl/resolve_result'
8
6
 
9
7
  class Hocon::Impl::ConfigReference
10
8
  include Hocon::Impl::Unmergeable
11
9
  include Hocon::Impl::AbstractConfigValue
12
10
 
11
+ # Require these lazily, to avoid circular dependencies
12
+ require 'hocon/impl/resolve_source'
13
+ require 'hocon/impl/resolve_result'
14
+
15
+
13
16
  NotPossibleToResolve = Hocon::Impl::AbstractConfigValue::NotPossibleToResolve
14
17
  UnresolvedSubstitutionError = Hocon::ConfigError::UnresolvedSubstitutionError
15
18
 
@@ -212,7 +212,7 @@ class Hocon::Impl::SimpleConfigOrigin
212
212
  if a.origin_type == b.origin_type
213
213
  a.origin_type
214
214
  else
215
- Hocon::Impl::OriginType.GENERIC
215
+ Hocon::Impl::OriginType::GENERIC
216
216
  end
217
217
 
218
218
  # first use the "description" field which has no line numbers
@@ -0,0 +1,21 @@
1
+ # These are some opening comments
2
+ # These are some additional opening comments
3
+ foo.bar {
4
+ // the baz is is blah blah
5
+ baz = 42
6
+ boom = [1, 2, {derp : duh }, 4]
7
+ empty = []
8
+
9
+ # abracadabra setting
10
+ abracadabra = "hi"
11
+ }
12
+
13
+ // as for the yippee
14
+ # it entails some things
15
+ foo.bar.yahoo = "yippee"
16
+
17
+ # truthy
18
+ foo.bar.truthy = true
19
+
20
+ # falsy
21
+ foo.bar.falsy = false
@@ -0,0 +1,26 @@
1
+ foo {
2
+ # These are some opening comments
3
+ # These are some additional opening comments
4
+ bar {
5
+ # falsy
6
+ falsy=false
7
+ # truthy
8
+ truthy=true
9
+ # as for the yippee
10
+ # it entails some things
11
+ yahoo=yippee
12
+ # the baz is is blah blah
13
+ baz=42
14
+ boom=[
15
+ 1,
16
+ 2,
17
+ {
18
+ derp=duh
19
+ },
20
+ 4
21
+ ]
22
+ empty=[]
23
+ # abracadabra setting
24
+ abracadabra=hi
25
+ }
26
+ }
@@ -0,0 +1,17 @@
1
+ foo {
2
+ bar {
3
+ falsy=false
4
+ truthy=true
5
+ yahoo=yippee
6
+ baz=42
7
+ boom=[
8
+ 1,
9
+ 2,
10
+ {
11
+ derp=duh
12
+ },
13
+ 4
14
+ ]
15
+ abracadabra=hi
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ jruby-puppet: {
2
+ jruby-pools: [{environment: production}]
3
+ load-path: [/usr/lib/ruby/site_ruby/1.8, /usr/lib/ruby/site_ruby/1.8]
4
+ master-conf-dir: /etc/puppet
5
+ master-var-dir: /var/lib/puppet
6
+ }
7
+
8
+ webserver: {
9
+ host: 1.2.3.4
10
+ }
@@ -0,0 +1,17 @@
1
+ jruby-puppet {
2
+ jruby-pools=[
3
+ {
4
+ environment=production
5
+ }
6
+ ]
7
+ load-path=[
8
+ "/usr/lib/ruby/site_ruby/1.8",
9
+ "/usr/lib/ruby/site_ruby/1.8"
10
+ ]
11
+ master-conf-dir="/etc/puppet"
12
+ master-var-dir="/var/lib/puppet"
13
+ }
14
+
15
+ webserver {
16
+ host="1.2.3.4"
17
+ }
@@ -0,0 +1,17 @@
1
+ jruby-puppet {
2
+ jruby-pools=[
3
+ {
4
+ environment=production
5
+ }
6
+ ]
7
+ load-path=[
8
+ "/usr/lib/ruby/site_ruby/1.8",
9
+ "/usr/lib/ruby/site_ruby/1.8"
10
+ ]
11
+ master-conf-dir="/etc/puppet"
12
+ master-var-dir="/var/lib/puppet"
13
+ }
14
+
15
+ webserver {
16
+ host="1.2.3.4"
17
+ }
@@ -0,0 +1,2 @@
1
+ a: true
2
+ b: ${a}
@@ -0,0 +1,2 @@
1
+ a=true
2
+ b=true
@@ -0,0 +1,6 @@
1
+ {
2
+ "kermit": "frog",
3
+ "miss": "piggy",
4
+ "bert": "ernie",
5
+ "janice": "guitar"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "kermit"="frog",
3
+ "miss"="piggy",
4
+ "bert"="ernie",
5
+ "janice"="guitar"
6
+ }
@@ -0,0 +1,2 @@
1
+ #
2
+ foo = bar
@@ -0,0 +1 @@
1
+ include "cycle.conf"
@@ -0,0 +1,5 @@
1
+ base=41
2
+ # included without file() in a subdir
3
+ include "subdir/foo.conf"
4
+ # included using file() in a subdir
5
+ include file("subdir/baz.conf")
@@ -0,0 +1,4 @@
1
+ // The {} inside the [] is needed because
2
+ // just [ include ] means an array with the
3
+ // string "include" in it.
4
+ a = [ { include "test01.conf" } ]
@@ -0,0 +1,5 @@
1
+ foo=42
2
+ # included without file()
3
+ include "bar.conf"
4
+ # included using file()
5
+ include file("bar-file.conf")
@@ -0,0 +1,80 @@
1
+ {
2
+ "ints" : {
3
+ "fortyTwo" : 42,
4
+ "fortyTwoAgain" : ${ints.fortyTwo}
5
+ },
6
+
7
+ "floats" : {
8
+ "fortyTwoPointOne" : 42.1,
9
+ "fortyTwoPointOneAgain" : ${floats.fortyTwoPointOne}
10
+ },
11
+
12
+ "strings" : {
13
+ "abcd" : "abcd",
14
+ "abcdAgain" : ${strings.a}${strings.b}${strings.c}${strings.d},
15
+ "a" : "a",
16
+ "b" : "b",
17
+ "c" : "c",
18
+ "d" : "d",
19
+ "concatenated" : null bar 42 baz true 3.14 hi,
20
+ "double" : "3.14",
21
+ "number" : "57",
22
+ "null" : "null",
23
+ "true" : "true",
24
+ "yes" : "yes",
25
+ "false" : "false",
26
+ "no" : "no"
27
+ },
28
+
29
+ "arrays" : {
30
+ "empty" : [],
31
+ "ofInt" : [1, 2, 3],
32
+ "ofString" : [ ${strings.a}, ${strings.b}, ${strings.c} ],
33
+ "ofDouble" : [3.14, 4.14, 5.14],
34
+ "ofNull" : [null, null, null],
35
+ "ofBoolean" : [true, false],
36
+ "ofArray" : [${arrays.ofString}, ${arrays.ofString}, ${arrays.ofString}],
37
+ "ofObject" : [${ints}, ${booleans}, ${strings}],
38
+ "firstElementNotASubst" : [ "a", ${strings.b} ]
39
+ },
40
+
41
+ "booleans" : {
42
+ "true" : true,
43
+ "trueAgain" : ${booleans.true},
44
+ "false" : false,
45
+ "falseAgain" : ${booleans.false}
46
+ },
47
+
48
+ "nulls" : {
49
+ "null" : null,
50
+ "nullAgain" : ${nulls.null}
51
+ },
52
+
53
+ "durations" : {
54
+ "second" : 1s,
55
+ "secondsList" : [1s,2seconds,3 s, 4000],
56
+ "secondAsNumber" : 1000,
57
+ "halfSecond" : 0.5s,
58
+ "millis" : 1 milli,
59
+ "micros" : 2000 micros
60
+ },
61
+
62
+ "memsizes" : {
63
+ "meg" : 1M,
64
+ "megsList" : [1M, 1024K, 1048576],
65
+ "megAsNumber" : 1048576,
66
+ "halfMeg" : 0.5M
67
+ },
68
+
69
+ "system" : {
70
+ "javaversion" : ${?java.version},
71
+ "userhome" : ${?user.home},
72
+ "home" : ${?HOME},
73
+ "pwd" : ${?PWD},
74
+ "shell" : ${?SHELL},
75
+ "lang" : ${?LANG},
76
+ "path" : ${?PATH},
77
+ "not_here" : ${?NOT_HERE},
78
+ "concatenated" : Your Java version is ${?system.javaversion} and your user.home is ${?system.userhome}
79
+ }
80
+ }