pysfi 0.1.0__py3-none-any.whl → 0.1.4__py3-none-any.whl
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.
- pysfi-0.1.4.dist-info/METADATA +107 -0
- pysfi-0.1.4.dist-info/RECORD +17 -0
- {pysfi-0.1.0.dist-info → pysfi-0.1.4.dist-info}/WHEEL +1 -1
- {pysfi-0.1.0.dist-info → pysfi-0.1.4.dist-info}/entry_points.txt +1 -0
- sfi/__init__.py +3 -0
- sfi/alarmclock/alarmclock.py +367 -367
- sfi/bumpversion/__init__.py +3 -0
- sfi/bumpversion/bumpversion.py +535 -0
- sfi/embedinstall/embedinstall.py +418 -418
- sfi/makepython/makepython.py +310 -68
- sfi/pyloadergen/pyloadergen.py +995 -1042
- pysfi-0.1.0.dist-info/METADATA +0 -78
- pysfi-0.1.0.dist-info/RECORD +0 -17
- sfi/pyloadergen/tests/__init__.py +0 -0
- sfi/pyloadergen/tests/test_pyloadergen.py +0 -290
pysfi-0.1.0.dist-info/METADATA
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pysfi
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Single File commands for Interactive python.
|
|
5
|
-
Requires-Python: >=3.8
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
|
|
8
|
-
# sfi
|
|
9
|
-
|
|
10
|
-
Single File commands for Interactive python.
|
|
11
|
-
|
|
12
|
-
## Overview
|
|
13
|
-
|
|
14
|
-
sfi is a Python project that provides single-file command-line utilities, designed to be lightweight and easy-to-use.
|
|
15
|
-
|
|
16
|
-
## Available Commands
|
|
17
|
-
|
|
18
|
-
### [filedate](sfi/filedate/README.md)
|
|
19
|
-
|
|
20
|
-
A file date management tool that normalizes date prefixes in filenames.
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# Install using uv (recommended)
|
|
26
|
-
uv add sfi
|
|
27
|
-
|
|
28
|
-
# Or using pip
|
|
29
|
-
pip install sfi
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Development
|
|
33
|
-
|
|
34
|
-
### Requirements
|
|
35
|
-
|
|
36
|
-
- Python >= 3.8
|
|
37
|
-
- [uv](https://github.com/astral-sh/uv) (recommended) or pip
|
|
38
|
-
|
|
39
|
-
### Development Dependencies
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
uv pip install -e ".[dev]"
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Code Standards
|
|
46
|
-
|
|
47
|
-
The project uses Ruff for code linting and formatting:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# Check code
|
|
51
|
-
ruff check .
|
|
52
|
-
|
|
53
|
-
# Format code
|
|
54
|
-
ruff format .
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Project Structure
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
sfi/
|
|
61
|
-
├── pyproject.toml # Main project configuration
|
|
62
|
-
├── README.md
|
|
63
|
-
└── sfi/
|
|
64
|
-
├── __init__.py
|
|
65
|
-
└── filedate/ # filedate command module
|
|
66
|
-
├── __init__.py
|
|
67
|
-
├── filedate.py # Main implementation
|
|
68
|
-
├── pyproject.toml
|
|
69
|
-
└── README.md # Detailed documentation
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## License
|
|
73
|
-
|
|
74
|
-
MIT License
|
|
75
|
-
|
|
76
|
-
## Contributing
|
|
77
|
-
|
|
78
|
-
Issues and Pull Requests are welcome!
|
pysfi-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
sfi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
sfi/alarmclock/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
sfi/alarmclock/alarmclock.py,sha256=65G8OyTGpe4oQ2SFerQG1N9PVJ4KxO7WzgsTxpGm4O0,12509
|
|
4
|
-
sfi/embedinstall/embedinstall.py,sha256=N5EbTDdX4bE3W0qHGAwAUuepqFr0sbdZuPI3KWrtuUY,14936
|
|
5
|
-
sfi/filedate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
sfi/filedate/filedate.py,sha256=DpVp26lumE_Lz_4TgqUEX8IxtK3Y6yHSEFV8qJyegyk,3645
|
|
7
|
-
sfi/makepython/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
sfi/makepython/makepython.py,sha256=9-PPKlxAnaHm9NPhfpn1jcnEYix84rAM77tkHGQeWtA,2244
|
|
9
|
-
sfi/projectparse/projectparse.py,sha256=Ojg-z4lZEtjEBpJYWyznTgL307N45AxlQKnRkEH0P70,5525
|
|
10
|
-
sfi/pyloadergen/pyloadergen.py,sha256=yfMOeusAXm89gM02h21zQVoaSt6dkA2khXxfuU6Ognk,34182
|
|
11
|
-
sfi/pyloadergen/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
sfi/pyloadergen/tests/test_pyloadergen.py,sha256=rprkF2Flhg23S875ZWgaJYvwAHdHHh4K4mm5zetYx2I,12817
|
|
13
|
-
sfi/pypacker/fspacker.py,sha256=3tlS7qiWoH_kOzsp9eSWsQ-SY7-bSTugwfB-HIL69iE,3238
|
|
14
|
-
pysfi-0.1.0.dist-info/METADATA,sha256=S3mdC8SfZ4sl3pU9MneCAwu3Qf5c4r07x-bcN4ACJOw,1402
|
|
15
|
-
pysfi-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
-
pysfi-0.1.0.dist-info/entry_points.txt,sha256=aV9Do3TJC0HT-QMorLRmj-KYeCvRYqkdNgE5HeYj98w,320
|
|
17
|
-
pysfi-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
"""Test suite for pyloadergen module."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import tempfile
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from unittest import mock
|
|
8
|
-
|
|
9
|
-
from sfi.pyloadergen import pyloadergen
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TestSelectTemplate:
|
|
13
|
-
"""Test template selection logic."""
|
|
14
|
-
|
|
15
|
-
def test_windows_gui_template_non_debug(self):
|
|
16
|
-
"""Test Windows GUI template selection in non-debug mode."""
|
|
17
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", True): # noqa: SIM117
|
|
18
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", False):
|
|
19
|
-
result = pyloadergen.select_template("gui", False)
|
|
20
|
-
assert result == pyloadergen._WINDOWS_GUI_TEMPLATE
|
|
21
|
-
|
|
22
|
-
def test_windows_console_template_non_debug(self):
|
|
23
|
-
"""Test Windows console template selection in non-debug mode."""
|
|
24
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", True): # noqa: SIM117
|
|
25
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", False):
|
|
26
|
-
result = pyloadergen.select_template("console", False)
|
|
27
|
-
assert result == pyloadergen._WINDOWS_CONSOLE_TEMPLATE
|
|
28
|
-
|
|
29
|
-
def test_windows_gui_template_debug(self):
|
|
30
|
-
"""Test that debug mode forces console template on Windows."""
|
|
31
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", True): # noqa: SIM117
|
|
32
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", False):
|
|
33
|
-
result = pyloadergen.select_template("gui", True)
|
|
34
|
-
assert result == pyloadergen._WINDOWS_CONSOLE_TEMPLATE
|
|
35
|
-
|
|
36
|
-
def test_macos_gui_template_non_debug(self):
|
|
37
|
-
"""Test macOS GUI template selection in non-debug mode."""
|
|
38
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", False): # noqa: SIM117
|
|
39
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", True):
|
|
40
|
-
result = pyloadergen.select_template("gui", False)
|
|
41
|
-
assert result == pyloadergen._MACOS_GUI_TEMPLATE
|
|
42
|
-
|
|
43
|
-
def test_macos_console_template_debug(self):
|
|
44
|
-
"""Test that debug mode forces console template on macOS."""
|
|
45
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", False): # noqa: SIM117
|
|
46
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", True):
|
|
47
|
-
result = pyloadergen.select_template("gui", True)
|
|
48
|
-
assert result == pyloadergen._MACOS_CONSOLE_TEMPLATE
|
|
49
|
-
|
|
50
|
-
def test_unix_gui_template_non_debug(self):
|
|
51
|
-
"""Test Unix GUI template selection in non-debug mode."""
|
|
52
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", False): # noqa: SIM117
|
|
53
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", False):
|
|
54
|
-
result = pyloadergen.select_template("gui", False)
|
|
55
|
-
assert result == pyloadergen._UNIX_GUI_TEMPLATE
|
|
56
|
-
|
|
57
|
-
def test_unix_console_template_debug(self):
|
|
58
|
-
"""Test that debug mode forces console template on Unix."""
|
|
59
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", False): # noqa: SIM117
|
|
60
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_macos", False):
|
|
61
|
-
result = pyloadergen.select_template("gui", True)
|
|
62
|
-
assert result == pyloadergen._UNIX_CONSOLE_TEMPLATE
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class TestGenerateCSource:
|
|
66
|
-
"""Test C source code generation."""
|
|
67
|
-
|
|
68
|
-
def test_replace_entry_file_placeholder(self):
|
|
69
|
-
"""Test that ENTRY_FILE placeholder is replaced."""
|
|
70
|
-
template = "script: ${ENTRY_FILE}"
|
|
71
|
-
result = pyloadergen.generate_c_source(template, "my_script.py", False)
|
|
72
|
-
assert "my_script.py" in result
|
|
73
|
-
assert "${ENTRY_FILE}" not in result
|
|
74
|
-
|
|
75
|
-
def test_replace_debug_mode_placeholder_true(self):
|
|
76
|
-
"""Test that DEBUG_MODE placeholder is replaced with 1."""
|
|
77
|
-
template = "debug: ${DEBUG_MODE}"
|
|
78
|
-
result = pyloadergen.generate_c_source(template, "test.py", True)
|
|
79
|
-
assert "debug: 1" in result
|
|
80
|
-
assert "${DEBUG_MODE}" not in result
|
|
81
|
-
|
|
82
|
-
def test_replace_debug_mode_placeholder_false(self):
|
|
83
|
-
"""Test that DEBUG_MODE placeholder is replaced with 0."""
|
|
84
|
-
template = "debug: ${DEBUG_MODE}"
|
|
85
|
-
result = pyloadergen.generate_c_source(template, "test.py", False)
|
|
86
|
-
assert "debug: 0" in result
|
|
87
|
-
assert "${DEBUG_MODE}" not in result
|
|
88
|
-
|
|
89
|
-
def test_replace_both_placeholders(self):
|
|
90
|
-
"""Test that both placeholders are replaced correctly."""
|
|
91
|
-
template = "file: ${ENTRY_FILE}, debug: ${DEBUG_MODE}"
|
|
92
|
-
result = pyloadergen.generate_c_source(template, "main.py", True)
|
|
93
|
-
assert "file: main.py" in result
|
|
94
|
-
assert "debug: 1" in result
|
|
95
|
-
assert "${ENTRY_FILE}" not in result
|
|
96
|
-
assert "${DEBUG_MODE}" not in result
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class TestGetCompilerArgs:
|
|
100
|
-
"""Test compiler argument retrieval."""
|
|
101
|
-
|
|
102
|
-
def test_gcc_compiler_args(self):
|
|
103
|
-
"""Test GCC compiler arguments."""
|
|
104
|
-
args = pyloadergen.get_compiler_args("gcc")
|
|
105
|
-
assert "-std=c99" in args
|
|
106
|
-
assert "-Wall" in args
|
|
107
|
-
assert "-pedantic" in args
|
|
108
|
-
assert "-Werror" in args
|
|
109
|
-
|
|
110
|
-
def test_clang_compiler_args(self):
|
|
111
|
-
"""Test Clang compiler arguments."""
|
|
112
|
-
args = pyloadergen.get_compiler_args("clang")
|
|
113
|
-
assert "-std=c99" in args
|
|
114
|
-
assert "-Wall" in args
|
|
115
|
-
assert "-pedantic" in args
|
|
116
|
-
assert "-Werror" in args
|
|
117
|
-
|
|
118
|
-
def test_cl_compiler_args(self):
|
|
119
|
-
"""Test MSVC (cl) compiler arguments."""
|
|
120
|
-
args = pyloadergen.get_compiler_args("cl")
|
|
121
|
-
assert "/std:c99" in args
|
|
122
|
-
assert "/Wall" in args
|
|
123
|
-
assert "/WX" in args
|
|
124
|
-
assert "/Werror" in args
|
|
125
|
-
|
|
126
|
-
def test_cl_exe_compiler_args(self):
|
|
127
|
-
"""Test cl.exe compiler arguments (full path)."""
|
|
128
|
-
args = pyloadergen.get_compiler_args("C:\\vc\\bin\\cl.exe")
|
|
129
|
-
assert "/std:c99" in args
|
|
130
|
-
assert "/Wall" in args
|
|
131
|
-
assert "/WX" in args
|
|
132
|
-
assert "/Werror" in args
|
|
133
|
-
|
|
134
|
-
def test_unknown_compiler_args(self):
|
|
135
|
-
"""Test unknown compiler returns empty list."""
|
|
136
|
-
args = pyloadergen.get_compiler_args("unknown_compiler")
|
|
137
|
-
assert args == []
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
class TestFindCompiler:
|
|
141
|
-
"""Test compiler detection."""
|
|
142
|
-
|
|
143
|
-
def test_find_compiler_gcc(self):
|
|
144
|
-
"""Test finding gcc compiler."""
|
|
145
|
-
with mock.patch("shutil.which") as mock_which:
|
|
146
|
-
mock_which.return_value = "/usr/bin/gcc"
|
|
147
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", False):
|
|
148
|
-
result = pyloadergen.find_compiler()
|
|
149
|
-
assert result == "gcc"
|
|
150
|
-
|
|
151
|
-
def test_find_compiler_clang(self):
|
|
152
|
-
"""Test finding clang compiler."""
|
|
153
|
-
# Mock shutil.which to return clang for clang but not for gcc
|
|
154
|
-
with mock.patch("shutil.which") as mock_which:
|
|
155
|
-
|
|
156
|
-
def which_side_effect(cmd):
|
|
157
|
-
# Return gcc None, clang first
|
|
158
|
-
if cmd == "gcc":
|
|
159
|
-
return None
|
|
160
|
-
elif cmd == "clang":
|
|
161
|
-
return "/usr/bin/clang"
|
|
162
|
-
return None
|
|
163
|
-
|
|
164
|
-
mock_which.side_effect = which_side_effect
|
|
165
|
-
|
|
166
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.is_windows", False):
|
|
167
|
-
result = pyloadergen.find_compiler()
|
|
168
|
-
assert result == "clang"
|
|
169
|
-
|
|
170
|
-
def test_no_compiler_found(self):
|
|
171
|
-
"""Test when no compiler is found."""
|
|
172
|
-
with mock.patch("shutil.which") as mock_which:
|
|
173
|
-
mock_which.return_value = None
|
|
174
|
-
result = pyloadergen.find_compiler()
|
|
175
|
-
assert result is None
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
class TestCompilerOptions:
|
|
179
|
-
"""Test compiler options dictionary."""
|
|
180
|
-
|
|
181
|
-
def test_compiler_options_has_gcc(self):
|
|
182
|
-
"""Test GCC options are defined."""
|
|
183
|
-
assert "gcc" in pyloadergen._COMPILER_OPTIONS
|
|
184
|
-
assert "-std=c99" in pyloadergen._COMPILER_OPTIONS["gcc"]
|
|
185
|
-
|
|
186
|
-
def test_compiler_options_has_clang(self):
|
|
187
|
-
"""Test Clang options are defined."""
|
|
188
|
-
assert "clang" in pyloadergen._COMPILER_OPTIONS
|
|
189
|
-
assert "-std=c99" in pyloadergen._COMPILER_OPTIONS["clang"]
|
|
190
|
-
|
|
191
|
-
def test_compiler_options_has_cl(self):
|
|
192
|
-
"""Test MSVC options are defined."""
|
|
193
|
-
assert "cl" in pyloadergen._COMPILER_OPTIONS
|
|
194
|
-
assert "/std:c99" in pyloadergen._COMPILER_OPTIONS["cl"]
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class TestTemplateContent:
|
|
198
|
-
"""Test template content validation."""
|
|
199
|
-
|
|
200
|
-
def test_windows_gui_template_has_winmain(self):
|
|
201
|
-
"""Test Windows GUI template has WinMain entry point."""
|
|
202
|
-
assert "int APIENTRY WinMain" in pyloadergen._WINDOWS_GUI_TEMPLATE
|
|
203
|
-
|
|
204
|
-
def test_windows_console_template_has_main(self):
|
|
205
|
-
"""Test Windows console template has main entry point."""
|
|
206
|
-
assert "int main(" in pyloadergen._WINDOWS_CONSOLE_TEMPLATE
|
|
207
|
-
|
|
208
|
-
def test_unix_gui_template_has_main(self):
|
|
209
|
-
"""Test Unix GUI template has main entry point."""
|
|
210
|
-
assert "int main(" in pyloadergen._UNIX_GUI_TEMPLATE
|
|
211
|
-
|
|
212
|
-
def test_unix_console_template_has_main(self):
|
|
213
|
-
"""Test Unix console template has main entry point."""
|
|
214
|
-
assert "int main(" in pyloadergen._UNIX_CONSOLE_TEMPLATE
|
|
215
|
-
|
|
216
|
-
def test_macos_gui_template_has_main(self):
|
|
217
|
-
"""Test macOS GUI template has main entry point."""
|
|
218
|
-
assert "int main(" in pyloadergen._MACOS_GUI_TEMPLATE
|
|
219
|
-
|
|
220
|
-
def test_macos_console_template_has_main(self):
|
|
221
|
-
"""Test macOS console template has main entry point."""
|
|
222
|
-
assert "int main(" in pyloadergen._MACOS_CONSOLE_TEMPLATE
|
|
223
|
-
|
|
224
|
-
def test_windows_templates_have_placeholder(self):
|
|
225
|
-
"""Test Windows templates contain placeholders."""
|
|
226
|
-
assert "${ENTRY_FILE}" in pyloadergen._WINDOWS_GUI_TEMPLATE
|
|
227
|
-
assert "${DEBUG_MODE}" in pyloadergen._WINDOWS_GUI_TEMPLATE
|
|
228
|
-
assert "${ENTRY_FILE}" in pyloadergen._WINDOWS_CONSOLE_TEMPLATE
|
|
229
|
-
|
|
230
|
-
def test_unix_templates_have_placeholder(self):
|
|
231
|
-
"""Test Unix templates contain placeholder."""
|
|
232
|
-
assert "${ENTRY_FILE}" in pyloadergen._UNIX_GUI_TEMPLATE
|
|
233
|
-
assert "${ENTRY_FILE}" in pyloadergen._UNIX_CONSOLE_TEMPLATE
|
|
234
|
-
|
|
235
|
-
def test_macos_templates_have_placeholder(self):
|
|
236
|
-
"""Test macOS templates contain placeholder."""
|
|
237
|
-
assert "${ENTRY_FILE}" in pyloadergen._MACOS_GUI_TEMPLATE
|
|
238
|
-
assert "${ENTRY_FILE}" in pyloadergen._MACOS_CONSOLE_TEMPLATE
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
class TestCompileCSource:
|
|
242
|
-
"""Test C source compilation."""
|
|
243
|
-
|
|
244
|
-
def test_compile_creates_executable(self):
|
|
245
|
-
"""Test compilation creates executable file."""
|
|
246
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
247
|
-
c_source = Path(temp_dir) / "test.c"
|
|
248
|
-
c_source.write_text("#include <stdio.h>\nint main() { return 0; }")
|
|
249
|
-
output = Path(temp_dir) / "test.exe"
|
|
250
|
-
|
|
251
|
-
with mock.patch("subprocess.run") as mock_run:
|
|
252
|
-
mock_run.return_value = mock.Mock(returncode=0, stdout="", stderr="")
|
|
253
|
-
result = pyloadergen.compile_c_source(str(c_source), str(output), "gcc")
|
|
254
|
-
assert result is True
|
|
255
|
-
|
|
256
|
-
def test_compile_failure(self):
|
|
257
|
-
"""Test compilation failure."""
|
|
258
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
259
|
-
c_source = Path(temp_dir) / "test.c"
|
|
260
|
-
c_source.write_text("invalid C code")
|
|
261
|
-
output = Path(temp_dir) / "test.exe"
|
|
262
|
-
|
|
263
|
-
with mock.patch("subprocess.run") as mock_run:
|
|
264
|
-
mock_run.return_value = mock.Mock(returncode=1, stdout="", stderr="error")
|
|
265
|
-
result = pyloadergen.compile_c_source(str(c_source), str(output), "gcc")
|
|
266
|
-
assert result is False
|
|
267
|
-
|
|
268
|
-
def test_compiler_not_found(self):
|
|
269
|
-
"""Test when compiler is not found."""
|
|
270
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
271
|
-
c_source = Path(temp_dir) / "test.c"
|
|
272
|
-
c_source.write_text("int main() { return 0; }")
|
|
273
|
-
output = Path(temp_dir) / "test.exe"
|
|
274
|
-
|
|
275
|
-
with mock.patch("subprocess.run", side_effect=FileNotFoundError):
|
|
276
|
-
result = pyloadergen.compile_c_source(str(c_source), str(output), "gcc")
|
|
277
|
-
assert result is False
|
|
278
|
-
|
|
279
|
-
def test_no_compiler_specified_finds_one(self):
|
|
280
|
-
"""Test auto-detection of compiler when none specified."""
|
|
281
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
282
|
-
c_source = Path(temp_dir) / "test.c"
|
|
283
|
-
c_source.write_text("int main() { return 0; }")
|
|
284
|
-
output = Path(temp_dir) / "test.exe"
|
|
285
|
-
|
|
286
|
-
with mock.patch("subprocess.run") as mock_run:
|
|
287
|
-
mock_run.return_value = mock.Mock(returncode=0, stdout="", stderr="")
|
|
288
|
-
with mock.patch("sfi.pyloadergen.pyloadergen.find_compiler", return_value="gcc"):
|
|
289
|
-
result = pyloadergen.compile_c_source(str(c_source), str(output), None)
|
|
290
|
-
assert result is True
|