Skip to content

Commit

Permalink
Even more refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Matistjati committed Aug 18, 2024
1 parent 194c7b1 commit 554892a
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 126 deletions.
2 changes: 1 addition & 1 deletion problemtools/md2html.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def convert(problem: str, options: argparse.Namespace) -> bool:
with open("problem.css", "w") as output_file:
with open(os.path.join(templatepath, "problem.css"), "r") as input_file:
output_file.write(input_file.read())

return True


Expand Down
117 changes: 65 additions & 52 deletions problemtools/problem2pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,80 +12,93 @@

def convert(options: argparse.Namespace) -> bool:
problem_root = os.path.realpath(options.problem)

if statement_common.find_statement_extension(problem_root, language=options.language) == "md":
return md2pdf(options)
else:
return latex2pdf(options)


def md2pdf(options: argparse.Namespace) -> bool:
problem_root = os.path.realpath(options.problem)
problembase = os.path.splitext(os.path.basename(problem_root))[0]
destfile = string.Template(options.destfile).safe_substitute(problem=problembase)

if statement_common.find_statement_extension(problem_root, language=options.language) == "md":
statement_path = statement_common.find_statement(problem_root, extension="md", language=options.language)
statement_path = statement_common.find_statement(problem_root, extension="md", language=options.language)

if not os.path.isfile(statement_path):
raise Exception(f"Error! {statement_path} is not a file")
if not os.path.isfile(statement_path):
raise Exception(f"Error! {statement_path} is not a file")

templatepaths = [os.path.join(os.path.dirname(__file__), 'templates/markdown_pdf'),
os.path.join(os.path.dirname(__file__), '../templates/markdown_pdf'),
'/usr/lib/problemtools/templates/markdown_pdf']
templatepath = next((p for p in templatepaths
if os.path.isdir(p) and os.path.isfile(os.path.join(p, "fix_tables.md"))),
None)
table_fix_path = os.path.join(templatepath, "fix_tables.md")
if not os.path.isfile(table_fix_path):
raise Exception("Could not find markdown pdf template")
templatepaths = [os.path.join(os.path.dirname(__file__), 'templates/markdown_pdf'),
os.path.join(os.path.dirname(__file__), '../templates/markdown_pdf'),
'/usr/lib/problemtools/templates/markdown_pdf']
templatepath = next((p for p in templatepaths
if os.path.isdir(p) and os.path.isfile(os.path.join(p, "fix_tables.md"))),
None)
table_fix_path = os.path.join(templatepath, "fix_tables.md")
if not os.path.isfile(table_fix_path):
raise Exception("Could not find markdown pdf template")

with open(table_fix_path, "r") as file:
table_fix = file.read()
with open(table_fix_path, "r") as file:
table_fix = file.read()

statement_dir = os.path.join(problem_root, "problem_statement")
with open(statement_path, "r") as file:
statement_md = file.read()
statement_dir = os.path.join(problem_root, "problem_statement")
with open(statement_path, "r") as file:
statement_md = file.read()

problem_name = statement_common.get_problem_name(problem_root, options.language)
problem_name = statement_common.get_problem_name(problem_root, options.language)

# Add code that adds vertical and horizontal lines to all tables
statement_md = r'\centerline{\huge %s}' % problem_name + statement_md
statement_md = table_fix + statement_md
# Add code that adds vertical and horizontal lines to all tables
statement_md = r'\centerline{\huge %s}' % problem_name + statement_md
statement_md = table_fix + statement_md

# Hacky: html samples -> md. Then we append to the markdown document
samples = "\n".join(statement_common.format_samples(problem_root, to_pdf=True))
samples = "\n".join(statement_common.format_samples(problem_root, to_pdf=True))

# If we don't add newline, the table might get attached to a footnote
statement_md += "\n" + samples
# If we don't add newline, the topmost table might get attached to a footnote
statement_md += "\n" + samples

with tempfile.NamedTemporaryFile(mode='w', suffix=".md") as temp_file:
temp_file.write(statement_md)
temp_file.flush()
command = ["pandoc", temp_file.name, "-o", f"{problembase}.pdf", f"--resource-path={statement_dir}"]
return subprocess.run(command, capture_output=True, text=True, shell=False, check=True)
with tempfile.NamedTemporaryFile(mode='w', suffix=".md") as temp_file:
temp_file.write(statement_md)
temp_file.flush()
command = ["pandoc", temp_file.name, "-o", destfile, f"--resource-path={statement_dir}"]
return subprocess.run(command, capture_output=True, text=True, shell=False, check=True)

