Skip to content

Commit 19427e8

Browse files
mryzhovCopilotakuporos
authored
[PY] Using pyproject.toml for python api management (#30048)
### Details: - Moved project configuration to pyproject.toml - That would be needed to enable dependencies management using poetry or uv tools. Example PRs: - openvinotoolkit/openvino_tokenizers#467 - openvinotoolkit/openvino_tokenizers#473 - openvinotoolkit/openvino.genai#2159 ### Tickets: - *ticket-id* --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Anastasia Kuporosova <anastasia.kuporosova@intel.com>
1 parent 239eef5 commit 19427e8

File tree

7 files changed

+136
-108
lines changed

7 files changed

+136
-108
lines changed

.github/workflows/py_checks.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ jobs:
106106

107107
# Run pyright to assert no regressions in type hinting
108108
- name: Run pyright on Python API
109-
run: python -m pyright ./src/openvino -p ./pyproject.toml
110-
working-directory: src/bindings/python
109+
run: python -m pyright --verbose
111110

112111
# layer_tests Flake code-style
113112
- name: Run flake8 on python tests in openvino/tests/layer_tests

pyproject.toml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
[project]
2+
name = "openvino"
3+
dynamic = ["version", "entry-points", "scripts"]
4+
description = "OpenVINO(TM) Runtime"
5+
readme = {file = "README.md", content-type="text/markdown"}
6+
license = {text = "OSI Approved :: Apache Software License"}
7+
authors = [
8+
{ name = "OpenVINO Developers", email = "openvino@intel.com" },
9+
]
10+
classifiers = [
11+
"Programming Language :: Python :: 3.9",
12+
"Programming Language :: Python :: 3.10",
13+
"Programming Language :: Python :: 3.11",
14+
"Programming Language :: Python :: 3.12",
15+
"Programming Language :: Python :: 3.13",
16+
]
17+
requires-python = ">=3.9"
18+
19+
dependencies = [
20+
"numpy>=1.16.6,<2.3.0",
21+
"openvino-telemetry>=2023.2.1",
22+
"packaging"
23+
]
24+
25+
[build-system]
26+
requires = [
27+
"setuptools>=70,<=80.3.1",
28+
"wheel<=0.45.1",
29+
"cmake<=3.31.6",
30+
"patchelf<=0.17.2.2; sys_platform == 'linux' and platform_machine == 'x86_64'"
31+
]
32+
build-backend = "setuptools.build_meta"
33+
34+
[tool.setuptools]
35+
license-files = [
36+
"LICENSE",
37+
"licensing/runtime-third-party-programs.txt",
38+
"licensing/onetbb_third-party-programs.txt",
39+
"licensing/onednn_third-party-programs.txt",
40+
]
41+
[tool.setuptools.packages.find]
42+
where = ["./src/bindings/python"]
43+
include = ["pyopenvino"]
44+
45+
[tool.black]
46+
line-length = 160
47+
include = '\.pyi?$'
48+
49+
[tool.pyright]
50+
include = ["src/bindings/python/src"]
51+
exclude = ["src/bindings/python/src/pyopenvino"]
52+
ignore = [
53+
"**/ops.py",
54+
"**/utils/data_helpers/data_dispatcher.py",
55+
"**/utils/types.py",
56+
"**/utils/decorators.py",
57+
"**/frontend/frontend.py",
58+
"**/_ov_api.py",
59+
"**/_op_base.py",
60+
"**/utils/node_factory.py",
61+
"**/frontend/tensorflow",
62+
"**/frontend/pytorch",
63+
"**/frontend/jax"
64+
]
65+
reportInvalidTypeForm = false
66+
reportMissingModuleSource = false
67+
reportFunctionMemberAccess = false
68+
reportAttributeAccessIssue = false
69+
reportMissingImports = false
70+
reportIncompatibleMethodOverride = false

src/bindings/python/wheel/setup.py renamed to setup.py

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from setuptools.command.build_clib import build_clib
2121
from setuptools.command.install import install
2222
from setuptools.command.build import build
23+
from setuptools.command.bdist_wheel import bdist_wheel
2324
from setuptools.errors import SetupError
2425

2526
WHEEL_PACKAGE_DIR = "openvino"
@@ -42,14 +43,14 @@
4243
ARCH = "riscv64"
4344

4445
# The following variables can be defined in environment or .env file
45-
SCRIPT_DIR = Path(__file__).resolve().parents[0]
46+
SCRIPT_DIR = Path(__file__).resolve().parent
4647
WORKING_DIR = Path.cwd()
47-
BUILD_BASE = f"{WORKING_DIR}/build_{PYTHON_VERSION}"
48-
OPENVINO_SOURCE_DIR = SCRIPT_DIR.parents[3]
49-
OPENVINO_BINARY_DIR = os.getenv("OPENVINO_BINARY_DIR")
48+
BUILD_BASE = f"build_{PYTHON_VERSION}"
49+
OPENVINO_SOURCE_DIR = os.getenv("OPENVINO_SOURCE_DIR", SCRIPT_DIR)
50+
OPENVINO_BINARY_DIR = os.getenv("OPENVINO_BINARY_DIR", f'{OPENVINO_SOURCE_DIR}/build_wheel')
5051
OPENVINO_PYTHON_BINARY_DIR = os.getenv("OPENVINO_PYTHON_BINARY_DIR", "python_build")
5152
CONFIG = os.getenv("BUILD_TYPE", "Release")
52-
OV_RUNTIME_LIBS_DIR = os.getenv("OV_RUNTIME_LIBS_DIR", f"runtime/{LIBS_DIR}/{ARCH}/{CONFIG}")
53+
OV_RUNTIME_LIBS_DIR = os.getenv("OV_RUNTIME_LIBS_DIR", f"runtime/{LIBS_DIR}/{ARCH}")
5354
TBB_LIBS_DIR = os.getenv("TBB_LIBS_DIR", f"runtime/3rdparty/tbb/{LIBS_DIR}")
5455
PUGIXML_LIBS_DIR = os.getenv("PUGIXML_LIBS_DIR", f"runtime/3rdparty/pugixml/{LIBS_DIR}")
5556
PY_PACKAGES_DIR = os.getenv("PY_PACKAGES_DIR", "python")
@@ -285,26 +286,22 @@ def cmake_build_and_install(self, install_cfg):
285286
"""Runs cmake (configure, build and install) if artfiacts are not already built / installed."""
286287
plat_specifier = ".{0}-{1}.{2}".format(self.plat_name, *sys.version_info[:2])
287288
self.build_temp = os.path.join(self.build_base, "temp" + plat_specifier)
288-
self.announce(f"Create build directory: {self.build_temp}", level=3)
289+
self.announce(f"Create build directory: {self.build_temp}", level=log.INFO)
289290
# build some components which have not been built yet
290291
for comp, comp_data in install_cfg.items():
291292
cpack_comp_name = comp_data.get("name")
292293
source_dir = comp_data.get("source_dir", OPENVINO_SOURCE_DIR)
293294
binary_dir = comp_data.get("binary_dir", OPENVINO_BINARY_DIR)
294295
install_dir = comp_data.get("install_dir")
295296
prefix = comp_data.get("prefix")
296-
297+
297298
# perform installation steps if we are not given a full path
298299
if not os.path.isabs(install_dir):
299300
# install_dir is just a sub-dir after install prefix, let's make a full path
300-
comp_data["install_dir"] = os.path.join(prefix, install_dir)
301-
302-
# even perform a build in case of binary directory does not exist
303-
binary_dir = binary_dir if os.path.isabs(binary_dir) else os.path.join(self.build_temp, binary_dir)
304-
305301
if not os.path.exists(binary_dir):
302+
# even perform a build in case of binary directory does not exist
306303
binary_dir = os.path.join(self.build_temp, binary_dir)
307-
self.announce(f"Configuring {comp} cmake project", level=3)
304+
self.announce(f"Configuring {comp} cmake project", level=log.INFO)
308305
self.spawn(["cmake",
309306
f"-DOpenVINODeveloperPackage_DIR={OPENVINO_BINARY_DIR}",
310307
f"-DPython3_EXECUTABLE={sys.executable}",
@@ -316,12 +313,12 @@ def cmake_build_and_install(self, install_cfg):
316313
"-S", source_dir,
317314
"-B", binary_dir])
318315

319-
self.announce(f"Building {comp} project", level=3)
316+
self.announce(f"Building {comp} project", level=log.INFO)
320317
self.spawn(["cmake", "--build", binary_dir,
321318
"--config", CONFIG,
322319
"--parallel", str(self.jobs)])
323320

324-
self.announce(f"Installing {comp}", level=3)
321+
self.announce(f"Installing {comp}", level=log.INFO)
325322
self.spawn(["cmake", "--install", binary_dir,
326323
"--prefix", prefix,
327324
"--config", CONFIG,
@@ -351,7 +348,6 @@ def run(self):
351348
(dst / path_rel.parent).mkdir(exist_ok=True, parents=True)
352349
copyfile(path, dst / path_rel)
353350

354-
355351
class PrepareLibs(build_clib):
356352
"""Prepares prebuilt libraries.
357353
@@ -371,7 +367,7 @@ def run(self):
371367
def post_install(self, install_cfg):
372368
"""Install prebuilt libraries to the temp directories, set rpath."""
373369
for comp, comp_data in install_cfg.items():
374-
install_dir = comp_data.get("install_dir")
370+
install_dir = os.path.join(comp_data.get("prefix"), comp_data.get("install_dir"))
375371

376372
# we need to resolve symlinks before setting rpath to avoid doing it multiple times
377373
install_dir_path = Path(install_dir)
@@ -425,11 +421,11 @@ def resolve_symlinks(self, local_base_dir: Path):
425421
link_file_name_new = os.path.basename(symlink)
426422
if len(link_file_name_new) > len(link_file_name_old):
427423
# replace libX.so/libX.dylib with libX.so.Y/libX.Y.dylib
428-
self.announce(f"Unlink symlink {file_dict[real_name]}, use {symlink} instead", level=3)
424+
self.announce(f"Unlink symlink {file_dict[real_name]}, use {symlink} instead", level=log.INFO)
429425
os.unlink(file_dict[real_name])
430426
file_dict[real_name] = symlink
431427
else:
432-
self.announce(f"Unlink symlink {symlink}, use {file_dict[real_name]} instead", level=3)
428+
self.announce(f"Unlink symlink {symlink}, use {file_dict[real_name]} instead", level=log.INFO)
433429
os.unlink(symlink)
434430
else:
435431
file_dict[real_name] = symlink
@@ -440,7 +436,7 @@ def resolve_symlinks(self, local_base_dir: Path):
440436
for real_name, symlink in file_dict.items():
441437
os.unlink(symlink)
442438
os.rename(real_name, symlink)
443-
self.announce(f"Resolved symlink {symlink} as {real_name}", level=3)
439+
self.announce(f"Resolved symlink {symlink} as {real_name}", level=log.INFO)
444440

445441
def copy_package_libs(self, src_dirs):
446442
"""Collect package data files (clibs and other plugin support files) from preinstalled dirs and put all runtime libraries to the subpackage."""
@@ -465,10 +461,10 @@ def copy_package_libs(self, src_dirs):
465461
if file_path.is_file() and not is_blacklisted(file_name, blacklist_patterns):
466462
dst_file = os.path.join(package_clibs_dir, file_name)
467463
copyfile(file_path, dst_file)
468-
self.announce(f"Copy {file_path} to {dst_file}", level=3)
464+
self.announce(f"Copy {file_path} to {dst_file}", level=log.INFO)
469465

470466
if Path(package_clibs_dir).exists():
471-
self.announce(f"Adding {WHEEL_LIBS_PACKAGE} package", level=3)
467+
self.announce(f"Adding {WHEEL_LIBS_PACKAGE} package", level=log.INFO)
472468
packages.append(WHEEL_LIBS_PACKAGE)
473469
package_data.update({WHEEL_LIBS_PACKAGE: ["*"]})
474470

@@ -518,16 +514,16 @@ def copy_package_data(self, src_dirs):
518514
if file_path.is_file() and not is_blacklisted(file_name, blacklist_patterns):
519515
dst_file = os.path.join(package_clibs_dir, file_name)
520516
move(file_path, dst_file)
521-
self.announce(f"Move {file_path} to {dst_file}", level=3)
517+
self.announce(f"Move {file_path} to {dst_file}", level=log.INFO)
522518

523519
# collect all cmake files in one directory
524520
for file_path in Path(src).rglob("*.cmake"):
525521
file_name = os.path.basename(file_path)
526522
if file_path.is_file() and not is_blacklisted(file_name, blacklist_patterns):
527523
dst_file = os.path.join(package_cmake_dir, file_name)
528-
self.announce(f"Move {file_path} to {dst_file}", level=3)
524+
self.announce(f"Move {file_path} to {dst_file}", level=log.INFO)
529525
move(file_path, dst_file)
530-
self.announce("Patch cmake configurations", level=3)
526+
self.announce("Patch cmake configurations", level=log.INFO)
531527
replace_strings_in_file(dst_file,
532528
openvino_replacements if file_name.startswith("OpenVINO") else tbb_replacements)
533529

@@ -592,12 +588,34 @@ def run(self):
592588

593589

594590
class CustomInstall(install):
595-
"""Enable build_clib during the installation."""
596-
591+
"""Custom install command."""
597592
def run(self):
593+
"""Enable build_clib during the installation."""
598594
self.run_command("build")
599-
install.run(self)
595+
super().run()
596+
597+
598+
class CustomBdistWheel(bdist_wheel):
599+
"""Custom bdist_wheel command."""
600+
def initialize_options(self):
601+
"""Set default values for all the options that this command supports."""
602+
super().initialize_options()
600603

604+
def finalize_options(self):
605+
"""Set final values for all the options that this command supports."""
606+
super().finalize_options()
607+
608+
platform_tag = os.getenv("PLATFORM_TAG")
609+
if platform_tag:
610+
self.plat_name = platform_tag
611+
self.plat_name_supplied = True
612+
613+
build_number = os.getenv("WHEEL_BUILD")
614+
if build_number:
615+
self.build_number = build_number
616+
617+
def run(self):
618+
super().run()
601619

602620
class CustomClean(Command):
603621
"""Clean up staging directories."""
@@ -613,7 +631,7 @@ def finalize_options(self):
613631
def clean_install_prefix(self, install_cfg):
614632
for comp, comp_data in install_cfg.items():
615633
install_prefix = comp_data.get("prefix")
616-
self.announce(f"Cleaning {comp}: {install_prefix}", level=3)
634+
self.announce(f"Cleaning {comp}: {install_prefix}", level=log.INFO)
617635
if os.path.exists(install_prefix):
618636
rmtree(install_prefix)
619637

@@ -723,13 +741,6 @@ def get_description(desc_file_path):
723741
return description
724742

725743

726-
def get_install_requires(requirements_file_path):
727-
"""Read dependencies from requirements.txt."""
728-
with open(requirements_file_path, "r", encoding="utf-8") as fstream:
729-
install_requirements = fstream.read()
730-
return install_requirements
731-
732-
733744
def get_install_dirs_list(install_cfg):
734745
"""Collect all available directories with clibs or python extensions."""
735746
install_dirs = []
@@ -784,8 +795,8 @@ def concat_files(input_files, output_file):
784795
ext_modules = find_prebuilt_extensions(get_install_dirs_list(PY_INSTALL_CFG))
785796
entry_points = find_entry_points(PY_INSTALL_CFG)
786797

787-
long_description_md = OPENVINO_SOURCE_DIR / "docs" / "dev" / "pypi_publish" / "pypi-openvino-rt.md"
788-
md_files = [long_description_md, OPENVINO_SOURCE_DIR / "docs" / "dev" / "pypi_publish" / "pre-release-note.md"]
798+
long_description_md = Path(OPENVINO_SOURCE_DIR) / "docs" / "dev" / "pypi_publish" / "pypi-openvino-rt.md"
799+
md_files = [long_description_md, Path(OPENVINO_SOURCE_DIR) / "docs" / "dev" / "pypi_publish" / "pre-release-note.md"]
789800
docs_url = "https://docs.openvino.ai/2023.0/index.html"
790801

791802
if os.getenv("CI_BUILD_DEV_TAG"):
@@ -797,20 +808,15 @@ def concat_files(input_files, output_file):
797808

798809
setup(
799810
name="openvino",
800-
version=WHEEL_VERSION,
801-
build=os.getenv("WHEEL_BUILD", "000"),
802-
author_email="openvino@intel.com",
803-
license="OSI Approved :: Apache Software License",
804-
author="Intel(R) Corporation",
805-
description="OpenVINO(TM) Runtime",
806-
install_requires=get_install_requires(SCRIPT_DIR.parents[0] / "requirements.txt"),
811+
version=f'{WHEEL_VERSION}',
807812
long_description=get_description(long_description_md),
808813
long_description_content_type="text/markdown",
809814
download_url="https://github.com/openvinotoolkit/openvino/releases",
810815
url=docs_url,
811816
entry_points=entry_points,
812817
cmdclass={
813818
"build": CustomBuild,
819+
"bdist_wheel": CustomBdistWheel,
814820
"install": CustomInstall,
815821
"build_clib": PrepareLibs,
816822
"build_ext": CopyExt,

src/bindings/python/CMakeLists.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ macro(ov_define_setup_py_packaging_vars)
242242
WHEEL_VERSION=${WHEEL_VERSION}
243243
WHEEL_BUILD=${WHEEL_BUILD}
244244
# build locations
245+
OPENVINO_SOURCE_DIR=${OpenVINO_SOURCE_DIR}
245246
OPENVINO_BINARY_DIR=${OpenVINO_BINARY_DIR}
246247
OPENVINO_PYTHON_BINARY_DIR=${OpenVINOPython_BINARY_DIR}
247248
# to create proper directories for BA, OVC tools
@@ -276,7 +277,8 @@ macro(ov_define_setup_py_dependencies)
276277

277278
list(APPEND ov_setup_py_deps
278279
${openvino_py_files}
279-
"${CMAKE_CURRENT_SOURCE_DIR}/wheel/setup.py"
280+
"${OpenVINO_SOURCE_DIR}/pyproject.toml"
281+
"${OpenVINO_SOURCE_DIR}/setup.py"
280282
"${OpenVINOPython_SOURCE_DIR}/requirements.txt"
281283
"${OpenVINOPython_SOURCE_DIR}/wheel/readme.txt"
282284
"${OpenVINO_SOURCE_DIR}/LICENSE"
@@ -321,13 +323,12 @@ if(ENABLE_PYTHON_PACKAGING)
321323
set(openvino_meta_info_file "${ov_install_lib}/${openvino_meta_info_subdir}/PKG-INFO")
322324

323325
add_custom_command(OUTPUT ${openvino_meta_info_file}
324-
COMMAND ${CMAKE_COMMAND} -E remove_directory
325-
"${ov_python_package_prefix}"
326+
COMMAND ${CMAKE_COMMAND} -E remove_directory "${ov_python_package_prefix}"
326327
COMMAND ${setup_py_env}
327328
# variables to reflect options (extensions only or full wheel package)
328329
PYTHON_EXTENSIONS_ONLY=ON
329330
SKIP_RPATH=ON
330-
"${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/wheel/setup.py"
331+
"${Python3_EXECUTABLE}" "${OpenVINO_SOURCE_DIR}/setup.py"
331332
--no-user-cfg
332333
--quiet
333334
build

src/bindings/python/pyproject.toml

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)