Skip to content
This repository was archived by the owner on Apr 15, 2025. It is now read-only.
Draft
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<img src="https://img.shields.io/discord/933860922039099444?color=blue&label=chat&logo=discord" alt="Chat on Discord">
</a>
<a href="https://prisma.io">
<img src="https://img.shields.io/static/v1?label=prisma&message=5.19.0&color=blue&logo=prisma" alt="Supported Prisma version is 5.19.0">
<img src="https://img.shields.io/static/v1?label=prisma&message=6.0.0&color=blue&logo=prisma" alt="Supported Prisma version is 6.0.0">
</a>
<a href="https://github.com/astral-sh/ruff">
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FJacobCoffee%2Fbfb02a83c8da3cbf53f7772f2cee02ec%2Fraw%2Facb94daa3aedecda67e2c7d8c5aec9765db0734d%2Fformat-badge.json" alt="Code style: ruff">
Expand Down
2 changes: 1 addition & 1 deletion databases/sync_tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_foreign_key_violation_error(client: Prisma) -> None:
"""The ForeignKeyViolationError is raised when a foreign key is invalid."""
with pytest.raises(
ForeignKeyViolationError,
match=re.compile(r'foreign key constraint failed on the field', re.IGNORECASE),
match=re.compile(r'Foreign key constraint violated', re.IGNORECASE),
):
client.post.create(
data={
Expand Down
2 changes: 1 addition & 1 deletion databases/tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async def test_foreign_key_violation_error(client: Prisma) -> None:
"""The ForeignKeyViolationError is raised when a foreign key is invalid."""
with pytest.raises(
ForeignKeyViolationError,
match=re.compile(r'foreign key constraint failed on the field', re.IGNORECASE),
match=re.compile(r'Foreign key constraint violated', re.IGNORECASE),
):
await client.post.create(
data={
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<img src="https://img.shields.io/discord/933860922039099444?color=blue&label=chat&logo=discord" alt="Chat on Discord">
</a>
<a href="https://prisma.io">
<img src="https://img.shields.io/static/v1?label=prisma&message=5.19.0&color=blue&logo=prisma" alt="Supported Prisma version is 5.19.0">
<img src="https://img.shields.io/static/v1?label=prisma&message=6.0.0&color=blue&logo=prisma" alt="Supported Prisma version is 6.0.0">
</a>
<a href="https://github.com/astral-sh/ruff">
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2FJacobCoffee%2Fbfb02a83c8da3cbf53f7772f2cee02ec%2Fraw%2Facb94daa3aedecda67e2c7d8c5aec9765db0734d%2Fformat-badge.json" alt="Code style: ruff">
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/binaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Prisma Client Python _should_ automatically download the correct binaries for yo
- Clone the prisma-engines repository at the current version that the python client supports:

```
git clone https://github.com/prisma/prisma-engines --branch=5.19.0
git clone https://github.com/prisma/prisma-engines --branch=6.0.0
```

- Build the binaries following the steps found [here](https://github.com/prisma/prisma-engines#building-prisma-engines)
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,15 @@ This option controls the version of Prisma to use. It should be noted that this

| Option | Environment Variable | Default |
| ---------------- | --------------------- | -------- |
| `prisma_version` | `PRISMA_VERSION` | `5.19.0` |
| `prisma_version` | `PRISMA_VERSION` | `6.0.0` |

### Expected Engine Version

This is an internal option that is here as a safeguard for the `prisma_version` option. If you modify the `prisma_version` option then you must also update this option to use the corresponding engine version. You can find a list of engine versions [here](https://github.com/prisma/prisma-engines).

| Option | Environment Variable | Default |
| ------------------------- | -------------------------------- | ------------------------------------------ |
| `expected_engine_version` | `PRISMA_EXPECTED_ENGINE_VERSION` | `5fe21811a6ba0b952a3bc71400666511fe3b902f` |
| `expected_engine_version` | `PRISMA_EXPECTED_ENGINE_VERSION` | `5dbef10bdbfb579e07d35cc85fb1518d357cb99e` |


### Binary Platform
Expand Down
2 changes: 1 addition & 1 deletion pipelines/requirements/node.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nodejs-bin==16.15.1a4
nodejs-wheel-binaries==20.14.0
2 changes: 1 addition & 1 deletion requirements/node.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nodejs-bin
nodejs-wheel-binaries>=20.14.0
8 changes: 4 additions & 4 deletions src/prisma/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,14 @@ def Field(*, env: str | None = None, **extra: Any) -> Any:


if TYPE_CHECKING:
import nodejs as _nodejs
import nodejs_wheel as _nodejs_wheel

nodejs = make_optional(_nodejs)
nodejs_wheel = make_optional(_nodejs_wheel)
else:
try:
import nodejs
import nodejs_wheel
except ImportError:
nodejs = None
nodejs_wheel = None


# Note: this shim is due to an inconsistency with string enums
Expand Down
6 changes: 3 additions & 3 deletions src/prisma/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ class DefaultConfig(BaseSettings):
# doesn't change then the CLI is incorrectly cached
prisma_version: str = Field(
env='PRISMA_VERSION',
default='5.19.0',
default='6.0.0',
)

# Engine binary versions can be found under https://github.com/prisma/prisma-engine/commits/main
expected_engine_version: str = Field(
env='PRISMA_EXPECTED_ENGINE_VERSION',
default='5fe21811a6ba0b952a3bc71400666511fe3b902f',
default='5dbef10bdbfb579e07d35cc85fb1518d357cb99e',
)

# Home directory, used to build the `binary_cache_dir` option by default, useful in multi-user
Expand All @@ -56,7 +56,7 @@ class DefaultConfig(BaseSettings):
# Whether or not to use the global node installation (if available)
use_global_node: bool = Field(env='PRISMA_USE_GLOBAL_NODE', default=True)

# Whether or not to use the `nodejs-bin` package (if installed)
# Whether or not to use the `nodejs-wheel-binaries` package (if installed)
use_nodejs_bin: bool = Field(env='PRISMA_USE_NODEJS_BIN', default=True)

# Extra arguments to pass to nodeenv, arguments are passed after the path, e.g. python -m nodeenv <path> <extra args>
Expand Down
3 changes: 1 addition & 2 deletions src/prisma/_types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Any, Type, Tuple, Mapping, TypeVar, Callable, Coroutine
from typing import Any, Type, Tuple, TypeVar, Callable, Coroutine
from typing_extensions import (
Literal as Literal,
NewType,
Expand Down Expand Up @@ -60,7 +60,6 @@ class _GenericAlias(Protocol):
# NOTE: we don't support some options as their type hints are not publicly exposed
# https://github.com/encode/httpx/discussions/1977
class HttpConfig(TypedDict, total=False):
app: Callable[[Mapping[str, Any], Any], Any]
http1: bool
http2: bool
limits: httpx.Limits
Expand Down
46 changes: 28 additions & 18 deletions src/prisma/cli/_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import shutil
import logging
import subprocess
import importlib.metadata
from abc import ABC, abstractmethod
from typing import IO, Any, Union, Mapping, cast
from pathlib import Path
Expand All @@ -14,18 +15,18 @@
from .. import config
from .._proxy import LazyProxy
from ..errors import PrismaError
from .._compat import nodejs, get_args
from .._compat import get_args, nodejs_wheel
from ..binaries import platform

log: logging.Logger = logging.getLogger(__name__)
File = Union[int, IO[Any]]
Target = Literal['node', 'npm']

# taken from https://github.com/prisma/prisma/blob/main/package.json
MIN_NODE_VERSION = (16, 13)
MIN_NODE_VERSION = (18, 18)

# mapped the node version above from https://nodejs.org/en/download/releases/
MIN_NPM_VERSION = (6, 14)
MIN_NPM_VERSION = (10, 0)

# we only care about the first two entries in the version number
VERSION_RE = re.compile(r'v?(\d+)(?:\.?(\d+))')
Expand All @@ -43,7 +44,7 @@ def __init__(self, *, target: str) -> None:
class MissingNodejsBinError(PrismaError):
def __init__(self) -> None:
super().__init__(
'Attempted to access a function that requires the `nodejs-bin` package to be installed but it is not.'
'Attempted to access a function that requires the `nodejs-wheel-binaries` package to be installed but it is not.'
)


Expand Down Expand Up @@ -182,7 +183,7 @@ def from_nodeenv(cls, target: Target) -> NodeBinaryStrategy:
)
except Exception as exc:
print( # noqa: T201
'nodeenv installation failed; You may want to try installing `nodejs-bin` as it is more reliable.',
'nodeenv installation failed; You may want to try installing `nodejs-wheel-binaries` as it is more reliable.',
file=sys.stderr,
)
raise exc
Expand Down Expand Up @@ -212,11 +213,11 @@ def from_nodeenv(cls, target: Target) -> NodeBinaryStrategy:

class NodeJSPythonStrategy(Strategy):
target: Target
resolver: Literal['nodejs-bin']
resolver: Literal['nodejs-wheel-binaries']

def __init__(self, *, target: Target) -> None:
self.target = target
self.resolver = 'nodejs-bin'
self.resolver = 'nodejs-wheel-binaries'

@override
def __run__(
Expand All @@ -228,36 +229,43 @@ def __run__(
stderr: File | None = None,
env: Mapping[str, str] | None = None,
) -> subprocess.CompletedProcess[bytes]:
if nodejs is None:
if nodejs_wheel is None:
raise MissingNodejsBinError()

func = None
if self.target == 'node':
func = nodejs.node.run
func = nodejs_wheel.node
elif self.target == 'npm':
func = nodejs.npm.run
func = nodejs_wheel.npm
else:
raise UnknownTargetError(target=self.target)

return cast(
proc = cast(
'subprocess.CompletedProcess[bytes]',
func(
args,
check=check,
cwd=cwd,
env=env,
stdout=stdout,
stderr=stderr,
return_completed_process=True,
),
)
if check:
proc.check_returncode()

return proc

@property
def node_path(self) -> Path:
"""Returns the path to the `node` binary"""
if nodejs is None:
if nodejs_wheel is None:
raise MissingNodejsBinError()

return Path(nodejs.node.path)
if os.name == 'nt':
return Path(nodejs_wheel.executable.ROOT_DIR).joinpath('node.exe')

return Path(nodejs_wheel.executable.ROOT_DIR).joinpath('bin/node')

@property
@override
Expand All @@ -273,9 +281,11 @@ def resolve(target: Target) -> Node:
raise UnknownTargetError(target=target)

if config.use_nodejs_bin:
log.debug('Checking if nodejs-bin is installed')
if nodejs is not None:
log.debug('Using nodejs-bin with version: %s', nodejs.node_version)
log.debug('Checking if nodejs-wheel-binaries is installed')
if nodejs_wheel is not None:
log.debug(
'Using nodejs-wheel-binaries with version: %s', importlib.metadata.version('nodejs-wheel-binaries')
)
return NodeJSPythonStrategy(target=target)

return NodeBinaryStrategy.resolve(target)
Expand Down Expand Up @@ -342,7 +352,7 @@ def _should_use_binary(target: Target, path: Path) -> bool:

This only applies to the global node installation as:

- the minimum version of `nodejs-bin` is higher than our requirement
- the minimum version of `nodejs-wheel-binaries` is higher than our requirement
- `nodeenv` defaults to the latest stable version of node
"""
if target == 'node':
Expand Down
9 changes: 1 addition & 8 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import warnings
from typing import TYPE_CHECKING, Any, Mapping
from typing import TYPE_CHECKING, Any
from pathlib import Path
from datetime import timedelta

Expand Down Expand Up @@ -127,8 +126,6 @@ def mock___init__(real__init__: Any, *args: Any, **kwargs: Any) -> None:

getter = patch_method(monkeypatch, httpx.AsyncClient, '__init__', mock___init__)

def mock_app(args: Mapping[str, object], data: object) -> object: ...

async def _test(config: HttpConfig) -> None:
client = Prisma(
http=config,
Expand Down Expand Up @@ -157,10 +154,6 @@ async def _test(config: HttpConfig) -> None:
},
)

with warnings.catch_warnings():
warnings.simplefilter('ignore')
await _test({'app': mock_app})


def test_old_client_alias() -> None:
"""Ensure that Prisma can be imported from the root package under the Client alias"""
Expand Down
14 changes: 7 additions & 7 deletions tests/test_node/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pytest_subprocess import FakeProcess

from prisma.cli import _node as node
from prisma._compat import nodejs
from prisma._compat import nodejs_wheel
from prisma._config import Config
from prisma.cli._node import Target

Expand Down Expand Up @@ -57,7 +57,7 @@ def test_resolve_bad_target() -> None:


@parametrize_target
@pytest.mark.skipif(nodejs is None, reason='nodejs-bin is not installed')
@pytest.mark.skipif(nodejs_wheel is None, reason='nodejs-bin is not installed')
def test_nodejs_bin(target: Target) -> None:
"""When `nodejs-bin` is installed, it is resolved to and can be successfully used"""
with set_config(
Expand All @@ -67,7 +67,7 @@ def test_nodejs_bin(target: Target) -> None:
)
):
strategy = node.resolve(target)
assert strategy.resolver == 'nodejs-bin'
assert strategy.resolver == 'nodejs-wheel-binaries'
assert_strategy(strategy)


Expand Down Expand Up @@ -230,14 +230,14 @@ def _register_process(stdout: str) -> None:
assert version == (1, 32433)
assert node._should_use_binary(target, path) is False

_register_process('v16.15.a4')
_register_process('v18.19.a4')
version = node._get_binary_version(target, path)
assert version == (16, 15)
assert version == (18, 19)
assert node._should_use_binary(target, path) is True

_register_process('v16.13.1')
_register_process('v18.18.1')
version = node._get_binary_version(target, path)
assert version == (16, 13)
assert version == (18, 18)
assert node._should_use_binary(target, path) is True


Expand Down
Loading