Skip to content

Commit

Permalink
Allow comments before parameter definition #976
Browse files Browse the repository at this point in the history
  • Loading branch information
Bo Peng committed May 30, 2018
1 parent 5bf8319 commit 73bffa1
Showing 1 changed file with 89 additions and 12 deletions.
101 changes: 89 additions & 12 deletions src/sos/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def __init__(self, context: Optional['SoS_ScriptContent'] = None,
self.names = [] if names is None else names
self.comment = ''
self.comment_ended = False
self.other_comment = ''
# everything before step process
self.statements = []
self.global_parameters = {}
Expand Down Expand Up @@ -322,13 +323,58 @@ def extend(self, line: str) -> None:

def add_comment(self, line: str) -> None:
'''Add comment line'''
if self.empty() and not self.comment_ended:
self.comment += (' ' if self.comment else '') + \
line.lstrip('#').strip()
# case 1:
#
# [10]
# #
# # <- self.empty, not ended
#
# case 2:
#
# [10]
# #
# #
#
# # <- self.empty, ended
#
#
if self.empty():
if self.comment_ended:
# belong to others
self.other_comment += (' ' if self.other_comment else '') + \
line.lstrip('#').strip()
else:
self.comment += (' ' if self.comment else '') + \
line.lstrip('#').strip()
# case 3:
#
# [10]
# #
# input:
# # <- not self.empty, not ended
#
# case 4:
#
# [10]
# #
# #
#
# # <- not self.empty, ended
else:
if self.comment_ended:
# replace with new comment
self.other_comment = line.lstrip('#').strip()
else:
self.other_comment += (' ' if self.other_comment else '') + \
line.lstrip('#').strip()
self.comment_ended = False

def end_comment(self) -> None:
if self.comment_ended:
self.other_comment = ''
self.comment_ended = True


def add_directive(self, key: Optional[str], value: str, lineno: Optional[int] = None) -> None:
'''Assignments are items with ':' type '''
if key is None:
Expand All @@ -339,10 +385,11 @@ def add_directive(self, key: Optional[str], value: str, lineno: Optional[int] =
self._action_options += value
else:
# new directive, the comment before it are used
self.statements.append([':', key, value])
self.statements.append([':', key, value, self.other_comment])
self.values = [value]
if lineno:
self.lineno = lineno
self.other_comment = ''

def add_script(self, key: str, value: str, lineno: Optional[int] = None) -> None:
'''script starts with key: value'''
Expand All @@ -354,6 +401,7 @@ def add_script(self, key: str, value: str, lineno: Optional[int] = None) -> None
self._action_options = value
if lineno:
self.lineno = lineno
self.other_comment = ''

def add_statement(self, line: str, lineno: Optional[int] = None) -> None:
'''statements are regular python statements'''
Expand All @@ -368,6 +416,7 @@ def add_statement(self, line: str, lineno: Optional[int] = None) -> None:
self.statements.append(['!', line])
if lineno:
self.lineno = lineno
self.other_comment = ''

def wrap_script(self) -> None:
'''convert action: script to task: action(script)'''
Expand Down Expand Up @@ -453,7 +502,7 @@ def finalize(self) -> None:
f'{self.step_name()}: Invalid parameter definition: {statement[2]}')
self.statements[idx] = ['!',
f'if "sos_handle_parameter_" in globals():\n {name} = sos_handle_parameter_({name.strip()!r}, {value})\n', statement[2].strip()]
self.parameters[name] = value
self.parameters[name] = (value, statement[3])
# handle tasks
task_directive = [idx for idx, statement in enumerate(
self.statements) if statement[0] == ':' and statement[1] == 'task']
Expand Down Expand Up @@ -523,8 +572,21 @@ def show(self):
x: y for x, y in self.parameters.items() if x not in self.global_parameters}
if local_parameters:
print(' Parameters:')
for name, value in local_parameters.items():
print(f' --{name:15} {value.strip()}')
for name, (value, comment) in local_parameters.items():
par_str = f' --{name} {value.strip()}'
if len(par_str) > 24:
print(par_str)
if comment:
print('\n'.join(textwrap.wrap(comment,
width=textWidth,
initial_indent=' '*24,
subsequent_indent=' ' * 24)))
else:
print(par_str + '\n'.join(textwrap.wrap(comment,
width=textWidth,
initial_indent=' '*(24 - len(par_str)),
subsequent_indent=' ' * 24)))



class SoS_Workflow:
Expand Down Expand Up @@ -1015,6 +1077,7 @@ def _read(self, fp: TextIOBase) -> None:
f'FOLLOW\t{lineno}\t{line}')
else:
# ignored.
cursect.add_comment(line)
if self.transcript:
self.transcript.write(f'FOLLOW\t{lineno}\t{line}')
continue
Expand All @@ -1026,8 +1089,7 @@ def _read(self, fp: TextIOBase) -> None:
else:
if cursect.category() in ('statements', 'script'):
cursect.extend(line)
elif cursect.comment:
cursect.end_comment()
cursect.end_comment()
if self.transcript:
self.transcript.write(f'FOLLOW\t{lineno}\t{line}')
continue
Expand Down Expand Up @@ -1361,14 +1423,16 @@ def workflow(self, workflow_name: Optional[str] = None, use_default: bool = True

def print_help(self, script_name: str):
'''print a help message from the script'''
textWidth = max(60, shutil.get_terminal_size((80, 20)).columns)

if len(script_name) > 20:
print(f'usage: sos run {script_name}')
print(' [workflow_name] [options] [workflow_options]')
else:
print(f'usage: sos run {script_name} [workflow_name] [options] [workflow_options]')
print(' workflow_name: Single or combined workflows defined in this script')
print(' options: Single-hyphen sos parameters (see "sos run -h" for details)')
print(' workflow_options: Double-hyphen workflow-specific parameters\n')
print(' workflow_options: Double-hyphen workflow-specific parameters')
description = [x.lstrip('# ').strip() for x in self.description]
description = textwrap.dedent('\n'.join(description)).strip()
if description:
Expand All @@ -1382,8 +1446,21 @@ def print_help(self, script_name: str):
global_parameters.update(section.global_parameters)
if global_parameters:
print('\nGlobal Parameters:')
for k, v in global_parameters.items():
print(f' --{k:19} {v.strip()}')
for name, (value,comment) in global_parameters.items():
par_str = f' --{name} {value.strip()}'
if len(par_str) > 24:
print(par_str)
if comment:
print('\n'.join(textwrap.wrap(comment,
width=textWidth,
initial_indent=' '*24,
subsequent_indent=' ' * 24)))
else:
print(par_str + '\n'.join(textwrap.wrap(comment,
width=textWidth,
initial_indent=' '*(24 - len(par_str)),
subsequent_indent=' ' * 24)))

print('\nSections')
for section in self.sections:
section.show()

0 comments on commit 73bffa1

Please sign in to comment.