Skip to content

Commit 4f2f890

Browse files
author
Sylvain MARIE
committed
Minor performance improvement: Converter.create_from_fun() does not generate a new type everytime a converter needs to be created from a callable - now a single class ConverterWithFuncs is used. Fixed #32
1 parent 88bec75 commit 4f2f890

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

pyfields/validate_n_convert.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,26 +298,51 @@ def create_from_fun(cls,
298298
:param validation_fun:
299299
:return:
300300
"""
301+
# Mandatory conversion callable
301302
if is_mini_lambda(converter_fun):
302303
is_mini = True
303304
converter_fun = converter_fun.as_function()
304305
else:
305306
is_mini = False
306307
converter_fun_3params = make_3params_callable(converter_fun, is_mini_lambda=is_mini)
307-
methods_dict = {'__slots__': (), 'convert': staticmethod(converter_fun_3params)}
308308

309+
# Optional acceptance callable
309310
if validation_fun is not None:
310311
if is_mini_lambda(validation_fun):
311312
is_mini = True
312313
validation_fun = validation_fun.as_function()
313314
else:
314315
is_mini = False
315316
validation_fun_3params = make_3params_callable(validation_fun, is_mini_lambda=is_mini)
316-
methods_dict['accepts'] = staticmethod(validation_fun_3params)
317+
else:
318+
validation_fun_3params = None
319+
320+
# Finally create the converter instance
321+
return ConverterWithFuncs(name=converter_fun_3params.__name__,
322+
accepts_fun=validation_fun_3params,
323+
convert_fun=converter_fun_3params)
324+
317325

318-
# create the type dynamically and instantiate
319-
c_type = type('SimpleConverter', (Converter,), methods_dict)
320-
return c_type(name=converter_fun_3params.__name__)
326+
# noinspection PyAbstractClass
327+
class ConverterWithFuncs(Converter):
328+
"""
329+
Represents a converter for which the `accepts` and `convert` methods can be provided in the constructor.
330+
"""
331+
__slots__ = ('accepts', 'convert')
332+
333+
def __init__(self, convert_fun, name=None, accepts_fun=None):
334+
# call super to set the name
335+
super(ConverterWithFuncs, self).__init__(name=name)
336+
337+
# use the convert method
338+
self.convert = convert_fun
339+
340+
# use the accepts method if provided, otherwise use parent's
341+
if accepts_fun is not None:
342+
self.accepts = accepts_fun
343+
else:
344+
# use parent method - bind it on this instance
345+
self.accepts = Converter.accepts.__get__(self, ConverterWithFuncs)
321346

322347

323348
if use_type_hints:

0 commit comments

Comments
 (0)