Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep comments #27

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions hjson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
__author__ = 'Christian Zangl <[email protected]>'

from decimal import Decimal
import re

from .scanner import HjsonDecodeError
from .decoder import HjsonDecoder
Expand Down Expand Up @@ -640,3 +641,137 @@ def simple_first(kv):
elements to the top, then container elements.
"""
return (isinstance(kv[1], (list, dict, tuple)), kv[0])


def loadWithComments(fp, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None,
object_pairs_hook=None, use_decimal=False, **kw):
"""
returns Tuple[Dict[str, Any], List[Tuple[str, str, str, int]]]
A tuple containing the comment,
the previous line's text,
the next line's text,
the string index of the comment
"""
jsonString = fp.read()
return loadsWithComments(jsonString, encoding=encoding, cls=cls, object_hook=object_hook, parse_float=parse_float,
parse_int=parse_int, object_pairs_hook=object_pairs_hook, use_decimal=use_decimal, **kw)


def loadsWithComments(jsonString, encoding=None, cls=None, object_hook=None, parse_float=None,
parse_int=None, object_pairs_hook=None, use_decimal=False, **kw):
"""
returns Tuple[Dict[str, Any], List[Tuple[str, str, str, int]]]
A tuple containing the comment,
the previous line's text,
the next line's text,
the string index of the comment
"""

jsonObject = loads(jsonString, encoding=encoding, cls=cls, object_hook=object_hook, parse_float=parse_float,
parse_int=parse_int, object_pairs_hook=object_pairs_hook, use_decimal=use_decimal, **kw)

commentPositions = []
comments = re.findall(r"(\s+//.*)|(\s+#.*)|(\s+/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)", jsonString)
for found in comments:
for comment in found:
if comment != '':
prevLine = ''
nextLine = ''
commentIndex = jsonString.find(comment)
commentEndIndex = commentIndex + len(comment)

prevNewLineIndex = jsonString.rfind('\n', 0, commentIndex + 1)
prevNewLineIndex = 0 if prevNewLineIndex == -1 else prevNewLineIndex
prevPrevNewLineIndex = jsonString.rfind('\n', 0, prevNewLineIndex)
prevPrevNewLineIndex = 0 if prevPrevNewLineIndex == -1 else prevPrevNewLineIndex
if prevNewLineIndex == 0 and prevPrevNewLineIndex == 0:
prevLine = '{'
else:
prevLine = jsonString[prevPrevNewLineIndex:prevNewLineIndex]
prevLine = prevLine.replace('\n', '')

nextNewLineIndex = jsonString.find('\n', commentEndIndex)
nextNewLineIndex = len(jsonString) if nextNewLineIndex == -1 else nextNewLineIndex
nextNextNewLineIndex = jsonString.find('\n', nextNewLineIndex + 1)
nextNextNewLineIndex = len(jsonString) if nextNextNewLineIndex == -1 else nextNextNewLineIndex
if nextNewLineIndex == len(jsonString) and nextNextNewLineIndex == len(jsonString):
nextLine = '}'
else:
nextLine = jsonString[nextNewLineIndex:nextNextNewLineIndex]
nextLine = nextLine.replace('\n', '')

commentPositions.append((comment[1:], prevLine, nextLine, commentIndex))
if comment != '':
prevLine = ''
nextLine = ''
commentIndex = jsonString.find(comment)
commentEndIndex = commentIndex + len(comment)

prevNewLineIndex = jsonString.rfind('\n', 0, commentIndex + 1)
prevNewLineIndex = 0 if prevNewLineIndex == -1 else prevNewLineIndex
prevPrevNewLineIndex = jsonString.rfind('\n', 0, prevNewLineIndex)
prevPrevNewLineIndex = 0 if prevPrevNewLineIndex == -1 else prevPrevNewLineIndex
if prevNewLineIndex == 0 and prevPrevNewLineIndex == 0:
prevLine = '{'
else:
prevLine = jsonString[prevPrevNewLineIndex:prevNewLineIndex]
prevLine = prevLine.replace('\n', '')

nextNewLineIndex = jsonString.find('\n', commentEndIndex)
nextNewLineIndex = len(jsonString) if nextNewLineIndex == -1 else nextNewLineIndex
nextNextNewLineIndex = jsonString.find('\n', nextNewLineIndex + 1)
nextNextNewLineIndex = len(jsonString) if nextNextNewLineIndex == -1 else nextNextNewLineIndex
if nextNewLineIndex == len(jsonString) and nextNextNewLineIndex == len(jsonString):
nextLine = '}'
else:
nextLine = jsonString[nextNewLineIndex:nextNextNewLineIndex]
nextLine = nextLine.replace('\n', '')

commentPositions.append((comment[1:], prevLine, nextLine, commentIndex))

return jsonObject, commentPositions


def dumpWithComments(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, cls=None, indent=None,
encoding='utf-8', default=None, use_decimal=True, namedtuple_as_object=True, tuple_as_array=True,
bigint_as_string=False, sort_keys=False, item_sort_key=None, for_json=False,
int_as_string_bitcount=None, **kw):

hjsonString = dumpsWithComments(obj, skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
cls=cls, encoding=encoding, default=default, use_decimal=use_decimal,
namedtuple_as_object=namedtuple_as_object, tuple_as_array=tuple_as_array,
bigint_as_string=bigint_as_string, sort_keys=sort_keys, item_sort_key=item_sort_key,
for_json=for_json, int_as_string_bitcount=int_as_string_bitcount, **kw)
fp.write(hjsonString)


def dumpsWithComments(obj, commentPositions, skipkeys=False, ensure_ascii=True, check_circular=True,
cls=None, encoding='utf-8', default=None, use_decimal=True, namedtuple_as_object=True,
tuple_as_array=True, bigint_as_string=False, sort_keys=False, item_sort_key=None,
for_json=False, int_as_string_bitcount=None, **kw):

hjsonString = dumps(obj, skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
cls=cls, encoding=encoding, default=default, use_decimal=use_decimal,
namedtuple_as_object=namedtuple_as_object, tuple_as_array=tuple_as_array,
bigint_as_string=bigint_as_string, sort_keys=sort_keys, item_sort_key=item_sort_key,
for_json=for_json, int_as_string_bitcount=int_as_string_bitcount, indent=' ', **kw)
prevPrevLineIndex = 0
prevNextLineIndex = 0
for comments in commentPositions:
comment = comments[0]
prevLine = comments[1]
commentIndex = comments[3]
if ':' in prevLine:
prevLine = prevLine[:prevLine.find(':') + 1]
nextLine = comments[2]
if ':' in nextLine:
nextLine = nextLine[:nextLine.find(':') + 1]
# Find where previous line begins
prevLineIndex = hjsonString.rfind(prevLine, prevPrevLineIndex, commentIndex)
# Find next \n char after previous line beginning
newlineCharAfterPrevLineIndex = hjsonString.find('\n', prevLineIndex)
nextLineIndex = hjsonString.find(nextLine, prevNextLineIndex)
hjsonString = hjsonString[:newlineCharAfterPrevLineIndex + 1] + comment + '\n' + hjsonString[nextLineIndex:]
prevPrevLineIndex = prevLineIndex
prevNextLineIndex = nextLineIndex
return hjsonString