Skip to content

Commit 076f71a

Browse files
author
Jan Iwaszkiewicz
authored
[PyOV] Adjust style in dev docs (openvinotoolkit#17440)
1 parent 5eab00a commit 076f71a

File tree

7 files changed

+89
-53
lines changed

7 files changed

+89
-53
lines changed

src/bindings/python/docs/build.md

+5
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ OpenVINO can be built based on specific virtual environments such as [venv](http
6363
## Run tests to verify OpenVINO™ Python API
6464

6565
Follow instructions in [How to test OpenVINO™ Python API?](./test_examples.md#Running_OpenVINO™_Python_API_tests) to verify the build.
66+
67+
## See also
68+
* [OpenVINO™ README](../../../../README.md)
69+
* [OpenVINO™ bindings README](../../README.md)
70+
* [Developer documentation](../../../../docs/dev/index.md)

src/bindings/python/docs/code_examples.md

+34-29
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
# Examples of OpenVINO™ Python API code
22

3-
#### Building and environment
3+
### Building and environment
44
Instructions can be found in ["Building the OpenVINO™ Python API"](./build.md).
55

6-
### Different ways of extending OpenVINO™ Python API
6+
## Different ways of extending OpenVINO™ Python API
77

8-
###### Before start: Project's naming conventions
8+
### Before start: Project's naming conventions
99
General guide:
1010
* Snake case (also known as the *lower_case_with_underscores* style) is used across the codebase. That includes modules (`runtime`, `offline_transformations`), function names, and arguments/variables (`async_infer`, `wait`, `path_to_xml`).
1111
* Naming of classes is an exception to the above rule. The *CamelCase* style is used in this case, for example: `Core`, `InferRequest` or `AsyncInferQueue`.
1212
* If bindings (explained later in the [Pure pybind11 solution](#pure-pybind11-solution) section) are created to expose existing C++ code, make them similar to their C++ counterparts, regarding both names and placement, for example, C++'s `ov::InferRequest` and Python's `openvino.runtime.InferRequest`. If alignment is not possible, try to describe your class/function/module as well as possible, such as the pair of `openvino.runtime.ConstOutput/openvino.runtime.Output` which relates to `ov::Output<const ov::Node>/ov::Output<ov::Node>`. This naming points out the functional difference between both classes - one is an immutable and the other a mutable version.
1313

1414
<!-- Pure Python solution describes Python based approach -->
15-
#### Pure Python solution
15+
## Pure Python solution
1616
One of the simplest ways to extend the existing codebase is by writing it in pure Python.
1717

18-
###### Before start: Layout of the project
18+
### Layout of the project
1919
How does OpenVINO™ packaging work? It is strictly connected to the layout of the Python API itself and reused in different supporting packages like tools and extensions. The main namespace of `openvino` provides a unified place that connects all packages together during import, **which is the required part**. However, it is up to the developer how to organize the rest of the package. There are also other common namespaces which follow the same rules:
2020
* `openvino.tools`
2121
* ...
2222

2323
For further reading, please refer to: https://packaging.python.org/en/latest/guides/packaging-namespace-packages/
2424

25-
##### Creating new package that extends OpenVINO™ project namespace
26-
Let's go over the example available in `openvino/src/bindings/python/docs/examples/openvino`:
25+
### Creating new package that extends OpenVINO™ project namespace
26+
Let's go over the example available in [examples folder](./examples/openvino):
2727

2828
```
2929
openvino/ <-- Main package/namespace
3030
├── __init__.py <-- Unified file between all packages
31-
└── mymodule/ <-- This is your new module and it's contents:)
31+
└── mymodule/ <-- This is your new module and its contents
3232
├── __init__.py
3333
├── ...
3434
└── myclass.py
@@ -48,8 +48,8 @@ obj.say_hello()
4848
>>> "Hello! Let's work on OV together!"
4949
```
5050

51-
##### Extending of existing API (sub)modules
52-
But how to extend existing API? Let's navigate to `openvino/src/bindings/python/src/openvino` and add something to project helpers. Create new directory and fill it's contents:
51+
### Extending of existing API (sub)modules
52+
But how to extend existing API? Let's navigate to [main bindings folder](./../src/openvino/) and add something to project helpers. Create new directory and fill it's contents:
5353

5454
```
5555
openvino/
@@ -67,18 +67,20 @@ openvino/
6767
└── utils.py
6868
```
6969

70-
Let's add in `custom_module/custom_helpers.py`:
70+
Let's add in [`custom_helpers.py`](./examples/custom_module/custom_helpers.py):
71+
<!-- TODO: Link with code -->
7172
```python
7273
def top1_index(results: list) -> int:
7374
return results.index(max(results))
7475
```
7576

76-
Import it to a new module in `custom_module/__init__.py`:
77+
Import it to a new module in [`custom_module/__init__.py`](./examples/custom_module/__init__.py):
78+
<!-- TODO: Link with code -->
7779
```python
7880
from openvino.helpers.custom_module.custom_helpers import top1_index
7981
```
8082

81-
Follow it with correct import in `helpers/__init__.py`:
83+
Follow it with correct import in [`helpers/__init__.py`](./../src/openvino/helpers/__init__.py):
8284
```python
8385
from openvino.helpers.custom_module import top1_index
8486
```
@@ -97,35 +99,33 @@ Following this method, developers can add new modules and adjust existing ones,
9799

98100
<!-- Pure pybind11 solution describes C++ based approach -->
99101

100-
#### Pure pybind11 solution
102+
## Pure pybind11 solution
101103
The second approach to extend OpenVINO™ codebase is utilizing the *pybind11* library. It allows to write C++ based code, thus creating so-called Python bindings.
102104

103105
**The example in this section covers the scenario of adding new features to a newly created submodule. Extending existing codebase can be done in a similar fashion by working on already implemented classes and modules.**
104106

105-
###### Before start: What is pybind11?
107+
### Before start: What is pybind11?
106108
It is a thridparty project that allows to expose C++ code as a Python library.
107109

108110
Link to offical documentation: https://pybind11.readthedocs.io/en/stable/
109111
Link to project repository: https://github.com/pybind/pybind11
110112

111-
##### Adding new (sub)module
113+
### Adding new (sub)module
112114
Adding a new module could be done only by using *pybind11* built-in capabilities.
113115

114-
Navigate to the main project file responsible for creation of the whole package, let's call it "registering-point":
115-
116-
openvino/src/bindings/python/src/pyopenvino/pyopenvino.cpp
116+
Navigate to the main project file responsible for creation of the whole package [`pyopenvino.cpp`](./../src/pyopenvino/pyopenvino.cpp), let's call it "registering-point".
117117

118118
Add a new submodule by writing:
119119
```cpp
120120
py::module mymodule = m.def_submodule("mymodule", "My first feature - openvino.runtime.mymodule");
121121
```
122122
This is a shorthand way of adding new submodules which can later be used to extend the package. The mysterious `m` is actaully the main OpenVINO™ module called `pyopenvino` -- it is registered with `PYBIND11_MODULE(pyopenvino, m)` at the top of the "registering-point" file. Later imports from it are done by calling upon the `openvino._pyopenvino` package.
123123

124-
Keep in mind that in most real-life scenarios, modules and classes are registered in different files. The general idea is to create a helper function that will hold all of the registered modules, classes, and functions. This function needs to be exposed within a separate header file and included in "registering-point". The project's common guideline suggests to use names in the following convention: `regmodule_[domain]_[name_of_the_module]` or `regclass_[domain]_[name_of_the_class]`. Where optional `[domain]` generally points to parts of the API such as graph or frontend, or stay empty in the case of core runtime. Examples can be found in the "registering-point" file, `openvino/src/bindings/python/src/pyopenvino/pyopenvino.cpp`.
124+
Keep in mind that in most real-life scenarios, modules and classes are registered in different files. The general idea is to create a helper function that will hold all of the registered modules, classes, and functions. This function needs to be exposed within a separate header file and included in "registering-point". The project's common guideline suggests to use names in the following convention: `regmodule_[domain]_[name_of_the_module]` or `regclass_[domain]_[name_of_the_class]`. Where optional `[domain]` generally points to parts of the API such as graph or frontend, or stay empty in the case of core runtime. Examples can be found in the "registering-point" file [`pyopenvino.cpp`](../src/pyopenvino/pyopenvino.cpp).
125125

126126
*Note: Submodules can be "chained" as well. Refer to the official documentation for more details: https://pybind11.readthedocs.io/en/stable/reference.html#_CPPv4N7module_13def_submoduleEPKcPKc*
127127

128-
##### Binding of classes and functions
128+
### Binding of classes and functions
129129
When the module is created, classes can be added to it. Let's assume a class called `MyTensor` needs to be added in a new module. Here is a list of required features:
130130

131131
* Handle construction from the `ov::Tensor` class and 1-D initialization from Python built-in list.
@@ -245,9 +245,9 @@ Note: **bindings** that are created for classes are sometimes called **wrappers*
245245

246246
MyTensor wraps (around) Tensor class.
247247

248-
However, in OpenVINO™ there is an unwritten distinction between "everyday" wrappers and more complex ones (with this article published... it is now a written one ;) ). An example may be found in `openvino/src/bindings/python/src/pyopenvino/core/infer_request.hpp`, where `InferRequest` is actually wrapped inside `InferRequestWrapper`, similarly to the `Tensor` and `MyTensor` scenario. It helps to extend original object capabilities with members and functions that do not necessarily belong to the C++ API. Thus, explicitly calling something a **wrapper** in the project indicates that binding is probably inheriting or using the composition technique to include the original class, later extending it in some way.
248+
However, in OpenVINO™ there is an unwritten distinction between "everyday" wrappers and more complex ones (with this article published... it is now a written one ;) ). An example may be found in [`core/infer_request.hpp`](./../src/pyopenvino/core/infer_request.hpp), where `InferRequest` is actually wrapped inside `InferRequestWrapper`, similarly to the `Tensor` and `MyTensor` scenario. It helps to extend original object capabilities with members and functions that do not necessarily belong to the C++ API. Thus, explicitly calling something a **wrapper** in the project indicates that binding is probably inheriting or using the composition technique to include the original class, later extending it in some way.
249249

250-
##### Overloads of functions
250+
### Overloads of functions
251251
One of the main advantages of *pybind11* is the ability to resolve overloaded functions. Let's assume that a previously created function is extended to print any message passed by the user.
252252

253253
```cpp
@@ -299,11 +299,11 @@ Notice that only functions with correct arguments are **not** throwing exception
299299

300300
<!-- Mixed solution describes both approaches combined -->
301301

302-
#### Mix between Python and pybind11
302+
## Mix between Python and pybind11
303303
Although *pybind11* is a powerful tool, it is sometimes required (or simply easier and more efficent) to combine both approaches and utilize both languages to achive best results.
304304

305-
##### Making pybind11-based module/class visible in OpenVINO™ package
306-
Let's move a new class from `openvino._pyopenvino.mymodule` to the actual package. Simply introduce a new import statement in the desired file. Let it be `openvino/src/bindings/python/src/openvino/runtime/__init__.py`:
305+
### Making pybind11-based module/class visible in OpenVINO™ package
306+
Let's move a new class from `openvino._pyopenvino.mymodule` to the actual package. Simply introduce a new import statement in the desired file. Let it be [`openvino/runtime/__init__.py`](./../src/openvino/runtime/__init__.py):
307307
```python
308308
from openvino._pyopenvino.mymodule import MyTensor
309309
```
@@ -317,10 +317,10 @@ ov.MyTensor
317317

318318
Same rule applies to whole modules and free functions. **This is a required step when adding something to the public API**. Without exposing it, all of the work is hidden in the depths of the `pyopenvino` namespace, rendering it hard to access for the user.
319319

320-
##### Yet another Python layer
320+
### Yet another Python layer
321321
As mentioned earlier, it may be helpful to utilize Python in-between to achieve hard C++ feats in a more efficient way. Let's extend the previously created `say_hello` function a little bit.
322322

323-
First, create a new file in the `openvino/src/bindings/python/src/openvino/runtime` directory and call it `mymodule_ext.py`. There are no strict rules for naming, just make sure the names are in good taste. Import the class here:
323+
First, create a new file in the [runtime directory](./../src/openvino/runtime/) and call it `mymodule_ext.py`. There are no strict rules for naming, just make sure the names are in good taste. Import the class here:
324324
```python
325325
from openvino._pyopenvino.mymodule import MyTensor as MyTensorBase
326326
```
@@ -402,8 +402,13 @@ Great! Now the class has reached its destination, from C++, to Python, to Python
402402

403403
This concludes developer work on OpenVINO™ Python API. Don't forget to recompile your builds and have a good time while writing your code!:)
404404

405-
### Testing the new code
405+
## Testing the new code
406406

407407
Coding is now finished. Let's move on to testing.
408408

409409
To learn how to test your code, refer to the guide on [how to test OpenVINO™ Python API?](./test_examples.md#Running_OpenVINO™_Python_API_tests)
410+
411+
## See also
412+
* [OpenVINO™ README](../../../../README.md)
413+
* [OpenVINO™ bindings README](../../README.md)
414+
* [Developer documentation](../../../../docs/dev/index.md)

src/bindings/python/docs/contributing.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
# Contributing to OpenVINO™ Python API
22

3-
#### Prerequisites
3+
## Prerequisites
44

5-
##### Enviroment
6-
In case the Python version you have is not supported by OpenVINO, you can refer to [openvino/src/bindings/python/docs/python_version_upgrade.md](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/python/docs/python_version_upgrade.md) for instructions on how to download and build a newer, supported Python version.
5+
### Enviroment
6+
In case the Python version you have is not supported by OpenVINO, you can refer to ["Python version upgrade" guide](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/python/docs/python_version_upgrade.md) for instructions on how to download and build a newer, supported Python version.
77

8-
The environment setup is described as part of the pyenv example in [the build.md page](./build.md#Example:_using_pyenv_with_OpenVINO™_on_Linux_based_system).
8+
The environment setup is described as part of the pyenv example in [Building the OpenVINO™ Python API](./build.md#Example:_using_pyenv_with_OpenVINO™_on_Linux_based_system).
99

10-
##### Building
11-
Building instructions can be found in [build.md](./build.md#_Building_the_OpenVINO™_Python_API).
10+
### Building
11+
Building instructions can be found in [Building the OpenVINO™ Python API](./build.md#_Building_the_OpenVINO™_Python_API).
1212

1313
## Contribution guidelines and best practices
1414

15-
#### How to contribute to Python API?
15+
### How to contribute to Python API?
1616
It is nothing special... :) First, make sure that all prerequisites are met and focus on writing the code itself. A good starting point is to have some knowledge of the Python language. C++ is also a vital language for OpenVINO™, so it is not a surprise that it is used in this part of the project as well.
1717

1818
Code snippets and detailed explanations can be found here:
1919

2020
[Examples of OpenVINO™ Python API code](./code_example.md)
2121

22-
##### Always test out our code! Don't forget about it before pushing and triggering CIs.
22+
### Always test out our code! Don't forget about it before pushing and triggering CIs.
2323

2424
To learn how to test your code, refer to the guide on [how to test OpenVINO™ Python API?](./test_examples.md#Running_OpenVINO™_Python_API_tests)
2525

@@ -35,12 +35,12 @@ mypy src/openvino/ --config-file ./setup.cfg
3535

3636
**Python API CIs are composed of both functional tests and codestyle checks and may fail because of warnings/errors in both stages.**
3737

38-
##### Adding dependencies to the project
38+
### Adding dependencies to the project
3939
Remember that a new module/feature may be dependent on various third party modules. Please add a sufficient `requirements.txt` file and mention it in a Pull Request description. Consider other project requirements and dependencies of your module to make `requirements.txt` as compact as possible.
4040

4141
**Please look for current supported Python versions and check if packages are compatibile with them and not depreacated.**
4242

43-
#### Description of the Pull Request
43+
### Description of the Pull Request
4444
Please append all PR titles with a tag `[PyOV]` or `[PYTHON]`. Feel free to describe any level of relevant details in the PR, it helps a lot with the review process. The minimum requirement is a compact description of changes made, the form of a bullet-point list is really appreciated.
4545

4646
Template for external contributors:
@@ -63,3 +63,8 @@ Requirements introduced/changed: <-- only if applicable
6363
Tickets:
6464
XXXX, YYYY <-- only numbers from tickets
6565
```
66+
67+
## See also
68+
* [OpenVINO™ README](../../../../README.md)
69+
* [OpenVINO™ bindings README](../../README.md)
70+
* [Developer documentation](../../../../docs/dev/index.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (C) 2018-2023 Intel Corporation
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
from openvino.helpers.custom_module.custom_helpers import top1_index
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (C) 2018-2023 Intel Corporation
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
def top1_index(results: list) -> int:
6+
return results.index(max(results))

src/bindings/python/docs/python_version_upgrade.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Python version upgrade
22

3-
#### Notes
3+
### Notes
44
Upgrade described in this documentation file can be useful when using a system such as Ubuntu18, which default Python is no longer supported (in this case Python 3.6). The recommended action is to use a newer system instead of upgrading Python.
55

66
*Warning: You make all changes at your own risk.*
@@ -35,3 +35,8 @@ Verify your installation:
3535
python3.8 --version
3636
> Python 3.8.13
3737
```
38+
39+
## See also
40+
* [OpenVINO™ README](../../../../README.md)
41+
* [OpenVINO™ bindings README](../../README.md)
42+
* [Developer documentation](../../../../docs/dev/index.md)

0 commit comments

Comments
 (0)