Skip to content

Commit

Permalink
fixed number conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
darthbear committed Dec 15, 2014
1 parent 42aa8f2 commit 0f54c90
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 38 deletions.
54 changes: 27 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ It is available on pypi so you can install it as follows:
enable_logging = false
resolver = null
# you can use substitution with unquoted strings. If it it not found in the document, it defaults to environment variables
home_dir = ${HOME}
home_dir = ${HOME} # you can substitute with environment variables
"mysql" = {
host = "abc.com" # change it
port = 3306 # default
Expand Down Expand Up @@ -82,70 +82,70 @@ We provide a conversion tool to convert from HOCON to the JSON, .properties and
"active": true,
"enable_logging": false,
"resolver": null,
"home_dir": "/Users/fdang",
"home_dir": "/Users/darthbear",
"mysql": {
"host": "abc.com",
"port": 3306,
"username": "scott ",
"username": "scott",
"password": "tiger",
"retries": 3
},
"ips": [
"192.168 0.0 0.1 ",
"192.168.0.1",
"192.168.0.2",
"192.168 0.0 0.3 "
"192.168.0.3"
]
},
"motd": "\n Hello \"man\"!\n How is it going?\n ",
"retries_msg": "You have 3 retries"
}

#### .properties

$ cat samples/databases.conf | pyhocon -f properties

databases.active = true
databases.enable_logging = false
databases.home_dir = /Users/fdang
databases.home_dir = /Users/darthbear
databases.mysql.host = abc.com
databases.mysql.port = 3306
databases.mysql.username = scott
databases.mysql.password = tiger
databases.mysql.retries = 3
databases.ips.0 = 192.168 0.0 0.1
databases.ips.0 = 192.168.0.1
databases.ips.1 = 192.168.0.2
databases.ips.2 = 192.168 0.0 0.3
databases.ips.2 = 192.168.0.3
motd = \
Hello "man"\!\
How is it going?\

retries_msg = You have 3 retries

#### YAML

$ cat samples/databases.conf | pyhocon -f yaml

databases:
active: true
enable_logging: false
resolver: None
home_dir: /Users/fdang
mysql:
host: abc.com
port: 3306
username: scott
password: tiger
retries: 3
ips:
- 192.168 0.0 0.1
- 192.168.0.2
- 192.168 0.0 0.3
motd: |
databases:
active: true
enable_logging: false
resolver: None
home_dir: /Users/darthbear
mysql:
host: abc.com
port: 3306
username: scott
password: tiger
retries: 3
ips:
- 192.168.0.1
- 192.168.0.2
- 192.168.0.3
motd: |

Hello "man"!
How is it going?

retries_msg: You have 3 retries
retries_msg: You have 3 retries

## TODO

Expand Down
11 changes: 6 additions & 5 deletions pyhocon/config_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
import re
from pyparsing import *
from pyhocon.config_tree import ConfigTree, ConfigSubstitution, ConfigList, ConfigValues, ConfigUnquotedString
from pyhocon.config_tree import ConfigTree, ConfigSubstitution, ConfigList, ConfigValues, ConfigUnquotedString, \
ConfigSlashString
from pyhocon.exceptions import ConfigSubstitutionException


Expand Down Expand Up @@ -70,21 +71,21 @@ def create_substitution(token):
eol = Word('\n\r').suppress()
eol_comma = Word('\n\r,').suppress()
comment = ((Literal('#') | Literal('//')) - SkipTo(eol)).suppress()
number_expr = Regex('[+-]?(\d*\.\d+|\d+(\.\d+)?)([eE]\d+)?').setParseAction(convert_number)
number_expr = Regex('[+-]?(\d*\.\d+|\d+(\.\d+)?)([eE]\d+)?(?=\s*[\n\r\]\},/#])').setParseAction(convert_number)

