diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1a842c4ea7..80cae43a7f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,8 +14,6 @@ jobs: - typer-slim - typer - typer-cli - env: - dir: ${{ matrix.package == 'typer-slim' && './' || matrix.package == 'typer' && 'typer_package' || matrix.package == 'typer-cli' && 'typer_cli_package' }} permissions: id-token: write steps: @@ -34,9 +32,8 @@ jobs: - name: Install build dependencies run: pip install build - name: Build distribution - working-directory: ${{ env.dir }} + env: + TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} run: python -m build - name: Publish uses: pypa/gh-action-pypi-publish@v1.8.11 - with: - packages-dir: ${{ env.dir }}/dist/ diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index c16d19d7b4..d2a33d30e2 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -18,8 +18,6 @@ jobs: - typer-slim - typer - typer-cli - env: - dir: ${{ matrix.package == 'typer-slim' && './' || matrix.package == 'typer' && 'typer_package' || matrix.package == 'typer-cli' && 'typer_cli_package' }} steps: - name: Dump GitHub context env: @@ -36,25 +34,24 @@ jobs: - name: Install build dependencies run: pip install build - name: Build source distribution - working-directory: ${{ env.dir }} + env: + TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} run: python -m build --sdist - name: Decompress source distribution - working-directory: ${{ env.dir }} run: | cd dist tar xvf typer*.tar.gz - name: Install test dependencies - if: ${{ matrix.package == 'typer-slim' }} + if: ${{ matrix.package != 'typer-cli' }} run: | cd dist/typer*/ pip install -r requirements-tests.txt - name: Run source distribution tests - if: ${{ matrix.package == 'typer-slim' }} + if: ${{ matrix.package != 'typer-cli' }} run: | cd dist/typer*/ bash scripts/test.sh - name: Build wheel distribution - working-directory: ${{ env.dir }} run: | cd dist pip wheel --no-deps typer*.tar.gz diff --git a/README.md b/README.md index 0d4d824aa1..6bb4983a9f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The key features are: * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **Start simple**: The simplest example adds only 2 lines of code to your app: **1 import, 1 function call**. * **Grow large**: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments. -* **Run scripts**: Typer includes a `typer` command that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. +* **Run scripts**: Typer includes a `typer` command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. ## FastAPI of CLIs @@ -355,13 +355,10 @@ By default it also comes with extra standard dependencies: * shellingham: to automatically detect the current shell when installing completion. * With `shellingham` you can just use `--install-completion`. * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. -* `typer-cli`: adds the `typer` command to your shell: - * Quickly run scripts (that don't have to use Typer) with shell completion. - * Generate docs for your Typer applications. ### `typer-slim` -If you don't want the extra dependencies, install `typer-slim` instead. +If you don't want the extra standard optional dependencies, install `typer-slim` instead. When you install with: @@ -369,15 +366,15 @@ When you install with: pip install typer ``` -...it's the equivalent of: +...it includes the same code and dependencies as: ```bash pip install "typer-slim[standard]" ``` -The `standard` extra dependencies are `rich`, `shellingham`, `typer-cli`. +The `standard` extra dependencies are `rich` and `shellingham`. -**Note**: even if you don't install `typer-cli` you can still use it's functionality by calling `typer` as a module, e.g. `python -m typer`. +**Note**: The `typer` command is only included in the `typer` package. ## License diff --git a/docs/index.md b/docs/index.md index 0d4d824aa1..6bb4983a9f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,7 +37,7 @@ The key features are: * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **Start simple**: The simplest example adds only 2 lines of code to your app: **1 import, 1 function call**. * **Grow large**: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments. -* **Run scripts**: Typer includes a `typer` command that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. +* **Run scripts**: Typer includes a `typer` command/program that you can use to run scripts, automatically converting them to CLIs, even if they don't use Typer internally. ## FastAPI of CLIs @@ -355,13 +355,10 @@ By default it also comes with extra standard dependencies: * shellingham: to automatically detect the current shell when installing completion. * With `shellingham` you can just use `--install-completion`. * Without `shellingham`, you have to pass the name of the shell to install completion for, e.g. `--install-completion bash`. -* `typer-cli`: adds the `typer` command to your shell: - * Quickly run scripts (that don't have to use Typer) with shell completion. - * Generate docs for your Typer applications. ### `typer-slim` -If you don't want the extra dependencies, install `typer-slim` instead. +If you don't want the extra standard optional dependencies, install `typer-slim` instead. When you install with: @@ -369,15 +366,15 @@ When you install with: pip install typer ``` -...it's the equivalent of: +...it includes the same code and dependencies as: ```bash pip install "typer-slim[standard]" ``` -The `standard` extra dependencies are `rich`, `shellingham`, `typer-cli`. +The `standard` extra dependencies are `rich` and `shellingham`. -**Note**: even if you don't install `typer-cli` you can still use it's functionality by calling `typer` as a module, e.g. `python -m typer`. +**Note**: The `typer` command is only included in the `typer` package. ## License diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index 6fb8075c87..6cec65fe23 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -68,12 +68,12 @@ The first step is to install **Typer**: ```console $ pip install typer ---> 100% -Successfully installed typer click shellingham rich typer-cli +Successfully installed typer click shellingham rich ``` -By default, `typer` comes with `rich`, `shellingham`, and `typer-cli`. +By default, `typer` comes with `rich` and `shellingham`. !!! note If you are an advanced user and want to opt out of these default extra dependencies, you can instead install `typer-slim`. @@ -82,7 +82,7 @@ By default, `typer` comes with `rich`, `shellingham`, and `typer-cli`. pip install typer ``` - ...is the equivalent of: + ...includes the same optional dependencies as: ```bash pip install "typer-slim[standard]" diff --git a/pdm_build.py b/pdm_build.py new file mode 100644 index 0000000000..4629801f0e --- /dev/null +++ b/pdm_build.py @@ -0,0 +1,55 @@ +import os +from typing import Any, Dict, List + +from pdm.backend.hooks import Context + +TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "typer") + + +def pdm_build_initialize(context: Context): + metadata = context.config.metadata + # Get main version + version = metadata["version"] + # Get package names to keep in sync with the same main version + sync_dependencies: List[str] = context.config.data["tool"]["tiangolo"][ + "_internal-slim-build" + ]["sync-dependencies"] + # Get custom config for the current package, from the env var + config: Dict[str, Any] = context.config.data["tool"]["tiangolo"][ + "_internal-slim-build" + ]["packages"][TIANGOLO_BUILD_PACKAGE] + project_config: Dict[str, Any] = config["project"] + # Get main optional dependencies, extras + optional_dependencies: Dict[str, List[str]] = metadata.get( + "optional-dependencies", {} + ) + # Get custom optional dependencies name to always include in this (non-slim) package + include_optional_dependencies: List[str] = config.get( + "include-optional-dependencies", [] + ) + # Override main [project] configs with custom configs for this package + for key, value in project_config.items(): + metadata[key] = value + # Get custom build config for the current package + build_config: Dict[str, Any] = ( + config.get("tool", {}).get("pdm", {}).get("build", {}) + ) + # Override PDM build config with custom build config for this package + for key, value in build_config.items(): + context.config.build_config[key] = value + # Get main dependencies + dependencies: List[str] = metadata.get("dependencies", []) + # Add optional dependencies to the default dependencies for this (non-slim) package + for include_optional in include_optional_dependencies: + optional_dependencies_group = optional_dependencies.get(include_optional, []) + dependencies.extend(optional_dependencies_group) + # Sync versions in dependencies + new_dependencies = [] + for dep in dependencies: + if dep in sync_dependencies: + new_dep = f"{dep}=={version}" + new_dependencies.append(new_dep) + else: + new_dependencies.append(dep) + if new_dependencies != dependencies: + metadata["dependencies"] = new_dependencies diff --git a/pyproject.toml b/pyproject.toml index f5abe95d3c..b648d38ad4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,15 +3,12 @@ requires = ["pdm-backend"] build-backend = "pdm.backend" [project] -# pip install typer-slim: is only the Typer library, without extras -# pip install typer: is typer-slim[standard], with extras and typer-cli -name = "typer-slim" +name = "typer" dynamic = ["version"] description = "Typer, build great CLIs. Easy to code. Based on Python type hints." authors = [ {name = "Sebastián Ramírez", email = "tiangolo@gmail.com"}, ] -readme = "README.md" requires-python = ">=3.7" classifiers = [ "Intended Audience :: Information Technology", @@ -38,16 +35,12 @@ dependencies = [ "click >= 8.0.0", "typing-extensions >= 3.7.4.3", ] - +readme = "README.md" [project.urls] Documentation = "https://typer.tiangolo.com/" homepage = "https://github.com/tiangolo/typer" [project.optional-dependencies] -all = [ - "shellingham >=1.3.0", - "rich >=10.11.0", -] standard = [ "shellingham >=1.3.0", "rich >=10.11.0", @@ -65,6 +58,50 @@ source-includes = [ "scripts/", ] +[tool.tiangolo._internal-slim-build] +sync-dependencies = [ + "typer-slim[standard]", + "typer-cli", + "typer" +] + +[tool.tiangolo._internal-slim-build.packages.typer-slim.project] +name = "typer-slim" + +[tool.tiangolo._internal-slim-build.packages.typer] +include-optional-dependencies = ["standard"] + +[tool.tiangolo._internal-slim-build.packages.typer.project] +optional-dependencies = {} + +[tool.tiangolo._internal-slim-build.packages.typer.project.scripts] +typer = "typer.cli:main" + +[tool.tiangolo._internal-slim-build.packages.typer-cli.project] +name = "typer-cli" +readme = "typer-cli/README.md" +dependencies = [ + "typer", +] +optional-dependencies = {} + +[tool.tiangolo._internal-slim-build.packages.typer-cli.tool.pdm.build] +# excludes needs to explicitly exclude the top level python packages, +# otherwise PDM includes them by default +# A "*" glob pattern can't be used here because in PDM internals, the patterns are put +# in a set (unordered, order varies) and each excluded file is assigned one of the +# glob patterns that matches, as the set is unordered, the matched pattern could be "*" +# independent of the order here. And then the internal code would give it a lower score +# than the one for a default included file. +# By not using "*" and explicitly excluding the top level packages, they get a higher +# score than the default inclusion +excludes = ["typer", "tests", "pdm_build.py"] +# source-includes needs to explicitly define some value because PDM will check the +# truthy value of the list, and if empty, will include some defaults, including "tests", +# an empty string doesn't match anything, but makes the list truthy, so that PDM +# doesn't override it during the build. +source-includes = [""] + [tool.isort] profile = "black" known_third_party = ["typer", "click"] diff --git a/typer_cli_package/README.md b/typer-cli/README.md similarity index 82% rename from typer_cli_package/README.md rename to typer-cli/README.md index dba1a0dcf7..0ebe65102c 100644 --- a/typer_cli_package/README.md +++ b/typer-cli/README.md @@ -30,9 +30,13 @@ Typer is a library for building