else:
# Set up template if necessary
with template.Template(problem_root, language=options.language) as templ:
texfile = templ.get_file_name()

origcwd = os.getcwd()
def latex2pdf(options: argparse.Namespace) -> bool:
problem_root = os.path.realpath(options.problem)
problembase = os.path.splitext(os.path.basename(problem_root))[0]
destfile = string.Template(options.destfile).safe_substitute(problem=problembase)

os.chdir(os.path.dirname(texfile))
params = ['pdflatex', '-interaction=nonstopmode']
output = None
if options.quiet:
output = open(os.devnull, 'w')
if options.nopdf:
params.append('-draftmode')
# Set up template if necessary
with template.Template(problem_root, language=options.language) as templ:
texfile = templ.get_file_name()

params.append(texfile)
origcwd = os.getcwd()

os.chdir(os.path.dirname(texfile))
params = ['pdflatex', '-interaction=nonstopmode']
output = None
if options.quiet:
output = open(os.devnull, 'w')
if options.nopdf:
params.append('-draftmode')

params.append(texfile)

status = subprocess.call(params, stdout=output)
if status == 0:
status = subprocess.call(params, stdout=output)
if status == 0:
status = subprocess.call(params, stdout=output)

if output is not None:
output.close()
if output is not None:
output.close()

os.chdir(origcwd)

os.chdir(origcwd)
if status == 0 and not options.nopdf:
shutil.move(os.path.splitext(texfile)[0] + '.pdf', destfile)

if status == 0 and not options.nopdf:
shutil.move(os.path.splitext(texfile)[0] + '.pdf', destfile)
return status == 0

return status == 0

def get_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
Expand Down
181 changes: 108 additions & 73 deletions problemtools/statement_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,55 +82,7 @@ def format_samples(problem_root: str, to_pdf: bool = False) -> List[str]:
casenum = 1
for sample in sorted(os.listdir(sample_path)):
if sample.endswith(".interaction"):
if to_pdf:
line = r"""\begin{tabular}{p{0.3\textwidth} p{0.5\textwidth} p{0.0\textwidth}}
\textbf{Read} & \textbf{Sample Interaction %i} & \textbf{Write} \\
\end{tabular}""" % casenum
else:
line = f"""
<table class="sample" summary="sample data">
<tr>
<th style="text-align:left; width:33%;">Read</th>
<th style="text-align:center; width:33%;">Sample Interaction {casenum}</th>
<th style="text-align:right; width:33%;">Write</th>
</tr>
</table>"""

with open(os.path.join(sample_path, sample), "r", encoding="utf-8") as infile:
sample_interaction = infile.readlines()
lines = []
for interaction in sample_interaction:
data = interaction[1:]
if to_pdf:
if interaction[0] == '>':
left = True
elif interaction[0] == '<':
left = False
else:
print(f"Warning: Interaction had unknown prefix {interaction[0]}")
lines.append(r"""
\begin{table}[H]
%(justify)s\begin{tabular}{|p{0.6\textwidth}|}
\hline
%(text)s \\
\hline
\end{tabular}
\end{table}""" % {"justify": "" if left else "\\hspace*{\\fill}\n",
"text": data})
else:
line_type = ""
if interaction[0] == '>':
line_type = "sampleinteractionwrite"
elif interaction[0] == '<':
line_type = "sampleinteractionread"
else:
print(f"Warning: Interaction had unknown prefix {interaction[0]}")
lines.append(f"""<div class="{line_type}"><pre>{data}</pre></div>""")

if to_pdf:
samples.append(line + '\\vspace{-15pt}'.join(lines))
else:
samples.append(line + ''.join(lines))
samples.append(format_interactive_sample(sample_path, sample, casenum, to_pdf))
casenum += 1
continue

Expand All @@ -140,35 +92,118 @@ def format_samples(problem_root: str, to_pdf: bool = False) -> List[str]:
outpath = os.path.join(sample_path, sample_name + ".ans")
if not os.path.isfile(outpath):
continue
with open(os.path.join(sample_path, sample), "r", encoding="utf-8") as infile:
sample_input = infile.read()
with open(outpath, "r", encoding="utf-8") as outfile:
sample_output = outfile.read()

