From e44e2db7c6c813054354a000a57dac6e02e2de1e Mon Sep 17 00:00:00 2001
From: Bert Palm <bert.palm@ufz.de>
Date: Tue, 23 Mar 2021 20:00:41 +0100
Subject: [PATCH] added signatureMaker, a code generation script

---
 signatureMaker.py | 159 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)
 create mode 100644 signatureMaker.py

diff --git a/signatureMaker.py b/signatureMaker.py
new file mode 100644
index 000000000..c68ed4b93
--- /dev/null
+++ b/signatureMaker.py
@@ -0,0 +1,159 @@
+from saqc.funcs import *
+from saqc.core.register import FUNC_MAP
+import os
+
+
+def start_with_exactly_N_spaces(line: str, N: int):
+    return line.startswith(' ' * N) and not line.startswith(' ' * (N + 1))
+
+
+def find_original_signature(fh, fname):
+    sig = []
+    start = end = False
+    for line in fh.readlines():
+
+        # find start of signature
+        if not start:
+
+            if line.startswith(f'def {fname}'):
+                sig.append(line)
+                start = True
+            continue
+
+        # find end of signature
+        if '"""' in line or start_with_exactly_N_spaces(line, 4):
+            end = True
+            break  # do not append line
+
+        # found last line of signature
+        if '->' in line:
+            end = True
+
+        sig.append(line)
+
+        if end:
+            break
+
+    # if end or/and start was not found,
+    # something went wrong
+    if end is False:
+        sig = None
+
+    return sig
+
+
+def replace_core_signatures(readlines, writelines, fname, fh):
+    start = end = False
+    for line in readlines:
+
+        # append the rest of the file, the loop ends here
+        if end is True:
+            fh.write(line)
+            continue
+
+        # find start of signature, loop starts here
+        if not start:
+
+            if line.startswith(f'    def {fname}'):
+                start = True
+
+                # insert the replacement
+                for rline in writelines:
+                    fh.write('    ')
+                    fh.write(rline)
+
+            else:
+                fh.write(line)
+                continue
+
+        # found line after end of signature
+        if '"""' in line or start_with_exactly_N_spaces(line, 8):
+            end = True
+            fh.write(line)
+            continue
+
+        # found last line of signature
+        if '->' in line:
+            end = True
+            continue
+
+
+def replace_datafieldflagger(lines):
+    import re
+    empty = re.compile(' *\n')
+    data = re.compile('.*(data[=: ][^,]*, ?)')  # eg. 'data: DictOfSeries,'
+    flagger = re.compile('.*(flagger[=: ][^,]*, ?)')  # eg. 'flagger: Flagger,'
+    pattern = [data, flagger]
+    i = 0
+    replaced = []
+    for line in lines:
+        if 'copy' in line:
+            i = i
+
+        if i < len(pattern):
+            found = pattern[i].match(line)
+            if found:
+                match = found[1]  # regex group
+                replacement = ''
+                if i == 0:
+                    replacement = 'self, '
+                line = line.replace(match, replacement, 1)
+                i += 1
+
+                # find in same line
+                for j in range(i, len(pattern)):
+                    found = pattern[i].match(line)
+                    if found:
+                        line = line.replace(found[1], '', 1)
+                        i += 1
+
+        empty_line = empty.match(line)
+        if empty_line:
+            continue
+
+        replaced.append(line)
+
+    return replaced
+
+
+def autoreplace_signature():
+    postfix = '_autosignature'
+    saqc_path = 'saqc/core/modules/'
+    touched_modules = []
+
+    for name in FUNC_MAP:
+        module, fname = name.split('.')
+
+        with open(f'saqc/funcs/{module}.py', 'r') as fh:
+            lines = find_original_signature(fh, fname)
+
+        if lines is None:
+            warnings.warn(f"end of signature of '{fname}' not found - ignoring")
+            continue
+
+        lines = replace_datafieldflagger(lines)
+        print(''.join(lines))
+
+        readfile = f'{saqc_path}{module}.py'
+        writefile = f'{saqc_path}{module}{postfix}.py'
+        if module in touched_modules:
+            readfile = writefile
+        else:
+            touched_modules.append(module)
+
+        with open(readfile, 'r') as fh:
+            readlines = fh.readlines()
+
+        with open(writefile, 'w') as fh:
+            replace_core_signatures(readlines, lines, fname, fh)
+
+    files = os.listdir('saqc/core/modules/')
+    for new in files:
+        if postfix in new:
+            old = saqc_path + new.replace(postfix, '')
+            new = saqc_path + new
+            os.replace(new, old)
+
+
+if __name__ == '__main__':
+    autoreplace_signature()
-- 
GitLab