Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
138
Merge Requests
138
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
erp5
Commits
14ebe535
Commit
14ebe535
authored
Apr 20, 2018
by
Tomáš Peterka
Committed by
Tomáš Peterka
Apr 25, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[hal_json] Allow parameter instrospection for External Methods
parent
56db74f4
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
68 additions
and
23 deletions
+68
-23
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
...rtal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
+41
-20
product/ERP5Type/patches/ExternalMethod.py
product/ERP5Type/patches/ExternalMethod.py
+27
-3
No files found.
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
View file @
14ebe535
...
@@ -223,15 +223,37 @@ def selectKwargsForCallable(func, initial_kwargs, kwargs_dict):
...
@@ -223,15 +223,37 @@ def selectKwargsForCallable(func, initial_kwargs, kwargs_dict):
In case the function cannot state required arguments it throws an AttributeError.
In case the function cannot state required arguments it throws an AttributeError.
"""
"""
if
not
hasattr
(
func
,
'params'
):
if
hasattr
(
func
,
'params'
):
# In case the func is actualy Script (Python) or ERP5 Python Script
func_param_list
=
[
tuple
(
map
(
lambda
x
:
x
.
strip
(),
func_param
.
split
(
'='
)))
for
func_param
in
func
.
params
().
split
(
","
)]
elif
hasattr
(
func
,
"func_args"
):
# In case the func is an External Method
func_param_list
=
func
.
func_args
if
len
(
func_param_list
)
>
0
and
func_param_list
[
0
]
==
"self"
:
func_param_list
=
func_param_list
[
1
:]
func_default_list
=
func
.
func_defaults
func_param_list
=
[(
func_param
,
func_default_list
[
i
])
if
len
(
func_default_list
)
>=
(
i
+
1
)
else
(
func_param
,
)
for
i
,
func_param
in
enumerate
(
func_param_list
)]
else
:
# TODO: cover the case of Callables
# For anything else give up in advance and just return initial guess of the callee
return
initial_kwargs
return
initial_kwargs
func_param_list
=
[
func_param
.
strip
()
for
func_param
in
func
.
params
().
split
(
","
)]
# func_param_list is a list of tuples - first item is parameter name and optinal second item is the default value
func_param_name_list
=
[
func_param
if
'='
not
in
func_param
else
func_param
.
split
(
'='
)[
0
]
func_param_name_list
=
[
item
[
0
]
for
item
in
func_param_list
]
for
func_param
in
func_param_list
if
'*'
not
in
func_param
]
for
func_param_name
in
func_param_name_list
:
for
func_param_name
in
func_param_name_list
:
if
func_param_name
in
kwargs_dict
and
func_param_name
not
in
initial_kwargs
:
if
'*'
in
func_param_name
:
initial_kwargs
[
func_param_name
]
=
kwargs_dict
.
get
(
func_param_name
)
continue
# move necessary parameters from kwargs_dict to initial_kwargs
if
func_param_name
not
in
initial_kwargs
and
func_param_name
in
kwargs_dict
:
func_param_value
=
kwargs_dict
.
get
(
func_param_name
)
if
callable
(
func_param_value
):
initial_kwargs
[
func_param_name
]
=
func_param_value
()
# evaluate lazy attributes
else
:
initial_kwargs
[
func_param_name
]
=
func_param_value
# MIDDLE-DANGEROUS!
# MIDDLE-DANGEROUS!
# In case of reports (later even exports) substitute None for unknown
# In case of reports (later even exports) substitute None for unknown
# parameters. We suppose Python syntax for parameters!
# parameters. We suppose Python syntax for parameters!
...
@@ -240,14 +262,21 @@ def selectKwargsForCallable(func, initial_kwargs, kwargs_dict):
...
@@ -240,14 +262,21 @@ def selectKwargsForCallable(func, initial_kwargs, kwargs_dict):
# this way we can mimic synchronous rendering when all form field values
# this way we can mimic synchronous rendering when all form field values
# were available in `kwargs_dict`. It is obviously wrong behaviour.
# were available in `kwargs_dict`. It is obviously wrong behaviour.
for
func_param
in
func_param_list
:
for
func_param
in
func_param_list
:
if
"*"
in
func_param
:
if
"*"
in
func_param
[
0
]
:
continue
continue
if
"="
in
func_param
:
if
len
(
func_param
)
>
1
:
# default value exists
continue
continue
# now we have only mandatory parameters
# now we have only mandatory parameters
func_param
=
func_param
.
strip
()
func_param
=
func_param
[
0
]
.
strip
()
if
func_param
not
in
initial_kwargs
:
if
func_param
not
in
initial_kwargs
:
initial_kwargs
[
func_param
]
=
None
initial_kwargs
[
func_param
]
=
None
# If the method does not specify **kwargs we need to remove unwanted parameters
if
len
(
func_param_name_list
)
>
0
and
"**"
not
in
func_param_name_list
[
-
1
]:
initial_param_list
=
tuple
(
initial_kwargs
.
keys
())
# copy the keys
for
initial_param
in
initial_param_list
:
if
initial_param
not
in
func_param_name_list
:
del
initial_kwargs
[
initial_param
]
return
initial_kwargs
return
initial_kwargs
...
@@ -785,17 +814,9 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
...
@@ -785,17 +814,9 @@ def renderField(traversed_document, field, form, value=None, meta_type=None, key
# still in the request which is not our case because we do asynchronous rendering
# still in the request which is not our case because we do asynchronous rendering
if
list_method
is
not
None
:
if
list_method
is
not
None
:
selectKwargsForCallable
(
list_method
,
list_method_query_dict
,
REQUEST
)
selectKwargsForCallable
(
list_method
,
list_method_query_dict
,
REQUEST
)
# Now if the list_method does not specify **kwargs we need to remove
# unwanted parameters like "portal_type" which is everywhere
if
(
True
):
# editable_column_list (we need that template fields resolution
if
hasattr
(
list_method
,
'params'
)
and
"**"
not
in
list_method
.
params
():
# (issued by existence of `form_relative_url`) always kicks in
_param_key_list
=
tuple
(
list_method_query_dict
.
keys
())
# copy the keys
for
param_key
in
_param_key_list
:
if
param_key
not
in
list_method
.
params
():
# we search in raw string
del
list_method_query_dict
[
param_key
]
# but it is enough
if
(
True
):
# editable_column_list (used to be but we need
# template fields resolution (issued by existence of `form_relative_url`)
# to always kick in
list_method_custom
=
url_template_dict
[
"custom_search_template"
]
%
{
list_method_custom
=
url_template_dict
[
"custom_search_template"
]
%
{
"root_url"
:
site_root
.
absolute_url
(),
"root_url"
:
site_root
.
absolute_url
(),
"script_id"
:
script
.
id
,
"script_id"
:
script
.
id
,
...
...
product/ERP5Type/patches/ExternalMethod.py
View file @
14ebe535
...
@@ -25,12 +25,29 @@ class _(PatchClass(ExternalMethod)):
...
@@ -25,12 +25,29 @@ class _(PatchClass(ExternalMethod)):
@
property
@
property
def
func_defaults
(
self
):
def
func_defaults
(
self
):
"""Return a tuple of default values.
The first value is for the "second" parameter (self is ommited)
Example:
componentFunction(self, form_id='', **kw)
will have func_defaults = ('', )
"""
return
self
.
_getFunction
()[
1
]
return
self
.
_getFunction
()[
1
]
@
property
@
property
def
func_code
(
self
):
def
func_code
(
self
):
return
self
.
_getFunction
()[
2
]
return
self
.
_getFunction
()[
2
]
@
property
def
func_args
(
self
):
"""Return list of parameter names.
Example:
componentFunction(self, form_id='', **kw)
will have func_args = ['self', 'form_id']
"""
return
self
.
_getFunction
()[
4
]
def
getFunction
(
self
,
reload
=
False
):
def
getFunction
(
self
,
reload
=
False
):
return
self
.
_getFunction
(
reload
)[
0
]
return
self
.
_getFunction
(
reload
)[
0
]
...
@@ -74,14 +91,21 @@ class _(PatchClass(ExternalMethod)):
...
@@ -74,14 +91,21 @@ class _(PatchClass(ExternalMethod)):
except
AttributeError
:
except
AttributeError
:
pass
pass
code
=
f
.
func_code
code
=
f
.
func_code
args
=
getargs
(
code
)[
0
]
argument_object
=
getargs
(
code
)
# reconstruct back the original names
arg_list
=
argument_object
.
args
[:]
if
argument_object
.
varargs
:
arg_list
.
append
(
'*'
+
argument_object
.
varargs
)
if
argument_object
.
keywords
:
arg_list
.
append
(
'**'
+
argument_object
.
keywords
)
i
=
isinstance
(
f
,
MethodType
)
i
=
isinstance
(
f
,
MethodType
)
ff
=
f
.
__func__
if
i
else
f
ff
=
f
.
__func__
if
i
else
f
has_self
=
len
(
arg
s
)
>
i
and
args
[
i
]
==
'self'
has_self
=
len
(
arg
_list
)
>
i
and
arg_list
[
i
]
==
'self'
i
+=
has_self
i
+=
has_self
if
i
:
if
i
:
code
=
FuncCode
(
ff
,
i
)
code
=
FuncCode
(
ff
,
i
)
self
.
_v_f
=
_f
=
(
f
,
f
.
func_defaults
,
code
,
has_self
)
self
.
_v_f
=
_f
=
(
f
,
f
.
func_defaults
,
code
,
has_self
,
arg_list
)
return
_f
return
_f
def
__call__
(
self
,
*
args
,
**
kw
):
def
__call__
(
self
,
*
args
,
**
kw
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment