You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: src/bindings/python/docs/code_examples.md
+34-29
Original file line number
Diff line number
Diff line change
@@ -1,34 +1,34 @@
1
1
# Examples of OpenVINO™ Python API code
2
2
3
-
####Building and environment
3
+
### Building and environment
4
4
Instructions can be found in ["Building the OpenVINO™ Python API"](./build.md).
5
5
6
-
###Different ways of extending OpenVINO™ Python API
6
+
## Different ways of extending OpenVINO™ Python API
7
7
8
-
######Before start: Project's naming conventions
8
+
### Before start: Project's naming conventions
9
9
General guide:
10
10
* 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`).
11
11
* Naming of classes is an exception to the above rule. The *CamelCase* style is used in this case, for example: `Core`, `InferRequest` or `AsyncInferQueue`.
12
12
* 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.
13
13
14
14
<!-- Pure Python solution describes Python based approach -->
15
-
####Pure Python solution
15
+
## Pure Python solution
16
16
One of the simplest ways to extend the existing codebase is by writing it in pure Python.
17
17
18
-
###### Before start: Layout of the project
18
+
### Layout of the project
19
19
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:
20
20
*`openvino.tools`
21
21
* ...
22
22
23
23
For further reading, please refer to: https://packaging.python.org/en/latest/guides/packaging-namespace-packages/
24
24
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):
27
27
28
28
```
29
29
openvino/ <-- Main package/namespace
30
30
├── __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
32
32
├── __init__.py
33
33
├── ...
34
34
└── myclass.py
@@ -48,8 +48,8 @@ obj.say_hello()
48
48
>>>"Hello! Let's work on OV together!"
49
49
```
50
50
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:
53
53
54
54
```
55
55
openvino/
@@ -67,18 +67,20 @@ openvino/
67
67
└── utils.py
68
68
```
69
69
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 -->
71
72
```python
72
73
deftop1_index(results: list) -> int:
73
74
return results.index(max(results))
74
75
```
75
76
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 -->
77
79
```python
78
80
from openvino.helpers.custom_module.custom_helpers import top1_index
79
81
```
80
82
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):
82
84
```python
83
85
from openvino.helpers.custom_module import top1_index
84
86
```
@@ -97,35 +99,33 @@ Following this method, developers can add new modules and adjust existing ones,
97
99
98
100
<!-- Pure pybind11 solution describes C++ based approach -->
99
101
100
-
####Pure pybind11 solution
102
+
## Pure pybind11 solution
101
103
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.
102
104
103
105
**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.**
104
106
105
-
######Before start: What is pybind11?
107
+
### Before start: What is pybind11?
106
108
It is a thridparty project that allows to expose C++ code as a Python library.
107
109
108
110
Link to offical documentation: https://pybind11.readthedocs.io/en/stable/
109
111
Link to project repository: https://github.com/pybind/pybind11
110
112
111
-
#####Adding new (sub)module
113
+
### Adding new (sub)module
112
114
Adding a new module could be done only by using *pybind11* built-in capabilities.
113
115
114
-
Navigate to the main project file responsible for creation of the whole package, let's call it "registering-point":
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".
117
117
118
118
Add a new submodule by writing:
119
119
```cpp
120
120
py::module mymodule = m.def_submodule("mymodule", "My first feature - openvino.runtime.mymodule");
121
121
```
122
122
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.
123
123
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).
125
125
126
126
*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*
127
127
128
-
#####Binding of classes and functions
128
+
### Binding of classes and functions
129
129
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:
130
130
131
131
* 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*
245
245
246
246
MyTensor wraps (around) Tensor class.
247
247
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.
249
249
250
-
#####Overloads of functions
250
+
### Overloads of functions
251
251
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.
252
252
253
253
```cpp
@@ -299,11 +299,11 @@ Notice that only functions with correct arguments are **not** throwing exception
299
299
300
300
<!-- Mixed solution describes both approaches combined -->
301
301
302
-
####Mix between Python and pybind11
302
+
## Mix between Python and pybind11
303
303
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.
304
304
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):
307
307
```python
308
308
from openvino._pyopenvino.mymodule import MyTensor
309
309
```
@@ -317,10 +317,10 @@ ov.MyTensor
317
317
318
318
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.
319
319
320
-
#####Yet another Python layer
320
+
### Yet another Python layer
321
321
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.
322
322
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:
324
324
```python
325
325
from openvino._pyopenvino.mymodule import MyTensor as MyTensorBase
326
326
```
@@ -402,8 +402,13 @@ Great! Now the class has reached its destination, from C++, to Python, to Python
402
402
403
403
This concludes developer work on OpenVINO™ Python API. Don't forget to recompile your builds and have a good time while writing your code!:)
404
404
405
-
###Testing the new code
405
+
## Testing the new code
406
406
407
407
Coding is now finished. Let's move on to testing.
408
408
409
409
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)
Copy file name to clipboardexpand all lines: src/bindings/python/docs/contributing.md
+15-10
Original file line number
Diff line number
Diff line change
@@ -1,25 +1,25 @@
1
1
# Contributing to OpenVINO™ Python API
2
2
3
-
####Prerequisites
3
+
## Prerequisites
4
4
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.
7
7
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).
9
9
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).
12
12
13
13
## Contribution guidelines and best practices
14
14
15
-
####How to contribute to Python API?
15
+
### How to contribute to Python API?
16
16
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.
17
17
18
18
Code snippets and detailed explanations can be found here:
19
19
20
20
[Examples of OpenVINO™ Python API code](./code_example.md)
21
21
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.
23
23
24
24
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)
**Python API CIs are composed of both functional tests and codestyle checks and may fail because of warnings/errors in both stages.**
37
37
38
-
#####Adding dependencies to the project
38
+
### Adding dependencies to the project
39
39
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.
40
40
41
41
**Please look for current supported Python versions and check if packages are compatibile with them and not depreacated.**
42
42
43
-
####Description of the Pull Request
43
+
### Description of the Pull Request
44
44
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.
45
45
46
46
Template for external contributors:
@@ -63,3 +63,8 @@ Requirements introduced/changed: <-- only if applicable
Copy file name to clipboardexpand all lines: src/bindings/python/docs/python_version_upgrade.md
+6-1
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Python version upgrade
2
2
3
-
####Notes
3
+
### Notes
4
4
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.
0 commit comments