From ca690398300e040ab50cd596c35bb0a2301f40e1 Mon Sep 17 00:00:00 2001
From: Tue Herlau <tuhe@dtu.dk>
Date: Wed, 12 Jul 2023 18:02:36 +0200
Subject: [PATCH] Fixed windows wexpect issue

---
 requirements.txt                     |   3 +-
 setup.py                             |   2 +-
 src/codesnipper.egg-info/PKG-INFO    |   2 +-
 src/codesnipper.egg-info/SOURCES.txt |   3 +-
 src/snipper/block_parsing.py         |   2 +-
 src/snipper/fix_bf.py                |   5 +-
 src/snipper/fix_i.py                 |  12 +++-
 src/snipper/fix_o.py                 | 101 +++++++++++++++++++++------
 src/snipper/snip_dir.py              |   6 +-
 src/snipper/snipper_main.py          |   9 ++-
 src/snipper/version.py               |   2 +-
 11 files changed, 107 insertions(+), 40 deletions(-)

diff --git a/requirements.txt b/requirements.txt
index 40f9707..c856bc0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
-wexpect
+# wexpect
+git+https://github.com/raczben/wexpect.git@dev # Changing to dev bc of venv incompatibility stuff. (th juli 2023: problem with 4.0.0).
 pexpect
diff --git a/setup.py b/setup.py
index 8f18475..7a8d934 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 # Use:  pipreqs.exe slider --no-pin --force for requirements_pip.txt
 # https://packaging.python.org/tutorials/packaging-projects/
 # py -m build && twine upload dist/*
-# Linux> python -m build && twine upload dist/*
+# Linux> python -m build && python -m twine upload dist/*
 # Local install: sudo pip install -e ./
 
 import setuptools
diff --git a/src/codesnipper.egg-info/PKG-INFO b/src/codesnipper.egg-info/PKG-INFO
index 5857de1..ddbe216 100644
--- a/src/codesnipper.egg-info/PKG-INFO
+++ b/src/codesnipper.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: codesnipper
-Version: 0.1.17
+Version: 0.1.18.5
 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
diff --git a/src/codesnipper.egg-info/SOURCES.txt b/src/codesnipper.egg-info/SOURCES.txt
index 20caaa7..805b20b 100644
--- a/src/codesnipper.egg-info/SOURCES.txt
+++ b/src/codesnipper.egg-info/SOURCES.txt
@@ -21,4 +21,5 @@ src/snipper/load_citations.py
 src/snipper/snip_dir.py
 src/snipper/snipper_main.py
 src/snipper/test.py
-src/snipper/version.py
\ No newline at end of file
+src/snipper/version.py
+tests/test_python.py
\ No newline at end of file
diff --git a/src/snipper/block_parsing.py b/src/snipper/block_parsing.py
index ebca172..654144d 100644
--- a/src/snipper/block_parsing.py
+++ b/src/snipper/block_parsing.py
@@ -121,7 +121,7 @@ def strip_tag(lines, tag):
     lines2 = []
     for l in lines:
         dx = l.find(tag)
-        if dx > 0:
+        if dx >= 0:
             l = l[:dx]
             if len(l.strip()) == 0:
                 l = None
diff --git a/src/snipper/fix_bf.py b/src/snipper/fix_bf.py
index dc2eb63..9d3faeb 100644
--- a/src/snipper/fix_bf.py
+++ b/src/snipper/fix_bf.py
@@ -66,7 +66,7 @@ def fix_f(lines, debug, keep=False):
     return lines2
 
 # stats = {'n': 0}
-def _block_fun(lines, start_extra, end_extra, keep=False, permute=False, questionmarks=False, halfquestionmarks=False, silent=False, nolines=False):
+def _block_fun(lines, start_extra, end_extra, keep=False, permute=False, questionmarks=False, halfquestionmarks=False, silent=False, nolines=False, noerror=False):
     methods = {'remove': 0}
     # if method not in ['remove', 'permute', 'questionmark', 'halfquestionmark']:
     #     assert False
