hocon 0.9.5 → 1.0.1

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.
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
+ }