Skip to content

Commit f5bc5ce

Browse files
authored
Merge branch 'main' into windows
2 parents de549c5 + 15640d3 commit f5bc5ce

File tree

4 files changed

+32
-37
lines changed

4 files changed

+32
-37
lines changed

Diff for: .github/workflows/run-tests.yml

+12-5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ on:
1212
- "tests/**"
1313
- "uv.lock"
1414
- "pyproject.toml"
15+
- ".github/workflows/**"
1516
pull_request:
1617
paths:
1718
- "src/**"
1819
- "tests/**"
1920
- "uv.lock"
2021
- "pyproject.toml"
22+
- ".github/workflows/**"
2123

2224
workflow_dispatch:
2325

@@ -26,20 +28,25 @@ permissions:
2628

2729
jobs:
2830
run_tests:
29-
name: Run tests
30-
runs-on: ubuntu-latest
31+
name: "Run tests: Python ${{ matrix.python-version }} on ${{ matrix.os }}"
32+
runs-on: ${{ matrix.os }}
33+
strategy:
34+
matrix:
35+
os: [ubuntu-latest, windows-latest, macos-latest]
36+
python-version: ["3.10"]
37+
fail-fast: false
3138

3239
steps:
3340
- uses: actions/checkout@v4
3441

3542
- name: Install uv
3643
uses: astral-sh/setup-uv@v4
3744

38-
- name: Set up Python
39-
run: uv python install 3.11
45+
- name: Set up Python ${{ matrix.python-version }}
46+
run: uv python install ${{ matrix.python-version }}
4047

4148
- name: Install FastMCP
42-
run: uv sync --extra dev
49+
run: uv sync --extra tests
4350

4451
- name: Run tests
4552
run: uv run pytest -vv

Diff for: README.md

+5-8
Original file line numberDiff line numberDiff line change
@@ -464,23 +464,20 @@ FastMCP requires Python 3.10+ and [uv](https://docs.astral.sh/uv/).
464464

465465
### Installation
466466

467-
Create a fork of this repository, then clone it:
467+
For development, we recommend installing FastMCP with development dependencies, which includes various utilities the maintainers find useful.
468468

469469
```bash
470-
git clone https://github.com/YouFancyUserYou/fastmcp.git
470+
git clone https://github.com/jlowin/fastmcp.git
471471
cd fastmcp
472+
uv sync --frozen --extra dev
472473
```
473474

474-
Next, create a virtual environment and install FastMCP:
475+
For running tests only (e.g., in CI), you only need the testing dependencies:
475476

476477
```bash
477-
uv venv
478-
source .venv/bin/activate
479-
uv sync --frozen --all-extras --dev
478+
uv sync --frozen --extra tests
480479
```
481480

482-
483-
484481
### Testing
485482

486483
Please make sure to test any new functionality. Your tests should be simple and atomic and anticipate change rather than cement complex patterns.

Diff for: pyproject.toml

+3-5
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,14 @@ requires = ["hatchling>=1.21.0", "hatch-vcs>=0.4.0"]
2323
build-backend = "hatchling.build"
2424

2525
[project.optional-dependencies]
26-
dev = [
27-
"copychat>=0.5.2",
28-
"ipython>=8.12.3",
29-
"pdbpp>=0.10.3",
26+
tests = [
3027
"pre-commit",
31-
"pytest-xdist>=3.6.1",
3228
"pytest>=8.3.3",
3329
"pytest-asyncio>=0.23.5",
30+
"pytest-xdist>=3.6.1",
3431
"ruff",
3532
]
33+
dev = ["fastmcp[tests]", "copychat>=0.5.2", "ipython>=8.12.3", "pdbpp>=0.10.3"]
3634

3735
[tool.pytest.ini_options]
3836
asyncio_mode = "auto"

Diff for: src/fastmcp/resources/base.py

+12-19
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,26 @@
11
"""Base classes and interfaces for FastMCP resources."""
22

33
import abc
4-
from typing import Annotated, Union
4+
from typing import Union
55

66
from pydantic import (
77
AnyUrl,
88
BaseModel,
9-
BeforeValidator,
109
ConfigDict,
1110
Field,
1211
FileUrl,
1312
ValidationInfo,
1413
field_validator,
1514
)
16-
from pydantic.networks import _BaseUrl # TODO: remove this once pydantic is updated
17-
18-
19-
def maybe_cast_str_to_any_url(x) -> AnyUrl:
20-
if isinstance(x, FileUrl):
21-
return x
22-
elif isinstance(x, AnyUrl):
23-
return x
24-
elif isinstance(x, str):
25-
if x.startswith("file://"):
26-
return FileUrl(x)
27-
return AnyUrl(x)
28-
raise ValueError(f"Expected str or AnyUrl, got {type(x)}")
29-
30-
31-
LaxAnyUrl = Annotated[_BaseUrl | str, BeforeValidator(maybe_cast_str_to_any_url)]
3215

3316

3417
class Resource(BaseModel, abc.ABC):
3518
"""Base class for all resources."""
3619

3720
model_config = ConfigDict(validate_default=True)
3821

39-
uri: LaxAnyUrl = Field(default=..., description="URI of the resource")
22+
# uri: Annotated[AnyUrl, BeforeValidator(maybe_cast_str_to_any_url)] = Field(
23+
uri: AnyUrl = Field(default=..., description="URI of the resource")
4024
name: str | None = Field(description="Name of the resource", default=None)
4125
description: str | None = Field(
4226
description="Description of the resource", default=None
@@ -47,6 +31,15 @@ class Resource(BaseModel, abc.ABC):
4731
pattern=r"^[a-zA-Z0-9]+/[a-zA-Z0-9\-+.]+$",
4832
)
4933

34+
@field_validator("uri", mode="before")
35+
def validate_uri(cls, uri: AnyUrl | str) -> AnyUrl:
36+
if isinstance(uri, str):
37+
# AnyUrl doesn't support triple-slashes, but files do ("file:///absolute/path")
38+
if uri.startswith("file://"):
39+
return FileUrl(uri)
40+
return AnyUrl(uri)
41+
return uri
42+
5043
@field_validator("name", mode="before")
5144
@classmethod
5245
def set_default_name(cls, name: str | None, info: ValidationInfo) -> str:

0 commit comments

Comments
 (0)