Skip to content
This repository was archived by the owner on Aug 25, 2024. It is now read-only.

Commit 0a2e053

Browse files
committed
start on dep tree
Signed-off-by: John Andersen <[email protected]>
1 parent cd77675 commit 0a2e053

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import sys
2+
import pathlib
3+
import argparse
4+
import unittest.mock
5+
import importlib.util
6+
7+
from dffml.base import config
8+
from dffml.util.os import chdir
9+
from dffml.df.base import opimp_in, op
10+
from dffml.df.types import Input, DataFlow
11+
from dffml.service.dev import SetupPyKWArg
12+
from dffml.operation.output import GetMulti
13+
from dffml.df.memory import MemoryOrchestrator
14+
from dffml.util.asynctestcase import AsyncTestCase
15+
16+
from shouldi.pypi import *
17+
18+
19+
def remove_package_versions(packages):
20+
no_versions = []
21+
22+
appended = False
23+
for package in packages:
24+
for char in [">", "<", "="]:
25+
if char in package:
26+
no_versions.append(package.split(char)[0].strip())
27+
appended = True
28+
break
29+
if not appended:
30+
no_versions.append(package.strip())
31+
appended = False
32+
33+
return no_versions
34+
35+
36+
PACKAGE_DEPS_KWARGS = dict(
37+
inputs={"src": pypi_package_contents.op.outputs["directory"],},
38+
outputs={"package": pypi_package_json.op.inputs["package"]},
39+
expand=["package"],
40+
)
41+
42+
43+
@op(**PACKAGE_DEPS_KWARGS)
44+
async def package_deps_setup_py(src: str):
45+
setup_py_path = list(pathlib.Path(src).rglob("**/setup.py"))
46+
if not setup_py_path:
47+
return
48+
49+
setup_py_path = setup_py_path[0]
50+
51+
deps = SetupPyKWArg.get_kwargs(str(setup_py_path)).get(
52+
"install_requires", []
53+
)
54+
55+
no_versions = {}
56+
57+
print(src, remove_package_versions(deps))
58+
59+
return {"package": remove_package_versions(deps)}
60+
61+
62+
@op(**PACKAGE_DEPS_KWARGS)
63+
async def package_deps_setup_cfg(src: str):
64+
# TODO
65+
return {"package": []}
66+
67+
68+
@op(**PACKAGE_DEPS_KWARGS)
69+
async def package_deps_requirements_txt(src: str):
70+
# TODO
71+
return {"package": []}
72+
73+
74+
SUBFLOW = DataFlow.auto(*[opimp for opimp in opimp_in(sys.modules[__name__])])
75+
SUBFLOW.seed.append(
76+
Input(
77+
value=[pypi_package_json.op.inputs["package"].name],
78+
definition=GetMulti.op.inputs["spec"],
79+
)
80+
)
81+
# Do not allow package names in the subflow to re-trigger the whole subflow
82+
# again, since this will cause version numbers and directories to get crossed
83+
SUBFLOW.flow["pypi_package_json"].inputs["package"] = ["seed"]
84+
SUBFLOW.update_by_origin()
85+
86+
87+
def create_parent_flow():
88+
"""
89+
This function exists so that shouldi_dataflow_as_operation doesn't end up
90+
in the subflow when we grab from sys.modules[__name__]
91+
"""
92+
93+
@config
94+
class ShouldIDataFlowAsOperationConfig:
95+
dataflow: DataFlow
96+
97+
@op(
98+
inputs={"package": pypi_package_json.op.inputs["package"]},
99+
outputs={"package": pypi_package_json.op.inputs["package"]},
100+
expand=["package"],
101+
config_cls=ShouldIDataFlowAsOperationConfig,
102+
)
103+
async def shouldi_dataflow_as_operation(self, package: str):
104+
async with self.octx.parent(self.config.dataflow) as octx:
105+
async for ctx, result in octx.run(
106+
{
107+
package: [
108+
Input(
109+
value=package,
110+
definition=self.parent.op.inputs["package"],
111+
)
112+
]
113+
}
114+
):
115+
packages = result[self.parent.op.inputs["package"].name]
116+
# Remove input package from list
117+
packages = list(filter(lambda pkg: pkg != package, packages))
118+
# TODO Deduplicate
119+
return {"package": packages}
120+
121+
dataflow = DataFlow.auto(shouldi_dataflow_as_operation, GetMulti)
122+
dataflow.seed.append(
123+
Input(
124+
value=[pypi_package_json.op.inputs["package"].name],
125+
definition=GetMulti.op.inputs["spec"],
126+
)
127+
)
128+
dataflow.configs[
129+
"shouldi_dataflow_as_operation"
130+
] = ShouldIDataFlowAsOperationConfig(dataflow=SUBFLOW)
131+
dataflow.flow["shouldi_dataflow_as_operation"].inputs["package"].append(
132+
"seed"
133+
)
134+
dataflow.update_by_origin()
135+
return dataflow
136+
137+
138+
DATAFLOW = create_parent_flow()
139+
140+
141+
class TestOperations(AsyncTestCase):
142+
async def test_run(self):
143+
check = {"shouldi": [], "dffml-config-yaml": []}
144+
async with MemoryOrchestrator.withconfig({}) as orchestrator:
145+
async with orchestrator(DATAFLOW) as octx:
146+
async for ctx, results in octx.run(
147+
{
148+
package_name: [
149+
Input(
150+
value=package_name,
151+
definition=pypi_package_json.op.inputs[
152+
"package"
153+
],
154+
),
155+
]
156+
for package_name in check.keys()
157+
}
158+
):
159+
ctx_str = (await ctx.handle()).as_string()
160+
with self.subTest(package=ctx_str):
161+
print(ctx_str, results)
162+
print(DATAFLOW.flow)
163+
continue
164+
self.assertEqual(
165+
check[ctx_str],
166+
results[
167+
pypi_package_json.op.inputs["package"].name
168+
],
169+
)

0 commit comments

Comments
 (0)