Clean code with black and create setup.py.
This commit is contained in:
parent
833d16752a
commit
6a65529e06
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
*~
|
*~
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
|
**/.mypy_cache
|
||||||
|
*.egg-info
|
||||||
|
@ -17,26 +17,25 @@ class CompileResult(enum.Enum):
|
|||||||
|
|
||||||
class documentclass(element):
|
class documentclass(element):
|
||||||
|
|
||||||
classname = 'standalone'
|
classname = "standalone"
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'package': '\\usepackage{pkgoptions}{{{pkgname}}}',
|
"package": "\\usepackage{pkgoptions}{{{pkgname}}}",
|
||||||
'options': '[{content}]',
|
"options": "[{content}]",
|
||||||
'def': '\\def\\{name}{nargs}{{{value}}}',
|
"def": "\\def\\{name}{nargs}{{{value}}}",
|
||||||
'content': """\\documentclass{options}{{{classname}}}
|
"content": """\\documentclass{options}{{{classname}}}
|
||||||
{packages}
|
{packages}
|
||||||
{preamble}
|
{preamble}
|
||||||
\\begin{{document}}
|
\\begin{{document}}
|
||||||
{content}
|
{content}
|
||||||
\\end{{document}}
|
\\end{{document}}
|
||||||
"""
|
""",
|
||||||
}
|
}
|
||||||
|
|
||||||
output_aux_folder = '.pyltk'
|
output_aux_folder = ".pyltk"
|
||||||
auto_tex_folder_name = 'tex2pdf'
|
auto_tex_folder_name = "tex2pdf"
|
||||||
|
|
||||||
def __init__(self, classname, childrens=[], options=[],
|
def __init__(self, classname, childrens=[], options=[], packages=[], preamble=[]):
|
||||||
packages=[], preamble=[]):
|
|
||||||
super().__init__(parent=None, childrens=childrens)
|
super().__init__(parent=None, childrens=childrens)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.classname = classname
|
self.classname = classname
|
||||||
@ -60,38 +59,44 @@ class documentclass(element):
|
|||||||
self.preamble.append(value)
|
self.preamble.append(value)
|
||||||
|
|
||||||
def add_def(self, name, nargs, value):
|
def add_def(self, name, nargs, value):
|
||||||
self.preamble.append(self.fmt().format('def', {
|
self.preamble.append(
|
||||||
'name': name,
|
self.fmt().format(
|
||||||
'nargs': '#{}'.format(nargs) if nargs > 0 else '',
|
"def",
|
||||||
'value': value
|
{
|
||||||
}))
|
"name": name,
|
||||||
|
"nargs": "#{}".format(nargs) if nargs > 0 else "",
|
||||||
|
"value": value,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def format_preamble(self, defs):
|
def format_preamble(self, defs):
|
||||||
return '\n'.join(str(p) for p in self.preamble)
|
return "\n".join(str(p) for p in self.preamble)
|
||||||
|
|
||||||
def format_packages(self, pkgs):
|
def format_packages(self, pkgs):
|
||||||
out = []
|
out = []
|
||||||
for pkg in sorted(pkgs):
|
for pkg in sorted(pkgs):
|
||||||
options = ''
|
options = ""
|
||||||
if pkgs[pkg] is not True:
|
if pkgs[pkg] is not True:
|
||||||
options = self.format_options(pkgs[pkg])
|
options = self.format_options(pkgs[pkg])
|
||||||
out.append(self.fmt().format('package', {
|
out.append(
|
||||||
'pkgname': pkg,
|
self.fmt().format("package", {"pkgname": pkg, "pkgoptions": options})
|
||||||
'pkgoptions': options
|
)
|
||||||
}))
|
return "\n".join(out)
|
||||||
return '\n'.join(out)
|
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'options': self.format_options(self.options),
|
"content",
|
||||||
'packages': self.format_packages(self.packages),
|
{
|
||||||
'preamble': self.format_preamble(self.preamble),
|
"options": self.format_options(self.options),
|
||||||
'classname': self.classname,
|
"packages": self.format_packages(self.packages),
|
||||||
'content': super().content()
|
"preamble": self.format_preamble(self.preamble),
|
||||||
})
|
"classname": self.classname,
|
||||||
|
"content": super().content(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def compile(self, outfile, infile='auto', outlog=None,
|
def compile(self, outfile, infile="auto", outlog=None, compile_twice=False):
|
||||||
compile_twice=False):
|
|
||||||
""" Compile the given document into a PDF file.
|
""" Compile the given document into a PDF file.
|
||||||
|
|
||||||
If infile is not None, and infile already exists, the document
|
If infile is not None, and infile already exists, the document
|
||||||
@ -116,55 +121,62 @@ class documentclass(element):
|
|||||||
res = CompileResult.ERROR
|
res = CompileResult.ERROR
|
||||||
|
|
||||||
output_aux_folder = os.path.join(outdir, self.output_aux_folder)
|
output_aux_folder = os.path.join(outdir, self.output_aux_folder)
|
||||||
auto_tex_folder = os.path.join(output_aux_folder,
|
auto_tex_folder = os.path.join(output_aux_folder, self.auto_tex_folder_name)
|
||||||
self.auto_tex_folder_name)
|
|
||||||
|
|
||||||
# Make aux directory
|
# Make aux directory
|
||||||
os.makedirs(output_aux_folder, exist_ok=True)
|
os.makedirs(output_aux_folder, exist_ok=True)
|
||||||
|
|
||||||
# Remove extension if exists
|
# Remove extension if exists
|
||||||
if outfile.endswith('.pdf'):
|
if outfile.endswith(".pdf"):
|
||||||
outfile = outfile[:-4]
|
outfile = outfile[:-4]
|
||||||
|
|
||||||
to_delete = False
|
to_delete = False
|
||||||
|
|
||||||
if infile == 'auto':
|
if infile == "auto":
|
||||||
os.makedirs(auto_tex_folder, exist_ok=True)
|
os.makedirs(auto_tex_folder, exist_ok=True)
|
||||||
infile = '{}/{}.tex'.format(auto_tex_folder, outfile)
|
infile = "{}/{}.tex".format(auto_tex_folder, outfile)
|
||||||
|
|
||||||
if infile is None:
|
if infile is None:
|
||||||
to_delete = True
|
to_delete = True
|
||||||
infile = os.path.join(outdir, '.pyltk-{}.tex'.format(outfile))
|
infile = os.path.join(outdir, ".pyltk-{}.tex".format(outfile))
|
||||||
|
|
||||||
to_create = True
|
to_create = True
|
||||||
new_content = self.content()
|
new_content = self.content()
|
||||||
|
|
||||||
# If the input file already exists...
|
# If the input file already exists...
|
||||||
if os.path.exists(infile):
|
if os.path.exists(infile):
|
||||||
with open(infile, 'r') as infd:
|
with open(infile, "r") as infd:
|
||||||
old_content = infd.read()
|
old_content = infd.read()
|
||||||
|
|
||||||
# Content has not changed
|
# Content has not changed
|
||||||
if old_content == new_content \
|
if (
|
||||||
and os.path.exists(os.path.join(outdir, outfile) + '.pdf') \
|
old_content == new_content
|
||||||
and os.path.getctime(infile) <= \
|
and os.path.exists(os.path.join(outdir, outfile) + ".pdf")
|
||||||
os.path.getctime(os.path.join(outdir, outfile) + '.pdf'):
|
and os.path.getctime(infile)
|
||||||
|
<= os.path.getctime(os.path.join(outdir, outfile) + ".pdf")
|
||||||
|
):
|
||||||
to_create = False
|
to_create = False
|
||||||
|
|
||||||
if to_create:
|
if to_create:
|
||||||
with open(infile, 'w') as infd:
|
with open(infile, "w") as infd:
|
||||||
infd.write(self.content())
|
infd.write(self.content())
|
||||||
call = ['pdflatex', '-halt-on-error',
|
call = [
|
||||||
'-output-directory', output_aux_folder,
|
"pdflatex",
|
||||||
'-jobname', outfile, infile]
|
"-halt-on-error",
|
||||||
|
"-output-directory",
|
||||||
|
output_aux_folder,
|
||||||
|
"-jobname",
|
||||||
|
outfile,
|
||||||
|
infile,
|
||||||
|
]
|
||||||
res = subprocess.call(call, stdout=outlog)
|
res = subprocess.call(call, stdout=outlog)
|
||||||
if compile_twice:
|
if compile_twice:
|
||||||
res = subprocess.call(call, stdout=outlog)
|
res = subprocess.call(call, stdout=outlog)
|
||||||
if res == 0:
|
if res == 0:
|
||||||
os.replace(
|
os.replace(
|
||||||
os.path.join(
|
os.path.join(output_aux_folder, outfile + ".pdf"),
|
||||||
output_aux_folder, outfile + '.pdf'),
|
os.path.join(outdir, outfile + ".pdf"),
|
||||||
os.path.join(outdir, outfile + '.pdf'))
|
)
|
||||||
res = CompileResult.SUCCESS
|
res = CompileResult.SUCCESS
|
||||||
else:
|
else:
|
||||||
res = CompileResult.ERROR
|
res = CompileResult.ERROR
|
||||||
|
@ -18,7 +18,7 @@ class element:
|
|||||||
are no subclasses of `element`. """
|
are no subclasses of `element`. """
|
||||||
|
|
||||||
# Joiner for childrens
|
# Joiner for childrens
|
||||||
sep = '\n'
|
sep = "\n"
|
||||||
|
|
||||||
# Automatically add label after element if present
|
# Automatically add label after element if present
|
||||||
autolabel = True
|
autolabel = True
|
||||||
@ -26,8 +26,7 @@ class element:
|
|||||||
# Do not wrap non-element in wrapper_element
|
# Do not wrap non-element in wrapper_element
|
||||||
raw = False
|
raw = False
|
||||||
|
|
||||||
def __init__(self, parent=None, childrens=[], label=None,
|
def __init__(self, parent=None, childrens=[], label=None, raw=False, **kargs):
|
||||||
raw=False, **kargs):
|
|
||||||
""" Create a new element with given parameters.
|
""" Create a new element with given parameters.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -80,25 +79,25 @@ class element:
|
|||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
value = self.format_options_dict(value)
|
value = self.format_options_dict(value)
|
||||||
elif isinstance(value, list) or isinstance(value, tuple):
|
elif isinstance(value, list) or isinstance(value, tuple):
|
||||||
value = ','.join(value)
|
value = ",".join(value)
|
||||||
else:
|
else:
|
||||||
value = str(value).strip()
|
value = str(value).strip()
|
||||||
if value[0] == '{' and value[1] == '}':
|
if value[0] == "{" and value[1] == "}":
|
||||||
value = value[1:-1]
|
value = value[1:-1]
|
||||||
opts.append('{key}={{{value}}}'.format(key=k, value=value))
|
opts.append("{key}={{{value}}}".format(key=k, value=value))
|
||||||
return ', '.join(opts)
|
return ", ".join(opts)
|
||||||
|
|
||||||
def format_options(self, options):
|
def format_options(self, options):
|
||||||
if not options:
|
if not options:
|
||||||
return ''
|
return ""
|
||||||
return self.fmt().format('options', {
|
return self.fmt().format(
|
||||||
'content': self.format_options_dict(options)
|
"options", {"content": self.format_options_dict(options)}
|
||||||
})
|
)
|
||||||
|
|
||||||
def format_label(self, label):
|
def format_label(self, label):
|
||||||
if not label:
|
if not label:
|
||||||
return ''
|
return ""
|
||||||
return '\\label{{{}}}'.format(label)
|
return "\\label{{{}}}".format(label)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
out = self.content().strip()
|
out = self.content().strip()
|
||||||
@ -111,7 +110,7 @@ class wrapper_element(element):
|
|||||||
|
|
||||||
""" Wrapper for standard python types working as latex elements. """
|
""" Wrapper for standard python types working as latex elements. """
|
||||||
|
|
||||||
escape_list = ['_', '#', '%']
|
escape_list = ["_", "#", "%"]
|
||||||
|
|
||||||
def __init__(self, data, parent=None, autoescape=True):
|
def __init__(self, data, parent=None, autoescape=True):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@ -122,7 +121,7 @@ class wrapper_element(element):
|
|||||||
if not self.autoescape:
|
if not self.autoescape:
|
||||||
return s
|
return s
|
||||||
for e in self.escape_list:
|
for e in self.escape_list:
|
||||||
s = s.replace(e, '\\' + e)
|
s = s.replace(e, "\\" + e)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
|
@ -7,19 +7,25 @@ class figure(element):
|
|||||||
""" Class representing a latex figure. """
|
""" Class representing a latex figure. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'caption': '\\caption{{{content}}}',
|
"caption": "\\caption{{{content}}}",
|
||||||
'content': """\\begin{{figure}}[{options}]
|
"content": """\\begin{{figure}}[{options}]
|
||||||
{centered}
|
{centered}
|
||||||
{inner}
|
{inner}
|
||||||
{caption}{label}
|
{caption}{label}
|
||||||
\\end{{figure}}"""
|
\\end{{figure}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
autolabel = False
|
autolabel = False
|
||||||
|
|
||||||
def __init__(self, childrens=None, parent=None,
|
def __init__(
|
||||||
caption=None, options='!h',
|
self,
|
||||||
centered=True, label=None):
|
childrens=None,
|
||||||
|
parent=None,
|
||||||
|
caption=None,
|
||||||
|
options="!h",
|
||||||
|
centered=True,
|
||||||
|
label=None,
|
||||||
|
):
|
||||||
""" Create a figure with given options.
|
""" Create a figure with given options.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -29,18 +35,21 @@ class figure(element):
|
|||||||
super().__init__(parent, childrens, label=label)
|
super().__init__(parent, childrens, label=label)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.caption = caption
|
self.caption = caption
|
||||||
self.centered = ''
|
self.centered = ""
|
||||||
if centered:
|
if centered:
|
||||||
self.centered = '\\centering'
|
self.centered = "\\centering"
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
caption = ''
|
caption = ""
|
||||||
if self.caption:
|
if self.caption:
|
||||||
caption = self.fmt().format('caption', {'content': self.caption})
|
caption = self.fmt().format("caption", {"content": self.caption})
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'options': self.options,
|
"content",
|
||||||
'centered': self.centered,
|
{
|
||||||
'caption': caption,
|
"options": self.options,
|
||||||
'label': self.format_label(self.label),
|
"centered": self.centered,
|
||||||
'inner': super().content()
|
"caption": caption,
|
||||||
})
|
"label": self.format_label(self.label),
|
||||||
|
"inner": super().content(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
@ -7,8 +7,8 @@ class includegraphics(element):
|
|||||||
""" Class representing a latex includegrahics. """
|
""" Class representing a latex includegrahics. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'options': '[{content}]',
|
"options": "[{content}]",
|
||||||
'element': '\\includegraphics{options}{{{filename}}}'
|
"element": "\\includegraphics{options}{{{filename}}}",
|
||||||
}
|
}
|
||||||
|
|
||||||
autolabel = False
|
autolabel = False
|
||||||
@ -18,7 +18,7 @@ class includegraphics(element):
|
|||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('element', {
|
return self.fmt().format(
|
||||||
'filename': self.filename,
|
"element",
|
||||||
'options': self.format_options(self.options)
|
{"filename": self.filename, "options": self.format_options(self.options)},
|
||||||
})
|
)
|
||||||
|
@ -11,23 +11,19 @@ class inline_element(element):
|
|||||||
def __init__(self, content, parent=None):
|
def __init__(self, content, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.value = content
|
self.value = content
|
||||||
self.templates = {
|
self.templates = {"wrapper": self.wrapper}
|
||||||
'wrapper': self.wrapper
|
|
||||||
}
|
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('wrapper', {
|
return self.fmt().format("wrapper", {"value": self.value})
|
||||||
'value': self.value
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class it(inline_element):
|
class it(inline_element):
|
||||||
wrapper = '\\textit{{{value}}}'
|
wrapper = "\\textit{{{value}}}"
|
||||||
|
|
||||||
|
|
||||||
class bf(inline_element):
|
class bf(inline_element):
|
||||||
wrapper = '\\textbf{{{value}}}'
|
wrapper = "\\textbf{{{value}}}"
|
||||||
|
|
||||||
|
|
||||||
class mt(inline_element):
|
class mt(inline_element):
|
||||||
wrapper = '${value}$'
|
wrapper = "${value}$"
|
||||||
|
@ -5,15 +5,11 @@ from .element import element
|
|||||||
|
|
||||||
class input_element(element):
|
class input_element(element):
|
||||||
|
|
||||||
templates = {
|
templates = {"element": "\\input{{{filename}}}"}
|
||||||
'element': '\\input{{{filename}}}'
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, filename, parent=None):
|
def __init__(self, filename, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.filename = filename.replace('.tex', '')
|
self.filename = filename.replace(".tex", "")
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('element', {
|
return self.fmt().format("element", {"filename": self.filename})
|
||||||
'filename': self.filename
|
|
||||||
})
|
|
||||||
|
@ -6,10 +6,7 @@ from .element import element
|
|||||||
|
|
||||||
class generic_element(element):
|
class generic_element(element):
|
||||||
|
|
||||||
templates = {
|
templates = {"element": "\\{name}{options}{attributes}", "options": "[{content}]"}
|
||||||
'element': '\\{name}{options}{attributes}',
|
|
||||||
'options': '[{content}]'
|
|
||||||
}
|
|
||||||
|
|
||||||
autolabel = False
|
autolabel = False
|
||||||
|
|
||||||
@ -17,22 +14,23 @@ class generic_element(element):
|
|||||||
super().__init__(parent, **kargs)
|
super().__init__(parent, **kargs)
|
||||||
self.name = name
|
self.name = name
|
||||||
if not args:
|
if not args:
|
||||||
self.attributes = '{}'
|
self.attributes = "{}"
|
||||||
else:
|
else:
|
||||||
self.attributes = ''
|
self.attributes = ""
|
||||||
for arg in args:
|
for arg in args:
|
||||||
self.attributes += '{{{}}}'.format(arg)
|
self.attributes += "{{{}}}".format(arg)
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('element', {
|
return self.fmt().format(
|
||||||
'name': self.name,
|
"element",
|
||||||
'attributes': self.attributes,
|
{
|
||||||
'options': self.format_options(self.options)
|
"name": self.name,
|
||||||
})
|
"attributes": self.attributes,
|
||||||
|
"options": self.format_options(self.options),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class factory:
|
class factory:
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return lambda *args, **kargs: \
|
return lambda *args, **kargs: generic_element(name, *args, **kargs)
|
||||||
generic_element(name, *args, **kargs)
|
|
||||||
|
@ -7,7 +7,7 @@ class makebox(element):
|
|||||||
""" Class representing an unindented makebox. """
|
""" Class representing an unindented makebox. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'content': """{noindent}\\makebox[{width}]{{
|
"content": """{noindent}\\makebox[{width}]{{
|
||||||
{inner}
|
{inner}
|
||||||
}}"""
|
}}"""
|
||||||
}
|
}
|
||||||
@ -25,17 +25,20 @@ class makebox(element):
|
|||||||
|
|
||||||
self.width = width
|
self.width = width
|
||||||
if self.width is None:
|
if self.width is None:
|
||||||
self.width = '\\textwidth'
|
self.width = "\\textwidth"
|
||||||
elif type(self.width) != 'str':
|
elif type(self.width) != "str":
|
||||||
self.width = '{}\\textwidth'.format(self.width)
|
self.width = "{}\\textwidth".format(self.width)
|
||||||
|
|
||||||
self.noindent = ''
|
self.noindent = ""
|
||||||
if self.noindent:
|
if self.noindent:
|
||||||
self.noindent = '\\noindent'
|
self.noindent = "\\noindent"
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'inner': super().content(),
|
"content",
|
||||||
'width': self.width,
|
{
|
||||||
'noindent': self.noindent
|
"inner": super().content(),
|
||||||
})
|
"width": self.width,
|
||||||
|
"noindent": self.noindent,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
@ -7,12 +7,12 @@ class axis(element):
|
|||||||
""" Class representing an axis. """
|
""" Class representing an axis. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'options': '[{content}]',
|
"options": "[{content}]",
|
||||||
'legends': '\\legend{{{content}}}',
|
"legends": "\\legend{{{content}}}",
|
||||||
'content': """\\begin{{axis}}{options}
|
"content": """\\begin{{axis}}{options}
|
||||||
{inner}
|
{inner}
|
||||||
{legend}
|
{legend}
|
||||||
\\end{{axis}}"""
|
\\end{{axis}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, parent=None, legend=None, label=None, **kwargs):
|
def __init__(self, *args, parent=None, legend=None, label=None, **kwargs):
|
||||||
@ -23,17 +23,24 @@ class axis(element):
|
|||||||
self.add(arg)
|
self.add(arg)
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
leg = ''
|
leg = ""
|
||||||
if self.legend:
|
if self.legend:
|
||||||
if type(self.legend) is str:
|
if type(self.legend) is str:
|
||||||
leg = self.legend
|
leg = self.legend
|
||||||
else:
|
else:
|
||||||
leg = self.fmt().format('legends', {
|
leg = self.fmt().format(
|
||||||
'content': ', '.join('{{{}}}'.format(p.legend)
|
"legends",
|
||||||
for p in self.childrens)
|
{
|
||||||
})
|
"content": ", ".join(
|
||||||
return self.fmt().format('content', {
|
"{{{}}}".format(p.legend) for p in self.childrens
|
||||||
'options': self.format_options(self.options),
|
)
|
||||||
'inner': super().content(),
|
},
|
||||||
'legend': leg
|
)
|
||||||
})
|
return self.fmt().format(
|
||||||
|
"content",
|
||||||
|
{
|
||||||
|
"options": self.format_options(self.options),
|
||||||
|
"inner": super().content(),
|
||||||
|
"legend": leg,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
@ -4,13 +4,11 @@ from .generic_plot import generic_plot
|
|||||||
|
|
||||||
|
|
||||||
class coordinates_plot(generic_plot):
|
class coordinates_plot(generic_plot):
|
||||||
|
|
||||||
def __init__(self, *args, **kargs):
|
def __init__(self, *args, **kargs):
|
||||||
super().__init__(*args, **kargs)
|
super().__init__(*args, **kargs)
|
||||||
|
|
||||||
def format_data(self, data):
|
def format_data(self, data):
|
||||||
pts = []
|
pts = []
|
||||||
for d in data:
|
for d in data:
|
||||||
pts.append('({}, {})'.format(
|
pts.append("({}, {})".format(*self.format_values(d)))
|
||||||
*self.format_values(d)))
|
return "coordinates {{{}}}".format("".join(pts))
|
||||||
return 'coordinates {{{}}}'.format(''.join(pts))
|
|
||||||
|
@ -4,10 +4,8 @@ from .generic_plot import generic_plot
|
|||||||
|
|
||||||
|
|
||||||
class errorbars_plot(generic_plot):
|
class errorbars_plot(generic_plot):
|
||||||
|
|
||||||
def __init__(self, legend, data, precision=5, label=None, options=[]):
|
def __init__(self, legend, data, precision=5, label=None, options=[]):
|
||||||
options = options + [
|
options = options + ["error bars/.cd", ("y dir", "both"), ("y explicit")]
|
||||||
'error bars/.cd', ('y dir', 'both'), ('y explicit')]
|
|
||||||
super().__init__(legend, data, label=label, options=options)
|
super().__init__(legend, data, label=label, options=options)
|
||||||
|
|
||||||
def format_data(self, data):
|
def format_data(self, data):
|
||||||
@ -19,7 +17,12 @@ class errorbars_plot(generic_plot):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
p = d[2]
|
p = d[2]
|
||||||
n = p
|
n = p
|
||||||
rows.append('({x}, {y}) += (0, {p}) -= (0, {n})'.format(
|
rows.append(
|
||||||
x=self.format_value(x), y=self.format_value(y),
|
"({x}, {y}) += (0, {p}) -= (0, {n})".format(
|
||||||
p=self.format_value(p), n=self.format_value(n)))
|
x=self.format_value(x),
|
||||||
return 'coordinates {{{}}}'.format('\n'.join(rows))
|
y=self.format_value(y),
|
||||||
|
p=self.format_value(p),
|
||||||
|
n=self.format_value(n),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return "coordinates {{{}}}".format("\n".join(rows))
|
||||||
|
@ -7,9 +7,9 @@ class generic_plot(element):
|
|||||||
""" Class representing a pgfplots plot. """
|
""" Class representing a pgfplots plot. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'options': '+[{content}]',
|
"options": "+[{content}]",
|
||||||
'content': """\\addplot{options} {data};{legend}""",
|
"content": """\\addplot{options} {data};{legend}""",
|
||||||
'legend': """\\addlegendentry{{{content}}}"""
|
"legend": """\\addlegendentry{{{content}}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, legend, data, precision=6, label=None, options=[]):
|
def __init__(self, legend, data, precision=6, label=None, options=[]):
|
||||||
@ -21,32 +21,31 @@ class generic_plot(element):
|
|||||||
|
|
||||||
def format_options(self, options):
|
def format_options(self, options):
|
||||||
if not options:
|
if not options:
|
||||||
return ''
|
return ""
|
||||||
opts = []
|
opts = []
|
||||||
for opt in options:
|
for opt in options:
|
||||||
if type(opt) is not str:
|
if type(opt) is not str:
|
||||||
opt = '{}={}'.format(*opt)
|
opt = "{}={}".format(*opt)
|
||||||
opts.append(str(opt))
|
opts.append(str(opt))
|
||||||
return self.fmt().format('options', {
|
return self.fmt().format("options", {"content": ", ".join(opts)})
|
||||||
'content': ', '.join(opts)
|
|
||||||
})
|
|
||||||
|
|
||||||
def format_value(self, value):
|
def format_value(self, value):
|
||||||
return '{:.{prec}f}'.format(value, prec=self.precision)
|
return "{:.{prec}f}".format(value, prec=self.precision)
|
||||||
|
|
||||||
def format_values(self, values):
|
def format_values(self, values):
|
||||||
return [self.format_value(value) for value in values]
|
return [self.format_value(value) for value in values]
|
||||||
|
|
||||||
def format_legend(self, legend):
|
def format_legend(self, legend):
|
||||||
if not legend:
|
if not legend:
|
||||||
return ''
|
return ""
|
||||||
return self.fmt().format('legend', {
|
return self.fmt().format("legend", {"content": legend})
|
||||||
'content': legend
|
|
||||||
})
|
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'data': self.format_data(self.data),
|
"content",
|
||||||
'options': self.format_options(self.options),
|
{
|
||||||
'legend': self.format_legend(self.legend)
|
"data": self.format_data(self.data),
|
||||||
})
|
"options": self.format_options(self.options),
|
||||||
|
"legend": self.format_legend(self.legend),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
@ -7,12 +7,12 @@ class semilogyaxis(axis):
|
|||||||
""" Class representing an axis. """
|
""" Class representing an axis. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'options': '[{content}]',
|
"options": "[{content}]",
|
||||||
'legends': '\\legend{{{content}}}',
|
"legends": "\\legend{{{content}}}",
|
||||||
'content': """\\begin{{semilogyaxis}}{options}
|
"content": """\\begin{{semilogyaxis}}{options}
|
||||||
{inner}
|
{inner}
|
||||||
{legend}
|
{legend}
|
||||||
\\end{{semilogyaxis}}"""
|
\\end{{semilogyaxis}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kargs):
|
def __init__(self, *args, **kargs):
|
||||||
@ -23,12 +23,12 @@ class semilogxaxis(axis):
|
|||||||
""" Class representing an axis. """
|
""" Class representing an axis. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'options': '[{content}]',
|
"options": "[{content}]",
|
||||||
'legends': '\\legend{{{content}}}',
|
"legends": "\\legend{{{content}}}",
|
||||||
'content': """\\begin{{semilogxaxis}}{options}
|
"content": """\\begin{{semilogxaxis}}{options}
|
||||||
{inner}
|
{inner}
|
||||||
{legend}
|
{legend}
|
||||||
\\end{{semilogxaxis}}"""
|
\\end{{semilogxaxis}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kargs):
|
def __init__(self, *args, **kargs):
|
||||||
|
@ -7,13 +7,12 @@ class resizebox(element):
|
|||||||
""" Class representing a latex resizebox. """
|
""" Class representing a latex resizebox. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'content': """\\resizebox{{{width}}}{{{height}}}{{
|
"content": """\\resizebox{{{width}}}{{{height}}}{{
|
||||||
{inner}
|
{inner}
|
||||||
}}"""
|
}}"""
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, content=None, parent=None,
|
def __init__(self, content=None, parent=None, width="\\linewidth", height="!"):
|
||||||
width="\\linewidth", height="!"):
|
|
||||||
""" Create a resizebox with given width and height.
|
""" Create a resizebox with given width and height.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -28,12 +27,11 @@ class resizebox(element):
|
|||||||
super().__init__(parent, content)
|
super().__init__(parent, content)
|
||||||
self.width = width
|
self.width = width
|
||||||
if type(width) is not str:
|
if type(width) is not str:
|
||||||
self.width = '{}\\linewidth'.format(width)
|
self.width = "{}\\linewidth".format(width)
|
||||||
self.height = height
|
self.height = height
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'width': self.width,
|
"content",
|
||||||
'height': self.height,
|
{"width": self.width, "height": self.height, "inner": super().content()},
|
||||||
'inner': super().content()
|
)
|
||||||
})
|
|
||||||
|
@ -4,7 +4,6 @@ from .element import element
|
|||||||
|
|
||||||
|
|
||||||
class strelement(element):
|
class strelement(element):
|
||||||
|
|
||||||
def __init__(self, content, parent=None):
|
def __init__(self, content, parent=None):
|
||||||
self.inner = content
|
self.inner = content
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ class subfloat(element):
|
|||||||
""" Class representing a latex subfloat. """
|
""" Class representing a latex subfloat. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'content': """\\subfloat[{caption}{label}]{{
|
"content": """\\subfloat[{caption}{label}]{{
|
||||||
{inner}
|
{inner}
|
||||||
}}"""
|
}}"""
|
||||||
}
|
}
|
||||||
@ -19,8 +19,11 @@ class subfloat(element):
|
|||||||
self.caption = caption
|
self.caption = caption
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'caption': self.caption,
|
"content",
|
||||||
'label': self.format_label(self.label),
|
{
|
||||||
'inner': super().content()
|
"caption": self.caption,
|
||||||
})
|
"label": self.format_label(self.label),
|
||||||
|
"inner": super().content(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
@ -8,19 +8,25 @@ class table(element):
|
|||||||
""" Class representing a latex figure. """
|
""" Class representing a latex figure. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'caption': '\\caption{{{content}}}',
|
"caption": "\\caption{{{content}}}",
|
||||||
'content': """\\begin{{table}}[{options}]
|
"content": """\\begin{{table}}[{options}]
|
||||||
{centered}
|
{centered}
|
||||||
{inner}
|
{inner}
|
||||||
{caption}{label}
|
{caption}{label}
|
||||||
\\end{{table}}"""
|
\\end{{table}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
autolabel = False
|
autolabel = False
|
||||||
|
|
||||||
def __init__(self, childrens=None, parent=None,
|
def __init__(
|
||||||
caption=None, options='!ht',
|
self,
|
||||||
centered=True, label=None):
|
childrens=None,
|
||||||
|
parent=None,
|
||||||
|
caption=None,
|
||||||
|
options="!ht",
|
||||||
|
centered=True,
|
||||||
|
label=None,
|
||||||
|
):
|
||||||
""" Create a table with given options.
|
""" Create a table with given options.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -30,25 +36,27 @@ class table(element):
|
|||||||
super().__init__(parent, childrens, label=label)
|
super().__init__(parent, childrens, label=label)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.caption = caption
|
self.caption = caption
|
||||||
self.centered = ''
|
self.centered = ""
|
||||||
if centered:
|
if centered:
|
||||||
self.centered = '\\centering'
|
self.centered = "\\centering"
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
caption = ''
|
caption = ""
|
||||||
if self.caption:
|
if self.caption:
|
||||||
caption = self.fmt().format('caption', {'content': self.caption})
|
caption = self.fmt().format("caption", {"content": self.caption})
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'options': self.options,
|
"content",
|
||||||
'centered': self.centered,
|
{
|
||||||
'caption': caption,
|
"options": self.options,
|
||||||
'label': self.format_label(self.label),
|
"centered": self.centered,
|
||||||
'inner': super().content()
|
"caption": caption,
|
||||||
})
|
"label": self.format_label(self.label),
|
||||||
|
"inner": super().content(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class tabledf(table):
|
class tabledf(table):
|
||||||
|
|
||||||
def __init__(self, df, header=None, multilevels=False, fmt=None, **kargs):
|
def __init__(self, df, header=None, multilevels=False, fmt=None, **kargs):
|
||||||
super().__init__(**kargs)
|
super().__init__(**kargs)
|
||||||
self.add(tabulardf(df, header, multilevels, fmt))
|
self.add(tabulardf(df, header, multilevels, fmt))
|
||||||
|
@ -14,8 +14,9 @@ class row_element(element):
|
|||||||
|
|
||||||
""" Class representing a row of a tabular element. """
|
""" Class representing a row of a tabular element. """
|
||||||
|
|
||||||
def __init__(self, columns, parent, label=None,
|
def __init__(
|
||||||
wrapper=False, endline=False, fmt=None):
|
self, columns, parent, label=None, wrapper=False, endline=False, fmt=None
|
||||||
|
):
|
||||||
super().__init__(parent, columns, label=label, raw=(fmt is not None))
|
super().__init__(parent, columns, label=label, raw=(fmt is not None))
|
||||||
self.wrapper = wrapper
|
self.wrapper = wrapper
|
||||||
self.endline = endline
|
self.endline = endline
|
||||||
@ -28,23 +29,22 @@ class row_element(element):
|
|||||||
if self.__fmt:
|
if self.__fmt:
|
||||||
row = map(self.__fmt, self.childrens)
|
row = map(self.__fmt, self.childrens)
|
||||||
if self.wrapper:
|
if self.wrapper:
|
||||||
cw = 1/len(self.childrens)
|
cw = 1 / len(self.childrens)
|
||||||
wp = lambda c: self.wrapper(c, width=cw)
|
wp = lambda c: self.wrapper(c, width=cw)
|
||||||
row = map(wp, row)
|
row = map(wp, row)
|
||||||
out = ' & '.join(map(str, row))
|
out = " & ".join(map(str, row))
|
||||||
if self.endline:
|
if self.endline:
|
||||||
out += '\\\\'
|
out += "\\\\"
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
class hline_element(row_element):
|
class hline_element(row_element):
|
||||||
|
def __init__(self, command="hline", parent=None):
|
||||||
def __init__(self, command='hline', parent=None):
|
|
||||||
super().__init__([], parent)
|
super().__init__([], parent)
|
||||||
self.command = command
|
self.command = command
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return '\\' + self.command
|
return "\\" + self.command
|
||||||
|
|
||||||
|
|
||||||
# instance of hline element
|
# instance of hline element
|
||||||
@ -55,13 +55,20 @@ class tabular(element):
|
|||||||
""" Class representing a latex tabular. """
|
""" Class representing a latex tabular. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'content': """\\begin{{{name}}}{{{columns}}}
|
"content": """\\begin{{{name}}}{{{columns}}}
|
||||||
{inner}
|
{inner}
|
||||||
\\end{{{name}}}"""
|
\\end{{{name}}}"""
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, parent=None, rows=[], columns=None,
|
def __init__(
|
||||||
autowrap=False, label=None, name='tabular'):
|
self,
|
||||||
|
parent=None,
|
||||||
|
rows=[],
|
||||||
|
columns=None,
|
||||||
|
autowrap=False,
|
||||||
|
label=None,
|
||||||
|
name="tabular",
|
||||||
|
):
|
||||||
""" Create a tabular with given rows and column specification.
|
""" Create a tabular with given rows and column specification.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -103,21 +110,18 @@ class tabular(element):
|
|||||||
self.addrow(row, **kargs)
|
self.addrow(row, **kargs)
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'name': self.name,
|
"content",
|
||||||
'columns': self.columns,
|
{"name": self.name, "columns": self.columns, "inner": super().content()},
|
||||||
'inner': super().content()
|
)
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class multicolumn(element):
|
class multicolumn(element):
|
||||||
""" Class representing a multicolumn element. """
|
""" Class representing a multicolumn element. """
|
||||||
|
|
||||||
templates = {
|
templates = {"content": """\\multicolumn{{{ncolumns}}}{{{align}}}{{{content}}}"""}
|
||||||
'content': """\\multicolumn{{{ncolumns}}}{{{align}}}{{{content}}}"""
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, ncolumns, content='', alignment='c', **kargs):
|
def __init__(self, ncolumns, content="", alignment="c", **kargs):
|
||||||
super().__init__(**kargs)
|
super().__init__(**kargs)
|
||||||
self.ncolumns = ncolumns
|
self.ncolumns = ncolumns
|
||||||
self.inner = content
|
self.inner = content
|
||||||
@ -126,15 +130,13 @@ class multicolumn(element):
|
|||||||
def content(self):
|
def content(self):
|
||||||
if self.ncolumns == 1:
|
if self.ncolumns == 1:
|
||||||
return self.inner
|
return self.inner
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'ncolumns': self.ncolumns,
|
"content",
|
||||||
'content': self.inner,
|
{"ncolumns": self.ncolumns, "content": self.inner, "align": self.alignment},
|
||||||
'align': self.alignment
|
)
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class tabulardf(tabular):
|
class tabulardf(tabular):
|
||||||
|
|
||||||
def __init__(self, df, header=None, multilevels=False, fmt=None, **kargs):
|
def __init__(self, df, header=None, multilevels=False, fmt=None, **kargs):
|
||||||
if header is None:
|
if header is None:
|
||||||
multilevels, header = self.create_header(df)
|
multilevels, header = self.create_header(df)
|
||||||
@ -145,7 +147,7 @@ class tabulardf(tabular):
|
|||||||
ncols = len(header)
|
ncols = len(header)
|
||||||
header = [header]
|
header = [header]
|
||||||
|
|
||||||
kargs.setdefault('columns', 'r' * ncols)
|
kargs.setdefault("columns", "r" * ncols)
|
||||||
super().__init__(**kargs)
|
super().__init__(**kargs)
|
||||||
self.addrows(header)
|
self.addrows(header)
|
||||||
self.addhline()
|
self.addhline()
|
||||||
|
@ -7,17 +7,17 @@ class tikzpicture(element):
|
|||||||
""" Class representing a latex tikzfigure. """
|
""" Class representing a latex tikzfigure. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'options': '[{content}]',
|
"options": "[{content}]",
|
||||||
'content': """\\begin{{tikzpicture}}{options}
|
"content": """\\begin{{tikzpicture}}{options}
|
||||||
{inner}
|
{inner}
|
||||||
\\end{{tikzpicture}}"""
|
\\end{{tikzpicture}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, childrens=None, parent=None, label=None, **kargs):
|
def __init__(self, childrens=None, parent=None, label=None, **kargs):
|
||||||
super().__init__(parent, childrens, label=label, **kargs)
|
super().__init__(parent, childrens, label=label, **kargs)
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format(
|
||||||
'inner': super().content(),
|
"content",
|
||||||
'options': self.format_options(self.options)
|
{"inner": super().content(), "options": self.format_options(self.options)},
|
||||||
})
|
)
|
||||||
|
20
setup.cfg
Normal file
20
setup.cfg
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[flake8]
|
||||||
|
# Use black line length:
|
||||||
|
max-line-length = 88
|
||||||
|
extend-ignore =
|
||||||
|
# See https://github.com/PyCQA/pycodestyle/issues/373
|
||||||
|
E203,
|
||||||
|
|
||||||
|
[mypy]
|
||||||
|
warn_return_any = True
|
||||||
|
warn_unused_configs = True
|
||||||
|
namespace_packages = True
|
||||||
|
|
||||||
|
[tox:tox]
|
||||||
|
envlist = py36,py37,py38,py36-lint
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
deps =
|
||||||
|
pytest
|
||||||
|
commands =
|
||||||
|
pytest tests
|
37
setup.py
Normal file
37
setup.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
dev_requires = [
|
||||||
|
"black",
|
||||||
|
"flake8",
|
||||||
|
"flake8-black",
|
||||||
|
"mypy",
|
||||||
|
"pytest",
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
# Name of the package:
|
||||||
|
name="pyltk",
|
||||||
|
# Version of the package:
|
||||||
|
version="0.0.1",
|
||||||
|
# Find the package automatically (include everything):
|
||||||
|
packages=find_packages(),
|
||||||
|
# Author information:
|
||||||
|
author="Mikaël Capelle",
|
||||||
|
author_email="capelle.mikael@gmail.com",
|
||||||
|
# Description of the package:
|
||||||
|
description="Python library to generate and build LaTeX files",
|
||||||
|
include_package_data=True,
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.6",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
|
],
|
||||||
|
# License:
|
||||||
|
license="MIT",
|
||||||
|
# Requirements:
|
||||||
|
install_requires=[],
|
||||||
|
extras_require={"dev": dev_requires},
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user