Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9b47eb6

Browse files
authored
Merge pull request #6048 from ckan/update-converter-selection-logic
Do not rely on error message when selecting validator signature
2 parents 3d28c4f + 020aff3 commit 9b47eb6

17 files changed

Lines changed: 87 additions & 63 deletions

File tree

changes/6048.removal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Only user-defined functions can be used as validators. Attempt to use
2+
mock-object, built-in function or class will cause TypeError.

ckan/lib/navl/dictization_functions.py

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -219,35 +219,27 @@ def augment_data(data, schema):
219219

220220

221221
def convert(converter, key, converted_data, errors, context):
222-
223-
try:
224-
value = converter(converted_data.get(key))
225-
converted_data[key] = value
226-
return
227-
except TypeError as e:
228-
# hack to make sure the type error was caused by the wrong
229-
# number of arguments given.
230-
if converter.__name__ not in str(e):
231-
raise
232-
except Invalid as e:
233-
errors[key].append(e.error)
234-
return
235-
236222
try:
237-
converter(key, converted_data, errors, context)
238-
return
239-
except Invalid as e:
240-
errors[key].append(e.error)
241-
return
242-
except TypeError as e:
243-
# hack to make sure the type error was caused by the wrong
244-
# number of arguments given.
245-
if converter.__name__ not in str(e):
246-
raise
247-
223+
nargs = converter.__code__.co_argcount
224+
except AttributeError:
225+
raise TypeError(
226+
f"{converter.__name__} cannot be used as validator "
227+
"because it is not a user-defined function")
228+
if nargs == 1:
229+
params = (converted_data.get(key),)
230+
elif nargs == 2:
231+
params = (converted_data.get(key), context)
232+
elif nargs == 4:
233+
params = (key, converted_data, errors, context)
234+
else:
235+
raise TypeError(
236+
"Wrong number of arguments for "
237+
f"{converter.__name__}(expected 1, 2 or 4): {nargs}")
248238
try:
249-
value = converter(converted_data.get(key), context)
250-
converted_data[key] = value
239+
value = converter(*params)
240+
# 4-args version sets value internally
241+
if nargs != 4:
242+
converted_data[key] = value
251243
return
252244
except Invalid as e:
253245
errors[key].append(e.error)

ckan/lib/navl/validators.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
def identity_converter(key, data, errors, context):
1616
return
1717

18+
1819
def keep_extras(key, data, errors, context):
1920

2021
extras = data.pop(key, {})

ckan/logic/action/update.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -999,9 +999,10 @@ def term_translation_update(context, data_dict):
999999

10001000
_check_access('term_translation_update', context, data_dict)
10011001

1002-
schema = {'term': [validators.not_empty, text_type],
1003-
'term_translation': [validators.not_empty, text_type],
1004-
'lang_code': [validators.not_empty, text_type]}
1002+
schema = {'term': [validators.not_empty, validators.unicode_safe],
1003+
'term_translation': [
1004+
validators.not_empty, validators.unicode_safe],
1005+
'lang_code': [validators.not_empty, validators.unicode_safe]}
10051006

10061007
data, errors = _validate(data_dict, schema, context)
10071008
if errors:

ckan/logic/schema.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from functools import wraps
44
import inspect
55

