diff --git a/dist/codesnipper-0.0.2-py3-none-any.whl b/dist/codesnipper-0.0.2-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..a3de71167725d94f82ba94271db109d7a5baa198 Binary files /dev/null and b/dist/codesnipper-0.0.2-py3-none-any.whl differ diff --git a/dist/codesnipper-0.0.2.tar.gz b/dist/codesnipper-0.0.2.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..128343f9db99e65419e5a8c62fb3bed6fa91d662 Binary files /dev/null and b/dist/codesnipper-0.0.2.tar.gz differ diff --git a/docs/build_docs.py b/docs/build_docs.py index 02f77913273a5c32c9672b84bfd54b06cdb79912..46e7a45ce1114a3e4007293330f919b5f36d400e 100644 --- a/docs/build_docs.py +++ b/docs/build_docs.py @@ -20,10 +20,8 @@ if __name__ == "__main__": from snipper.fix_s import save_s from snipper.snipper_main import censor_file - - # - # EX_BASE = "../examples" - # np = EX_BASE + "/new_project" + EX_BASE = "../examples" + np = EX_BASE + "/latex" # if os.path.isdir(np): # shutil.rmtree(np) @@ -40,7 +38,7 @@ if __name__ == "__main__": # my_nup(np + "/index.pdf") # my_nup(f"{np_basic1}/index.pdf") # - # # convert.pdf2png(np + "/index.pdf", "./index0.png") + convert.pdf2png(np + "/index.pdf", "./index.png", scale_to=600) # output = np +"/index_2up.pdf" # # data = {} diff --git a/example/__pycache__/load_references.cpython-38.pyc b/examples/__pycache__/load_references.cpython-38.pyc similarity index 100% rename from example/__pycache__/load_references.cpython-38.pyc rename to examples/__pycache__/load_references.cpython-38.pyc diff --git a/examples/block_processor.py b/examples/block_processor.py new file mode 100644 index 0000000000000000000000000000000000000000..c8662f7f5baa7c158e26f8565a62c8bf66e67acb --- /dev/null +++ b/examples/block_processor.py @@ -0,0 +1,63 @@ +from snipper.fix_s import get_s #!s +from snipper.block_parsing import block_split +import textwrap +import numpy as np + +# Implement a sieve here. +def primes_sieve(limit): + limitn = limit+1 #!b + primes = range(2, limitn) + + for i in primes: + factors = list(range(i, limitn, i)) + for f in factors[1:]: + if f in primes: + primes.remove(f) + return primes #!b +#!s + +def obscure(blk, fun): + blok = block_split(blk, "#!b") + lines2 = blok['first'] + fun(blok['block']) + blok['last'] + s = '\n'.join(lines2) + print(s) + return s + +# driver program +if __name__ == '__main__': + with open(__file__, 'r') as f: + s = f.read().splitlines() + blk = get_s(s)[''] + + def cmnt(lines): + whitespace = " " * (len(lines[0]) - len(lines[0].lstrip())) + lines = textwrap.dedent("\n".join(lines)).splitlines() + lines = ["# " + l for l in lines] + return lines, whitespace + + def f1(lines): + lines, whitespace = cmnt(lines) + lines = [lines[i] for i in np.random.permutation(len(lines))] + lines = textwrap.indent("\n".join(lines), whitespace).splitlines() + return lines + + obscure(blk, f1) + + def f2(lines): + lines, whitespace = cmnt(lines) + kp = """#'"[](){},.+-012345679:=""" + l2 = [] + for line in lines: + line2 = [] + for w in line.split(' '): + if w in ['', 'return', 'if', 'else' '=', '#', "for", "in"]: + line2.append(w) + else: + w2 = "".join( [ (t if t in kp else '?') for t in w] ) + line2.append(w2) + l2.append(" ".join(line2)) + lines = l2 + lines = textwrap.indent("\n".join(lines), whitespace).splitlines() + return lines + + obscure(blk, f2) diff --git a/example/citations.py b/examples/citations.py similarity index 100% rename from example/citations.py rename to examples/citations.py diff --git a/examples/cs101_instructor/homework1.py b/examples/cs101_instructor/homework1.py new file mode 100644 index 0000000000000000000000000000000000000000..49ed989a2f83b491f310646921c0cf224eb99503 --- /dev/null +++ b/examples/cs101_instructor/homework1.py @@ -0,0 +1,20 @@ +def myfun(): #!s + """ + Simple aux references \ref{eq1} in \ref{sec1}. + Simple bibtex citations: \cite{bertsekasII} and \cite[Somewhere around the middle]{herlau} + + Example of custom command (reference notes) + > \nref{fig1} + + Other example of custom command (reference assignment) + > \aref2{sec1} + """ + print("See \\ref{sec1}") # Also works. + return 42 #!s + +def fun1(l1, l2): + s1 = sum(l1) #!s + s2 = sum(l2) + print("Hello worlds!") #!s + return s1 + s2 + diff --git a/example/exercise1.py b/examples/exercise1.py similarity index 100% rename from example/exercise1.py rename to examples/exercise1.py diff --git a/example/latex/br.pdf b/examples/latex/br.pdf similarity index 100% rename from example/latex/br.pdf rename to examples/latex/br.pdf diff --git a/example/latex/index.aux b/examples/latex/index.aux similarity index 100% rename from example/latex/index.aux rename to examples/latex/index.aux diff --git a/example/latex/index.bbl b/examples/latex/index.bbl similarity index 100% rename from example/latex/index.bbl rename to examples/latex/index.bbl diff --git a/example/latex/index.blg b/examples/latex/index.blg similarity index 100% rename from example/latex/index.blg rename to examples/latex/index.blg diff --git a/example/latex/index.log b/examples/latex/index.log similarity index 100% rename from example/latex/index.log rename to examples/latex/index.log diff --git a/example/latex/index.out b/examples/latex/index.out similarity index 100% rename from example/latex/index.out rename to examples/latex/index.out diff --git a/example/latex/index.pdf b/examples/latex/index.pdf similarity index 100% rename from example/latex/index.pdf rename to examples/latex/index.pdf diff --git a/example/latex/index.synctex.gz b/examples/latex/index.synctex.gz similarity index 100% rename from example/latex/index.synctex.gz rename to examples/latex/index.synctex.gz diff --git a/example/latex/index.tex b/examples/latex/index.tex similarity index 100% rename from example/latex/index.tex rename to examples/latex/index.tex diff --git a/example/latex/library.bib b/examples/latex/library.bib similarity index 100% rename from example/latex/library.bib rename to examples/latex/library.bib diff --git a/example/load_references.py b/examples/load_references.py similarity index 93% rename from example/load_references.py rename to examples/load_references.py index 9718dde77f21095e8477d4437f3b1765c8f7f911..aad5a0fead00b9240c8387f9f28dc6f5ec17b592 100644 --- a/example/load_references.py +++ b/examples/load_references.py @@ -3,7 +3,7 @@ import os def reference_example(): # Load references and insert them. - from snipper.citations import get_bibtex, get_aux #!s=a + from snipper.load_citations import get_bibtex, get_aux #!s=a bibfile = "latex/library.bib" auxfile = 'latex/index.aux' bibtex = get_bibtex(bibfile) diff --git a/example/output/citations.py b/examples/output/citations.py similarity index 100% rename from example/output/citations.py rename to examples/output/citations.py diff --git a/example/output/load_references_a.py b/examples/output/load_references_a.py similarity index 71% rename from example/output/load_references_a.py rename to examples/output/load_references_a.py index 304c800fad3b5988a1f866385416f228499815f1..672cac255810264aa57dc7339c0dbb8134fdf56e 100644 --- a/example/output/load_references_a.py +++ b/examples/output/load_references_a.py @@ -1,5 +1,5 @@ # load_references.py - from snipper.citations import get_bibtex, get_aux + from snipper.load_citations import get_bibtex, get_aux bibfile = "latex/library.bib" auxfile = 'latex/index.aux' bibtex = get_bibtex(bibfile) diff --git a/example/output/load_references_b.py b/examples/output/load_references_b.py similarity index 100% rename from example/output/load_references_b.py rename to examples/output/load_references_b.py diff --git a/examples/process_cs101.py b/examples/process_cs101.py new file mode 100644 index 0000000000000000000000000000000000000000..0268b192b2690b67385f69724140a42e962becd3 --- /dev/null +++ b/examples/process_cs101.py @@ -0,0 +1,25 @@ +def main(): + from snipper.snip_dir import snip_dir + from snipper.load_citations import get_aux, get_bibtex + bibfile = get_bibtex('latex/library.bib') + auxfile = get_aux('latex/index.aux') + + references = dict(bibtex=bibfile, + aux=auxfile, + commands=[ + dict(command='\\aref2', output="(Assignment 2, \\ref{%s})", aux=auxfile), + dict(command='\\href', output="\cite[\\ref{%s}]{herlau}", aux=auxfile), + ] + ) + + + output = snip_dir(source_dir="./cs101_instructorm", dest_dir="./cs101_students", output_dir="./cs101_output", + references=references, + ) + + a = 234 + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/codesnipper.egg-info/PKG-INFO b/src/codesnipper.egg-info/PKG-INFO index 487bc49d1a1da8cad30d409ce4d898b017babc34..070de1a0d19a7a2a6bbd234536ec5b69ef17e895 100644 --- a/src/codesnipper.egg-info/PKG-INFO +++ b/src/codesnipper.egg-info/PKG-INFO @@ -1,11 +1,11 @@ Metadata-Version: 2.1 Name: codesnipper -Version: 0.0.1 +Version: 0.0.2 Summary: A lightweight framework for censoring student solutions files and extracting code + output Home-page: https://lab.compute.dtu.dk/tuhe/snipper Author: Tue Herlau Author-email: tuhe@dtu.dk -License: UNKNOWN +License: MIT Project-URL: Bug Tracker, https://lab.compute.dtu.dk/tuhe/snipper/issues Platform: UNKNOWN Classifier: Programming Language :: Python :: 3 @@ -15,8 +15,158 @@ Requires-Python: >=3.8 Description-Content-Type: text/markdown License-File: LICENSE -# Snip -A lightweight framework for removing code from student solutions. Currently used at DTU. +# Snipper +A lightweight framework for removing code from student solutions. +## Installation +```console +pip install codesnipper +``` +## What it does +This project address the following three challenges for administering a python-based course + - You need to maintain a (working) version for debugging as well as a version handed out to students (with code missing) + - You ideally want to make references in source code to course material *"(see equation 2.1 in exercise 5)"* but these tend to go out of date + - You want to include code snippets and code output in lectures notes/exercises/beamer slides + - You want to automatically create student solutions +This framework address these problems and allow you to maintain a **single**, working project repository. + +The project is currently used in **02465** at DTU. An example of student code can be found at: + - https://gitlab.gbar.dtu.dk/02465material/02465students/blob/master/irlc/ex02/dp.py + +A set of lectures notes where all code examples/output are automatically generated from the working repository can be found a +- https://lab.compute.dtu.dk/tuhe/books (see **Sequential decision making**) + +## How it works +The basic functionality is quite simple. You start with your working script in your private repository and add special tags to the script. +In this case I have added the tags `#!b` (cut a block) and `#!f` (cut function scope). +```python +def myfun(): #!f The error I am going to raise + """ The function docstring will not be removed""" + print("This is a function") + return 42 + +def a_long_function(): + a = 234 + print("a line") + print("a line") #!b + print("a line") + print("a line") #!b Insert three missing print statements. + print("a line") + return a + +if __name__ == "__main__": + myfun() +``` +This will produce the following file: +```python +def myfun(): + """ The function docstring will not be removed""" + # TODO: 2 lines missing. + raise NotImplementedError("The error I am going to raise") + +def a_long_function(): + a = 234 + print("a line") + # TODO: 3 lines missing. + raise NotImplementedError("Insert three missing print statements.") + print("a line") + return a + +if __name__ == "__main__": + myfun() +``` +You can also use the framework to capture code snippets, outputs and interactive python output. +To do this, save the following in `foo.py` +```python +def myfun(): #!s This snippet will be saved to foo.py in the output directory. + print("Hello") #!s + +print("Do not capture me") +for i in range(4): #!o + print("Output", i) +print("Goodbuy world") #!o +print("don't capture me") + +# Interactive pythong example +print("Hello World") #!i #!i # this is a single-line cutout. +```` +These block-tags will create a file `foo.py` (in the output directory) containing +```python +def myfun(): + print("Hello") +``` +A file `foo.txt` containing the captured output +```txt +Output 0 +Output 1 +Output 2 +Output 3 +Goodbuy world +``` +and a typeset version of an interactive python session in `foo.pyi` (use `pycon` in minted; this gitlab server appears not to support `pycon`) +```pycon +>>> print("hello world") +Hello World" +``` +All these files can be directly imported into `LaTeX` using e.g. `minted`: You never need to mix `LaTeX` code and python again! + + +## References: +Bibliography references can be loaded from `references.bib`-files and in-document references from the `.aux` file. +For this example, we will insert references shown in the `examples/latex/index.tex`-document. To do so, we can use these tags: +```python +def myfun(): #!s + """ + To solve this exercise, look at \ref{eq1} in \ref{sec1}. + You can also look at \cite{bertsekasII} and \cite{herlau} + More specifically, look at \cite[Equation 117]{bertsekasII} and \cite[\ref{fig1}]{herlau} + + We can also write a special tag to reduce repetition: \nref{fig1} and \nref{sec1}. + """ + return 42 #!s + +``` +We can manually compile this example by first loading the aux-files and the bibliographies as follows: +```python +# load_references.py + from snipper.citations import get_bibtex, get_aux + bibfile = "latex/library.bib" + auxfile = 'latex/index.aux' + bibtex = get_bibtex(bibfile) + aux = get_aux(auxfile) +``` +Next, we load the python file containing the reference code and fix all references based on the aux and bibliography data. +```python +# load_references.py + file = "citations.py" + with open(file, 'r') as f: + lines = f.read().splitlines() + lines = fix_aux(lines, aux=aux) + lines = fix_aux_special(lines, aux=aux, command='\\nref', bibref='herlau') + lines = fix_bibtex(lines, bibtex=bibtex) + with open('output/citations.py', 'w') as f: + f.write("\n".join(lines)) +``` +The middle command is a convenience feature: It allows us to specify a special citation command `\nref{..}` which always compiles to `\cite[\ref{...}]{herlau}`. This is useful if e.g. `herlau` is the bibtex key for your lecture notes. The result is as follows: +```python +""" +References: + [Ber07] Dimitri P. Bertsekas. Dynamic Programming and Optimal Control, Vol. II. Athena Scientific, 3rd edition, 2007. ISBN 1886529302. + [Her21] Tue Herlau. Sequential decision making. (See 02465_Notes.pdf), 2021. +""" +def myfun(): #!s + """ + To solve this exercise, look at eq. (1) in Section 1. + You can also look at (Ber07) and (Her21) + More specifically, look at (Ber07, Equation 117) and (Her21, Figure 1) + + We can also write a special tag to reduce repetition: (Her21, Figure 1) and (Her21, Section 1). + """ + return 42 #!s +``` +Note this example uses the low-level api. Normally you would just pass the bibtex and aux-file to the main censor-file command. + +## Additional features: +- You can name tags using `#!s=bar` to get a `foo_bar.py` snippet. This is useful when you need to cut multiple sessions. This also works for the other tags. diff --git a/src/codesnipper.egg-info/SOURCES.txt b/src/codesnipper.egg-info/SOURCES.txt index 8b9ec963f866926c6443dfdfdce0f0fd577af5ee..0064f64f775fd70dcb7864eb21a94d63b9516fe6 100644 --- a/src/codesnipper.egg-info/SOURCES.txt +++ b/src/codesnipper.egg-info/SOURCES.txt @@ -9,5 +9,8 @@ src/codesnipper.egg-info/dependency_links.txt src/codesnipper.egg-info/requires.txt src/codesnipper.egg-info/top_level.txt src/snipper/__init__.py +src/snipper/citations.py +src/snipper/fix_cite.py +src/snipper/fix_s.py src/snipper/snip_dir.py -src/snipper/snipper.py \ No newline at end of file +src/snipper/snipper_main.py \ No newline at end of file diff --git a/src/codesnipper.egg-info/requires.txt b/src/codesnipper.egg-info/requires.txt index 7f7afbf3bf54b346092be6a72070fcbd305ead1e..4ba7d8fcd57f03899543a71a0d303d13cb5072a3 100644 --- a/src/codesnipper.egg-info/requires.txt +++ b/src/codesnipper.egg-info/requires.txt @@ -1 +1,3 @@ -jinja2 +pexpect +wexpect +pybtex diff --git a/src/snipper/__pycache__/citations.cpython-38.pyc b/src/snipper/__pycache__/citations.cpython-38.pyc deleted file mode 100644 index 9a647f415713b55177e96ceff6c8c791938806ce..0000000000000000000000000000000000000000 Binary files a/src/snipper/__pycache__/citations.cpython-38.pyc and /dev/null differ diff --git a/src/snipper/__pycache__/fix_s.cpython-38.pyc b/src/snipper/__pycache__/fix_s.cpython-38.pyc index a4e3cf8604fe8f78dcdcc41bf88f448690de8363..b161b2c89e36fa9e9f5a4b97990c7c3ba4833196 100644 Binary files a/src/snipper/__pycache__/fix_s.cpython-38.pyc and b/src/snipper/__pycache__/fix_s.cpython-38.pyc differ diff --git a/src/snipper/block_parsing.py b/src/snipper/block_parsing.py new file mode 100644 index 0000000000000000000000000000000000000000..0b1009c05c3266267f825bf7bb5d760fd4fd83f6 --- /dev/null +++ b/src/snipper/block_parsing.py @@ -0,0 +1,78 @@ +def f2(lines, tag, i=0, j=0): + for k in range(i, len(lines)): + index = lines[k].find(tag, j if k == i else 0) + if index >= 0: + return k, index + return None, None + + +def block_iterate(lines, tag): + contents = {'joined': lines} + while True: + contents = block_split(contents['joined'], tag) + if contents is None: + break + + yield contents + + +def block_split(lines, tag): + stag = tag[:2] # Start of any next tag. + + def join(contents): + return contents['first'] + [contents['block'][0] + contents['post1']] + contents['block'][1:-1] \ + + [contents['block'][-1] + contents['post2']] + contents['last'] + contents = {} + i, j = f2(lines, tag) + + def get_tag_args(line): + k = line.find(" ") + tag_args = (line[:k + 1] if k >= 0 else line)[len(tag):] + if len(tag_args) == 0: + return {'': ''} # No name. + tag_args = dict([t.split("=") for t in tag_args.split(";")]) + return tag_args + + if i is None: + return None + else: + start_tag_args = get_tag_args(lines[i][j:]) + START_TAG = f"{tag}={start_tag_args['']}" if '' in start_tag_args else tag + END_TAG = START_TAG + i2, j2 = f2(lines, END_TAG, i=i, j=j+1) + if i2 == None: + END_TAG = tag + i2, j2 = f2(lines, END_TAG, i=i, j=j+1) + if i2 == None: + print("\n".join( lines[i:])) + raise Exception("Did not find matching tag", tag) + + + if i == i2: + # Splitting a single line. To reduce confusion, this will be treated slightly differently: + l2 = lines[:i] + [lines[i][:j2], lines[i][j2:]] + lines[i2+1:] + c2 = block_split(l2, tag=tag) + c2['block'].pop() + c2['joined'] = join(c2) + return c2 + else: + contents['first'] = lines[:i] + contents['last'] = lines[i2+1:] + + def argpost(line, j): + nx_tag = line.find(stag, j+1) + arg1 = line[j+len(tag):nx_tag] + if nx_tag >= 0: + post = line[nx_tag:] + else: + post = '' + return arg1, post + + contents['arg1'], contents['post1'] = argpost(lines[i], j) + contents['arg2'], contents['post2'] = argpost(lines[i2], j2) + blk = [lines[i][:j]] + lines[i+1:i2] + [lines[i2][:j2]] + contents['block'] = blk + contents['joined'] = join(contents) + contents['start_tag_args'] = start_tag_args + contents['name'] = start_tag_args[''] + return contents \ No newline at end of file diff --git a/src/snipper/fix_bf.py b/src/snipper/fix_bf.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/snipper/fix_cite.py b/src/snipper/fix_cite.py index 475e44d5f36f80dd441574fc757cd6dec32c8b18..7fbc1b44a4728216c0c5bdad52d2ace5d239a0e5 100644 --- a/src/snipper/fix_cite.py +++ b/src/snipper/fix_cite.py @@ -1,34 +1,10 @@ -from snipper.citations import find_tex_cite +from snipper.load_citations import find_tex_cite from snipper.snipper_main import COMMENT -def fix_references(lines, info, strict=True): - for cmd in info['new_references']: - lines = fix_single_reference(lines, cmd, info['new_references'][cmd], strict=strict) - return lines -def fix_single_reference(lines, cmd, aux, strict=True): - references = aux - s = "\n".join(lines) - i = 0 - while True: - (i, j), reference, txt = find_tex_cite(s, start=i, key=cmd) - if i < 0: - break - if reference not in references: - er = "cref label not found for label: " + reference - if strict: - raise IndexError(er) - else: - print(er) - continue - r = references[reference] - rtxt = r['nicelabel'] - s = s[:i] + rtxt + s[j + 1:] - i = i + len(rtxt) - print(cmd, rtxt) - - lines = s.splitlines(keepends=False) - return lines +def fix_citations(): + # This should be the master function. + pass def fix_aux_special(lines, aux, command='\\nref', bibref='herlau'): @@ -70,4 +46,35 @@ def fix_bibtex(lines, bibtex): s = s[:i] + "References:\n" + "\n".join(all_refs) +"\n"+ s[i:] # s = s.replace(cpr, info['code_copyright']) - return s.splitlines() \ No newline at end of file + return s.splitlines() + + + +def fix_references(lines, info, strict=True): + for cmd in info['new_references']: + lines = fix_single_reference(lines, cmd, info['new_references'][cmd], strict=strict) + return lines + +def fix_single_reference(lines, cmd, aux, strict=True): + references = aux + s = "\n".join(lines) + i = 0 + while True: + (i, j), reference, txt = find_tex_cite(s, start=i, key=cmd) + if i < 0: + break + if reference not in references: + er = "cref label not found for label: " + reference + if strict: + raise IndexError(er) + else: + print(er) + continue + r = references[reference] + rtxt = r['nicelabel'] + s = s[:i] + rtxt + s[j + 1:] + i = i + len(rtxt) + print(cmd, rtxt) + + lines = s.splitlines(keepends=False) + return lines \ No newline at end of file diff --git a/src/snipper/fix_s.py b/src/snipper/fix_s.py index 0eed3c8ea9e9b15926a425aad73adc5aa60fcde5..b8f1d9b35abf9166bc0b194d8e59be6aa9068f19 100644 --- a/src/snipper/fix_s.py +++ b/src/snipper/fix_s.py @@ -1,79 +1,6 @@ -import functools from collections import defaultdict -from snipper.snipper_main import full_strip, block_process - -def f2(lines, tag, i=0, j=0): - for k in range(i, len(lines)): - index = lines[k].find(tag, j if k == i else 0) - if index >= 0: - return k, index - return None, None - -def block_iterate(lines, tag): - contents = {'joined': lines} - while True: - contents = block_split(contents['joined'], tag) - if contents is None: - break - - yield contents - -def block_split(lines, tag): - stag = tag[:2] # Start of any next tag. - - def join(contents): - return contents['first'] + [contents['block'][0] + contents['post1']] + contents['block'][1:-1] \ - + [contents['block'][-1] + contents['post2']] + contents['last'] - contents = {} - i, j = f2(lines, tag) - - def get_tag_args(line): - k = line.find(" ") - tag_args = (line[:k + 1] if k >= 0 else line)[len(tag):] - if len(tag_args) == 0: - return {'': ''} # No name. - tag_args = dict([t.split("=") for t in tag_args.split(";")]) - return tag_args - - if i is None: - return None - else: - start_tag_args = get_tag_args(lines[i][j:]) - START_TAG = f"{tag}={start_tag_args['']}" if '' in start_tag_args else tag - END_TAG = START_TAG - i2, j2 = f2(lines, END_TAG, i=i, j=j+1) - if i2 == None: - END_TAG = tag - i2, j2 = f2(lines, END_TAG, i=i, j=j+1) - - if i == i2: - # Splitting a single line. To reduce confusion, this will be treated slightly differently: - l2 = lines[:i] + [lines[i][:j2], lines[i][j2:]] + lines[i2+1:] - c2 = block_split(l2, tag=tag) - c2['block'].pop() - c2['joined'] = join(c2) - return c2 - else: - contents['first'] = lines[:i] - contents['last'] = lines[i2+1:] - - def argpost(line, j): - nx_tag = line.find(stag, j+1) - arg1 = line[j+len(tag):nx_tag] - if nx_tag >= 0: - post = line[nx_tag:] - else: - post = '' - return arg1, post - - contents['arg1'], contents['post1'] = argpost(lines[i], j) - contents['arg2'], contents['post2'] = argpost(lines[i2], j2) - blk = [lines[i][:j]] + lines[i+1:i2] + [lines[i2][:j2]] - contents['block'] = blk - contents['joined'] = join(contents) - contents['start_tag_args'] = start_tag_args - contents['name'] = start_tag_args[''] - return contents +import os +from snipper.block_parsing import block_iterate def get_s(lines): @@ -86,8 +13,6 @@ def get_s(lines): output[name] = [l for c in co for l in c['block']] return output -import os - def save_s(lines, output_dir, file_path): # save file snips to disk content = get_s(lines) if not os.path.isdir(output_dir): @@ -99,30 +24,6 @@ def save_s(lines, output_dir, file_path): # save file snips to disk with open(output_dir + "/" + os.path.basename(file_path)[:-3] + ("_" + name if len(name) > 0 else name) + ".py", 'w') as f: f.write(out) - # out = "\n".join([f"# {include_path_base}"] + ["\n".join(v[1]) for v in c if v[0] == outf]) - # with open(outf, 'w') as f: - # f.write(out) - - # def block_fun(lines, start_extra, end_extra, art, output, **kwargs): - # outf = output + ("_" + art if art is not None and len(art) > 0 else "") + ".py" - # lines = full_strip(lines) - # return lines, [outf, lines] - # try: - # a,b,c,_ = block_process(lines, tag="#!s", block_fun=functools.partial(block_fun, output=output)) - # if len(c)>0: - # kvs= { v[0] for v in c} - # for outf in kvs: - # out = "\n".join([f"# {include_path_base}"] + ["\n".join(v[1]) for v in c if v[0] == outf] ) - # with open(outf, 'w') as f: - # f.write(out) - # - # except Exception as e: - # print("lines are") - # print("\n".join(lines)) - # print("Bad thing in #!s command in file", file) - # raise e - # return lines - s1 = """ L1 L2 #!s=a @@ -147,5 +48,3 @@ if __name__ == "__main__": # contents = block_split(s1.splitlines(), tag="#!s") # contents = block_split(contents['joined'], tag="#!s") # lines2 = contents['first'] + - a = 234 - pass \ No newline at end of file diff --git a/src/snipper/citations.py b/src/snipper/load_citations.py similarity index 100% rename from src/snipper/citations.py rename to src/snipper/load_citations.py diff --git a/src/snipper/snip_dir.py b/src/snipper/snip_dir.py index 0a68a9d22b51eda7d2755f0effb11c3b89268d94..15657afecaa9afa3748157dd02c6b70c4687de0d 100644 --- a/src/snipper/snip_dir.py +++ b/src/snipper/snip_dir.py @@ -5,7 +5,15 @@ import time import fnmatch -def snip_dir(source_dir, dest_dir, exclude=None, clean_destination_dir=True): +def snip_dir(source_dir, # Sources + dest_dir, # Will write to this directory + output_dir=None, # Where snippets are going to be stored + references=None, # Reference database + exclude=None, clean_destination_dir=True): + + if references == None: + references = dict(aux=None, bibtex=None, commands=[]) + if exclude == None: exclude = [] if not os.path.exists(dest_dir): diff --git a/src/snipper/snipper_main.py b/src/snipper/snipper_main.py index 188603358c62a1b0c274b2c9a28d6e4901c1f768..dc6bbdcbdd5ccda5e590f0eb49938ec3192b8898 100644 --- a/src/snipper/snipper_main.py +++ b/src/snipper/snipper_main.py @@ -315,7 +315,6 @@ def censor_code(lines, keep=True): - def censor_file(file, info, paths, run_files=True, run_out_dirs=None, cut_files=True, solution_list=None, censor_files=True, include_path_base=None,