@@ -122,7 +122,8 @@ def _block_fun(lines, start_extra, end_extra, keep=False, permute=False, questio
                 lines = [id + todo]
             else:
                 lines = msg + lines
-            lines += [id + f'raise NotImplementedError("{ee}")']
+            if not noerror:
+                lines += [id + f'raise NotImplementedError("{ee}")']
             l2 = ([id + start_extra] if len(start_extra) > 0 else []) + lines # [id + f"# TODO: {cc} lines missing.",
             # id + f'raise NotImplementedError("{ee}")']
     return l2, cc
diff --git a/src/snipper/fix_i.py b/src/snipper/fix_i.py
index a498875..5ddbba5 100644
--- a/src/snipper/fix_i.py
+++ b/src/snipper/fix_i.py
@@ -23,7 +23,11 @@ def rsession(analyzer, lines, extra):
 
         import time
         an = we.spawn("python", encoding="utf-8", timeout=20)
-        an.setwinsize(400, 400) # set window size to avoid truncated output or input.
+        try:
+            an.setwinsize(400, 400) # set window size to avoid truncated output or input.
+        except AttributeError as e:
+            print("> Mulble pexpect('pyhon',...) does not support setwinsize on this system (windows?). Ignoring")
+
         an.expect([">>>"])
         l3 = """
 2 + 4 # Add two integers
@@ -130,7 +134,11 @@ def run_i(lines, file, output):
 
         if extra['python'] is None:
             an = we.spawn("python", encoding="utf-8", timeout=20)
-            an.setwinsize(400, 400)  # set window size to avoid truncated output or input.
+            try:
+                an.setwinsize(400, 400)  # set window size to avoid truncated output or input.
+            except AttributeError as e:
+                print("> Mulble pexpect('pyhon',...) does not support setwinsize on this system (windows?). Ignoring")
+
             an.expect([">>>"])
             extra['python'] = an
 
diff --git a/src/snipper/fix_o.py b/src/snipper/fix_o.py
index 58f3251..e92b4ff 100644
--- a/src/snipper/fix_o.py
+++ b/src/snipper/fix_o.py
@@ -1,35 +1,90 @@
 import functools
 import os
-from snipper.legacy import block_process
 from snipper.block_parsing import indent
+import sys
+import subprocess
 
 
-def run_o(lines, file, output):
-    def block_fun(lines, start_extra, end_extra, art, output, **kwargs):
-        id = indent(lines[0])
-        outf = output + ("_" + art if art is not None else "") + ".txt"
-        l2 = []
-        l2 += [id + "import sys", id + f"sys.stdout = open('{outf}', 'w')"]
-        l2 += lines
-        l2 += [indent(lines[-1]) + "sys.stdout = sys.__stdout__"]
-        return l2, None
+def o_block_funlines(lines, art, output):
+    id = indent(lines[0])
+    if not os.path.isdir(os.path.dirname(output)):
+        os.makedirs(os.path.dirname(output))
+    # art = name
+    outf = output + ("_" + art if art is not None and art != "" else "") + ".txt"
+    l2 = []
+    l2 += [id + "import sys", id + f"sys.stdout = open('{outf}', 'w')"]
+    l2 += lines
+    l2 += [indent(lines[-1]) + "sys.stdout = sys.__stdout__"]
+    return l2
+    pass
+
+def run_o(lines, file, output,package_base_dir=None):
+    # def block_fun(lines, start_extra, end_extra, art, output, **kwargs):
+    #     id = indent(lines[0])
+    #     outf = output + ("_" + art if art is not None else "") + ".txt"
+    #     l2 = []
+    #     l2 += [id + "import sys", id + f"sys.stdout = open('{outf}', 'w')"]
+    #     l2 += lines
+    #     l2 += [indent(lines[-1]) + "sys.stdout = sys.__stdout__"]
+    #
+    #
+    #     return l2, None
     try:
-        lines2, didfind, extra, _ = block_process(lines, tag="#!o", block_fun=functools.partial(block_fun, output=output) )
+        from snipper.block_parsing import block_split, block_join
+        # args = {k: v for k, v in b['start_tag_args'].items() if len(k) > 0}
+        # cutout.append(b['block'])
+        # b['block'], dn = _block_fun(b['block'], start_extra=b['arg1'], end_extra=b['arg2'], **args, keep=keep)
+        # # cutout += b['block']
+        # # method = b['start_tag_args'].get('', 'remove')
+        # # b['block'], dn = _block_fun(b['block'], start_extra=b['arg1'], end_extra=b['arg1'], **args, keep=keep)
+        # lines = block_join(b)
+
+        while True:
+            b = block_split(lines, tag="#!o")
+            if b is None:
+                break
+            # ex = b['name']
+            # o_block_fun(b['block'], None, )
+            l2 = o_block_funlines( b['block'], b['name'], output)
+            lines2 = b['first'] + l2 + b['last']
+            lines = b['first'] + b['block'] + b['last']
+            fp, ex = os.path.splitext(file)
+            file_run = fp + "_RUN_OUTPUT_CAPTURE" + ex
+            # lines = lines2
+            if os.path.exists(file_run):
+                print("file found mumble...")
+            else:
+                with open(file_run, 'w', encoding="utf-8") as f:
+                    f.write("\n".join(lines2))
+                python = sys.executable
+                if package_base_dir is None:
+                    cmd = f"cd {os.path.dirname(file_run)} && {python} {os.path.basename(file_run)}"
+                else:
+                    # cmd = f"cd {os.path.dirname(package_base_dir)} && {python} {os.path.basename(file_run)}"
+                    rp = os.path.relpath(file_run, package_base_dir).replace("\\", "/").replace("/", ".")[:-3]
+                    cmd = f"cd {package_base_dir} && {python} -m {rp}"
+
+                print(cmd)
+                s = subprocess.check_output(cmd, shell=True)
+                os.remove(file_run)
+
+
+        # lines2, didfind, extra, _ = block_process(lines, tag="#!o", block_fun=functools.partial(block_fun, output=output) )
     except Exception as e:
         print("Bad file: ", file)
         print("I was cutting the #!o tag")
         print("\n".join( lines) )
         raise(e)
 
-    if didfind:
-        fp, ex = os.path.splitext(file)
-        file_run = fp + "_RUN_OUTPUT_CAPTURE" +ex
-        if os.path.exists(file_run):
-            print("file found mumble...")
-        else:
-            with open(file_run, 'w', encoding="utf-8") as f:
-                f.write("\n".join(lines2) )
-            cmd = "python " + file_run
-            import subprocess
-            s = subprocess.check_output(cmd, shell=True)
-            os.remove(file_run)
\ No newline at end of file
+    # if didfind:
+    #     fp, ex = os.path.splitext(file)
+    #     file_run = fp + "_RUN_OUTPUT_CAPTURE" +ex
+    #     if os.path.exists(file_run):
+    #         print("file found mumble...")
+    #     else:
+    #         with open(file_run, 'w', encoding="utf-8") as f:
+    #             f.write("\n".join(lines2) )
+    #         cmd = "python " + file_run
+    #         import subprocess
+    #         s = subprocess.check_output(cmd, shell=True)
+    #         os.remove(file_run)
\ No newline at end of file
diff --git a/src/snipper/snip_dir.py b/src/snipper/snip_dir.py
index d55ee78..7c2a8a7 100644
--- a/src/snipper/snip_dir.py
+++ b/src/snipper/snip_dir.py
@@ -18,9 +18,10 @@ def snip_dir(source_dir,  # Sources
              license_head=None,
              censor_files=True,
              verbose=True,
+             package_base_dir=None, # When running files, this will be treated as the base of the package the file is run from.
              ):
-
-    print(f"Snipper fixing {source_dir} {cut_files=}, {censor_files=}, {output_dir=}")
+    if verbose:
+        print(f"Snipper fixing {source_dir} {cut_files=}, {censor_files=}, {output_dir=}")
     if dest_dir == None:
         dest_dir = tempfile.mkdtemp()
         print("[snipper]", "no destination dir was specified so using nonsense destination:", dest_dir)
@@ -84,6 +85,7 @@ def snip_dir(source_dir,  # Sources
                                references=references,
                                license_head=license_head,
                                censor_files=censor_files,
+                                    package_base_dir=package_base_dir,
                                **kwargs)
             if nrem > 0 and verbose:
                 print(f"{nrem}> {f}")
diff --git a/src/snipper/snipper_main.py b/src/snipper/snipper_main.py
index 094068e..96834f2 100644
--- a/src/snipper/snipper_main.py
+++ b/src/snipper/snipper_main.py
@@ -33,10 +33,11 @@ def censor_file(file, run_files=True, run_out_dirs=None, cut_files=True,
                 base_path=None,
                 strict=True,
                 references=None,
-                license_head=None):
+                license_head=None,
+                package_base_dir=None):
     if str(file).endswith("rst"):
         assert not run_files and not cut_files and not censor_files
-        print(file)
+        # print(file)
     # if str(file).endswith("md"):
     #     assert not run_files and not cut_files
 
@@ -71,7 +72,7 @@ def censor_file(file, run_files=True, run_out_dirs=None, cut_files=True,
             ofiles[0] = ofiles[0].replace("\\", "/")
 
             if run_files:
-                run_o(lines, file=file, output=ofiles[0])
+                run_o(lines, file=file, output=ofiles[0], package_base_dir=package_base_dir)
                 run_i(lines, file=file, output=ofiles[0])
             if cut_files:
                 save_s(lines, file_path=os.path.relpath(file, base_path), output_dir=run_out_dirs)
@@ -79,8 +80,6 @@ def censor_file(file, run_files=True, run_out_dirs=None, cut_files=True,
 
         if censor_files:
             lines = fix_f(lines, dbug)
-            # if "pacman" in str(file):
-            #     print("sdaf")
             lines, nB, cut = fix_b(lines)
         else:
             nB = 0
diff --git a/src/snipper/version.py b/src/snipper/version.py
index 86205cb..569cd72 100644
--- a/src/snipper/version.py
+++ b/src/snipper/version.py
@@ -1 +1 @@
-__version__ = "0.1.17"
+__version__ = "0.1.18.5"
-- 
GitLab