Skip to content

Commit f2d33df

Browse files
authored
fix: Improve validation errors in Crawlee CLI (#1140)
### Description - Add checks to ensure that the selected package manager is installed and executable. - Suppress cookie-cutter logs when a failure occurs. ### Issues - Closes: #1138
1 parent be5cc03 commit f2d33df

File tree

2 files changed

+42
-16
lines changed

2 files changed

+42
-16
lines changed

Diff for: src/crawlee/_cli.py

+27-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import importlib.resources
55
import json
6+
import sys
67
from pathlib import Path
78
from typing import Annotated, Optional, cast
89

@@ -199,19 +200,32 @@ def create(
199200
TextColumn('[progress.description]{task.description}'),
200201
transient=True,
201202
) as progress:
202-
progress.add_task(description='Bootstrapping...', total=None)
203-
cookiecutter(
204-
template=str(template_directory),
205-
no_input=True,
206-
extra_context={
207-
'project_name': project_name,
208-
'package_manager': package_manager,
209-
'crawler_type': crawler_type,
210-
'http_client': http_client,
211-
'enable_apify_integration': enable_apify_integration,
212-
'start_url': start_url,
213-
},
214-
)
203+
bootstrap_task = progress.add_task(description='Bootstrapping...', total=None)
204+
205+
try:
206+
cookiecutter(
207+
template=str(template_directory),
208+
no_input=True,
209+
extra_context={
210+
'project_name': project_name,
211+
'package_manager': package_manager,
212+
'crawler_type': crawler_type,
213+
'http_client': http_client,
214+
'enable_apify_integration': enable_apify_integration,
215+
'start_url': start_url,
216+
},
217+
)
218+
except Exception as exc:
219+
progress.update(bootstrap_task, visible=False)
220+
progress.refresh()
221+
222+
# Print just the last line of the error message (the actual error without traceback)
223+
if 'Hook script failed' in str(exc):
224+
typer.echo('Project creation failed. Check the error message above.', err=True)
225+
else:
226+
typer.echo(f'Project creation failed: {exc!s}', err=True)
227+
228+
sys.exit(1)
215229

216230
typer.echo(f'Your project "{project_name}" was created.')
217231

Diff for: src/crawlee/project_template/hooks/pre_gen_project.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# % if cookiecutter.package_manager in ['poetry', 'uv']
22
import subprocess
3+
import shutil
34
import re
5+
import sys
46

57
manager = "{{cookiecutter.package_manager}}"
68
manager_text = manager.title()
@@ -12,10 +14,20 @@
1214
r_version = '0.x'
1315
# % endif
1416

17+
# Check if package manager is available in PATH
18+
if not shutil.which(manager):
19+
sys.stderr.write(f'\nError: You selected {manager_text} as your package manager, but it is not installed. Please install it and try again.\n')
20+
sys.exit(1)
21+
22+
# Check if the package manager is executable
1523
try:
1624
version = subprocess.check_output([manager, '--version']).decode().strip()
17-
except OSError as exc:
18-
raise RuntimeError(f'You chose to use the {manager_text} package manager, but it does not seem to be installed') from exc
25+
except OSError:
26+
sys.stderr.write(f'\nError: Your selected package manager {manager_text} was found but failed to execute.\n')
27+
sys.exit(1)
28+
29+
# Check if the version matches the required regex
1930
if not re.match(version_regex, version):
20-
raise RuntimeError(f'{manager_text} {r_version} is required, but "{version}" is installed')
31+
sys.stderr.write(f'\nError: Your selected package manager {manager_text} requires version {r_version}, but {version} is installed.\n')
32+
sys.exit(1)
2133
# % endif

0 commit comments

Comments
 (0)