samples.append("""
samples.append(format_normal_sample(sample_path, sample, casenum, to_pdf))
casenum += 1

return samples


def format_normal_sample(sample_root: str, sample: str, casenum: int, to_pdf: bool) -> str:
"""
Args:
sample_root: root of the sample folder
sample: file name of the sample
casenum: which sample is this? (1, 2, 3...)
to_pdf: do we target pdf or html output
Returns:
str: the sample, ready to be pasted into a markdown doc and fed to pandoc
"""

with open(os.path.join(sample_root, sample), "r", encoding="utf-8") as infile:
sample_input = infile.read()
sample_name = sample[:-3]
outpath = os.path.join(sample_root, sample_name + ".ans")
with open(outpath, "r", encoding="utf-8") as outfile:
sample_output = outfile.read()

sample = """
<table class="sample" summary="sample data">
<tbody>
<tr>
<th>Sample Input %(case)d</th>
<th>Sample Output %(case)d</th>
</tr>
<tr>
<td><pre>%(input)s</pre></td>
<td><pre>%(output)s</pre></td>
</tr>
</tbody>
</table>""" % ({"case": casenum, "input": html.escape(sample_input),
"output": html.escape(sample_output)})

if to_pdf:
# If pdf, convert to markdown
with tempfile.NamedTemporaryFile(mode='w', suffix=".html") as temp_file:
temp_file.write(sample)
temp_file.flush()
command = ["pandoc", temp_file.name, "-t" , "markdown"]
return subprocess.run(command, capture_output=True, text=True,
shell=False, check=True).stdout
else:
return sample


def format_interactive_sample(sample_root: str, sample: str, casenum: int, to_pdf: bool) -> str:
"""
Args:
sample_root: root of the sample folder
sample: file name of the sample
casenum: which sample is this? (1, 2, 3...)
to_pdf: do we target pdf or html output
Returns:
str: the sample, ready to be pasted into a markdown doc and fed to pandoc
"""
if to_pdf:
line = r"""\begin{tabular}{p{0.3\textwidth} p{0.5\textwidth} p{0.0\textwidth}}
\textbf{Read} & \textbf{Sample Interaction %i} & \textbf{Write} \\
\end{tabular}""" % casenum
else:
line = f"""
<table class="sample" summary="sample data">
<tbody>
<tr>
<th>Sample Input %(case)d</th>
<th>Sample Output %(case)d</th>
<th style="text-align:left; width:33%;">Read</th>
<th style="text-align:center; width:33%;">Sample Interaction {casenum}</th>
<th style="text-align:right; width:33%;">Write</th>
</tr>
<tr>
<td><pre>%(input)s</pre></td>
<td><pre>%(output)s</pre></td>
</tr>
</tbody>
</table>"""
% ({"case": casenum, "input": html.escape(sample_input), "output": html.escape(sample_output)}))

with open(os.path.join(sample_root, sample), "r", encoding="utf-8") as infile:
sample_interaction = infile.readlines()
lines = []
for interaction in sample_interaction:
data = interaction[1:]
if to_pdf:
# If pdf, convert to markdown
with tempfile.NamedTemporaryFile(mode='w', suffix=".html") as temp_file:
temp_file.write(samples[-1])
temp_file.flush()
command = ["pandoc", temp_file.name, "-t" , "markdown"]
samples[-1] = subprocess.run(command, capture_output=True, text=True,
shell=False, check=True).stdout

casenum += 1
if interaction[0] == '>':
left = True
elif interaction[0] == '<':
left = False
else:
print(f"Warning: Interaction had unknown prefix {interaction[0]}")
lines.append(r"""
\begin{table}[H]
%(justify)s\begin{tabular}{|p{0.6\textwidth}|}
\hline
%(text)s \\
\hline
\end{tabular}
\end{table}""" % {"justify": "" if left else "\\hspace*{\\fill}\n",
"text": data})
else:
line_type = ""
if interaction[0] == '>':
line_type = "sampleinteractionwrite"
elif interaction[0] == '<':
line_type = "sampleinteractionread"
else:
print(f"Warning: Interaction had unknown prefix {interaction[0]}")
lines.append(f"""<div class="{line_type}"><pre>{data}</pre></div>""")

return samples
if to_pdf:
return line + '\\vspace{-15pt}'.join(lines)
else:
return line + ''.join(lines)

0 comments on commit 554892a

Please sign in to comment.