Skip to content

Commit 578a88e

Browse files
committed
Initial reformat of requirements.json creation
1 parent 6a5b357 commit 578a88e

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

src/sasctl/pzmm/write_json_files.py

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
import json
99
import pandas as pd
1010
import math
11+
import numpy as np
12+
from scipy.stats import kendalltau, gamma
13+
import types
14+
import pickle
15+
import pickletools
16+
from pipreqs import pipreqs
1117

1218

1319
class JSONFiles:
@@ -950,3 +956,178 @@ def convertDataRole(self, dataRole):
950956
conversion = 1
951957

952958
return conversion
959+
960+
def get_imports(self):
961+
"""[summary]
962+
963+
Yields
964+
-------
965+
[type]
966+
[description]
967+
"""
968+
969+
for name, val in globals().items():
970+
if isinstance(val, types.ModuleType):
971+
# Split ensures you get root package, not just imported function
972+
name = val.__name__.split(".")[0]
973+
yield name
974+
elif isinstance(val, type):
975+
name = val.__module__.split(".")[0]
976+
yield name
977+
978+
def get_pickle_file(self, pPath):
979+
"""[summary]
980+
981+
Parameters
982+
----------
983+
pPath : [type]
984+
[description]
985+
"""
986+
fileNames = []
987+
fileNames.extend(sorted(Path(pPath).glob("*.pickle")))
988+
989+
def get_modules_from_pickle_file(self, pickle_file):
990+
"""[summary]
991+
992+
Parameters
993+
----------
994+
pickle_file : [type]
995+
[description]
996+
997+
Returns
998+
-------
999+
[type]
1000+
[description]
1001+
"""
1002+
with (open(pickle_file, "rb")) as openfile:
1003+
obj = pickle.load(openfile)
1004+
dumps = pickle.dumps(obj)
1005+
1006+
modules = {mod.split(".")[0] for mod, _ in self.get_names(dumps)}
1007+
return modules
1008+
1009+
def createRequirementsJSON(self, jPath=Path.cwd()):
1010+
"""[summary]
1011+
1012+
Parameters
1013+
----------
1014+
jPath : [type], optional
1015+
[description], by default Path.cwd()
1016+
"""
1017+
1018+
imports = list(set(self.get_imports()))
1019+
1020+
with open("./imports.py", "w") as file:
1021+
for item in imports:
1022+
file.write("import %s\n" % item)
1023+
1024+
pipreqs.init(
1025+
{
1026+
"<path>": jPath,
1027+
"--savepath": None,
1028+
"--print": False,
1029+
"--use-local": None,
1030+
"--force": True,
1031+
"--proxy": None,
1032+
"--pypi-server": None,
1033+
"--diff": None,
1034+
"--clean": None,
1035+
}
1036+
)
1037+
1038+
module_version_map = {}
1039+
pickle_file = self.get_pickle_file(jPath)
1040+
filename = "./requirements.txt"
1041+
with open(filename, "r") as f:
1042+
modules_requirements_txt = set()
1043+
modules_pickle = self.get_modules_from_pickle_file(pickle_file)
1044+
for line in f:
1045+
module_parts = line.rstrip().split("==")
1046+
module = module_parts[0]
1047+
version = module_parts[1]
1048+
module_version_map[module] = version
1049+
modules_requirements_txt.add(module)
1050+
pip_name_list = list(modules_requirements_txt.union(modules_pickle))
1051+
1052+
for item in pip_name_list:
1053+
if item in module_version_map:
1054+
if module_version_map[item] == "0.0.0":
1055+
print(
1056+
"Warning: No pip install name found for package: "
1057+
+ item.split("==")[0]
1058+
)
1059+
pip_name_list.remove(item)
1060+
1061+
j = json.dumps(
1062+
[
1063+
{
1064+
"step": "install " + i,
1065+
"command": "pip install " + i + "==" + module_version_map[i],
1066+
}
1067+
if i in module_version_map
1068+
else {"step": "install " + i, "command": "pip install " + i}
1069+
for i in pip_name_list
1070+
],
1071+
indent=4,
1072+
)
1073+
with open("./requirements.json", "w") as file:
1074+
print(j, file=file)
1075+
1076+
def get_names(self, stream):
1077+
"""Generates (module, qualname) tuples from a pickle stream
1078+
1079+
Credit: https://stackoverflow.com/questions/64850179/inspecting-a-pickle-dump-for-dependencies
1080+
1081+
Parameters
1082+
----------
1083+
stream : [type]
1084+
[description]
1085+
1086+
Yields
1087+
-------
1088+
[type]
1089+
[description]
1090+
"""
1091+
1092+
stack, markstack, memo = [], [], []
1093+
mo = pickletools.markobject
1094+
1095+
for op, arg, pos in pickletools.genops(stream):
1096+
# simulate the pickle stack and marking scheme, insofar
1097+
# necessary to allow us to retrieve the names used by STACK_GLOBAL
1098+
1099+
before, after = op.stack_before, op.stack_after
1100+
numtopop = len(before)
1101+
1102+
if op.name == "GLOBAL":
1103+
yield tuple(arg.split(1, None))
1104+
elif op.name == "STACK_GLOBAL":
1105+
yield (stack[-2], stack[-1])
1106+
1107+
elif mo in before or (op.name == "POP" and stack and stack[-1] is mo):
1108+
markpos = markstack.pop()
1109+
while stack[-1] is not mo:
1110+
stack.pop()
1111+
stack.pop()
1112+
try:
1113+
numtopop = before.index(mo)
1114+
except ValueError:
1115+
numtopop = 0
1116+
elif op.name in {"PUT", "BINPUT", "LONG_BINPUT", "MEMOIZE"}:
1117+
if op.name == "MEMOIZE":
1118+
memo.append(stack[-1])
1119+
else:
1120+
memo[arg] = stack[-1]
1121+
numtopop, after = 0, [] # memoize and put do not pop the stack
1122+
elif op.name in {"GET", "BINGET", "LONG_BINGET"}:
1123+
arg = memo[arg]
1124+
1125+
if numtopop:
1126+
del stack[-numtopop:]
1127+
if mo in after:
1128+
markstack.append(pos)
1129+
1130+
if len(after) == 1 and op.arg is not None:
1131+
stack.append(arg)
1132+
else:
1133+
stack.extend(after)

0 commit comments

Comments
 (0)