chore: import upstream snapshot with attribution
tools_continuous_delivery / Private PyPI non-main branch release (push) Has been skipped
tools_continuous_delivery / Private PyPI main branch release (push) Failing after 2m42s
Publish Promptflow Doc / Build (push) Has been cancelled
Publish Promptflow Doc / Deploy (push) Has been cancelled
Flake8 Lint / flake8 (push) Has been cancelled
Spell check CI / Spell_Check (push) Has been cancelled
tools_continuous_delivery / Private PyPI non-main branch release (push) Has been skipped
tools_continuous_delivery / Private PyPI main branch release (push) Failing after 2m42s
Publish Promptflow Doc / Build (push) Has been cancelled
Publish Promptflow Doc / Deploy (push) Has been cancelled
Flake8 Lint / flake8 (push) Has been cancelled
Spell check CI / Spell_Check (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# ---------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# ---------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import site
|
||||
import typing
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from test_resources import REGISTERED_TEST_RESOURCES_FUNCTIONS
|
||||
from utils import REPO_ROOT_DIR, change_cwd, print_blue, run_cmd
|
||||
|
||||
PROMPT_FLOW_PKGS = [
|
||||
"promptflow-tracing",
|
||||
"promptflow-core",
|
||||
"promptflow-devkit",
|
||||
"promptflow-azure",
|
||||
"promptflow[azure]",
|
||||
"promptflow-tools",
|
||||
"promptflow-evals",
|
||||
"promptflow-recording",
|
||||
]
|
||||
|
||||
|
||||
def set_up_git_hook_scripts(verbose: bool) -> None:
|
||||
run_cmd(["pip", "install", "pre-commit"], verbose=False) # ensure pre-commit is installed
|
||||
cmd = ["pre-commit", "install"]
|
||||
print_blue("Running `pre-commit install` to set up the git hook scripts")
|
||||
run_cmd(cmd, verbose=verbose)
|
||||
|
||||
|
||||
def collect_and_install_from_pyproject() -> None:
|
||||
# collect dependencies from pyproject.toml and install
|
||||
deps = []
|
||||
# cwd is already changed to the package folder in the context
|
||||
# so we can safely open pyproject.toml here
|
||||
with open("pyproject.toml", mode="r", encoding="utf-8") as f:
|
||||
lines = f.readlines()
|
||||
collect_flag = False
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if line.startswith("["):
|
||||
if "[tool.poetry.group.dev.dependencies]" in line or "[tool.poetry.group.test.dependencies]" in line:
|
||||
collect_flag = True
|
||||
continue
|
||||
else:
|
||||
collect_flag = False
|
||||
if collect_flag and line:
|
||||
deps.append(line.split("=")[0].strip())
|
||||
cmd = ["pip", "install"] + deps
|
||||
run_cmd(cmd)
|
||||
|
||||
|
||||
def inject_pth_file() -> None:
|
||||
# content of the .pth file will be added to `sys.path`
|
||||
# for packages installed from pyproject.toml, this file should already be there
|
||||
# for `promptflow`, inject this, and we can avoid `conda env config vars set`
|
||||
# reference: https://docs.python.org/3/library/site.html
|
||||
site_packages_path = Path(site.getsitepackages()[0])
|
||||
with open(site_packages_path / "promptflow.pth", mode="w", encoding="utf-8") as f:
|
||||
f.write((REPO_ROOT_DIR / "src" / "promptflow").resolve().absolute().as_posix())
|
||||
|
||||
|
||||
def install_pkg_editable(pkg: str, verbose: bool, is_vscode: bool = False) -> None:
|
||||
if "[" in pkg:
|
||||
folder_name, extras = pkg.split("[")
|
||||
extras = f"[{extras}"
|
||||
else:
|
||||
folder_name = pkg
|
||||
extras = ""
|
||||
pkg_working_dir = REPO_ROOT_DIR / "src" / folder_name
|
||||
with change_cwd(pkg_working_dir):
|
||||
print_blue(f"- Setting up {pkg}")
|
||||
|
||||
# pip install -e . from pyproject.toml/setup.py
|
||||
print_blue(f"- Installing {pkg} from source")
|
||||
cmd = [sys.executable, "-m", "pip", "install", "--editable", f".{extras}"]
|
||||
run_cmd(cmd, verbose=verbose)
|
||||
|
||||
# dev and test dependencies
|
||||
print_blue(f"- Installing dev and test dependencies for {pkg}")
|
||||
# promptflow folder has "dev_requirements.txt", directly install it
|
||||
if folder_name == "promptflow":
|
||||
cmd = ["pip", "install", "-r", "dev_requirements.txt"]
|
||||
run_cmd(cmd, verbose=verbose)
|
||||
inject_pth_file()
|
||||
# promptflow-tools
|
||||
# reference: https://github.com/microsoft/promptflow/blob/main/src/promptflow-tools/README.dev.md
|
||||
elif pkg == "promptflow-tools":
|
||||
cmd = ["pip", "install", "-r", "requirements.txt"]
|
||||
run_cmd(cmd, verbose=verbose)
|
||||
cmd = ["pip", "install", "pytest", "pytest-mock"]
|
||||
run_cmd(cmd, verbose=verbose)
|
||||
# promptflow-* will have "pyproject.toml", parse and install
|
||||
# we can refine this leveraging `poetry export` later
|
||||
elif os.path.exists("pyproject.toml"):
|
||||
collect_and_install_from_pyproject()
|
||||
|
||||
# touch __init__.py for the package for VS Code
|
||||
# NOTE that this is a workaround to enable VS Code to recognize the namespace package
|
||||
# we should be able to remove this after we fully deprecate promptflow in local development
|
||||
if is_vscode:
|
||||
with open(pkg_working_dir / "promptflow" / "__init__.py", mode="w", encoding="utf-8") as f:
|
||||
f.write("__path__ = __import__('pkgutil').extend_path(__path__, __name__)\n")
|
||||
|
||||
|
||||
@dataclass
|
||||
class Arguments:
|
||||
packages: typing.List[str]
|
||||
verbose: bool = False
|
||||
vscode: bool = False
|
||||
|
||||
@staticmethod
|
||||
def parse_args() -> "Arguments":
|
||||
epilog = "Example usage: main.py --packages promptflow-tracing promptflow-core"
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Welcome to promptflow dev setup!",
|
||||
epilog=epilog,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--packages",
|
||||
required=False,
|
||||
nargs="+",
|
||||
type=str,
|
||||
default=PROMPT_FLOW_PKGS,
|
||||
help="packages to install in editable mode",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="turn on verbose output",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--vscode",
|
||||
action="store_true",
|
||||
help="extra setup step for Visual Studio Code",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
return Arguments(
|
||||
packages=args.packages,
|
||||
verbose=args.verbose,
|
||||
vscode=args.vscode,
|
||||
)
|
||||
|
||||
|
||||
def main(args: Arguments) -> None:
|
||||
for pkg in args.packages:
|
||||
install_pkg_editable(pkg, verbose=args.verbose, is_vscode=args.vscode)
|
||||
# invoke test resource template creation function if available
|
||||
if pkg in REGISTERED_TEST_RESOURCES_FUNCTIONS:
|
||||
REGISTERED_TEST_RESOURCES_FUNCTIONS[pkg]()
|
||||
set_up_git_hook_scripts(verbose=args.verbose)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(args=Arguments.parse_args())
|
||||
Reference in New Issue
Block a user