# multi line string using """
# Using fix described in http://pyparsing.wikispaces.com/share/view/3778969
multiline_string = Regex('""".*?"""', re.DOTALL | re.UNICODE).setParseAction(unescape_multi_string)
# single quoted line string
singleline_string = QuotedString(quoteChar='"', escChar='\\', multiline=True)
# default string that takes the rest of the line until an optional comment
# unquoted string that takes the rest of the line until an optional comment
# we support .properties multiline support which is like this:
# line1 \
# line2 \
# so a backslash precedes the \n
defaultline_string = Regex(r'(\\\n|[^\[\{\n\]\}#,=\$/])+', re.DOTALL).setParseAction(unescape_string)
unquoted_string = Regex(r'(\\\n|[^\[\{\n\]\}#,=\$/])+', re.DOTALL).setParseAction(unescape_string)
substitution_expr = Regex('\$\{[^\}]+\}').setParseAction(create_substitution)
string_expr = multiline_string | singleline_string | defaultline_string | comment | Literal('/')
string_expr = multiline_string | singleline_string | unquoted_string | comment | Literal('/')

value_expr = number_expr | true_expr | false_expr | null_expr | string_expr | substitution_expr
values_expr = ConcatenatedValueParser(value_expr - ZeroOrMore(value_expr + Optional(Literal('\\') + eol).suppress()))
Expand Down
8 changes: 7 additions & 1 deletion pyhocon/config_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def __init__(self, iterable):
token.parent = self
token.index = index

# if the last token is an unquoted string then stripright it
# if the last token is an unquoted string then right strip it
if isinstance(self.tokens[-1], ConfigUnquotedString):
self.tokens[-1] = self.tokens[-1].rstrip()

Expand Down Expand Up @@ -263,3 +263,9 @@ class ConfigUnquotedString(str):

def __init__(self, value):
super(ConfigUnquotedString, self).__init__(value)


class ConfigSlashString(str):

def __init__(self, value):
super(ConfigUnquotedString, self).__init__(value)
6 changes: 3 additions & 3 deletions pyhocon/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def to_yaml(config, level=0):
bet_lines = []
for key, item in config.items():
bet_lines.append('{indent}{key}: {value}'.format(
indent=''.rjust((level + 1) * 2, ' '),
indent=''.rjust(level * 2, ' '),
key=key,
value=HOCONConverter.to_yaml(item, level + 1))
)
Expand All @@ -77,15 +77,15 @@ def to_yaml(config, level=0):
lines += '\n'
bet_lines = []
for item in config_list:
bet_lines.append('{indent}- {value}'.format(indent=''.rjust((level + 1) * 2, ' '), value=HOCONConverter.to_yaml(item, level + 1)))
bet_lines.append('{indent}- {value}'.format(indent=''.rjust(level * 2, ' '), value=HOCONConverter.to_yaml(item, level + 1)))
lines += '\n'.join(bet_lines)
elif isinstance(config, str):
# if it contains a \n then it's multiline
lines = config.split('\n')
if len(lines) == 1:
lines = config
else:
lines = '|\n' + '\n'.join([line.rjust((level + 1) * 2, ' ') for line in lines])
lines = '|\n' + '\n'.join([line.rjust(level * 2, ' ') for line in lines])
elif config is True:
lines = 'true'
elif config is False:
Expand Down
2 changes: 1 addition & 1 deletion samples/database.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
enable_logging = false
resolver = null
# you can use substitution with unquoted strings. If it it not found in the document, it defaults to environment variables
home_dir = ${HOME}
home_dir = ${HOME} # you can substitute with environment variables
"mysql" = {
host = "abc.com" # change it
port = 3306 # default
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name='pyhocon',
version='0.1.4',
version='0.1.5',
description='HOCON parser for Python',
long_description='pyhocon is a HOCON parser for Python. Additionally we provide a tool (pyhocon) to convert any HOCON content into json, yaml and properties format.',
keywords='hocon parser',
Expand Down
2 changes: 2 additions & 0 deletions tests/test_config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def test_parse_simple_value(self):
\"\"\"
}
j = [1, 2, 3]
u = 192.168.1.3/32
}
"""
)
Expand All @@ -30,6 +31,7 @@ def test_parse_simple_value(self):
assert config.get_bool('t.d') is True
assert config.get_int('t.e.y.f') == 7
assert config.get('t.j') == [1, 2, 3]
assert config.get('t.u') == '192.168.1.3/32'

def test_parse_with_enclosing_brace(self):
config = ConfigFactory.parse_string(
Expand Down

0 comments on commit 0f54c90

Please sign in to comment.