Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [??] - ??

### Added

- `rsconnect` now detects Python interpreter version requirements from
`.python-version`, `pyproject.toml` and `setup.cfg`

## [1.25.2] - 2025-02-26

### Fixed
Expand Down
42 changes: 26 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,24 +219,34 @@ ensuring that you use the same Python that you use to run your Jupyter Notebook:
#### Python Version

When deploying Python content to Posit Connect,
the server will require matching `<MAJOR.MINOR>` versions of Python. For example,
a server with only Python 3.9 installed will fail to match content deployed with
Python 3.8. Your administrator may also enable exact Python version matching which
will be stricter and require matching major, minor, and patch versions. For more
information see the [Posit Connect Admin Guide chapter titled Python Version
the server will require a version of Python that matches the content
requirements.

For example, a server with only Python 3.9 installed will fail to match content
that requires Python 3.8.

`rsconnect` supports detecting Python version requirements in several ways:
1. A `.python-version` file exists. In such case
`rsconnect` will use its content to determine the python version requirement.
2. A `pyproject.toml` with a `project.requires-python` field exists.
In such case the requirement specified in the field will be used
if no `.python-version` file exists.
3. A `setup.cfg` with an `options.python_requires` field exists.
In such case the requirement specified in the field will be used
if **1** or **2** were not already satisfied.
4. If no other source of version requirement was found, then
the interpreter in use is considered the one required to run the content.

On Posit Connect `>=2025.03.0` the requirement detected by `rsconnect` is
always respected. Older Connect versions will instead rely only on the
python version used to deploy the content to determine the requirement.

For more information see the [Posit Connect Admin Guide chapter titled Python Version
Matching](https://docs.posit.co/connect/admin/python/#python-version-matching).

We recommend installing a version of Python on your client that is also available
in your Connect installation. If that's not possible, you can override
rsconnect-python's detected Python version and request a version of Python
that is installed in Connect, For example, this command:

```bash
rsconnect deploy api --override-python-version 3.11.5 my-api/
```

will deploy the content in `my-api` while requesting that Connect
use Python version 3.11.5.
We recommend providing a `pyproject.toml` with a `project.requires-python` field
if the deployed content is an installable package and a `.python-version` file
for plain directories.
Comment on lines +247 to +249
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ It's really nice to provide specific guidance like this.


> **Note**
> The packages and package versions listed in `requirements.txt` must be
Expand Down
7 changes: 2 additions & 5 deletions rsconnect/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@

from . import api
from .bundle import (
create_python_environment,
get_default_entrypoint,
make_api_bundle,
make_quarto_source_bundle,
read_manifest_file,
)
from .environment import Environment, EnvironmentException
from .environment import Environment
from .exception import RSConnectException
from .log import VERBOSE, logger
from .models import AppMode, AppModes
Expand Down Expand Up @@ -78,8 +77,6 @@ def failed(err: str):
passed()
except RSConnectException as exc:
failed("Error: " + exc.message)
except EnvironmentException as exc:
failed("Error: " + str(exc))
except Exception as exc:
traceback.print_exc()
failed("Internal error: " + str(exc))
Expand Down Expand Up @@ -375,7 +372,7 @@ def deploy_app(
)
)

environment = create_python_environment(
environment = Environment.create_python_environment(
directory, # pyright: ignore
force_generate,
python,
Expand Down
3 changes: 2 additions & 1 deletion rsconnect/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
from typing_extensions import NotRequired, TypedDict

from . import validation
from .bundle import _default_title, fake_module_file_from_directory
from .bundle import _default_title
from .environment import fake_module_file_from_directory
from .certificates import read_certificate_file
from .exception import DeploymentFailedException, RSConnectException
from .http_support import CookieJar, HTTPResponse, HTTPServer, JsonData, append_to_path
Expand Down
Loading
Loading