fishertools 0.2.1__py3-none-any.whl → 0.4.0__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.
- fishertools/__init__.py +16 -5
- fishertools/errors/__init__.py +11 -3
- fishertools/errors/exception_types.py +282 -0
- fishertools/errors/explainer.py +87 -1
- fishertools/errors/models.py +73 -1
- fishertools/errors/patterns.py +40 -0
- fishertools/examples/cli_example.py +156 -0
- fishertools/examples/learn_example.py +65 -0
- fishertools/examples/logger_example.py +176 -0
- fishertools/examples/menu_example.py +101 -0
- fishertools/examples/storage_example.py +175 -0
- fishertools/input_utils.py +185 -0
- fishertools/learn/__init__.py +19 -2
- fishertools/learn/examples.py +88 -1
- fishertools/learn/knowledge_engine.py +321 -0
- fishertools/learn/repl/__init__.py +19 -0
- fishertools/learn/repl/cli.py +31 -0
- fishertools/learn/repl/code_sandbox.py +229 -0
- fishertools/learn/repl/command_handler.py +544 -0
- fishertools/learn/repl/command_parser.py +165 -0
- fishertools/learn/repl/engine.py +479 -0
- fishertools/learn/repl/models.py +121 -0
- fishertools/learn/repl/session_manager.py +284 -0
- fishertools/learn/repl/test_code_sandbox.py +261 -0
- fishertools/learn/repl/test_code_sandbox_pbt.py +148 -0
- fishertools/learn/repl/test_command_handler.py +224 -0
- fishertools/learn/repl/test_command_handler_pbt.py +189 -0
- fishertools/learn/repl/test_command_parser.py +160 -0
- fishertools/learn/repl/test_command_parser_pbt.py +100 -0
- fishertools/learn/repl/test_engine.py +190 -0
- fishertools/learn/repl/test_session_manager.py +310 -0
- fishertools/learn/repl/test_session_manager_pbt.py +182 -0
- fishertools/learn/test_knowledge_engine.py +241 -0
- fishertools/learn/test_knowledge_engine_pbt.py +180 -0
- fishertools/patterns/__init__.py +46 -0
- fishertools/patterns/cli.py +175 -0
- fishertools/patterns/logger.py +140 -0
- fishertools/patterns/menu.py +99 -0
- fishertools/patterns/storage.py +127 -0
- fishertools/readme_transformer.py +631 -0
- fishertools/safe/__init__.py +6 -1
- fishertools/safe/files.py +329 -1
- fishertools/transform_readme.py +105 -0
- fishertools-0.4.0.dist-info/METADATA +104 -0
- fishertools-0.4.0.dist-info/RECORD +131 -0
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/WHEEL +1 -1
- tests/test_documentation_properties.py +329 -0
- tests/test_documentation_structure.py +349 -0
- tests/test_errors/test_exception_types.py +446 -0
- tests/test_errors/test_exception_types_pbt.py +333 -0
- tests/test_errors/test_patterns.py +52 -0
- tests/test_input_utils/__init__.py +1 -0
- tests/test_input_utils/test_input_utils.py +65 -0
- tests/test_learn/test_examples.py +179 -1
- tests/test_learn/test_explain_properties.py +307 -0
- tests/test_patterns_cli.py +611 -0
- tests/test_patterns_docstrings.py +473 -0
- tests/test_patterns_logger.py +465 -0
- tests/test_patterns_menu.py +440 -0
- tests/test_patterns_storage.py +447 -0
- tests/test_readme_enhancements_v0_3_1.py +2036 -0
- tests/test_readme_transformer/__init__.py +1 -0
- tests/test_readme_transformer/test_readme_infrastructure.py +1023 -0
- tests/test_readme_transformer/test_transform_readme_integration.py +431 -0
- tests/test_safe/test_files.py +726 -1
- fishertools-0.2.1.dist-info/METADATA +0 -256
- fishertools-0.2.1.dist-info/RECORD +0 -81
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integration tests for the README transformation script.
|
|
3
|
+
|
|
4
|
+
Tests the complete transformation process including:
|
|
5
|
+
- File reading and writing
|
|
6
|
+
- Backup creation and recovery
|
|
7
|
+
- Error handling for missing files
|
|
8
|
+
- End-to-end transformation workflow
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import tempfile
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
from fishertools.transform_readme import transform_readme
|
|
17
|
+
from fishertools.readme_transformer import BackupManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestTransformReadmeIntegration:
|
|
21
|
+
"""Integration tests for the transform_readme function."""
|
|
22
|
+
|
|
23
|
+
def test_transform_readme_success(self, tmp_path: Path) -> None:
|
|
24
|
+
"""Test successful README transformation."""
|
|
25
|
+
readme_path = tmp_path / "README.md"
|
|
26
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
27
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
28
|
+
|
|
29
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
30
|
+
|
|
31
|
+
assert result is True
|
|
32
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
33
|
+
assert "pip install fishertools" in transformed
|
|
34
|
+
assert "Для кого эта библиотека" in transformed
|
|
35
|
+
|
|
36
|
+
def test_transform_readme_with_backup(self, tmp_path: Path) -> None:
|
|
37
|
+
"""Test transformation with backup creation."""
|
|
38
|
+
readme_path = tmp_path / "README.md"
|
|
39
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
40
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
41
|
+
|
|
42
|
+
# Change to tmp_path directory so backups are created there
|
|
43
|
+
import os
|
|
44
|
+
original_cwd = os.getcwd()
|
|
45
|
+
try:
|
|
46
|
+
os.chdir(tmp_path)
|
|
47
|
+
result = transform_readme(str(readme_path), create_backup=True)
|
|
48
|
+
|
|
49
|
+
assert result is True
|
|
50
|
+
|
|
51
|
+
# Verify backup was created
|
|
52
|
+
backup_dir = tmp_path / ".readme_backups"
|
|
53
|
+
assert backup_dir.exists()
|
|
54
|
+
backups = list(backup_dir.glob("README_backup_*.md"))
|
|
55
|
+
assert len(backups) > 0
|
|
56
|
+
finally:
|
|
57
|
+
os.chdir(original_cwd)
|
|
58
|
+
|
|
59
|
+
def test_transform_readme_file_not_found(self, tmp_path: Path) -> None:
|
|
60
|
+
"""Test error handling when README file does not exist."""
|
|
61
|
+
readme_path = tmp_path / "nonexistent.md"
|
|
62
|
+
|
|
63
|
+
with pytest.raises(FileNotFoundError):
|
|
64
|
+
transform_readme(str(readme_path))
|
|
65
|
+
|
|
66
|
+
def test_transform_readme_preserves_content(self, tmp_path: Path) -> None:
|
|
67
|
+
"""Test that transformation preserves original content."""
|
|
68
|
+
readme_path = tmp_path / "README.md"
|
|
69
|
+
original_intro = "This is the original introduction"
|
|
70
|
+
original_content = "This is the original detailed content"
|
|
71
|
+
test_content = f"{original_intro}\n\n# Section\n\n{original_content}"
|
|
72
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
73
|
+
|
|
74
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
75
|
+
|
|
76
|
+
assert result is True
|
|
77
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
78
|
+
assert original_intro in transformed
|
|
79
|
+
assert original_content in transformed
|
|
80
|
+
|
|
81
|
+
def test_transform_readme_with_custom_features(self, tmp_path: Path) -> None:
|
|
82
|
+
"""Test transformation with custom features."""
|
|
83
|
+
readme_path = tmp_path / "README.md"
|
|
84
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
85
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
86
|
+
|
|
87
|
+
custom_features = [
|
|
88
|
+
{"task": "Custom Task 1", "function": "custom_func1()"},
|
|
89
|
+
{"task": "Custom Task 2", "function": "custom_func2()"},
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
result = transform_readme(
|
|
93
|
+
str(readme_path), create_backup=False, features=custom_features
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
assert result is True
|
|
97
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
98
|
+
assert "Custom Task 1" in transformed
|
|
99
|
+
assert "custom_func1()" in transformed
|
|
100
|
+
assert "Custom Task 2" in transformed
|
|
101
|
+
assert "custom_func2()" in transformed
|
|
102
|
+
|
|
103
|
+
def test_transform_readme_with_custom_audience(self, tmp_path: Path) -> None:
|
|
104
|
+
"""Test transformation with custom target audience bullets."""
|
|
105
|
+
readme_path = tmp_path / "README.md"
|
|
106
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
107
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
108
|
+
|
|
109
|
+
custom_bullets = [
|
|
110
|
+
"Custom bullet 1",
|
|
111
|
+
"Custom bullet 2",
|
|
112
|
+
"Custom bullet 3",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
result = transform_readme(
|
|
116
|
+
str(readme_path),
|
|
117
|
+
create_backup=False,
|
|
118
|
+
target_audience_bullets=custom_bullets,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
assert result is True
|
|
122
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
123
|
+
for bullet in custom_bullets:
|
|
124
|
+
assert bullet in transformed
|
|
125
|
+
|
|
126
|
+
def test_transform_readme_backup_recovery(self, tmp_path: Path) -> None:
|
|
127
|
+
"""Test backup creation and recovery mechanism."""
|
|
128
|
+
readme_path = tmp_path / "README.md"
|
|
129
|
+
original_content = "Original content"
|
|
130
|
+
readme_path.write_text(original_content, encoding="utf-8")
|
|
131
|
+
|
|
132
|
+
# Change to tmp_path directory so backups are created there
|
|
133
|
+
import os
|
|
134
|
+
original_cwd = os.getcwd()
|
|
135
|
+
try:
|
|
136
|
+
os.chdir(tmp_path)
|
|
137
|
+
# Transform with backup
|
|
138
|
+
result = transform_readme(str(readme_path), create_backup=True)
|
|
139
|
+
assert result is True
|
|
140
|
+
|
|
141
|
+
# Get the backup file
|
|
142
|
+
backup_dir = tmp_path / ".readme_backups"
|
|
143
|
+
backups = list(backup_dir.glob("README_backup_*.md"))
|
|
144
|
+
assert len(backups) > 0
|
|
145
|
+
|
|
146
|
+
backup_path = backups[0]
|
|
147
|
+
|
|
148
|
+
# Verify backup contains original content
|
|
149
|
+
backup_content = backup_path.read_text(encoding="utf-8")
|
|
150
|
+
assert backup_content == original_content
|
|
151
|
+
|
|
152
|
+
# Modify the README
|
|
153
|
+
readme_path.write_text("Modified content", encoding="utf-8")
|
|
154
|
+
|
|
155
|
+
# Recover from backup
|
|
156
|
+
backup_manager = BackupManager(str(readme_path), str(backup_dir))
|
|
157
|
+
backup_manager.restore_backup(backup_path)
|
|
158
|
+
|
|
159
|
+
# Verify recovery
|
|
160
|
+
recovered_content = readme_path.read_text(encoding="utf-8")
|
|
161
|
+
assert recovered_content == original_content
|
|
162
|
+
finally:
|
|
163
|
+
os.chdir(original_cwd)
|
|
164
|
+
|
|
165
|
+
def test_transform_readme_multiple_backups(self, tmp_path: Path) -> None:
|
|
166
|
+
"""Test creation of multiple backups."""
|
|
167
|
+
import time
|
|
168
|
+
import os
|
|
169
|
+
|
|
170
|
+
readme_path = tmp_path / "README.md"
|
|
171
|
+
readme_path.write_text("Content 1", encoding="utf-8")
|
|
172
|
+
|
|
173
|
+
original_cwd = os.getcwd()
|
|
174
|
+
try:
|
|
175
|
+
os.chdir(tmp_path)
|
|
176
|
+
# Create first backup
|
|
177
|
+
result1 = transform_readme(str(readme_path), create_backup=True)
|
|
178
|
+
assert result1 is True
|
|
179
|
+
|
|
180
|
+
# Wait to ensure different timestamp
|
|
181
|
+
time.sleep(1.1)
|
|
182
|
+
|
|
183
|
+
# Modify and create second backup
|
|
184
|
+
readme_path.write_text("Content 2", encoding="utf-8")
|
|
185
|
+
result2 = transform_readme(str(readme_path), create_backup=True)
|
|
186
|
+
assert result2 is True
|
|
187
|
+
|
|
188
|
+
# Verify both backups exist
|
|
189
|
+
backup_dir = tmp_path / ".readme_backups"
|
|
190
|
+
backups = list(backup_dir.glob("README_backup_*.md"))
|
|
191
|
+
assert len(backups) >= 2
|
|
192
|
+
finally:
|
|
193
|
+
os.chdir(original_cwd)
|
|
194
|
+
|
|
195
|
+
def test_transform_readme_validation_failure(self, tmp_path: Path) -> None:
|
|
196
|
+
"""Test handling of validation failures."""
|
|
197
|
+
readme_path = tmp_path / "README.md"
|
|
198
|
+
# Create a README with problematic content
|
|
199
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
200
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
201
|
+
|
|
202
|
+
# This should succeed with valid content
|
|
203
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
204
|
+
assert result is True
|
|
205
|
+
|
|
206
|
+
def test_transform_readme_empty_file(self, tmp_path: Path) -> None:
|
|
207
|
+
"""Test handling of empty README file."""
|
|
208
|
+
readme_path = tmp_path / "README.md"
|
|
209
|
+
readme_path.write_text("", encoding="utf-8")
|
|
210
|
+
|
|
211
|
+
# Should handle gracefully
|
|
212
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
213
|
+
|
|
214
|
+
# Result depends on implementation - may succeed or fail gracefully
|
|
215
|
+
# The important thing is it doesn't crash
|
|
216
|
+
assert isinstance(result, bool)
|
|
217
|
+
|
|
218
|
+
def test_transform_readme_large_file(self, tmp_path: Path) -> None:
|
|
219
|
+
"""Test handling of large README file."""
|
|
220
|
+
readme_path = tmp_path / "README.md"
|
|
221
|
+
|
|
222
|
+
# Create a large README with lots of content
|
|
223
|
+
large_content = "Introduction\n\n"
|
|
224
|
+
for i in range(100):
|
|
225
|
+
large_content += f"## Section {i}\n\nContent for section {i}\n\n"
|
|
226
|
+
|
|
227
|
+
readme_path.write_text(large_content, encoding="utf-8")
|
|
228
|
+
|
|
229
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
230
|
+
|
|
231
|
+
assert result is True
|
|
232
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
233
|
+
assert "pip install fishertools" in transformed
|
|
234
|
+
assert "Для кого эта библиотека" in transformed
|
|
235
|
+
|
|
236
|
+
def test_transform_readme_with_special_characters(self, tmp_path: Path) -> None:
|
|
237
|
+
"""Test handling of special characters in content."""
|
|
238
|
+
readme_path = tmp_path / "README.md"
|
|
239
|
+
test_content = "Introduction with émojis 🐍\n\n# Section\n\nContent with special chars: @#$%"
|
|
240
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
241
|
+
|
|
242
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
243
|
+
|
|
244
|
+
assert result is True
|
|
245
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
246
|
+
assert "émojis 🐍" in transformed
|
|
247
|
+
assert "@#$%" in transformed
|
|
248
|
+
|
|
249
|
+
def test_transform_readme_idempotent(self, tmp_path: Path) -> None:
|
|
250
|
+
"""Test that transformation is idempotent (can be run multiple times)."""
|
|
251
|
+
readme_path = tmp_path / "README.md"
|
|
252
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
253
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
254
|
+
|
|
255
|
+
# First transformation
|
|
256
|
+
result1 = transform_readme(str(readme_path), create_backup=False)
|
|
257
|
+
assert result1 is True
|
|
258
|
+
first_result = readme_path.read_text(encoding="utf-8")
|
|
259
|
+
|
|
260
|
+
# Second transformation - should not duplicate sections
|
|
261
|
+
result2 = transform_readme(str(readme_path), create_backup=False)
|
|
262
|
+
assert result2 is True
|
|
263
|
+
second_result = readme_path.read_text(encoding="utf-8")
|
|
264
|
+
|
|
265
|
+
# Both should have the required sections
|
|
266
|
+
assert "pip install fishertools" in first_result
|
|
267
|
+
assert "Для кого эта библиотека" in first_result
|
|
268
|
+
assert "pip install fishertools" in second_result
|
|
269
|
+
assert "Для кого эта библиотека" in second_result
|
|
270
|
+
|
|
271
|
+
# Count occurrences - should not increase significantly
|
|
272
|
+
first_install_count = first_result.count("pip install fishertools")
|
|
273
|
+
second_install_count = second_result.count("pip install fishertools")
|
|
274
|
+
|
|
275
|
+
# Allow for some variation but not doubling
|
|
276
|
+
assert second_install_count <= first_install_count + 1
|
|
277
|
+
|
|
278
|
+
def test_transform_readme_real_world_example(self, tmp_path: Path) -> None:
|
|
279
|
+
"""Test transformation with a realistic README structure."""
|
|
280
|
+
readme_path = tmp_path / "README.md"
|
|
281
|
+
realistic_content = """# Fishertools
|
|
282
|
+
|
|
283
|
+
**Инструменты, которые делают Python удобнее и безопаснее для новичков**
|
|
284
|
+
|
|
285
|
+
Fishertools - это Python библиотека, созданная специально для начинающих разработчиков.
|
|
286
|
+
|
|
287
|
+
## 🎯 Основные возможности
|
|
288
|
+
|
|
289
|
+
### 🚨 Объяснение ошибок Python
|
|
290
|
+
Получайте понятные объяснения ошибок на русском языке.
|
|
291
|
+
|
|
292
|
+
### 🛡️ Безопасные утилиты
|
|
293
|
+
Функции, которые предотвращают типичные ошибки новичков.
|
|
294
|
+
|
|
295
|
+
## 📦 Установка
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
pip install fishertools
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## 🚀 Быстрый старт
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
from fishertools import explain_error
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## 📖 Документация
|
|
308
|
+
|
|
309
|
+
Полная документация доступна на сайте.
|
|
310
|
+
"""
|
|
311
|
+
readme_path.write_text(realistic_content, encoding="utf-8")
|
|
312
|
+
|
|
313
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
314
|
+
|
|
315
|
+
assert result is True
|
|
316
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
317
|
+
|
|
318
|
+
# Verify all required sections are present
|
|
319
|
+
assert "Fishertools" in transformed
|
|
320
|
+
assert "pip install fishertools" in transformed
|
|
321
|
+
assert "Для кого эта библиотека" in transformed
|
|
322
|
+
assert "Задача" in transformed
|
|
323
|
+
assert "Что вызвать" in transformed
|
|
324
|
+
assert "explain_error(e)" in transformed
|
|
325
|
+
assert "safe_read_file(path)" in transformed
|
|
326
|
+
|
|
327
|
+
def test_transform_readme_preserves_formatting(self, tmp_path: Path) -> None:
|
|
328
|
+
"""Test that transformation preserves markdown formatting."""
|
|
329
|
+
readme_path = tmp_path / "README.md"
|
|
330
|
+
test_content = """Introduction
|
|
331
|
+
|
|
332
|
+
# Heading 1
|
|
333
|
+
|
|
334
|
+
## Heading 2
|
|
335
|
+
|
|
336
|
+
### Heading 3
|
|
337
|
+
|
|
338
|
+
- Bullet 1
|
|
339
|
+
- Bullet 2
|
|
340
|
+
|
|
341
|
+
1. Numbered 1
|
|
342
|
+
2. Numbered 2
|
|
343
|
+
|
|
344
|
+
**Bold text** and *italic text*
|
|
345
|
+
|
|
346
|
+
```python
|
|
347
|
+
code_block()
|
|
348
|
+
```
|
|
349
|
+
"""
|
|
350
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
351
|
+
|
|
352
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
353
|
+
|
|
354
|
+
assert result is True
|
|
355
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
356
|
+
|
|
357
|
+
# Verify formatting is preserved
|
|
358
|
+
assert "# Heading 1" in transformed
|
|
359
|
+
assert "## Heading 2" in transformed
|
|
360
|
+
assert "### Heading 3" in transformed
|
|
361
|
+
assert "- Bullet 1" in transformed
|
|
362
|
+
assert "1. Numbered 1" in transformed
|
|
363
|
+
assert "**Bold text**" in transformed
|
|
364
|
+
assert "*italic text*" in transformed
|
|
365
|
+
assert "```python" in transformed
|
|
366
|
+
|
|
367
|
+
def test_transform_readme_error_handling_io_error(self, tmp_path: Path) -> None:
|
|
368
|
+
"""Test error handling for IO errors."""
|
|
369
|
+
readme_path = tmp_path / "README.md"
|
|
370
|
+
readme_path.write_text("Content", encoding="utf-8")
|
|
371
|
+
|
|
372
|
+
# Make the file read-only to simulate IO error on write
|
|
373
|
+
import os
|
|
374
|
+
|
|
375
|
+
os.chmod(readme_path, 0o444)
|
|
376
|
+
|
|
377
|
+
try:
|
|
378
|
+
# This should fail gracefully
|
|
379
|
+
result = transform_readme(str(readme_path), create_backup=False)
|
|
380
|
+
# Result should be False due to write error
|
|
381
|
+
assert result is False
|
|
382
|
+
finally:
|
|
383
|
+
# Restore permissions for cleanup
|
|
384
|
+
os.chmod(readme_path, 0o644)
|
|
385
|
+
|
|
386
|
+
def test_transform_readme_with_all_options(self, tmp_path: Path) -> None:
|
|
387
|
+
"""Test transformation with all options specified."""
|
|
388
|
+
readme_path = tmp_path / "README.md"
|
|
389
|
+
test_content = "Introduction\n\n# Section\n\nContent"
|
|
390
|
+
readme_path.write_text(test_content, encoding="utf-8")
|
|
391
|
+
|
|
392
|
+
custom_features = [
|
|
393
|
+
{"task": "Task 1", "function": "func1()"},
|
|
394
|
+
{"task": "Task 2", "function": "func2()"},
|
|
395
|
+
]
|
|
396
|
+
|
|
397
|
+
custom_bullets = [
|
|
398
|
+
"Bullet 1",
|
|
399
|
+
"Bullet 2",
|
|
400
|
+
"Bullet 3",
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
import os
|
|
404
|
+
original_cwd = os.getcwd()
|
|
405
|
+
try:
|
|
406
|
+
os.chdir(tmp_path)
|
|
407
|
+
result = transform_readme(
|
|
408
|
+
str(readme_path),
|
|
409
|
+
create_backup=True,
|
|
410
|
+
features=custom_features,
|
|
411
|
+
target_audience_bullets=custom_bullets,
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
assert result is True
|
|
415
|
+
|
|
416
|
+
# Verify backup was created
|
|
417
|
+
backup_dir = tmp_path / ".readme_backups"
|
|
418
|
+
assert backup_dir.exists()
|
|
419
|
+
|
|
420
|
+
# Verify custom features are in the result
|
|
421
|
+
transformed = readme_path.read_text(encoding="utf-8")
|
|
422
|
+
assert "Task 1" in transformed
|
|
423
|
+
assert "func1()" in transformed
|
|
424
|
+
assert "Task 2" in transformed
|
|
425
|
+
assert "func2()" in transformed
|
|
426
|
+
|
|
427
|
+
# Verify custom bullets are in the result
|
|
428
|
+
for bullet in custom_bullets:
|
|
429
|
+
assert bullet in transformed
|
|
430
|
+
finally:
|
|
431
|
+
os.chdir(original_cwd)
|