Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Opencv
提交
fc810434
O
Opencv
项目概览
Greenplum
/
Opencv
9 个月 前同步成功
通知
7
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Opencv
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
fc810434
编写于
6月 21, 2023
作者:
A
Alexander Smorkalov
提交者:
GitHub
6月 21, 2023
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #23801 from VadimLevin:dev/vlevin/python-stubs-api-refinement
feat: manual refinement for Python API definition
上级
94211fb8
69ebecc5
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
108 addition
and
14 deletion
+108
-14
modules/python/src2/typing_stubs_generation/api_refinement.py
...les/python/src2/typing_stubs_generation/api_refinement.py
+48
-0
modules/python/src2/typing_stubs_generation/ast_utils.py
modules/python/src2/typing_stubs_generation/ast_utils.py
+18
-7
modules/python/src2/typing_stubs_generation/generation.py
modules/python/src2/typing_stubs_generation/generation.py
+13
-0
modules/python/src2/typing_stubs_generation/nodes/function_node.py
...ython/src2/typing_stubs_generation/nodes/function_node.py
+24
-6
modules/python/src2/typing_stubs_generator.py
modules/python/src2/typing_stubs_generator.py
+5
-1
未找到文件。
modules/python/src2/typing_stubs_generation/api_refinement.py
0 → 100644
浏览文件 @
fc810434
__all__
=
[
"apply_manual_api_refinement"
]
from
typing
import
Sequence
,
Callable
from
.nodes
import
NamespaceNode
,
FunctionNode
,
OptionalTypeNode
from
.ast_utils
import
find_function_node
,
SymbolName
def
apply_manual_api_refinement
(
root
:
NamespaceNode
)
->
None
:
# Export OpenCV exception class
builtin_exception
=
root
.
add_class
(
"Exception"
)
builtin_exception
.
is_exported
=
False
root
.
add_class
(
"error"
,
(
builtin_exception
,
))
for
symbol_name
,
refine_symbol
in
NODES_TO_REFINE
.
items
():
refine_symbol
(
root
,
symbol_name
)
def
make_optional_arg
(
arg_name
:
str
)
->
Callable
[[
NamespaceNode
,
SymbolName
],
None
]:
def
_make_optional_arg
(
root_node
:
NamespaceNode
,
function_symbol_name
:
SymbolName
)
->
None
:
function
=
find_function_node
(
root_node
,
function_symbol_name
)
for
overload
in
function
.
overloads
:
arg_idx
=
_find_argument_index
(
overload
.
arguments
,
arg_name
)
# Avoid multiplying optional qualification
if
isinstance
(
overload
.
arguments
[
arg_idx
].
type_node
,
OptionalTypeNode
):
continue
overload
.
arguments
[
arg_idx
].
type_node
=
OptionalTypeNode
(
overload
.
arguments
[
arg_idx
].
type_node
)
return
_make_optional_arg
def
_find_argument_index
(
arguments
:
Sequence
[
FunctionNode
.
Arg
],
name
:
str
)
->
int
:
for
i
,
arg
in
enumerate
(
arguments
):
if
arg
.
name
==
name
:
return
i
raise
RuntimeError
(
f
"Failed to find argument with name: '
{
name
}
' in
{
arguments
}
"
)
NODES_TO_REFINE
=
{
SymbolName
((
"cv"
,
),
(),
"resize"
):
make_optional_arg
(
"dsize"
),
SymbolName
((
"cv"
,
),
(),
"calcHist"
):
make_optional_arg
(
"mask"
),
}
modules/python/src2/typing_stubs_generation/ast_utils.py
浏览文件 @
fc810434
...
...
@@ -143,13 +143,24 @@ because 'GOpaque' class is not registered yet
return
scope
def
find_class_node
(
root
:
NamespaceNode
,
full_class_name
:
str
,
namespaces
:
Sequence
[
str
])
->
ClassNode
:
symbol_name
=
SymbolName
.
parse
(
full_class_name
,
namespaces
)
scope
=
find_scope
(
root
,
symbol_name
)
if
symbol_name
.
name
not
in
scope
.
classes
:
raise
SymbolNotFoundError
(
"Can't find {} in its scope"
.
format
(
symbol_name
))
return
scope
.
classes
[
symbol_name
.
name
]
def
find_class_node
(
root
:
NamespaceNode
,
class_symbol
:
SymbolName
,
create_missing_namespaces
:
bool
=
False
)
->
ClassNode
:
scope
=
find_scope
(
root
,
class_symbol
,
create_missing_namespaces
)
if
class_symbol
.
name
not
in
scope
.
classes
:
raise
SymbolNotFoundError
(
"Can't find {} in its scope"
.
format
(
class_symbol
)
)
return
scope
.
classes
[
class_symbol
.
name
]
def
find_function_node
(
root
:
NamespaceNode
,
function_symbol
:
SymbolName
,
create_missing_namespaces
:
bool
=
False
)
->
FunctionNode
:
scope
=
find_scope
(
root
,
function_symbol
,
create_missing_namespaces
)
if
function_symbol
.
name
not
in
scope
.
functions
:
raise
SymbolNotFoundError
(
"Can't find {} in its scope"
.
format
(
function_symbol
)
)
return
scope
.
functions
[
function_symbol
.
name
]
def
create_function_node_in_scope
(
scope
:
Union
[
NamespaceNode
,
ClassNode
],
...
...
modules/python/src2/typing_stubs_generation/generation.py
浏览文件 @
fc810434
...
...
@@ -10,6 +10,7 @@ import warnings
from
.ast_utils
import
get_enclosing_namespace
,
get_enum_module_and_export_name
from
.predefined_types
import
PREDEFINED_TYPES
from
.api_refinement
import
apply_manual_api_refinement
from
.nodes
import
(
ASTNode
,
ASTNodeType
,
NamespaceNode
,
ClassNode
,
FunctionNode
,
EnumerationNode
,
ConstantNode
)
...
...
@@ -47,6 +48,18 @@ def generate_typing_stubs(root: NamespaceNode, output_path: Path):
root (NamespaceNode): Root namespace node of the library AST.
output_path (Path): Path to output directory.
"""
# Perform special handling for function arguments that has some conventions
# not expressed in their API e.g. optionality of mutually exclusive arguments
# without default values:
# ```cxx
# cv::resize(cv::InputArray src, cv::OutputArray dst, cv::Size dsize,
# double fx = 0.0, double fy = 0.0, int interpolation);
# ```
# should accept `None` as `dsize`:
# ```python
# cv2.resize(image, dsize=None, fx=0.5, fy=0.5)
# ```
apply_manual_api_refinement
(
root
)
# Most of the time type nodes miss their full name (especially function
# arguments and return types), so resolution should start from the narrowest
# scope and gradually expanded.
...
...
modules/python/src2/typing_stubs_generation/nodes/function_node.py
浏览文件 @
fc810434
...
...
@@ -10,10 +10,12 @@ class FunctionNode(ASTNode):
This class defines an overload set rather then function itself, because
function without overloads is represented as FunctionNode with 1 overload.
"""
class
Arg
(
NamedTuple
):
name
:
str
type_node
:
Optional
[
TypeNode
]
=
None
default_value
:
Optional
[
str
]
=
None
class
Arg
:
def
__init__
(
self
,
name
:
str
,
type_node
:
Optional
[
TypeNode
]
=
None
,
default_value
:
Optional
[
str
]
=
None
)
->
None
:
self
.
name
=
name
self
.
type_node
=
type_node
self
.
default_value
=
default_value
@
property
def
typename
(
self
)
->
Optional
[
str
]:
...
...
@@ -24,8 +26,18 @@ class FunctionNode(ASTNode):
return
self
.
type_node
.
relative_typename
(
root
)
return
None
class
RetType
(
NamedTuple
):
type_node
:
TypeNode
=
NoneTypeNode
(
"void"
)
def
__str__
(
self
)
->
str
:
return
(
f
"Arg(name=
{
self
.
name
}
, type_node=
{
self
.
type_node
}
,"
f
" default_value=
{
self
.
default_value
}
)"
)
def
__repr__
(
self
)
->
str
:
return
str
(
self
)
class
RetType
:
def
__init__
(
self
,
type_node
:
TypeNode
=
NoneTypeNode
(
"void"
))
->
None
:
self
.
type_node
=
type_node
@
property
def
typename
(
self
)
->
str
:
...
...
@@ -34,6 +46,12 @@ class FunctionNode(ASTNode):
def
relative_typename
(
self
,
root
:
str
)
->
Optional
[
str
]:
return
self
.
type_node
.
relative_typename
(
root
)
def
__str__
(
self
)
->
str
:
return
f
"RetType(type_node=
{
self
.
type_node
}
)"
def
__repr__
(
self
)
->
str
:
return
str
(
self
)
class
Overload
(
NamedTuple
):
arguments
:
Sequence
[
"FunctionNode.Arg"
]
=
()
return_type
:
Optional
[
"FunctionNode.RetType"
]
=
None
...
...
modules/python/src2/typing_stubs_generator.py
浏览文件 @
fc810434
...
...
@@ -123,7 +123,11 @@ if sys.version_info >= (3, 6):
@
failures_wrapper
.
wrap_exceptions_as_warnings
(
ret_type_on_failure
=
ClassNodeStub
)
def
find_class_node
(
self
,
class_info
,
namespaces
):
# type: (Any, Sequence[str]) -> ClassNode
return
find_class_node
(
self
.
cv_root
,
class_info
.
full_original_name
,
namespaces
)
return
find_class_node
(
self
.
cv_root
,
SymbolName
.
parse
(
class_info
.
full_original_name
,
namespaces
),
create_missing_namespaces
=
True
)
@
failures_wrapper
.
wrap_exceptions_as_warnings
(
ret_type_on_failure
=
ClassNodeStub
)
def
create_class_node
(
self
,
class_info
,
namespaces
):
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录