lhtml-markup 2.0.1__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lhtml_markup-2.0.1/src/lhtml_markup.egg-info → lhtml_markup-2.2.0}/PKG-INFO +1 -1
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/pyproject.toml +1 -1
- lhtml_markup-2.2.0/src/lhtml/cli.py +98 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/export_html.py +9 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/process.py +18 -1
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0/src/lhtml_markup.egg-info}/PKG-INFO +1 -1
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/test/test_lhtml.py +149 -0
- lhtml_markup-2.0.1/src/lhtml/cli.py +0 -62
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/LICENSE.md +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/README.md +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/setup.cfg +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/__init__.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/__main__.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/ast_nodes.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/code.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/element_extract.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/errors.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/insert_in_text.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/listing.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/patterns.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/pipeline.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/tag_element.lark +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/tag_parser.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml/wrap_html.py +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml_markup.egg-info/SOURCES.txt +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml_markup.egg-info/dependency_links.txt +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml_markup.egg-info/entry_points.txt +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml_markup.egg-info/requires.txt +0 -0
- {lhtml_markup-2.0.1 → lhtml_markup-2.2.0}/src/lhtml_markup.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lhtml-markup"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "Lightweight HTML markup language — simplifies HTML authoring with shorthand syntax"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""LHTML command-line interface.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
lhtml [-w] file.l.html # Single file → stdout
|
|
5
|
+
lhtml [-w] file.l.html -o output.html # Single file → output file
|
|
6
|
+
lhtml [-w] a.l.html b.l.html # Multiple files → .html next to sources
|
|
7
|
+
lhtml [-w] a.l.html b.l.html -o build/ # Multiple files → output directory
|
|
8
|
+
python -m lhtml [same options]
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import argparse
|
|
13
|
+
|
|
14
|
+
from .pipeline import ProcessingPipeline
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_pipeline = ProcessingPipeline()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _ensure_trailing_newline(text):
|
|
21
|
+
if text and text[-1] != '\n':
|
|
22
|
+
return text + '\n'
|
|
23
|
+
return text
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _output_path_for(input_path, output_arg):
|
|
27
|
+
"""Determine the output path for a given input file.
|
|
28
|
+
|
|
29
|
+
If output_arg is a directory, write <dir>/<basename>.html.
|
|
30
|
+
If output_arg is a file path, return it directly (single-file mode).
|
|
31
|
+
If output_arg is None, derive .html from the input path.
|
|
32
|
+
"""
|
|
33
|
+
basename = os.path.basename(input_path)
|
|
34
|
+
name, _ = os.path.splitext(basename)
|
|
35
|
+
# Strip double extensions like .l.html → .html
|
|
36
|
+
if name.endswith('.l'):
|
|
37
|
+
name = name[:-2]
|
|
38
|
+
|
|
39
|
+
if output_arg is None:
|
|
40
|
+
# Write next to source
|
|
41
|
+
return os.path.join(os.path.dirname(input_path), name + '.html')
|
|
42
|
+
|
|
43
|
+
if os.path.isdir(output_arg) or output_arg.endswith('/'):
|
|
44
|
+
os.makedirs(output_arg, exist_ok=True)
|
|
45
|
+
return os.path.join(output_arg, name + '.html')
|
|
46
|
+
|
|
47
|
+
# Treat as a direct file path (single-file mode)
|
|
48
|
+
return output_arg
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _process_file(f_in, meta_base):
|
|
52
|
+
"""Process a single LHTML file and return the HTML output."""
|
|
53
|
+
meta = dict(meta_base)
|
|
54
|
+
dir_to_include = os.path.dirname(os.path.abspath(f_in))
|
|
55
|
+
if dir_to_include:
|
|
56
|
+
meta['directory_include'] = meta.get('directory_include', []) + [dir_to_include + '/']
|
|
57
|
+
|
|
58
|
+
with open(f_in) as fid:
|
|
59
|
+
txt = _ensure_trailing_newline(fid.read())
|
|
60
|
+
|
|
61
|
+
return _ensure_trailing_newline(_pipeline.run(txt, meta))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main():
|
|
65
|
+
"""CLI entry point."""
|
|
66
|
+
parser = argparse.ArgumentParser(description='Lightweight HTML')
|
|
67
|
+
parser.add_argument('inputFiles', nargs='+', help='Input file(s)')
|
|
68
|
+
parser.add_argument('-w', '--wrapAuto',
|
|
69
|
+
help='Wrap content in basic HTML template',
|
|
70
|
+
action='store_true')
|
|
71
|
+
parser.add_argument('-o', '--output',
|
|
72
|
+
help='Output file (single input) or directory (multiple inputs)')
|
|
73
|
+
args = parser.parse_args()
|
|
74
|
+
|
|
75
|
+
meta = {'directory_include': [os.getcwd() + '/']}
|
|
76
|
+
if args.wrapAuto:
|
|
77
|
+
meta['wrap-auto'] = True
|
|
78
|
+
|
|
79
|
+
single_file = len(args.inputFiles) == 1
|
|
80
|
+
single_to_stdout = single_file and args.output is None
|
|
81
|
+
|
|
82
|
+
for f_in in args.inputFiles:
|
|
83
|
+
if not os.path.isfile(f_in):
|
|
84
|
+
print(f'Error: file not found [{f_in}]')
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
html = _process_file(f_in, meta)
|
|
88
|
+
|
|
89
|
+
if single_to_stdout:
|
|
90
|
+
print(html)
|
|
91
|
+
else:
|
|
92
|
+
out_path = _output_path_for(f_in, args.output)
|
|
93
|
+
with open(out_path, 'w') as f_out:
|
|
94
|
+
f_out.write(html)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
if __name__ == '__main__':
|
|
98
|
+
main()
|
|
@@ -145,3 +145,12 @@ def export_html_video(elements, default_inline='', current_directory=''):
|
|
|
145
145
|
def check_is_closing_tag(elements):
|
|
146
146
|
"""A bare :: (empty tag, span of exactly 2) is a closing tag."""
|
|
147
147
|
return elements['tag'] == '' and elements['index_end'] - elements['index_start'] == 2
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def check_is_explicit_closing_tag(elements):
|
|
151
|
+
"""A named closing tag like ::div[-] or ::span[-].
|
|
152
|
+
|
|
153
|
+
Parsed as: tag='', text='div'/'span', []= '-'
|
|
154
|
+
(because the tag name appears after ::, not before)
|
|
155
|
+
"""
|
|
156
|
+
return elements['text'] != '' and elements['[]'] == '-'
|
|
@@ -15,7 +15,7 @@ from .element_extract import extract_bracket_elements
|
|
|
15
15
|
from .export_html import (
|
|
16
16
|
export_html_element_class_and_id, export_html_generic,
|
|
17
17
|
export_html_link, export_html_img, export_html_video,
|
|
18
|
-
check_is_closing_tag,
|
|
18
|
+
check_is_closing_tag, check_is_explicit_closing_tag,
|
|
19
19
|
)
|
|
20
20
|
from .listing import process_listing # noqa: F401 — re-exported
|
|
21
21
|
from .code import export_html_code
|
|
@@ -174,6 +174,23 @@ def _dispatch_tag(element, tag_to_close, current_directory, registry=None):
|
|
|
174
174
|
"""
|
|
175
175
|
tag = element['tag']
|
|
176
176
|
|
|
177
|
+
# Explicit closing tag: ::div[-], ::span[-], etc.
|
|
178
|
+
if check_is_explicit_closing_tag(element):
|
|
179
|
+
closing_name = element['text']
|
|
180
|
+
if not tag_to_close:
|
|
181
|
+
warnings.warn(
|
|
182
|
+
str(LHTMLTagStackError(source_pos=element.get('index_start', -1))),
|
|
183
|
+
stacklevel=3,
|
|
184
|
+
)
|
|
185
|
+
return '::??ERROR', True
|
|
186
|
+
if tag_to_close[-1] != closing_name:
|
|
187
|
+
warnings.warn(
|
|
188
|
+
f'Closing ::{closing_name}[-] but last opened tag is <{tag_to_close[-1]}> '
|
|
189
|
+
f'(position {element.get("index_start", -1)})',
|
|
190
|
+
stacklevel=3,
|
|
191
|
+
)
|
|
192
|
+
return '</' + tag_to_close.pop() + '>', True
|
|
193
|
+
|
|
177
194
|
# Try plugin registry first
|
|
178
195
|
if registry is not None:
|
|
179
196
|
handler = registry.get(tag)
|
|
@@ -169,6 +169,43 @@ class TestTags:
|
|
|
169
169
|
assert 'trick::' in r
|
|
170
170
|
|
|
171
171
|
|
|
172
|
+
# ---------------------------------------------------------------------------
|
|
173
|
+
# Explicit closing tags
|
|
174
|
+
# ---------------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
class TestExplicitClosing:
|
|
177
|
+
def test_explicit_div_close(self):
|
|
178
|
+
r = lhtml.run('\ndiv::[color:red;]\ncontent\n::div[-]\n')
|
|
179
|
+
assert '<div style="color:red;">' in r
|
|
180
|
+
assert '</div>' in r
|
|
181
|
+
assert '::div' not in r
|
|
182
|
+
|
|
183
|
+
def test_explicit_span_close(self):
|
|
184
|
+
r = lhtml.run('\nspan::[color:blue;] text ::span[-]\n')
|
|
185
|
+
# span with inline text uses :: self-closing, but ::span[-] is explicit
|
|
186
|
+
# Actually: span::[color:blue;] text :: is self-closing
|
|
187
|
+
# Let's test a block span
|
|
188
|
+
r = lhtml.run('\nspan::[color:blue;]\ntext\n::span[-]\n')
|
|
189
|
+
assert '<span style="color:blue;">' in r
|
|
190
|
+
assert '</span>' in r
|
|
191
|
+
|
|
192
|
+
def test_nested_explicit_close(self):
|
|
193
|
+
r = lhtml.run('\ndiv::[padding:10px;]\nspan::[color:red;]\ntext\n::span[-]\n::div[-]\n')
|
|
194
|
+
assert r.count('</span>') == 1
|
|
195
|
+
assert r.count('</div>') == 1
|
|
196
|
+
|
|
197
|
+
def test_bare_close_still_works(self):
|
|
198
|
+
r = lhtml.run('\ndiv::[color:green;]\ntext\n::\n')
|
|
199
|
+
assert '</div>' in r
|
|
200
|
+
|
|
201
|
+
def test_mismatch_warning(self):
|
|
202
|
+
with warnings.catch_warnings(record=True) as w:
|
|
203
|
+
warnings.simplefilter('always')
|
|
204
|
+
lhtml.run('\ndiv::[color:red;]\nspan::[color:blue;]\ntext\n::div[-]\n::span[-]\n')
|
|
205
|
+
mismatches = [x for x in w if 'but last opened' in str(x.message)]
|
|
206
|
+
assert len(mismatches) >= 1
|
|
207
|
+
|
|
208
|
+
|
|
172
209
|
# ---------------------------------------------------------------------------
|
|
173
210
|
# Verbatim tests
|
|
174
211
|
# ---------------------------------------------------------------------------
|
|
@@ -207,6 +244,118 @@ class TestPluginSystem:
|
|
|
207
244
|
assert set(reg.registered_tags()) == {'foo', 'bar'}
|
|
208
245
|
|
|
209
246
|
|
|
247
|
+
# ---------------------------------------------------------------------------
|
|
248
|
+
# Code blocks
|
|
249
|
+
# ---------------------------------------------------------------------------
|
|
250
|
+
|
|
251
|
+
class TestCodeBlocks:
|
|
252
|
+
def test_python_code_block(self):
|
|
253
|
+
r = lhtml.run('\ncode::[python]\ndef hello():\n pass\ncode::[-]\n')
|
|
254
|
+
assert '<pre>' in r
|
|
255
|
+
assert 'hello' in r
|
|
256
|
+
|
|
257
|
+
def test_cpp_code_block(self):
|
|
258
|
+
r = lhtml.run('\ncode::[c++]\nint x = 0;\ncode::[-]\n')
|
|
259
|
+
assert '<pre>' in r
|
|
260
|
+
|
|
261
|
+
def test_text_code_block(self):
|
|
262
|
+
r = lhtml.run('\ncode::[text]\nplain text\ncode::[-]\n')
|
|
263
|
+
assert 'plain text' in r
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
# ---------------------------------------------------------------------------
|
|
267
|
+
# Unnamed div (::() syntax)
|
|
268
|
+
# ---------------------------------------------------------------------------
|
|
269
|
+
|
|
270
|
+
class TestUnnamedDiv:
|
|
271
|
+
def test_unnamed_div_with_class(self):
|
|
272
|
+
r = lhtml.run('\n::(.highlight)[padding:10px;]\ncontent\n::\n')
|
|
273
|
+
assert 'class="highlight"' in r
|
|
274
|
+
assert 'style="padding:10px;"' in r
|
|
275
|
+
assert 'content' in r
|
|
276
|
+
|
|
277
|
+
def test_unnamed_div_style_only(self):
|
|
278
|
+
r = lhtml.run('\n::[color:red;]\ntext\n::\n')
|
|
279
|
+
assert '<div style="color:red;">' in r
|
|
280
|
+
|
|
281
|
+
def test_unnamed_div_wrapping_list(self):
|
|
282
|
+
r = lhtml.run('\n::(.box)\n* item one\n* item two\n::\n')
|
|
283
|
+
assert 'class="box"' in r
|
|
284
|
+
assert '<ul>' in r
|
|
285
|
+
assert '<li>' in r
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
# ---------------------------------------------------------------------------
|
|
289
|
+
# Inline close (:: on same line)
|
|
290
|
+
# ---------------------------------------------------------------------------
|
|
291
|
+
|
|
292
|
+
class TestInlineClose:
|
|
293
|
+
def test_empty_div_inline_close(self):
|
|
294
|
+
r = lhtml.run('\ndiv::[height:25px;]::\n')
|
|
295
|
+
assert '<div style="height:25px;"></div>' in r
|
|
296
|
+
|
|
297
|
+
def test_span_inline_close_with_class(self):
|
|
298
|
+
r = lhtml.run('\nspan::(.tag)[color:white;] label ::\n')
|
|
299
|
+
assert '<span class="tag" style="color:white;"> label </span>' in r
|
|
300
|
+
|
|
301
|
+
def test_unnamed_inline_close(self):
|
|
302
|
+
r = lhtml.run('\n::[margin:5px;]::\n')
|
|
303
|
+
assert '<div style="margin:5px;"></div>' in r
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
# ---------------------------------------------------------------------------
|
|
307
|
+
# Complex nesting
|
|
308
|
+
# ---------------------------------------------------------------------------
|
|
309
|
+
|
|
310
|
+
class TestComplexNesting:
|
|
311
|
+
def test_nested_divs_three_levels(self):
|
|
312
|
+
r = lhtml.run('\n::[padding:20px;]\n::[background:#eee;]\ndiv::[color:red;] deep ::\n::\n::\n')
|
|
313
|
+
assert '<div style="padding:20px;">' in r
|
|
314
|
+
assert '<div style="background:#eee;">' in r
|
|
315
|
+
assert '<div style="color:red;"> deep </div>' in r
|
|
316
|
+
assert r.count('</div>') == 3
|
|
317
|
+
|
|
318
|
+
def test_formatting_inside_nested_div(self):
|
|
319
|
+
r = lhtml.run('\n::[border:1px solid;]\n**bold** and __italic__\n::\n')
|
|
320
|
+
assert '<strong>bold</strong>' in r
|
|
321
|
+
assert '<em>italic</em>' in r
|
|
322
|
+
assert '<div style="border:1px solid;">' in r
|
|
323
|
+
|
|
324
|
+
def test_link_inside_div(self):
|
|
325
|
+
r = lhtml.run('\n::[padding:5px;]\nlink::https://example.com[click]\n::\n')
|
|
326
|
+
assert '<a href="https://example.com">click</a>' in r
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
# ---------------------------------------------------------------------------
|
|
330
|
+
# Mixed content (real-world patterns)
|
|
331
|
+
# ---------------------------------------------------------------------------
|
|
332
|
+
|
|
333
|
+
class TestMixedContent:
|
|
334
|
+
def test_heading_with_bold(self):
|
|
335
|
+
r = lhtml.run('\n= Title with **bold** word\n')
|
|
336
|
+
assert '<h1>Title with <strong>bold</strong> word</h1>' in r
|
|
337
|
+
|
|
338
|
+
def test_list_with_inline_code(self):
|
|
339
|
+
r = lhtml.run('\n* Use `printf` to print\n')
|
|
340
|
+
assert '<li>' in r
|
|
341
|
+
assert '<code class="code-inline">printf</code>' in r
|
|
342
|
+
|
|
343
|
+
def test_list_with_link(self):
|
|
344
|
+
r = lhtml.run('\n* See link::https://example.com[docs]\n')
|
|
345
|
+
assert '<li>' in r
|
|
346
|
+
assert '<a href="https://example.com">docs</a>' in r
|
|
347
|
+
|
|
348
|
+
def test_code_inside_styled_div(self):
|
|
349
|
+
r = lhtml.run('\n::[font-size:80%;]\ncode::[c++]\nint x;\ncode::[-]\n::\n')
|
|
350
|
+
assert '<div style="font-size:80%;">' in r
|
|
351
|
+
assert '<pre>' in r
|
|
352
|
+
|
|
353
|
+
def test_raw_html_passthrough_with_lhtml(self):
|
|
354
|
+
r = lhtml.run('\n<p>HTML</p>\ndiv::[color:red;] lhtml ::\n')
|
|
355
|
+
assert '<p>HTML</p>' in r
|
|
356
|
+
assert '<div style="color:red;"> lhtml </div>' in r
|
|
357
|
+
|
|
358
|
+
|
|
210
359
|
# ---------------------------------------------------------------------------
|
|
211
360
|
# Non-regression: real-world lab_website examples
|
|
212
361
|
# ---------------------------------------------------------------------------
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"""LHTML command-line interface.
|
|
2
|
-
|
|
3
|
-
Usage:
|
|
4
|
-
lhtml [-w] inputFile [-o outputFile]
|
|
5
|
-
python -m lhtml [-w] inputFile [-o outputFile]
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import os
|
|
9
|
-
import argparse
|
|
10
|
-
|
|
11
|
-
from .pipeline import ProcessingPipeline
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
_pipeline = ProcessingPipeline()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def _ensure_trailing_newline(text):
|
|
18
|
-
if text and text[-1] != '\n':
|
|
19
|
-
return text + '\n'
|
|
20
|
-
return text
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def main():
|
|
24
|
-
"""CLI entry point."""
|
|
25
|
-
parser = argparse.ArgumentParser(description='Lightweight HTML')
|
|
26
|
-
parser.add_argument('inputFile', help='Input filepath')
|
|
27
|
-
parser.add_argument('-w', '--wrapAuto',
|
|
28
|
-
help='Wrap content in basic HTML template',
|
|
29
|
-
action='store_true')
|
|
30
|
-
parser.add_argument('-o', '--outputFile', help='Output filepath')
|
|
31
|
-
args = parser.parse_args()
|
|
32
|
-
|
|
33
|
-
meta = {}
|
|
34
|
-
if args.wrapAuto:
|
|
35
|
-
meta['wrap-auto'] = True
|
|
36
|
-
|
|
37
|
-
meta['directory_include'] = [os.getcwd() + '/']
|
|
38
|
-
f_in = args.inputFile
|
|
39
|
-
|
|
40
|
-
if os.path.isfile(f_in):
|
|
41
|
-
dir_to_include = os.path.dirname(f_in)
|
|
42
|
-
if dir_to_include:
|
|
43
|
-
meta['directory_include'].append(
|
|
44
|
-
os.path.join(os.getcwd(), dir_to_include) + '/'
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
with open(f_in) as fid:
|
|
48
|
-
txt = _ensure_trailing_newline(fid.read())
|
|
49
|
-
|
|
50
|
-
html = _ensure_trailing_newline(_pipeline.run(txt, meta))
|
|
51
|
-
|
|
52
|
-
if args.outputFile:
|
|
53
|
-
with open(args.outputFile, 'w') as f_out:
|
|
54
|
-
f_out.write(html)
|
|
55
|
-
else:
|
|
56
|
-
print(html)
|
|
57
|
-
else:
|
|
58
|
-
print(f'Error: unrecognized input file [{f_in}]')
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if __name__ == '__main__':
|
|
62
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|