6-
from six import text_type
76
import ckan.model
87
import ckan.plugins as plugins
98
from ckan.logic import get_validator
@@ -422,9 +421,9 @@ def user_new_form_schema(
422421
schema = default_user_schema()
423422

424423
schema['email'] = [email_is_unique]
425-
schema['password1'] = [text_type, user_both_passwords_entered,
424+
schema['password1'] = [unicode_safe, user_both_passwords_entered,
426425
user_password_validator, user_passwords_match]
427-
schema['password2'] = [text_type]
426+
schema['password2'] = [unicode_safe]
428427

429428
return schema
430429

@@ -474,7 +473,7 @@ def default_generate_apikey_user_schema(
474473
def default_user_invite_schema(
475474
not_empty, unicode_safe):
476475
return {
477-
'email': [not_empty, text_type],
476+
'email': [not_empty, unicode_safe],
478477
'group_id': [not_empty],
479478
'role': [not_empty],
480479
}

ckan/tests/legacy/lib/test_navl.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from ckan.lib.navl.validators import (
1818
identity_converter,
1919
empty,
20+
unicode_safe,
2021
not_empty,
2122
ignore_missing,
2223
default,
@@ -346,8 +347,8 @@ def test_simple():
346347

347348
def test_simple_converter_types():
348349
schema = {
349-
"name": [not_empty, text_type],
350-
"age": [ignore_missing, int],
350+
"name": [not_empty, unicode_safe],
351+
"age": [ignore_missing, convert_int],
351352
"gender": [default("female")],
352353
}
353354

ckan/tests/logic/action/test_update.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,13 @@ def test_user_update_with_custom_schema(self):
274274
user = factories.User()
275275

276276
# A mock validator method, it doesn't do anything but it records what
277-
# params it gets called with and how many times.
278-
mock_validator = mock.MagicMock()
277+
# params it gets called with and how many times. We are using function
278+
# instead of MagicMock, because validator must have __code__ attribute
279+
calls = []
280+
281+
def mock_validator(v):
282+
calls.append(v)
283+
return v
279284

280285
# Build a custom schema by taking the default schema and adding our
281286
# mock method to its 'id' field.
@@ -294,6 +299,7 @@ def test_user_update_with_custom_schema(self):
294299
password=factories.User.password,
295300
fullname="updated full name",
296301
)
302+
assert calls == [user['id']]
297303

298304
def test_user_update_multiple(self):
299305
"""Test that updating multiple user attributes at once works."""

ckanext/audioview/plugin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import ckan.plugins as p
55

66
ignore_empty = p.toolkit.get_validator('ignore_empty')
7+
unicode_safe = p.toolkit.get_validator('unicode_safe')
78

89
DEFAULT_AUDIO_FORMATS = 'wav ogg mp3'
910

@@ -24,7 +25,7 @@ def info(self):
2425
return {'name': 'audio_view',
2526
'title': p.toolkit._('Audio'),
2627
'icon': 'file-audio-o',
27-
'schema': {'audio_url': [ignore_empty, text_type]},
28+
'schema': {'audio_url': [ignore_empty, unicode_safe]},
2829
'iframed': False,
2930
'always_available': True,
3031
'default_title': p.toolkit._('Audio'),

ckanext/datapusher/logic/schema.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# encoding: utf-8
22

3-
from six import text_type
4-
53
import ckan.plugins as p
64
import ckanext.datastore.logic.schema as dsschema
75

@@ -12,11 +10,12 @@
1210
ignore_missing = get_validator('ignore_missing')
1311
empty = get_validator('empty')
1412
boolean_validator = get_validator('boolean_validator')
13+
unicode_safe = get_validator('unicode_safe')
1514

1615

1716
def datapusher_submit_schema():
1817
schema = {
19-
'resource_id': [not_missing, not_empty, text_type],
18+
'resource_id': [not_missing, not_empty, unicode_safe],
2019
'id': [ignore_missing],
2120
'set_url_type': [ignore_missing, boolean_validator],
2221
'ignore_hash': [ignore_missing, boolean_validator],

ckanext/datastore/logic/schema.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
natural_number_validator = get_validator('natural_number_validator')
2525
configured_default = get_validator('configured_default')
2626
limit_to_configured_maximum = get_validator('limit_to_configured_maximum')
27+
unicode_safe = get_validator('unicode_safe')
2728

2829

2930
def rename(old, new):
@@ -103,12 +104,12 @@ def unicode_or_json_validator(value, context):
103104

104105
def datastore_create_schema():
105106
schema = {
106-
'resource_id': [ignore_missing, text_type, resource_id_exists],
107+
'resource_id': [ignore_missing, unicode_safe, resource_id_exists],
107108
'force': [ignore_missing, boolean_validator],
108109
'id': [ignore_missing],
109110
'aliases': [ignore_missing, list_of_strings_or_string],
110111
'fields': {
111-
'id': [not_empty, text_type],
112+
'id': [not_empty, unicode_safe],
112113
'type': [ignore_missing],
113114
'info': [ignore_missing],
114115
},
@@ -135,10 +136,10 @@ def datastore_create_schema():
135136

136137
def datastore_upsert_schema():
137138
schema = {
138-
'resource_id': [not_missing, not_empty, text_type],
139+
'resource_id': [not_missing, not_empty, unicode_safe],
139140
'force': [ignore_missing, boolean_validator],
140141
'id': [ignore_missing],
141-
'method': [ignore_missing, text_type, one_of(
142+
'method': [ignore_missing, unicode_safe, one_of(
142143
['upsert', 'insert', 'update'])],
143144
'calculate_record_count': [ignore_missing, default(False),
144145
boolean_validator],
@@ -151,7 +152,7 @@ def datastore_upsert_schema():
151152

152153
def datastore_delete_schema():
153154
schema = {
154-
'resource_id': [not_missing, not_empty, text_type],
155+
'resource_id': [not_missing, not_empty, unicode_safe],
155156
'force': [ignore_missing, boolean_validator],
156157
'id': [ignore_missing],
157158
'calculate_record_count': [ignore_missing, default(False),
@@ -164,12 +165,12 @@ def datastore_delete_schema():
164165

165166
def datastore_search_schema():
166167
schema = {
167-
'resource_id': [not_missing, not_empty, text_type],
168+
'resource_id': [not_missing, not_empty, unicode_safe],
168169
'id': [ignore_missing],
169170
'q': [ignore_missing, unicode_or_json_validator],
170171
'plain': [ignore_missing, boolean_validator],
171172
'filters': [ignore_missing, json_validator],
172-
'language': [ignore_missing, text_type],
173+
'language': [ignore_missing, unicode_safe],
173174
'limit': [
174175
configured_default('ckan.datastore.search.rows_default', 100),
175176
natural_number_validator,
@@ -213,5 +214,5 @@ def datastore_function_delete_schema():
213214

214215
def datastore_analyze_schema():
215216
return {
216-
'resource_id': [text_type, resource_id_exists],
217+
'resource_id': [unicode_safe, resource_id_exists],
217218
}

0 commit comments

Comments
 (0)