Skip to content

Commit 31f88da

Browse files
author
Steve Canny
committed
py3: extract cls_method_fn()
1 parent 70ce190 commit 31f88da

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

docx/opc/compat.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616

1717
if sys.version_info >= (3, 0):
1818

19+
def cls_method_fn(cls, method_name):
20+
"""
21+
Return the function object associated with the method of *cls* having
22+
*method_name*.
23+
"""
24+
return getattr(cls, method_name)
25+
1926
def is_string(obj):
2027
"""
2128
Return True if *obj* is a string, False otherwise.
@@ -28,6 +35,14 @@ def is_string(obj):
2835

2936
else:
3037

38+
def cls_method_fn(cls, method_name):
39+
"""
40+
Return the function object associated with the method of *cls* having
41+
*method_name*.
42+
"""
43+
unbound_method = getattr(cls, method_name)
44+
return unbound_method.__func__
45+
3146
def is_string(obj):
3247
"""
3348
Return True if *obj* is a string, False otherwise.

docx/opc/package.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from __future__ import absolute_import, print_function, unicode_literals
99

10+
from .compat import cls_method_fn
1011
from .constants import RELATIONSHIP_TYPE as RT
1112
from .oxml import CT_Relationships, nsmap, serialize_part_xml
1213
from .packuri import PACKAGE_URI, PackURI
@@ -333,7 +334,7 @@ class PartFactory(object):
333334
def __new__(cls, partname, content_type, reltype, blob, package):
334335
PartClass = None
335336
if cls.part_class_selector is not None:
336-
part_class_selector = cls.part_class_selector.__func__
337+
part_class_selector = cls_method_fn(cls, 'part_class_selector')
337338
PartClass = part_class_selector(content_type, reltype)
338339
if PartClass is None:
339340
PartClass = cls._part_cls_for(content_type)

tests/opc/test_package.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
from docx.opc.pkgreader import PackageReader
2020

2121
from ..unitutil import (
22-
cls_attr_mock, class_mock, instance_mock, loose_mock, method_mock
22+
cls_attr_mock, class_mock, function_mock, instance_mock, loose_mock,
23+
method_mock
2324
)
2425

2526

@@ -384,15 +385,14 @@ class DescribePartFactory(object):
384385
def it_constructs_part_from_selector_if_defined(
385386
self, cls_selector_fixture):
386387
# fixture ----------------------
387-
(cls_selector_fn_, partname, content_type, reltype, blob, package,
388-
CustomPartClass_, part_of_custom_type_) = cls_selector_fixture
388+
(cls_selector_fn_, part_load_params, CustomPartClass_,
389+
part_of_custom_type_) = cls_selector_fixture
390+
partname, content_type, reltype, blob, package = part_load_params
389391
# exercise ---------------------
390392
PartFactory.part_class_selector = cls_selector_fn_
391393
part = PartFactory(partname, content_type, reltype, blob, package)
392394
# verify -----------------------
393-
cls_selector_fn_.__func__.assert_called_once_with(
394-
content_type, reltype
395-
)
395+
cls_selector_fn_.assert_called_once_with(content_type, reltype)
396396
CustomPartClass_.load.assert_called_once_with(
397397
partname, content_type, blob, package
398398
)
@@ -430,25 +430,34 @@ def blob_(self, request):
430430
def blob_2_(self, request):
431431
return instance_mock(request, str)
432432

433+
@pytest.fixture
434+
def cls_method_fn_(self, request, cls_selector_fn_):
435+
return function_mock(
436+
request, 'docx.opc.package.cls_method_fn',
437+
return_value=cls_selector_fn_
438+
)
439+
433440
@pytest.fixture
434441
def cls_selector_fixture(
435-
self, request, cls_selector_fn_, partname_, content_type_,
436-
reltype_, blob_, package_, CustomPartClass_,
437-
part_of_custom_type_):
442+
self, request, cls_selector_fn_, cls_method_fn_, part_load_params,
443+
CustomPartClass_, part_of_custom_type_):
438444
def reset_part_class_selector():
439445
PartFactory.part_class_selector = original_part_class_selector
440446
original_part_class_selector = PartFactory.part_class_selector
441447
request.addfinalizer(reset_part_class_selector)
442448
return (
443-
cls_selector_fn_, partname_, content_type_, reltype_,
444-
blob_, package_, CustomPartClass_, part_of_custom_type_
449+
cls_selector_fn_, part_load_params, CustomPartClass_,
450+
part_of_custom_type_
445451
)
446452

447453
@pytest.fixture
448454
def cls_selector_fn_(self, request, CustomPartClass_):
449455
cls_selector_fn_ = loose_mock(request)
456+
# Python 3 version
457+
cls_selector_fn_.return_value = CustomPartClass_
458+
# Python 2 version
450459
cls_selector_fn_.__func__ = loose_mock(
451-
request, name='__func__', return_value=CustomPartClass_
460+
request, name='__func__', return_value=cls_selector_fn_
452461
)
453462
return cls_selector_fn_
454463

@@ -482,6 +491,11 @@ def package_(self, request):
482491
def package_2_(self, request):
483492
return instance_mock(request, OpcPackage)
484493

494+
@pytest.fixture
495+
def part_load_params(
496+
self, partname_, content_type_, reltype_, blob_, package_):
497+
return partname_, content_type_, reltype_, blob_, package_
498+
485499
@pytest.fixture
486500
def part_of_custom_type_(self, request):
487501
return instance_mock(request, Part)

tests/unitutil.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ def cls_attr_mock(request, cls, attr_name, name=None, **kwargs):
7070
return _patch.start()
7171

7272

73-
def function_mock(request, q_function_name):
73+
def function_mock(request, q_function_name, **kwargs):
7474
"""
7575
Return a mock patching the function with qualified name
7676
*q_function_name*. Patch is reversed after calling test returns.
7777
"""
78-
_patch = patch(q_function_name)
78+
_patch = patch(q_function_name, **kwargs)
7979
request.addfinalizer(_patch.stop)
8080
return _patch.start()
8181

0 commit comments

Comments
 (0)