testgenie-py 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/PKG-INFO +1 -1
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/pyproject.toml +1 -1
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/.coverage +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/controller/docker_controller.py +56 -38
- testgenie_py-0.2.1/testgen/docker/Dockerfile +31 -0
- testgenie_py-0.2.1/testgen/tests/test_boolean.py +69 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/file_utils.py +40 -10
- testgenie_py-0.2.0/testgen/docker/Dockerfile +0 -22
- testgenie_py-0.2.0/testgen/docker/poetry.lock +0 -599
- testgenie_py-0.2.0/testgen/docker/pyproject.toml +0 -29
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/README.md +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/ast_analyzer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/contracts/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/contracts/contract.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/contracts/no_exception_contract.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/contracts/nonnull_contract.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/fuzz_analyzer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/random_feedback_analyzer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/reinforcement_analyzer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/test_case_analyzer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/analyzer/test_case_analyzer_context.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/boolean.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/calculator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/code_to_fuzz.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/code_to_fuzz_lite.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/decisions.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/math_utils.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/no_types.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/code_to_test/sample_code_bin.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/controller/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/controller/cli_controller.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/code_generator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/doctest_generator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/generator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/pytest_generator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/test_generator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/generator/unit_test_generator.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/inspector/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/inspector/inspector.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/main.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/models/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/models/analysis_context.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/models/function_metadata.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/models/generator_context.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/models/test_case.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/presentation/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/presentation/cli_view.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/q_table/global_q_table.json +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/reinforcement/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/reinforcement/abstract_state.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/reinforcement/agent.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/reinforcement/environment.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/reinforcement/statement_coverage_state.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/service/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/service/analysis_service.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/service/cfg_service.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/service/generator_service.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/service/logging_service.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/service/service.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/sqlite/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/sqlite/db.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/sqlite/db_service.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/testgen.db +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/tests/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/tests/test_decisions.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/tree/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/tree/node.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/tree/tree_utils.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/coverage_utils.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/coverage_visualizer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/randomizer.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/utils.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/z3_utils/__init__.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/z3_utils/ast_to_z3.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/z3_utils/branch_condition.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/z3_utils/constraint_extractor.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/z3_utils/variable_finder.py +0 -0
- {testgenie_py-0.2.0 → testgenie_py-0.2.1}/testgen/util/z3_utils/z3_test_case.py +0 -0
Binary file
|
@@ -30,6 +30,7 @@ class DockerController:
|
|
30
30
|
def run_in_docker(self, project_root: str, docker_client: DockerClient, args: Namespace) -> bool:
|
31
31
|
self.args = args
|
32
32
|
self.debug_mode = True if args.debug else False
|
33
|
+
|
33
34
|
os.environ["RUNNING_IN_DOCKER"] = "1"
|
34
35
|
|
35
36
|
# Check if Docker image exists, build it if not
|
@@ -41,6 +42,7 @@ class DockerController:
|
|
41
42
|
return False
|
42
43
|
|
43
44
|
docker_args = [args.file_path] + [arg for arg in sys.argv[2:] if arg != "--safe"]
|
45
|
+
docker_args[0] = f"/controller/testgen/code_to_test/{os.path.basename(docker_args[0])}"
|
44
46
|
|
45
47
|
# Run the container with the same arguments
|
46
48
|
try:
|
@@ -51,48 +53,44 @@ class DockerController:
|
|
51
53
|
logs_output = self.get_logs(container)
|
52
54
|
self.debug(logs_output)
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
target_path = os.path.join(os.getcwd(), 'tests')
|
58
|
-
else:
|
59
|
-
target_path = args.output
|
60
|
-
os.makedirs(target_path, exist_ok=True)
|
56
|
+
except Exception as e:
|
57
|
+
print(f"Error running container: {e}")
|
58
|
+
sys.exit(1)
|
61
59
|
|
62
|
-
|
60
|
+
# Create the target directory if it doesn't exist
|
61
|
+
if args.output is None:
|
62
|
+
target_path = os.path.join(os.getcwd(), 'tests')
|
63
|
+
else:
|
64
|
+
target_path = args.output
|
65
|
+
os.makedirs(target_path, exist_ok=True)
|
63
66
|
|
64
|
-
|
67
|
+
self.debug(f"SERVICE target path after logs: {target_path}")
|
65
68
|
|
66
|
-
|
69
|
+
test_cases = self.service.parse_test_cases_from_logs(logs_output)
|
67
70
|
|
68
|
-
|
69
|
-
self.debug(f"Filepath in CLI CONTROLLER: {file_path}")
|
70
|
-
self.service.set_file_path(file_path)
|
71
|
+
print(f"Extracted {len(test_cases)} test cases from container.")
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
self.service.set_test_generator_format(DOCTEST_FORMAT)
|
76
|
-
else:
|
77
|
-
self.service.set_test_generator_format(UNITTEST_FORMAT)
|
73
|
+
file_path = os.path.abspath(args.file_path)
|
74
|
+
self.debug(f"Filepath in CLI CONTROLLER: {file_path}")
|
75
|
+
self.service.set_file_path(file_path)
|
78
76
|
|
79
|
-
|
80
|
-
|
77
|
+
if args.test_format == "pytest":
|
78
|
+
self.service.set_test_generator_format(PYTEST_FORMAT)
|
79
|
+
elif args.test_format == "doctest":
|
80
|
+
self.service.set_test_generator_format(DOCTEST_FORMAT)
|
81
|
+
else:
|
82
|
+
self.service.set_test_generator_format(UNITTEST_FORMAT)
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
self.service.run_coverage(test_file)
|
85
|
-
|
86
|
-
# Add explicit return True here
|
87
|
-
return True
|
84
|
+
test_file = self.service.generate_test_file(test_cases, target_path)
|
85
|
+
print(f"Unit tests saved to: {test_file}")
|
88
86
|
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
if not args.generate_only:
|
88
|
+
print("Running coverage...")
|
89
|
+
self.service.run_coverage(test_file)
|
90
|
+
|
91
|
+
# Add explicit return True here
|
92
|
+
return True
|
92
93
|
|
93
|
-
except Exception as e:
|
94
|
-
print(f"Error running container: {e}")
|
95
|
-
sys.exit(1)
|
96
94
|
|
97
95
|
def get_image(self, docker_client: DockerClient, image_name: str, project_root: str):
|
98
96
|
try:
|
@@ -129,15 +127,30 @@ class DockerController:
|
|
129
127
|
# Create Docker-specific environment variables
|
130
128
|
docker_env = {
|
131
129
|
"RUNNING_IN_DOCKER": "1",
|
132
|
-
"PYTHONPATH": "/controller"
|
133
|
-
"COVERAGE_FILE": "/tmp/.coverage", # Move coverage file to /tmp
|
134
|
-
"DB_PATH": "/tmp/testgen.db" # Move DB to /tmp
|
130
|
+
"PYTHONPATH": "/controller"
|
135
131
|
}
|
136
132
|
|
133
|
+
# Join arguments with proper escaping
|
134
|
+
args_str = ' '.join(f'"{arg}"' for arg in docker_args)
|
135
|
+
|
136
|
+
print(f"Docker args: {docker_args}")
|
137
|
+
print(f"Project root: {project_root}")
|
138
|
+
|
139
|
+
# Debug command to find file and then run testgenie with args
|
140
|
+
debug_cmd = f'find /controller -type f -name "*.py" | grep -i boolean || echo "File not found"; ' \
|
141
|
+
f'ls -la /controller; ' \
|
142
|
+
f'testgenie /controller/testgen/code_to_test/boolean.py --test-mode=fuzz --test-format=pytest'
|
143
|
+
|
137
144
|
return docker_client.containers.run(
|
138
145
|
image=image_name,
|
139
|
-
command=["
|
140
|
-
volumes={
|
146
|
+
command=["sh", "-c", debug_cmd],
|
147
|
+
volumes={
|
148
|
+
os.path.abspath(project_root): {
|
149
|
+
"bind": "/controller",
|
150
|
+
"mode": "rw"
|
151
|
+
}
|
152
|
+
},
|
153
|
+
working_dir="/controller",
|
141
154
|
environment=docker_env,
|
142
155
|
detach=True,
|
143
156
|
remove=True,
|
@@ -203,6 +216,11 @@ class DockerController:
|
|
203
216
|
print("Dockerfile not found in local project or package.")
|
204
217
|
sys.exit(1)
|
205
218
|
|
219
|
+
@staticmethod
|
220
|
+
def is_inside_docker() -> bool:
|
221
|
+
"""Check if the current process is running inside a Docker container."""
|
222
|
+
return os.environ.get("RUNNING_IN_DOCKER") in ("1", "true", "True")
|
223
|
+
|
206
224
|
def debug(self, message: str):
|
207
225
|
"""Log debug message"""
|
208
226
|
if self.debug_mode:
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Use Python 3.10 image
|
2
|
+
FROM python:3.10
|
3
|
+
|
4
|
+
# Install system dependencies
|
5
|
+
RUN apt-get update && apt-get install -y \
|
6
|
+
build-essential \
|
7
|
+
graphviz \
|
8
|
+
libgraphviz-dev \
|
9
|
+
pkg-config \
|
10
|
+
curl
|
11
|
+
|
12
|
+
# Install Poetry (optional, in case you ever need it)
|
13
|
+
RUN curl -sSL https://install.python-poetry.org | python3 - && \
|
14
|
+
ln -s /root/.local/bin/poetry /usr/local/bin/poetry
|
15
|
+
|
16
|
+
# Set environment variables
|
17
|
+
ENV POETRY_VIRTUALENVS_CREATE=false \
|
18
|
+
PYTHONUNBUFFERED=1 \
|
19
|
+
RUNNING_IN_DOCKER=true
|
20
|
+
|
21
|
+
# Install your package from PyPI
|
22
|
+
RUN python3 -m pip install --no-cache-dir testgenie-py
|
23
|
+
|
24
|
+
# Set a working directory (where your code will be mounted at runtime)
|
25
|
+
WORKDIR /controller
|
26
|
+
|
27
|
+
# Set up PYTHONPATH
|
28
|
+
ENV PYTHONPATH=/controller:/controller/testgen
|
29
|
+
|
30
|
+
# Default command
|
31
|
+
CMD ["testgenie"]
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
import testgen.code_to_test.boolean as boolean
|
4
|
+
|
5
|
+
def test_bin_and_0():
|
6
|
+
args = (False, False)
|
7
|
+
expected = False
|
8
|
+
result = boolean.bin_and(*args)
|
9
|
+
assert result == expected
|
10
|
+
|
11
|
+
def test_bin_and_1():
|
12
|
+
args = (True, True)
|
13
|
+
expected = True
|
14
|
+
result = boolean.bin_and(*args)
|
15
|
+
assert result == expected
|
16
|
+
|
17
|
+
def test_bin_and_2():
|
18
|
+
args = (True, False)
|
19
|
+
expected = False
|
20
|
+
result = boolean.bin_and(*args)
|
21
|
+
assert result == expected
|
22
|
+
|
23
|
+
def test_bin_xor_3():
|
24
|
+
args = (True, True)
|
25
|
+
expected = False
|
26
|
+
result = boolean.bin_xor(*args)
|
27
|
+
assert result == expected
|
28
|
+
|
29
|
+
def test_bin_xor_4():
|
30
|
+
args = (True, False)
|
31
|
+
expected = True
|
32
|
+
result = boolean.bin_xor(*args)
|
33
|
+
assert result == expected
|
34
|
+
|
35
|
+
def test_bin_xor_5():
|
36
|
+
args = (False, False)
|
37
|
+
expected = False
|
38
|
+
result = boolean.bin_xor(*args)
|
39
|
+
assert result == expected
|
40
|
+
|
41
|
+
def test_status_flags_6():
|
42
|
+
args = (True, False, True)
|
43
|
+
expected = 'admin-unverified'
|
44
|
+
result = boolean.status_flags(*args)
|
45
|
+
assert result == expected
|
46
|
+
|
47
|
+
def test_status_flags_7():
|
48
|
+
args = (False, False, False)
|
49
|
+
expected = 'inactive'
|
50
|
+
result = boolean.status_flags(*args)
|
51
|
+
assert result == expected
|
52
|
+
|
53
|
+
def test_status_flags_8():
|
54
|
+
args = (True, False, False)
|
55
|
+
expected = 'user-unverified'
|
56
|
+
result = boolean.status_flags(*args)
|
57
|
+
assert result == expected
|
58
|
+
|
59
|
+
def test_status_flags_9():
|
60
|
+
args = (False, True, True)
|
61
|
+
expected = 'admin-verified'
|
62
|
+
result = boolean.status_flags(*args)
|
63
|
+
assert result == expected
|
64
|
+
|
65
|
+
def test_status_flags_10():
|
66
|
+
args = (True, True, False)
|
67
|
+
expected = 'user-verified'
|
68
|
+
result = boolean.status_flags(*args)
|
69
|
+
assert result == expected
|
@@ -109,8 +109,23 @@ def load_and_parse_file_for_tree(file) -> Module:
|
|
109
109
|
tree = ast.parse(code)
|
110
110
|
return tree
|
111
111
|
|
112
|
-
def adjust_file_path_for_docker(file_path) -> str:
|
113
|
-
|
112
|
+
def adjust_file_path_for_docker(file_path: str) -> str:
|
113
|
+
"""Adjust the file path to be valid inside the Docker container."""
|
114
|
+
print(f"Docker - adjusting path: {file_path}")
|
115
|
+
|
116
|
+
# If already absolute to /controller, return as-is
|
117
|
+
if file_path.startswith("/controller/"):
|
118
|
+
print(f"Docker - already adjusted: {file_path}")
|
119
|
+
return file_path
|
120
|
+
|
121
|
+
# If relative, make absolute
|
122
|
+
adjusted_path = f"/controller/{file_path.lstrip('/')}"
|
123
|
+
print(f"Docker - adjusted to: {adjusted_path}")
|
124
|
+
return adjusted_path
|
125
|
+
|
126
|
+
|
127
|
+
"""def adjust_file_path_for_docker(file_path) -> str:
|
128
|
+
#Adjust file path for Docker environment to handle subdirectories and relative paths.
|
114
129
|
print(f"Docker - adjusting path: {file_path}")
|
115
130
|
|
116
131
|
# Try direct path first (maybe it's correct already)
|
@@ -144,13 +159,28 @@ def adjust_file_path_for_docker(file_path) -> str:
|
|
144
159
|
|
145
160
|
# Return original path if we couldn't find a better match
|
146
161
|
print(f"Docker - couldn't find file, returning original: {file_path}")
|
147
|
-
return file_path
|
162
|
+
return file_path"""
|
163
|
+
|
164
|
+
|
148
165
|
|
149
166
|
def get_project_root_in_docker(script_path) -> str:
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
project_root =
|
155
|
-
|
156
|
-
|
167
|
+
# Don't use sys.argv[0] as it points to the virtualenv
|
168
|
+
# Instead, find the actual project root
|
169
|
+
if os.path.exists('/mnt/c/Users/cjsei/thesis/dev/testgen'):
|
170
|
+
# Hard-coded path for now
|
171
|
+
project_root = '/mnt/c/Users/cjsei/thesis/dev/testgen'
|
172
|
+
else:
|
173
|
+
# Try to find project root by looking for pyproject.toml or similar
|
174
|
+
current_dir = os.path.dirname(os.path.abspath(script_path))
|
175
|
+
while current_dir != '/':
|
176
|
+
if os.path.exists(os.path.join(current_dir, 'pyproject.toml')) or \
|
177
|
+
os.path.exists(os.path.join(current_dir, 'setup.py')):
|
178
|
+
project_root = current_dir
|
179
|
+
break
|
180
|
+
current_dir = os.path.dirname(current_dir)
|
181
|
+
else:
|
182
|
+
# Fallback - use parent of script dir
|
183
|
+
project_root = os.path.dirname(os.path.dirname(os.path.abspath(script_path)))
|
184
|
+
|
185
|
+
print(f"Project root directory: {project_root}")
|
186
|
+
return project_root
|
@@ -1,22 +0,0 @@
|
|
1
|
-
FROM python:3.10
|
2
|
-
|
3
|
-
RUN apt-get update && apt-get install -y curl build-essential
|
4
|
-
|
5
|
-
RUN curl -sSL https://install.python-poetry.org | python3 - \
|
6
|
-
&& ln -s /root/.local/bin/poetry /usr/local/bin/poetry
|
7
|
-
|
8
|
-
ENV POETRY_VIRTUALENVS_CREATE=false \
|
9
|
-
PYTHONUNBUFFERED=1 \
|
10
|
-
RUNNING_IN_DOCKER=true
|
11
|
-
|
12
|
-
WORKDIR /controller
|
13
|
-
|
14
|
-
# Copy poetry files
|
15
|
-
COPY . .
|
16
|
-
|
17
|
-
ENV PYTHONPATH=/controller:/controller/testgen
|
18
|
-
|
19
|
-
RUN poetry install --no-root
|
20
|
-
|
21
|
-
# Entrypoint (Can be overridden by Docker SDK in Python)
|
22
|
-
CMD ["poetry", "run", "python", "-m", "testgen.main"]
|