Skip to content

Commit 873926f

Browse files
committed
move from time check to backup as file safety strategy
1 parent cc8b7fc commit 873926f

File tree

12 files changed

+3538
-3288
lines changed

12 files changed

+3538
-3288
lines changed

coverage.txt

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
============================= test session starts ==============================
2-
platform darwin -- Python 3.9.7, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
2+
platform darwin -- Python 3.9.12, pytest-7.1.1, pluggy-1.0.0
33
rootdir: /Users/johnmount/Documents/work/wvpy/pkg
44
plugins: anyio-3.5.0, cov-3.0.0
55
collected 20 items
@@ -19,16 +19,26 @@ tests/test_stats1.py . [ 90%]
1919
tests/test_threshold_stats.py . [ 95%]
2020
tests/test_typs_in_frame.py . [100%]
2121

22-
---------- coverage: platform darwin, python 3.9.7-final-0 -----------
22+
=============================== warnings summary ===============================
23+
../../../../opt/anaconda3/envs/research_env/lib/python3.9/site-packages/seaborn/rcmod.py:82
24+
/Users/johnmount/opt/anaconda3/envs/research_env/lib/python3.9/site-packages/seaborn/rcmod.py:82: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
25+
if LooseVersion(mpl.__version__) >= "3.0":
26+
27+
../../../../opt/anaconda3/envs/research_env/lib/python3.9/site-packages/setuptools/_distutils/version.py:351
28+
/Users/johnmount/opt/anaconda3/envs/research_env/lib/python3.9/site-packages/setuptools/_distutils/version.py:351: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
29+
other = LooseVersion(other)
30+
31+
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
32+
33+
---------- coverage: platform darwin, python 3.9.12-final-0 ----------
2334
Name Stmts Miss Cover
2435
---------------------------------------------
2536
wvpy/__init__.py 3 0 100%
2637
wvpy/jtools.py 146 32 78%
27-
wvpy/pysheet.py 79 79 0%
38+
wvpy/pysheet.py 89 89 0%
2839
wvpy/render_workbook.py 47 47 0%
2940
wvpy/util.py 321 7 98%
3041
---------------------------------------------
31-
TOTAL 596 165 72%
32-
42+
TOTAL 606 175 71%
3343

34-
============================= 20 passed in 14.28s ==============================
44+
======================= 20 passed, 2 warnings in 16.87s ========================

pkg/build/lib/wvpy/pysheet.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55

66
import argparse
77
import os
8+
import shutil
89
import sys
910
import traceback
1011
from wvpy.jtools import convert_py_file_to_notebook, convert_notebook_file_to_py
1112

1213

