Source code for pythonkss.comment
import codecs
import re
single_line_re = re.compile(r'^\s*\/\/')
single_line_strip_re = re.compile(r'\s*\/\/')
multi_line_start_re = re.compile(r'^\s*\/\*')
multi_line_end_re = re.compile(r'.*\*\/')
multi_line_start_strip_re = re.compile(r'\s*\/\*')
multi_line_end_strip_re = re.compile(r'\*\/')
multi_line_middle_strip_re = re.compile(r'^(\s*\*+)')
preceding_white_space_re = re.compile(r'^\s*')
def is_single_line_comment(line):
return single_line_re.match(line) is not None
def is_multi_line_comment_start(line):
return multi_line_start_re.match(line) is not None
def is_multi_line_comment_end(line):
if is_single_line_comment(line):
return False
return multi_line_end_re.match(line) is not None
def parse_single_line(line):
return single_line_strip_re.sub('', line).rstrip()
def parse_multi_line(line):
cleaned = multi_line_start_strip_re.sub('', line)
return multi_line_end_strip_re.sub('', cleaned).rstrip()
def normalize(lines):
cleaned = []
indents = []
for line in lines:
line = multi_line_middle_strip_re.sub('', line)
cleaned.append(line)
match = preceding_white_space_re.match(line)
if line:
indents.append(len(match.group()))
indent = min(indents) if indents else 0
return '\n'.join([l[indent:] for l in cleaned]).strip()
[docs]class CommentParser(object):
"""
The comment parser.
Takes a filename, and parses it into a list of comment blocks.
Used by :class:`pythonkss.parser.Parser`.
"""
def __init__(self, filename, variablemap=None):
"""
Args:
filename: The path to a style file.
variablemap (dict): Maps variable substitution strings to values.
We replace all occurrences of each key with the value in all parsed
comments.
"""
self.filename = filename
self.variablemap = variablemap
def _apply_variables_to_commentblock(self, commentblock):
for key, value in self.variablemap.items():
commentblock = commentblock.replace(key, value)
return commentblock
def _apply_variables_to_commentblocks(self, commentblocks):
commentblocks_with_variables_applied = []
for commentblock in commentblocks:
commentblocks_with_variables_applied.append(
self._apply_variables_to_commentblock(commentblock=commentblock))
return commentblocks_with_variables_applied
[docs] def parse(self):
"""
Parse the file and collect comment blocks in a list.
Returns:
list: Comment blocks list.
"""
blocks = []
current_block = []
inside_single_line_block = False
inside_multi_line_block = False
with codecs.open(self.filename, 'r', 'utf-8') as fileobj:
for line in fileobj:
# Parse single-line style
if is_single_line_comment(line) and not inside_multi_line_block:
parsed = parse_single_line(line)
if inside_single_line_block:
current_block.append(parsed)
else:
current_block = [parsed]
inside_single_line_block = True
# Prase multi-line style
if is_multi_line_comment_start(line) or inside_multi_line_block:
parsed = parse_multi_line(line)
if inside_multi_line_block:
current_block.append(parsed)
else:
current_block = [parsed]
inside_multi_line_block = True
# End a multi-line block if detected
if is_multi_line_comment_end(line):
inside_multi_line_block = False
# Store the current block if we're done
if is_single_line_comment(line) is False and inside_multi_line_block is False:
if current_block:
blocks.append(normalize(current_block))
inside_single_line_block = False
current_block = []
if self.variablemap:
blocks = self._apply_variables_to_commentblocks(commentblocks=blocks)
return blocks
@property
def blocks(self):
"""
Property that returns a list of comment blocks in the file.
Parses the file using :meth:`.parse` the first time it is called.
"""
if not hasattr(self, '_blocks'):
self._blocks = self.parse()
return self._blocks