deploynator 1.3.1__tar.gz → 1.3.4__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.
- {deploynator-1.3.1 → deploynator-1.3.4}/PKG-INFO +1 -1
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/__init__.py +1 -1
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/__main__.py +5 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_app.py +32 -1
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_deploy.py +6 -4
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_pypi.py +13 -3
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_toml.py +57 -10
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_toml.py +55 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/.gitignore +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/LICENSE +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/README.md +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_changelog.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_config.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_docs.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_git.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_mcp_server.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_models.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_platforms.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_readme.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_runner.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/deploynator/_semver.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/example.deploynator.toml +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/projects/deploynator.yaml +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/projects/lazyown.yaml +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/projects/template.yaml +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/pyproject.toml +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/specs/deploynator_toml_pipeline.spec.md +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/__init__.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/bdd_test_deploy.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_changelog.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_cli_mcp.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_config.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_deploy.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_init.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_install_example.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_models.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_path_deploy.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_pipeline.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_pypi.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_readme_footer.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_runner.py +0 -0
- {deploynator-1.3.1 → deploynator-1.3.4}/tests/test_semver.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: deploynator
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: Multi-platform deployer for GitHub, GitLab, and Bitbucket
|
|
5
5
|
Project-URL: Homepage, https://github.com/grisuno/deploynator
|
|
6
6
|
Project-URL: Repository, https://github.com/grisuno/deploynator
|
|
@@ -28,6 +28,10 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
28
28
|
"--workdir", type=str, default="",
|
|
29
29
|
help="Working directory (default: current dir)",
|
|
30
30
|
)
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"--verbose", "-v", action="store_true",
|
|
33
|
+
help="Verbose output (twine --verbose, full command + untruncated errors)",
|
|
34
|
+
)
|
|
31
35
|
|
|
32
36
|
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
33
37
|
|
|
@@ -199,6 +203,7 @@ def main(argv: list[str] | None = None) -> NoReturn | None:
|
|
|
199
203
|
no_test=getattr(args, "no_test", False),
|
|
200
204
|
no_docs=getattr(args, "no_docs", False),
|
|
201
205
|
no_pypi=getattr(args, "no_pypi", False),
|
|
206
|
+
verbose=getattr(args, "verbose", False),
|
|
202
207
|
)
|
|
203
208
|
sys.exit(0 if all(r.success for r in results) else 1)
|
|
204
209
|
|
|
@@ -128,6 +128,8 @@ ensure_pkg() {
|
|
|
128
128
|
|
|
129
129
|
ensure_pkg deploynator deploynator "git+https://github.com/grisuno/deploynator.git"
|
|
130
130
|
ensure_pkg readmenator readmenator readmenator
|
|
131
|
+
ensure_pkg build build build
|
|
132
|
+
ensure_pkg twine twine twine
|
|
131
133
|
|
|
132
134
|
if ! python3 -c "import deploynator" 2>/dev/null; then
|
|
133
135
|
echo "[!] deploynator not available and install failed (offline?)." >&2
|
|
@@ -195,8 +197,35 @@ version:
|
|
|
195
197
|
|
|
196
198
|
toml_path = os.path.join(base, "deploynator.toml")
|
|
197
199
|
if not os.path.isfile(toml_path):
|
|
200
|
+
from deploynator._toml import detect_test_commands, _has_python_tests
|
|
201
|
+
inferred: list[str] | None = None
|
|
202
|
+
try:
|
|
203
|
+
detected = detect_test_commands(base)
|
|
204
|
+
if detected is not None and not (
|
|
205
|
+
detected != ["make test-host"]
|
|
206
|
+
and detected[0].startswith("make")
|
|
207
|
+
and _has_python_tests(base)
|
|
208
|
+
):
|
|
209
|
+
inferred = detected
|
|
210
|
+
except ValueError:
|
|
211
|
+
inferred = None
|
|
212
|
+
if inferred is not None:
|
|
213
|
+
commands_repr = "[" + ", ".join(f'"{c}"' for c in inferred) + "]"
|
|
214
|
+
timeout = 900
|
|
215
|
+
else:
|
|
216
|
+
commands_repr = '["python -m pytest tests/ -q"]'
|
|
217
|
+
timeout = 300
|
|
218
|
+
content = self.DEPLOY_TOML_TEMPLATE.format(name=project_name)
|
|
219
|
+
content = content.replace(
|
|
220
|
+
'commands = ["python -m pytest tests/ -q"]',
|
|
221
|
+
f"commands = {commands_repr}",
|
|
222
|
+
).replace(
|
|
223
|
+
"timeout_s = 300",
|
|
224
|
+
f"timeout_s = {timeout}",
|
|
225
|
+
1,
|
|
226
|
+
)
|
|
198
227
|
with open(toml_path, "w") as f:
|
|
199
|
-
f.write(
|
|
228
|
+
f.write(content)
|
|
200
229
|
created.append(toml_path)
|
|
201
230
|
|
|
202
231
|
script_path = os.path.join(base, "deploy.sh")
|
|
@@ -327,6 +356,7 @@ version:
|
|
|
327
356
|
no_test: bool = False,
|
|
328
357
|
no_docs: bool = False,
|
|
329
358
|
no_pypi: bool = False,
|
|
359
|
+
verbose: bool = False,
|
|
330
360
|
) -> list[DeployResult]:
|
|
331
361
|
base = os.getcwd()
|
|
332
362
|
ctype = CommitType.from_string(commit_type)
|
|
@@ -395,6 +425,7 @@ version:
|
|
|
395
425
|
run_docs=not no_docs,
|
|
396
426
|
force_bump=bump or None,
|
|
397
427
|
run_pypi=not no_pypi,
|
|
428
|
+
verbose=verbose,
|
|
398
429
|
)
|
|
399
430
|
results.append(result)
|
|
400
431
|
self._print_result(result)
|
|
@@ -107,6 +107,7 @@ class DeployOrchestrator:
|
|
|
107
107
|
run_docs: bool = True,
|
|
108
108
|
force_bump: Optional[str] = None,
|
|
109
109
|
run_pypi: bool = True,
|
|
110
|
+
verbose: bool = False,
|
|
110
111
|
) -> DeployResult:
|
|
111
112
|
repo_path = self._resolve_project_path(project)
|
|
112
113
|
|
|
@@ -334,7 +335,8 @@ class DeployOrchestrator:
|
|
|
334
335
|
print("[!] PyPI packaging detected but no credentials "
|
|
335
336
|
"(TWINE_PASSWORD/PYPI_TOKEN/~/.pypirc). Skipping upload.")
|
|
336
337
|
else:
|
|
337
|
-
ok, msg = self._pypi.run(repo_path, toml_cfg, new_version_str, token=token
|
|
338
|
+
ok, msg = self._pypi.run(repo_path, toml_cfg, new_version_str, token=token,
|
|
339
|
+
verbose=verbose)
|
|
338
340
|
print(f"[{'OK' if ok else 'FAIL'}] {msg}")
|
|
339
341
|
if not ok:
|
|
340
342
|
return DeployResult(
|
|
@@ -343,10 +345,10 @@ class DeployOrchestrator:
|
|
|
343
345
|
success=False,
|
|
344
346
|
platforms_pushed=platforms_pushed,
|
|
345
347
|
releases_created=releases_created,
|
|
346
|
-
error=msg[:2000],
|
|
348
|
+
error=msg if verbose else msg[:2000],
|
|
347
349
|
)
|
|
348
350
|
else:
|
|
349
|
-
ok, msg = self._pypi.run(repo_path, toml_cfg, new_version_str)
|
|
351
|
+
ok, msg = self._pypi.run(repo_path, toml_cfg, new_version_str, verbose=verbose)
|
|
350
352
|
print(f"[{'OK' if ok else 'FAIL'}] {msg}")
|
|
351
353
|
if not ok:
|
|
352
354
|
return DeployResult(
|
|
@@ -355,7 +357,7 @@ class DeployOrchestrator:
|
|
|
355
357
|
success=False,
|
|
356
358
|
platforms_pushed=platforms_pushed,
|
|
357
359
|
releases_created=releases_created,
|
|
358
|
-
error=msg[:2000],
|
|
360
|
+
error=msg if verbose else msg[:2000],
|
|
359
361
|
)
|
|
360
362
|
|
|
361
363
|
return DeployResult(
|
|
@@ -105,7 +105,7 @@ class PyPIRunner:
|
|
|
105
105
|
shutil.rmtree(target)
|
|
106
106
|
|
|
107
107
|
def run(self, project_path: str, toml: TomlConfig, version: str,
|
|
108
|
-
token: str | None = None) -> tuple[bool, str]:
|
|
108
|
+
token: str | None = None, verbose: bool = False) -> tuple[bool, str]:
|
|
109
109
|
if not self.is_packaging_project(project_path):
|
|
110
110
|
return True, "PyPI skipped: no packaging files"
|
|
111
111
|
try:
|
|
@@ -120,7 +120,10 @@ class PyPIRunner:
|
|
|
120
120
|
timeout=toml.pypi_timeout_s,
|
|
121
121
|
)
|
|
122
122
|
if build.returncode != 0:
|
|
123
|
-
|
|
123
|
+
raw = (build.stderr or build.stdout or "").strip()
|
|
124
|
+
if verbose and raw:
|
|
125
|
+
print(raw)
|
|
126
|
+
err = raw if verbose else raw[-2000:]
|
|
124
127
|
hint = "" if "build" not in err.lower() else " (pip install build)"
|
|
125
128
|
return False, f"PyPI build failed for {version}{hint}: {err}"
|
|
126
129
|
dist_dir = os.path.join(project_path, "dist")
|
|
@@ -128,11 +131,15 @@ class PyPIRunner:
|
|
|
128
131
|
if not artifacts:
|
|
129
132
|
return False, f"PyPI build produced no artifacts for {version}"
|
|
130
133
|
cmd = [sys.executable, "-m", "twine", "upload", "--non-interactive"]
|
|
134
|
+
if verbose:
|
|
135
|
+
cmd += ["--verbose"]
|
|
131
136
|
if toml.pypi_repo == "testpypi":
|
|
132
137
|
cmd += ["--repository", "testpypi"]
|
|
133
138
|
elif toml.pypi_repo not in ("pypi", "testpypi"):
|
|
134
139
|
cmd += ["--repository-url", toml.pypi_repo]
|
|
135
140
|
cmd += [os.path.join("dist", a) for a in artifacts]
|
|
141
|
+
if verbose:
|
|
142
|
+
print(f"[...] {subprocess.list2cmdline(cmd)} (cwd={project_path})")
|
|
136
143
|
env = dict(os.environ)
|
|
137
144
|
token = token or os.environ.get("PYPI_TOKEN")
|
|
138
145
|
if token and not os.environ.get("TWINE_PASSWORD"):
|
|
@@ -150,6 +157,9 @@ class PyPIRunner:
|
|
|
150
157
|
except subprocess.TimeoutExpired:
|
|
151
158
|
return False, f"PyPI upload timed out after {toml.pypi_timeout_s}s"
|
|
152
159
|
if upload.returncode != 0:
|
|
153
|
-
|
|
160
|
+
raw = (upload.stderr or upload.stdout or "").strip()
|
|
161
|
+
if verbose and raw:
|
|
162
|
+
print(raw)
|
|
163
|
+
err = raw if verbose else raw[-2000:]
|
|
154
164
|
return False, f"PyPI upload failed for {version}: {err}"
|
|
155
165
|
return True, f"PyPI uploaded {version}: {', '.join(artifacts)}"
|
|
@@ -71,14 +71,42 @@ def _has_python_tests(project_path: str) -> bool:
|
|
|
71
71
|
return True
|
|
72
72
|
except OSError:
|
|
73
73
|
return False
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def looks_like_packaging_project(project_path: str) -> bool:
|
|
77
|
+
"""Inferencia runtime (multi-proyecto): ¿es un paquete PyPI?
|
|
78
|
+
|
|
79
|
+
Espejo liviano de PyPIRunner.is_packaging_project sin importar
|
|
80
|
+
_pypi (evita ciclo). El gate final sigue en PyPIRunner al
|
|
81
|
+
desplegar; aquí solo se usa para el default de pypi_enabled.
|
|
82
|
+
"""
|
|
83
|
+
pyproject = os.path.join(project_path, "pyproject.toml")
|
|
84
|
+
if os.path.isfile(pyproject) and not os.path.islink(pyproject):
|
|
85
|
+
try:
|
|
86
|
+
import tomllib
|
|
87
|
+
with open(pyproject, "rb") as f:
|
|
88
|
+
data = tomllib.load(f)
|
|
89
|
+
project = data.get("project", {})
|
|
90
|
+
if isinstance(project, dict) and project.get("name"):
|
|
91
|
+
return True
|
|
92
|
+
except Exception:
|
|
93
|
+
pass
|
|
94
|
+
for candidate in ("setup.py", "setup.cfg"):
|
|
95
|
+
candidate_path = os.path.join(project_path, candidate)
|
|
96
|
+
if os.path.isfile(candidate_path) and not os.path.islink(candidate_path):
|
|
97
|
+
return True
|
|
98
|
+
return False
|
|
74
99
|
return False
|
|
75
100
|
|
|
76
101
|
|
|
77
102
|
def detect_test_commands(project_path: str) -> list[str] | None:
|
|
78
103
|
"""Detecta comandos de test para proyectos C/autotools sin toml.
|
|
79
104
|
|
|
80
|
-
|
|
81
|
-
test
|
|
105
|
+
Runtime multi-proyecto, sin hardcodear nombres de proyecto:
|
|
106
|
+
Makefile (test-host canónico solo; si no, TODOS los targets de
|
|
107
|
+
test en una sola invocación `make test test-* ...`, p. ej.
|
|
108
|
+
`make test test-dsp test-transport`) → CMake (build+ctest) →
|
|
109
|
+
meson (setup+test).
|
|
82
110
|
Devuelve None si no hay nada detectable (caller usa pytest default).
|
|
83
111
|
"""
|
|
84
112
|
try:
|
|
@@ -86,12 +114,26 @@ def detect_test_commands(project_path: str) -> list[str] | None:
|
|
|
86
114
|
except ValueError:
|
|
87
115
|
targets = []
|
|
88
116
|
if targets:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
117
|
+
# `test-host` es la suite canónica (drivers internos propios):
|
|
118
|
+
# va sola, manda sobre todo (incluso sobre tests/*.py).
|
|
119
|
+
if "test-host" in targets:
|
|
120
|
+
return ["make test-host"]
|
|
121
|
+
combined: list[str] = []
|
|
122
|
+
for preferred in MAKE_TEST_PRIORITY[1:]:
|
|
123
|
+
# `tests` desnudo suele ser helper mkdir (dependencia order-only
|
|
124
|
+
# `| tests`), no runner: se excluye si hay otro target de test.
|
|
125
|
+
if preferred == "tests" and any(
|
|
126
|
+
t in targets for t in ("test", "check")
|
|
127
|
+
):
|
|
128
|
+
continue
|
|
129
|
+
if preferred in targets and preferred not in combined:
|
|
130
|
+
combined.append(preferred)
|
|
131
|
+
for extra in sorted(t for t in targets
|
|
132
|
+
if (t.startswith("test-") or t.startswith("test_"))
|
|
133
|
+
and t not in combined):
|
|
134
|
+
combined.append(extra)
|
|
135
|
+
if combined:
|
|
136
|
+
return [f"make {' '.join(combined)}"]
|
|
95
137
|
# Makefile sin target de test: al menos verifica que compila.
|
|
96
138
|
if "all" in targets:
|
|
97
139
|
return ["make"]
|
|
@@ -108,7 +150,12 @@ def detect_test_commands(project_path: str) -> list[str] | None:
|
|
|
108
150
|
|
|
109
151
|
|
|
110
152
|
def _auto_toml_config(project_path: str) -> TomlConfig | None:
|
|
111
|
-
"""Config auto para proyectos sin deploynator.toml (C primero).
|
|
153
|
+
"""Config auto para proyectos sin deploynator.toml (C primero).
|
|
154
|
+
|
|
155
|
+
Multi-proyecto: pypi_enabled se infiere al vuelo de los ficheros
|
|
156
|
+
de packaging (pyproject/setup.py/setup.cfg); el gate final sigue
|
|
157
|
+
en PyPIRunner.is_packaging_project al desplegar.
|
|
158
|
+
"""
|
|
112
159
|
detected = detect_test_commands(project_path)
|
|
113
160
|
if detected is None:
|
|
114
161
|
return None
|
|
@@ -124,7 +171,7 @@ def _auto_toml_config(project_path: str) -> TomlConfig | None:
|
|
|
124
171
|
test_commands=detected,
|
|
125
172
|
test_timeout_s=C_TEST_TIMEOUT_S,
|
|
126
173
|
docs_auto=True,
|
|
127
|
-
pypi_enabled=
|
|
174
|
+
pypi_enabled=looks_like_packaging_project(project_path),
|
|
128
175
|
)
|
|
129
176
|
|
|
130
177
|
|
|
@@ -159,3 +159,58 @@ class TestCMakefileDetection:
|
|
|
159
159
|
os.symlink(real, os.path.join(tmp, "Makefile"))
|
|
160
160
|
with pytest.raises(ValueError, match="Symlink"):
|
|
161
161
|
list_make_targets(tmp)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class TestMultiTargetAndPyPIInference:
|
|
165
|
+
"""Runtime multi-proyecto: todos los targets test en una invocación
|
|
166
|
+
y pypi_enabled inferido de los ficheros de packaging."""
|
|
167
|
+
|
|
168
|
+
def _mk(self, tmp, content):
|
|
169
|
+
with open(os.path.join(tmp, "Makefile"), "w") as f:
|
|
170
|
+
f.write(content)
|
|
171
|
+
|
|
172
|
+
def test_detect_combines_test_targets(self):
|
|
173
|
+
from deploynator._toml import detect_test_commands
|
|
174
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
175
|
+
self._mk(tmp, "test:\n\techo t\ntest-dsp:\n\techo d\n"
|
|
176
|
+
"test-transport:\n\techo r\ntests:\n\tmkdir -p tests\n")
|
|
177
|
+
assert detect_test_commands(tmp) == ["make test test-dsp test-transport"]
|
|
178
|
+
|
|
179
|
+
def test_detect_test_host_alone_wins(self):
|
|
180
|
+
from deploynator._toml import detect_test_commands
|
|
181
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
182
|
+
self._mk(tmp, "test-host:\n\techo h\ntest:\n\techo t\n"
|
|
183
|
+
"test-dsp:\n\techo d\n")
|
|
184
|
+
assert detect_test_commands(tmp) == ["make test-host"]
|
|
185
|
+
|
|
186
|
+
def test_detect_bare_tests_alone_kept(self):
|
|
187
|
+
from deploynator._toml import detect_test_commands
|
|
188
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
189
|
+
self._mk(tmp, "tests:\n\techo t\n")
|
|
190
|
+
assert detect_test_commands(tmp) == ["make tests"]
|
|
191
|
+
|
|
192
|
+
def test_auto_pypi_enabled_for_packaging(self):
|
|
193
|
+
from deploynator._toml import load_toml_config
|
|
194
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
195
|
+
self._mk(tmp, "test:\n\techo t\n")
|
|
196
|
+
with open(os.path.join(tmp, "pyproject.toml"), "w") as f:
|
|
197
|
+
f.write('[project]\nname = "x"\nversion = "0.1.0"\n')
|
|
198
|
+
cfg = load_toml_config(tmp)
|
|
199
|
+
assert cfg.test_commands == ["make test"]
|
|
200
|
+
assert cfg.pypi_enabled is True
|
|
201
|
+
|
|
202
|
+
def test_auto_pypi_disabled_for_plain_c(self):
|
|
203
|
+
from deploynator._toml import load_toml_config
|
|
204
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
205
|
+
self._mk(tmp, "test:\n\techo t\n")
|
|
206
|
+
cfg = load_toml_config(tmp)
|
|
207
|
+
assert cfg.test_commands == ["make test"]
|
|
208
|
+
assert cfg.pypi_enabled is False
|
|
209
|
+
|
|
210
|
+
def test_looks_like_packaging_setup_py(self):
|
|
211
|
+
from deploynator._toml import looks_like_packaging_project
|
|
212
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
213
|
+
assert looks_like_packaging_project(tmp) is False
|
|
214
|
+
with open(os.path.join(tmp, "setup.py"), "w") as f:
|
|
215
|
+
f.write("from setuptools import setup\nsetup(name='x')\n")
|
|
216
|
+
assert looks_like_packaging_project(tmp) is True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|