1314
def main() -> int:
14-
parser = argparse.ArgumentParser(description="Convert between .py and .ipynb (can have suffix, or guess suffix)")
15+
parser = argparse.ArgumentParser(description="Convert between .py and .ipynb or back (can have suffix, or guess suffix)")
1516
parser.add_argument('--quiet', action='store_true', help='delete input file')
1617
parser.add_argument('--delete', action='store_true', help='delete input file')
1718
parser.add_argument(
@@ -26,67 +27,79 @@ def main() -> int:
2627
assert len(set(args.infile)) == len(args.infile)
2728
assert isinstance(args.quiet, bool)
2829
assert isinstance(args.delete, bool)
30+
# set up the work request
31+
base_names_seen = set()
2932
input_suffices_seen = set()
3033
tasks = []
3134
other_suffix = {'.py': '.ipynb', '.ipynb': '.py'}
3235
for input_file_name in args.infile:
3336
assert isinstance(input_file_name, str)
3437
assert len(input_file_name) > 0
35-
suffix_seen = 'error' # placeholder
38+
suffix_seen = 'error' # placeholder/sentinel
39+
base_name = input_file_name
3640
if input_file_name.endswith('.py'):
3741
suffix_seen = '.py'
42+
base_name = input_file_name.removesuffix(suffix_seen)
3843
elif input_file_name.endswith('.ipynb'):
3944
suffix_seen = '.ipynb'
45+
base_name = input_file_name.removesuffix(suffix_seen)
4046
else:
4147
py_exists = os.path.exists(input_file_name + '.py')
4248
ipynb_exists = os.path.exists(input_file_name + '.ipynb')
4349
if py_exists == ipynb_exists:
44-
raise ValueError("if no suffix is specified, then exactly one of the .py or ipynb file forms must be present")
50+
raise ValueError(f'{base_name}: if no suffix is specified, then exactly one of the .py or ipynb file forms must be present')
4551
if py_exists:
4652
suffix_seen = '.py'
4753
else:
4854
suffix_seen = '.ipynb'
4955
input_file_name = input_file_name + suffix_seen
50-
assert suffix_seen in other_suffix.keys()
51-
input_suffices_seen.add(suffix_seen)
52-
if len(input_suffices_seen) != 1:
53-
raise ValueError(f"saw more than one input suffix: {input_suffices_seen}")
5456
assert os.path.exists(input_file_name)
55-
output_file_name = input_file_name.removesuffix(suffix_seen) + other_suffix[suffix_seen]
56-
if os.path.exists(output_file_name):
57-
if os.path.getmtime(output_file_name) > os.path.getmtime(input_file_name):
58-
raise ValueError(f"output {output_file_name} is already newer than input f{input_file_name}")
57+
assert suffix_seen in other_suffix.keys() # expected suffix
58+
assert base_name not in base_names_seen # each base file name only used once
59+
base_names_seen.add(base_name)
60+
input_suffices_seen.add(suffix_seen)
61+
if len(input_suffices_seen) != 1: # only one direction of conversion in batch job
62+
raise ValueError(f"conversion job may only have one input suffix: {input_suffices_seen}")
63+
output_file_name = base_name + other_suffix[suffix_seen]
5964
tasks.append((input_file_name, output_file_name))
60-
if len(input_suffices_seen) != 1:
61-
raise ValueError(f"expected only one input suffix: {input_suffices_seen}")
6265
# do the work
6366
for input_file_name, output_file_name in tasks:
67+
if not args.quiet:
68+
print(f'from "{input_file_name}" to "{output_file_name}"')
69+
# back up result target if present
70+
if os.path.exists(output_file_name):
71+
output_backup_file = f'{output_file_name}~'
72+
if not args.quiet:
73+
print(f' copying previous output target "{output_file_name}" to "{output_backup_file}"')
74+
shutil.copy2(output_file_name, output_backup_file)
75+
# convert
6476
if input_file_name.endswith('.py'):
6577
if not args.quiet:
66-
print(f"converting {input_file_name} to {output_file_name}")
78+
print(f" converting Python {input_file_name} to Jupyter notebook {output_file_name}")
6779
convert_py_file_to_notebook(
6880
py_file=input_file_name,
6981
ipynb_file=output_file_name,
7082
)
7183
elif input_file_name.endswith('.ipynb'):
7284
if not args.quiet:
73-
print(f"converting {input_file_name} to {output_file_name}")
85+
print(f' converting Jupyter notebook "{input_file_name}" to Python "{output_file_name}"')
7486
convert_notebook_file_to_py(
7587
ipynb_file=input_file_name,
7688
py_file=output_file_name)
7789
else:
7890
raise ValueError("input file name must end with .py or .ipynb")
79-
# do any deletions
80-
if args.delete:
81-
for input_file_name, output_file_name in tasks:
91+
# do any deletions
92+
if args.delete:
8293
input_backup_file = f'{input_file_name}~'
8394
if not args.quiet:
84-
print(f"moving {input_file_name} to {input_backup_file}")
95+
print(f" moving input {input_file_name} to {input_backup_file}")
8596
try:
8697
os.remove(input_backup_file)
8798
except FileNotFoundError:
8899
pass
89100
os.rename(input_file_name, input_backup_file)
101+
if not args.quiet:
102+
print()
90103
return 0
91104

92105

204 Bytes
Binary file not shown.

pkg/dist/wvpy-0.3.5.tar.gz

133 KB
Binary file not shown.

pkg/docs/search.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)