Files
agent-framework/python/pyproject.toml
T
Eduard van Valkenburg 50fdcbaf57 Python: chore(python): improve dependency range automation (#4343)
* chore(python): improve dependency range automation

- tighten dependency bounds and coding standards guidance\n- add dependency range validation workflow, reporting, and issue automation\n- update related tests and dependency pins for compatibility

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* updated text and pyarrow

* new lock

* fixed workflow

* updated deps

* fix tiktoken

* chore(python): refine dependency validation workflows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(python): add high-level dependency validation comments

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* WIP

* added additional comments and excludes

* added dev dependency handling and workflow and updates to package ranges

* added readme and simplified commands

* fix markers

* chore(python): address dependency review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Tighten dependency bounds, remove stale overrides, restore Python 3.10 support

- Apply dependency bound policy across all packages: stable >=1.0 deps use
  >=floor,<next_major; pre-1.0/prerelease deps use validated hard-bounded ranges
- Remove stale root tool.uv.override-dependencies (uvicorn, websockets, grpcio)
- Lower github_copilot requires-python to >=3.10 with github-copilot-sdk gated
  behind python_version >= 3.11 marker; import raises ImportError on 3.10
- Skip github_copilot pyright/mypy/test tasks on Python <3.11
- Use version-conditional pyrightconfig for samples on Python 3.10
- Add compatibility fix in core responses client for older openai typed dicts
- Normalize uv.lock prerelease mode and refresh dev dependencies
- Update CODING_STANDARD.md, DEV_SETUP.md, and package management skill docs

Closes #902

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* small tweaks

* add note in workflow

* fix workflows and several versions

* fix duplicate

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-13 12:32:37 +00:00

410 lines
14 KiB
TOML

[project]
name = "agent-framework"
description = "Microsoft Agent Framework for building AI Agents with Python. This package contains all the core and optional packages."
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
readme = "README.md"
requires-python = ">=3.10"
version = "1.0.0rc4"
license-files = ["LICENSE"]
urls.homepage = "https://aka.ms/agent-framework"
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true"
urls.issues = "https://github.com/microsoft/agent-framework/issues"
classifiers = [
"License :: OSI Approved :: MIT License",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Typing :: Typed",
]
dependencies = [
"agent-framework-core[all]==1.0.0rc4",
]
[dependency-groups]
dev = [
"uv==0.10.9",
"flit==3.12.0",
"ruff==0.15.5",
"pytest==9.0.2",
"pytest-asyncio==1.3.0",
"pytest-cov==7.0.0",
"pytest-xdist[psutil]==3.8.0",
"pytest-timeout==2.4.0",
"pytest-retry==1.7.0",
"mypy==1.19.1",
"pyright==1.1.408",
#tasks
"poethepoet==0.42.1",
"rich==13.7.1",
"tomli==2.4.0",
"prek==0.3.4",
]
[tool.uv]
package = false
prerelease = "if-necessary-or-explicit"
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
"sys_platform == 'win32'"
]
[tool.uv.workspace]
members = [ "packages/*" ]
[tool.uv.sources]
agent-framework = { workspace = true }
agent-framework-core = { workspace = true }
agent-framework-a2a = { workspace = true }
agent-framework-ag-ui = { workspace = true }
agent-framework-azure-ai-search = { workspace = true }
agent-framework-azure-cosmos = { workspace = true }
agent-framework-anthropic = { workspace = true }
agent-framework-azure-ai = { workspace = true }
agent-framework-azurefunctions = { workspace = true }
agent-framework-bedrock = { workspace = true }
agent-framework-chatkit = { workspace = true }
agent-framework-copilotstudio = { workspace = true }
agent-framework-declarative = { workspace = true }
agent-framework-devui = { workspace = true }
agent-framework-durabletask = { workspace = true }
agent-framework-foundry-local = { workspace = true }
agent-framework-lab = { workspace = true }
agent-framework-mem0 = { workspace = true }
agent-framework-ollama = { workspace = true }
agent-framework-purview = { workspace = true }
agent-framework-redis = { workspace = true }
agent-framework-github-copilot = { workspace = true }
agent-framework-claude = { workspace = true }
agent-framework-orchestrations = { workspace = true }
[tool.ruff]
line-length = 120
target-version = "py310"
fix = true
include = ["*.py", "*.pyi", "**/pyproject.toml", "*.ipynb"]
exclude = ["scripts"]
extend-exclude = [
"[{][{]cookiecutter.package_name[}][}]",
]
preview = true
[tool.ruff.lint]
fixable = ["ALL"]
unfixable = []
select = [
"ASYNC", # async checks
"B", # bugbear checks
"CPY", # copyright
"D", # pydocstyle checks
"E", # pycodestyle error checks
"ERA", # remove connected out code
"F", # pyflakes checks
"FIX", # fixme checks
"I", # isort
"INP", # implicit namespace package
"ISC", # implicit string concat
"Q", # flake8-quotes checks
"RET", # flake8-return check
"RSE", # raise exception parantheses check
"RUF", # RUF specific rules
"SIM", # flake8-simplify check
"T20", # typing checks
"TD", # todos
"W", # pycodestyle warning checks
"T100", # Debugger,
"S", # Bandit checks
]
ignore = [
"D100", # allow missing docstring in public module
"D104", # allow missing docstring in public package
"D418", # allow overload to have a docstring
"TD003", # allow missing link to todo issue
"FIX002", # allow todo
"B027", # allow empty non-abstract method in ABC
"B905", # `zip()` without an explicit `strict=` parameter
"RUF067", # allow version detection in __init__.py
]
[tool.ruff.lint.per-file-ignores]
# Ignore all directories named `tests` and `samples`.
"**/tests/**" = ["D", "INP", "TD", "ERA001", "RUF", "S"]
"samples/**" = ["D", "INP", "ERA001", "RUF", "S", "T201", "CPY"]
"*.ipynb" = ["CPY", "E501"]
[tool.ruff.format]
docstring-code-format = true
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.flake8-copyright]
notice-rgx = "^# Copyright \\(c\\) Microsoft\\. All rights reserved\\."
min-file-size = 1
[tool.pytest.ini_options]
testpaths = ['packages/**/tests', 'packages/**/ag_ui_tests']
norecursedirs = '**/lab/**'
addopts = "-ra -q -r fEX"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = []
timeout = 60
markers = [
"azure: marks tests as Azure provider specific",
"azure-ai: marks tests as Azure AI provider specific",
"openai: marks tests as OpenAI provider specific",
"integration: marks tests as integration tests that require external services",
]
[tool.coverage.run]
omit = [
"**/__init__.py"
]
[tool.pyright]
exclude = ["**/tests/**", "**/.venv/**", "packages/devui/frontend/**"]
typeCheckingMode = "strict"
reportUnnecessaryIsInstance = false
reportMissingTypeStubs = false
reportUnnecessaryCast = "error"
[tool.mypy]
plugins = ['pydantic.mypy']
strict = true
python_version = "3.10"
ignore_missing_imports = true
disallow_untyped_defs = true
no_implicit_optional = true
check_untyped_defs = true
warn_return_any = true
show_error_codes = true
warn_unused_ignores = false
disallow_incomplete_defs = true
disallow_untyped_decorators = true
[tool.bandit]
targets = ["agent_framework"]
exclude_dirs = ["tests", "scripts", "samples"]
[tool.poe]
executor.type = "uv"
[tool.poe.tasks]
markdown-code-lint = "uv run python scripts/check_md_code_blocks.py 'README.md' './packages/**/README.md' './samples/**/*.md' --exclude cookiecutter-agent-framework-lab --exclude tau2 --exclude 'packages/devui/frontend' --exclude context_providers/azure_ai_search"
prek-install = "prek install --overwrite"
install = "uv sync --all-packages --all-extras --dev --frozen --prerelease=if-necessary-or-explicit"
test = "python scripts/run_tasks_in_packages_if_exists.py test"
fmt = "python scripts/run_tasks_in_packages_if_exists.py fmt"
format.ref = "fmt"
lint = "python scripts/run_tasks_in_packages_if_exists.py lint"
samples-lint = "ruff check samples --fix --exclude samples/autogen-migration,samples/semantic-kernel-migration --ignore E501,ASYNC,B901,TD002"
pyright = "python scripts/run_tasks_in_packages_if_exists.py pyright"
mypy = "python scripts/run_tasks_in_packages_if_exists.py mypy"
typing = "python scripts/run_tasks_in_packages_if_exists.py mypy pyright"
samples-syntax.shell = "pyright -p $(python -c \"import sys; print('pyrightconfig.samples.py310.json' if sys.version_info < (3,11) else 'pyrightconfig.samples.json')\") --warnings"
samples-syntax.interpreter = "posix"
# cleaning
clean-dist-packages = "python scripts/run_tasks_in_packages_if_exists.py clean-dist"
clean-dist-meta = "rm -rf dist"
clean-dist = ["clean-dist-packages", "clean-dist-meta"]
# build and publish
build-packages = "python scripts/run_tasks_in_packages_if_exists.py build"
build-meta = "python -m flit build"
build = ["build-packages", "build-meta"]
publish = "uv publish"
# combined checks
check-packages = "python scripts/run_tasks_in_packages_if_exists.py fmt lint pyright"
check = ["check-packages", "samples-lint", "samples-syntax", "test", "markdown-code-lint"]
[tool.poe.tasks.all-tests-cov]
cmd = """
pytest --import-mode=importlib
-m "not integration"
--cov=agent_framework
--cov=agent_framework_core
--cov=agent_framework_a2a
--cov=agent_framework_ag_ui
--cov=agent_framework_anthropic
--cov=agent_framework_azure_ai
--cov=agent_framework_azure_ai_search
--cov=agent_framework_azurefunctions
--cov=agent_framework_chatkit
--cov=agent_framework_copilotstudio
--cov=agent_framework_mem0
--cov=agent_framework_purview
--cov=agent_framework_redis
--cov=agent_framework_orchestrations
--cov=agent_framework_declarative
--cov-config=pyproject.toml
--cov-report=term-missing:skip-covered
--ignore-glob=packages/lab/**
--ignore-glob=packages/devui/**
-rs
-n logical --dist worksteal
packages/**/tests
"""
[tool.poe.tasks.all-tests]
cmd = """
pytest --import-mode=importlib
-m "not integration"
--ignore-glob=packages/lab/**
--ignore-glob=packages/devui/**
-rs
-n logical --dist worksteal
packages/**/tests
"""
[tool.poe.tasks.venv]
cmd = "uv venv --clear --python $python"
args = [{ name = "python", default = "3.13", options = ['-p', '--python'] }]
[tool.poe.tasks.setup]
sequence = [
{ ref = "venv --python $python"},
{ ref = "install" },
{ ref = "prek-install" }
]
args = [{ name = "python", default = "3.13", options = ['-p', '--python'] }]
[tool.poe.tasks.upgrade-dev-dependency-pins]
cmd = "python -m scripts.dependencies.upgrade_dev_dependencies"
[tool.poe.tasks.upgrade-lockfile]
cmd = "uv lock --upgrade"
[tool.poe.tasks.upgrade-dev-dependencies]
sequence = [
{ ref = "upgrade-dev-dependency-pins" },
{ ref = "upgrade-lockfile" },
{ ref = "install" },
{ ref = "check" },
{ ref = "typing" },
{ ref = "test" },
]
[tool.poe.tasks.add-dependency-to-project]
cmd = "uv add --package ${project} ${dependency}"
args = [
{ name = "project", options = ["-p", "--project"] },
{ name = "dependency", options = ["-d", "--dependency"] },
]
[tool.poe.tasks.validate-dependency-bounds-test]
shell = "python -m scripts.dependencies.validate_dependency_bounds --mode test --package \"$project\""
args = [{ name = "project", default = "*", options = ["-p", "--project"] }]
[tool.poe.tasks.validate-dependency-bounds-project]
shell = """
command=(python -m scripts.dependencies.validate_dependency_bounds --mode "${mode}" --package "${project}")
if [ -n "${dependency}" ]; then
command+=(--dependencies "${dependency}")
fi
"${command[@]}"
"""
interpreter = "bash"
args = [
{ name = "mode", default = "both", options = ["-m", "--mode"] },
{ name = "project", default = "*", options = ["-p", "--project"] },
{ name = "dependency", default = "", options = ["-d", "--dependency"] },
]
[tool.poe.tasks.add-dependency-and-validate-bounds]
sequence = [
{ ref = "add-dependency-to-project --project ${project} --dependency ${dependency}" },
{ ref = "validate-dependency-bounds-project --mode both --project ${project} --dependency ${dependency}" },
]
args = [
{ name = "project", options = ["-p", "--project"] },
{ name = "dependency", options = ["-d", "--dependency"] },
]
[tool.poe.tasks.prek-pyright]
cmd = "uv run python scripts/run_tasks_in_changed_packages.py pyright --files ${files}"
args = [{ name = "files", default = ".", positional = true, multiple = true }]
[tool.poe.tasks.prek-check-packages]
cmd = "uv run python scripts/run_tasks_in_changed_packages.py fmt lint pyright --files ${files}"
args = [{ name = "files", default = ".", positional = true, multiple = true }]
[tool.poe.tasks.prek-markdown-code-lint]
cmd = """uv run python scripts/check_md_code_blocks.py ${files} --no-glob
--exclude cookiecutter-agent-framework-lab --exclude tau2
--exclude packages/devui/frontend --exclude context_providers/azure_ai_search"""
args = [{ name = "files", default = ".", positional = true, multiple = true }]
[tool.poe.tasks.prek-samples-check]
shell = """
HAS_SAMPLES=false
for f in ${files}; do
case "$f" in
samples/*) HAS_SAMPLES=true; break ;;
esac
done
if [ "$HAS_SAMPLES" = true ]; then
echo "Sample files changed, running samples checks..."
uv run ruff check samples --fix --exclude samples/autogen-migration,samples/semantic-kernel-migration --ignore E501,ASYNC,B901,TD002
uv run pyright -p pyrightconfig.samples.json --warnings
else
echo "No sample files changed, skipping samples checks"
fi
"""
interpreter = "bash"
args = [{ name = "files", default = ".", positional = true, multiple = true }]
[tool.poe.tasks.ci-mypy]
shell = """
# Try multiple strategies to get changed files
if [ -n "$GITHUB_BASE_REF" ]; then
# In GitHub Actions PR context
git fetch origin $GITHUB_BASE_REF --depth=1 2>/dev/null || true
CHANGED_FILES=$(git diff --name-only origin/$GITHUB_BASE_REF...HEAD -- . 2>/dev/null || \
git diff --name-only FETCH_HEAD...HEAD -- . 2>/dev/null || \
git diff --name-only HEAD^...HEAD -- . 2>/dev/null || \
echo ".")
else
# Local development
CHANGED_FILES=$(git diff --name-only origin/main...HEAD -- . 2>/dev/null || \
git diff --name-only main...HEAD -- . 2>/dev/null || \
git diff --name-only HEAD~1 -- . 2>/dev/null || \
echo ".")
fi
echo "Changed files: $CHANGED_FILES"
uv run python scripts/run_tasks_in_changed_packages.py mypy --files $CHANGED_FILES
"""
interpreter = "bash"
[tool.poe.tasks.prek-check]
sequence = [
{ ref = "prek-check-packages ${files}" },
{ ref = "prek-markdown-code-lint ${files}" },
{ ref = "prek-samples-check ${files}" }
]
args = [{ name = "files", default = ".", positional = true, multiple = true }]
[tool.setuptools.packages.find]
where = ["packages"]
include = ["agent_framework**"]
namespaces = true
[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
publish-url = "https://test.pypi.org/legacy/"
explicit = true
[tool.flit.module]
name = "agent_framework_meta"
[build-system]
requires = ["flit-core >= 3.11,<4.0"]
build-backend = "flit_core.buildapi"