From 7797334983803228f5b20a72ce6581d7d906154f Mon Sep 17 00:00:00 2001 From: Max Bohomolov Date: Sun, 19 Jul 2026 11:21:12 +0000 Subject: [PATCH 1/2] ensure compatibility with typer >=0.26 --- pyproject.toml | 4 +- src/crawlee/_cli.py | 114 +++++++++++++++++++++++++------------------- uv.lock | 10 ++-- 3 files changed, 72 insertions(+), 56 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 26f882cf7c..1da673a9eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,9 +65,7 @@ cli = [ "cookiecutter>=2.6.0", "inquirer>=3.3.0", "rich>=13.9.0", - # Pinned below 0.26, which breaks our `click.Choice` CLI options. - # See https://github.com/apify/crawlee-python/issues/2063. - "typer>=0.12.0,<0.26", + "typer>=0.12.0", ] curl-impersonate = ["curl-cffi>=0.9.0"] httpx = ["httpx[brotli,http2,zstd]>=0.27.0", "apify_fingerprint_datapoints>=0.0.2", "browserforge>=1.2.3"] diff --git a/src/crawlee/_cli.py b/src/crawlee/_cli.py index cb345949f6..9ccaf3880d 100644 --- a/src/crawlee/_cli.py +++ b/src/crawlee/_cli.py @@ -5,9 +5,7 @@ import json import sys from pathlib import Path -from typing import Annotated, cast - -from click import Choice +from typing import TYPE_CHECKING, Annotated, Literal, cast try: import inquirer @@ -34,6 +32,15 @@ default_enable_apify_integration = cookiecutter_json['enable_apify_integration'] default_install_project = cookiecutter_json['install_project'] +if TYPE_CHECKING: + # A `Literal` built from runtime data can't be introspected by PEP 586, + # so during type checking these aliases are plain `str`. + CrawlerType = HttpClientType = PackageManagerType = str +else: + CrawlerType = Literal[tuple(crawler_choices)] + HttpClientType = Literal[tuple(http_client_choices)] + PackageManagerType = Literal[tuple(package_manager_choices)] + @cli.callback(invoke_without_command=True) def callback( @@ -124,52 +131,63 @@ def _prompt_bool(message: str, *, default: bool) -> bool: @cli.command() def create( - project_name: str | None = typer.Argument( - default=None, - show_default=False, - help='The name of the project and the directory that will be created to contain it. ' - 'If none is given, you will be prompted.', - ), - crawler_type: str | None = typer.Option( - None, - '--crawler-type', - '--template', - show_default=False, - click_type=Choice(crawler_choices), - help='The library that will be used for crawling in your crawler. If none is given, you will be prompted.', - ), - http_client: str | None = typer.Option( - None, - show_default=False, - click_type=Choice(http_client_choices), - help='The library that will be used to make HTTP requests in your crawler. ' - 'If none is given, you will be prompted.', - ), - package_manager: str | None = typer.Option( - default=None, - show_default=False, - click_type=Choice(package_manager_choices), - help='Package manager to be used in the new project. If none is given, you will be prompted.', - ), - start_url: str | None = typer.Option( - default=None, - show_default=False, - metavar='[START_URL]', - help='The URL where crawling should start. If none is given, you will be prompted.', - ), + project_name: Annotated[ + str | None, + typer.Argument( + show_default=False, + help='The name of the project and the directory that will be created to contain it. ' + 'If none is given, you will be prompted.', + ), + ] = None, + crawler_type: Annotated[ + CrawlerType | None, + typer.Option( + '--crawler-type', + '--template', + show_default=False, + help='The library that will be used for crawling in your crawler. If none is given, you will be prompted.', + ), + ] = None, + http_client: Annotated[ + HttpClientType | None, + typer.Option( + show_default=False, + help='The library that will be used to make HTTP requests in your crawler. ' + 'If none is given, you will be prompted.', + ), + ] = None, + package_manager: Annotated[ + PackageManagerType | None, + typer.Option( + show_default=False, + help='Package manager to be used in the new project. If none is given, you will be prompted.', + ), + ] = None, + start_url: Annotated[ + str | None, + typer.Option( + show_default=False, + metavar='[START_URL]', + help='The URL where crawling should start. If none is given, you will be prompted.', + ), + ] = None, *, - enable_apify_integration: bool | None = typer.Option( - None, - '--apify/--no-apify', - show_default=False, - help='Should Apify integration be set up for you? If not given, you will be prompted.', - ), - install_project: bool | None = typer.Option( - None, - '--install/--no-install', - show_default=False, - help='Should the project be installed now? If not given, you will be prompted.', - ), + enable_apify_integration: Annotated[ + bool | None, + typer.Option( + '--apify/--no-apify', + show_default=False, + help='Should Apify integration be set up for you? If not given, you will be prompted.', + ), + ] = None, + install_project: Annotated[ + bool | None, + typer.Option( + '--install/--no-install', + show_default=False, + help='Should the project be installed now? If not given, you will be prompted.', + ), + ] = None, ) -> None: """Bootstrap a new Crawlee project.""" try: diff --git a/uv.lock b/uv.lock index 0404abfc52..3431a519d1 100644 --- a/uv.lock +++ b/uv.lock @@ -977,7 +977,7 @@ requires-dist = [ { name = "sqlalchemy", extras = ["asyncio"], marker = "extra == 'sql-sqlite'", specifier = ">=2.0.0,<3.0.0" }, { name = "stagehand", marker = "extra == 'stagehand'", specifier = ">=3.19.5" }, { name = "tldextract", specifier = ">=5.3.0" }, - { name = "typer", marker = "extra == 'cli'", specifier = ">=0.12.0,<0.26" }, + { name = "typer", marker = "extra == 'cli'", specifier = ">=0.12.0" }, { name = "typing-extensions", specifier = ">=4.10.0" }, { name = "wrapt", marker = "extra == 'otel'", specifier = ">=1.17.0" }, { name = "yarl", specifier = ">=1.18.0" }, @@ -4562,17 +4562,17 @@ wheels = [ [[package]] name = "typer" -version = "0.25.1" +version = "0.27.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, - { name = "click" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e4/51/9aed62104cea109b820bbd6c14245af756112017d309da813ef107d42e7e/typer-0.25.1.tar.gz", hash = "sha256:9616eb8853a09ffeabab1698952f33c6f29ffdbceb4eaeecf571880e8d7664cc", size = 122276, upload-time = "2026-04-30T19:32:16.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl", hash = "sha256:75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89", size = 58409, upload-time = "2026-04-30T19:32:18.271Z" }, + { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" }, ] [[package]] From 183c0907c5d23c2b59ceffbb24c0693643437a1e Mon Sep 17 00:00:00 2001 From: Max Bohomolov Date: Sun, 19 Jul 2026 11:24:51 +0000 Subject: [PATCH 2/2] bump typer --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1da673a9eb..79284c5197 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,7 @@ cli = [ "cookiecutter>=2.6.0", "inquirer>=3.3.0", "rich>=13.9.0", - "typer>=0.12.0", + "typer>=0.26.0", ] curl-impersonate = ["curl-cffi>=0.9.0"] httpx = ["httpx[brotli,http2,zstd]>=0.27.0", "apify_fingerprint_datapoints>=0.0.2", "browserforge>=1.2.3"] diff --git a/uv.lock b/uv.lock index 3431a519d1..3e4135a19c 100644 --- a/uv.lock +++ b/uv.lock @@ -977,7 +977,7 @@ requires-dist = [ { name = "sqlalchemy", extras = ["asyncio"], marker = "extra == 'sql-sqlite'", specifier = ">=2.0.0,<3.0.0" }, { name = "stagehand", marker = "extra == 'stagehand'", specifier = ">=3.19.5" }, { name = "tldextract", specifier = ">=5.3.0" }, - { name = "typer", marker = "extra == 'cli'", specifier = ">=0.12.0" }, + { name = "typer", marker = "extra == 'cli'", specifier = ">=0.26.0" }, { name = "typing-extensions", specifier = ">=4.10.0" }, { name = "wrapt", marker = "extra == 'otel'", specifier = ">=1.17.0" }, { name = "yarl", specifier = ">=1.18.0" },