From 3cb74665f7c9210a4df833e61d836f38b53603a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 22:09:23 +0000 Subject: [PATCH 01/20] Loader: extract `_classes_in` method --- mamba/loader.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mamba/loader.py b/mamba/loader.py index 56d2289..b13d710 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -22,7 +22,10 @@ def load_examples_from(self, module): return loaded def _example_groups_for(self, module): - return [klass for name, klass in inspect.getmembers(module, inspect.isclass) if self._is_example_group(name)] + return [klass for class_name, klass in self._classes_in(module) if self._is_example_group(class_name)] + + def _classes_in(self, module): + return inspect.getmembers(module, inspect.isclass) def _is_example_group(self, class_name): return class_name.endswith('__description') From c745163d6b916f0f935179530bead1be747a2ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 22:15:53 +0000 Subject: [PATCH 02/20] Loader: simplify subject retrieval The subject of an example group is either a class object or a string. The latter is only the case when the call to `getattr` returns the default vaule (the third argument given in the call). Hence we can chop the string just there instead of checking it later. --- mamba/loader.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index b13d710..25e0639 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -36,11 +36,11 @@ def _create_example_group(self, klass, execution_context=None): return ExampleGroup(self._subject(klass), execution_context=execution_context) def _subject(self, example_group): - subject = getattr(example_group, '_subject_class', example_group.__name__.replace('__description', '').replace('__pending', '')) - if isinstance(subject, str): - return subject[10:] - else: - return subject + return getattr( + example_group, + '_subject_class', + example_group.__name__.replace('__description', '').replace('__pending', '')[10:] + ) def _add_hooks_examples_and_nested_example_groups_to(self, klass, example_group): self._load_hooks(klass, example_group) From dc0f28f245b1696d501bf958314eb242993c4d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 22:19:52 +0000 Subject: [PATCH 03/20] Loader: extract computation of default subject to its own method --- mamba/loader.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mamba/loader.py b/mamba/loader.py index 25e0639..4574e06 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -39,9 +39,12 @@ def _subject(self, example_group): return getattr( example_group, '_subject_class', - example_group.__name__.replace('__description', '').replace('__pending', '')[10:] + self._generate_default_subject(example_group) ) + def _generate_default_subject(self, example_group): + return example_group.__name__.replace('__description', '').replace('__pending', '')[10:] + def _add_hooks_examples_and_nested_example_groups_to(self, klass, example_group): self._load_hooks(klass, example_group) self._load_examples(klass, example_group) From 0983fe9bb4dd6051af9793690b9372bf23b3e27b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 22:30:51 +0000 Subject: [PATCH 04/20] Loader: move `_methods_for` closer to its first usage and rename it to `_methods_in` for consistency with similar methods --- mamba/loader.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 4574e06..eece4fa 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -56,7 +56,10 @@ def _load_hooks(self, klass, example_group): example_group.hooks[hook.__name__].append(hook) def _hooks_in(self, example_group): - return [method for name, method in self._methods_for(example_group) if self._is_hook(name)] + return [method for name, method in self._methods_in(example_group) if self._is_hook(name)] + + def _methods_in(self, klass): + return inspect.getmembers(klass, inspect.isfunction if is_python3() else inspect.ismethod) def _is_hook(self, method_name): return method_name.startswith('before') or method_name.startswith('after') @@ -69,10 +72,7 @@ def _load_examples(self, klass, example_group): example_group.append(Example(example)) def _examples_in(self, example_group): - return [method for name, method in self._methods_for(example_group) if self._is_example(method)] - - def _methods_for(self, klass): - return inspect.getmembers(klass, inspect.isfunction if is_python3() else inspect.ismethod) + return [method for name, method in self._methods_in(example_group) if self._is_example(method)] def _is_example(self, method): return method.__name__[10:].startswith('it') or self._is_pending_example(method) @@ -94,7 +94,7 @@ def _load_nested_example_groups(self, klass, example_group): example_group.append(nested_example_group) def _load_helper_methods_to_execution_context(self, klass, execution_context): - helper_methods = [method for name, method in self._methods_for(klass) if not self._is_example(method)] + helper_methods = [method for name, method in self._methods_in(klass) if not self._is_example(method)] for method in helper_methods: if is_python3(): From 0203e329f3990cb7b5dd31cff61a6278eb858e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 22:43:51 +0000 Subject: [PATCH 05/20] Loader: rename three methods to better reflect their intentions _example_groups_for -> _top_level_classes_in: at the beginning, top-level classes are extracted, from either module objects or class objects themselves (in the case of nested examples). But they are not example groups yet. _is_example_group -> _is_name_of_example_group: the parameter is expected to be a string, hence it's not really a candidate for an example group. It's a name of something, and the method determines whether that something is an example group. _is_hook -> _is_name_of_hook: same as above. --- mamba/loader.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index eece4fa..3f1d94b 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -11,9 +11,9 @@ class Loader(object): def load_examples_from(self, module): loaded = [] - example_groups = self._example_groups_for(module) + top_level_classes = self._top_level_classes_in(module) - for klass in example_groups: + for klass in top_level_classes: example_group = self._create_example_group(klass) self._add_hooks_examples_and_nested_example_groups_to(klass, example_group) @@ -21,13 +21,13 @@ def load_examples_from(self, module): return loaded - def _example_groups_for(self, module): - return [klass for class_name, klass in self._classes_in(module) if self._is_example_group(class_name)] + def _top_level_classes_in(self, an_object): + return [klass for class_name, klass in self._classes_in(an_object) if self._is_name_of_example_group(class_name)] - def _classes_in(self, module): - return inspect.getmembers(module, inspect.isclass) + def _classes_in(self, an_object): + return inspect.getmembers(an_object, inspect.isclass) - def _is_example_group(self, class_name): + def _is_name_of_example_group(self, class_name): return class_name.endswith('__description') def _create_example_group(self, klass, execution_context=None): @@ -56,12 +56,12 @@ def _load_hooks(self, klass, example_group): example_group.hooks[hook.__name__].append(hook) def _hooks_in(self, example_group): - return [method for name, method in self._methods_in(example_group) if self._is_hook(name)] + return [method for name, method in self._methods_in(example_group) if self._is_name_of_hook(name)] def _methods_in(self, klass): return inspect.getmembers(klass, inspect.isfunction if is_python3() else inspect.ismethod) - def _is_hook(self, method_name): + def _is_name_of_hook(self, method_name): return method_name.startswith('before') or method_name.startswith('after') def _load_examples(self, klass, example_group): @@ -84,7 +84,7 @@ def _is_pending_example_group(self, example_group): return isinstance(example_group, PendingExampleGroup) def _load_nested_example_groups(self, klass, example_group): - for nested in self._example_groups_for(klass): + for nested in self._top_level_classes_in(klass): if isinstance(example_group, PendingExampleGroup): nested_example_group = PendingExampleGroup(self._subject(nested), execution_context=example_group.execution_context) else: From 25d7d018a67accfb372695e2b9bb8001135cd9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 23:44:31 +0000 Subject: [PATCH 06/20] Loader: rename `nested` to `nested_klass` to align with the rest of the code The fact that these classes are nested within klass is reflected in the call to _top_level_classes_in(klass). --- mamba/loader.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 3f1d94b..8a461dd 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -84,13 +84,13 @@ def _is_pending_example_group(self, example_group): return isinstance(example_group, PendingExampleGroup) def _load_nested_example_groups(self, klass, example_group): - for nested in self._top_level_classes_in(klass): + for nested_class in self._top_level_classes_in(klass): if isinstance(example_group, PendingExampleGroup): - nested_example_group = PendingExampleGroup(self._subject(nested), execution_context=example_group.execution_context) + nested_example_group = PendingExampleGroup(self._subject(nested_class), execution_context=example_group.execution_context) else: - nested_example_group = self._create_example_group(nested, execution_context=example_group.execution_context) + nested_example_group = self._create_example_group(nested_class, execution_context=example_group.execution_context) - self._add_hooks_examples_and_nested_example_groups_to(nested, nested_example_group) + self._add_hooks_examples_and_nested_example_groups_to(nested_class, nested_example_group) example_group.append(nested_example_group) def _load_helper_methods_to_execution_context(self, klass, execution_context): From 688dc4b7a0c0bf9c4d5fae4cf2c37398e7437da8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Sun, 6 Dec 2015 23:52:39 +0000 Subject: [PATCH 07/20] Loader: use `_is_pending_example_method` instead of having it inlined --- mamba/loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mamba/loader.py b/mamba/loader.py index 8a461dd..fe30c02 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -85,7 +85,7 @@ def _is_pending_example_group(self, example_group): def _load_nested_example_groups(self, klass, example_group): for nested_class in self._top_level_classes_in(klass): - if isinstance(example_group, PendingExampleGroup): + if self._is_pending_example_group(example_group): nested_example_group = PendingExampleGroup(self._subject(nested_class), execution_context=example_group.execution_context) else: nested_example_group = self._create_example_group(nested_class, execution_context=example_group.execution_context) From 74b4034b95f51532e56a35e707c444111c63385c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Mon, 7 Dec 2015 00:03:03 +0000 Subject: [PATCH 08/20] Loader: extract method from `_load_helper_methods_to_execution_context` This gives that method more symmetry with respect to the all other operations in the class. This also extracts another method from the extracted method, for more clearly stating what a helper method is. --- mamba/loader.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index fe30c02..c12d931 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -94,11 +94,15 @@ def _load_nested_example_groups(self, klass, example_group): example_group.append(nested_example_group) def _load_helper_methods_to_execution_context(self, klass, execution_context): - helper_methods = [method for name, method in self._methods_in(klass) if not self._is_example(method)] - - for method in helper_methods: + for method in self._helper_methods_in(klass): if is_python3(): setattr(execution_context, method.__name__, types.MethodType(method, execution_context)) else: setattr(execution_context, method.__name__, types.MethodType(method.im_func, execution_context, execution_context.__class__)) + def _helper_methods_in(self, klass): + return [method for name, method in self._methods_in(klass) if self._is_helper_method(method)] + + def _is_helper_method(self, method): + return not self._is_example(method) + From 2a516878c9c2483ccab646fdbf35cd90b0c78510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Mon, 7 Dec 2015 00:12:28 +0000 Subject: [PATCH 09/20] Loader: extract anotheranother method from `_load_helper_methods_to_execution_context` and bury Python version check --- mamba/loader.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index c12d931..119b8b3 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -94,11 +94,8 @@ def _load_nested_example_groups(self, klass, example_group): example_group.append(nested_example_group) def _load_helper_methods_to_execution_context(self, klass, execution_context): - for method in self._helper_methods_in(klass): - if is_python3(): - setattr(execution_context, method.__name__, types.MethodType(method, execution_context)) - else: - setattr(execution_context, method.__name__, types.MethodType(method.im_func, execution_context, execution_context.__class__)) + for helper_method in self._helper_methods_in(klass): + self._add_method_to_execution_context(helper_method, execution_context) def _helper_methods_in(self, klass): return [method for name, method in self._methods_in(klass) if self._is_helper_method(method)] @@ -106,3 +103,11 @@ def _helper_methods_in(self, klass): def _is_helper_method(self, method): return not self._is_example(method) + def _add_method_to_execution_context(self, method, execution_context): + setattr(execution_context, method.__name__, self._create_method_bound_to_object(method, execution_context)) + + def _create_method_bound_to_object(self, method, an_object): + if is_python3(): + return types.MethodType(method, an_object) + else: + return types.MethodType(method.im_func, an_object, an_object.__class__) From 68e8573ffb46975af0b8ba7b2cbc54ccb04a874d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Mon, 7 Dec 2015 00:21:08 +0000 Subject: [PATCH 10/20] Loader: rename parameter `example_group` to `klass` This delimits the boundary of the 'dichotomy' between classes and example groups, and makes all related query methods in the class have a similar signature. --- mamba/loader.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 119b8b3..e387bbc 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -55,8 +55,8 @@ def _load_hooks(self, klass, example_group): for hook in self._hooks_in(klass): example_group.hooks[hook.__name__].append(hook) - def _hooks_in(self, example_group): - return [method for name, method in self._methods_in(example_group) if self._is_name_of_hook(name)] + def _hooks_in(self, klass): + return [method for name, method in self._methods_in(klass) if self._is_name_of_hook(name)] def _methods_in(self, klass): return inspect.getmembers(klass, inspect.isfunction if is_python3() else inspect.ismethod) @@ -71,8 +71,8 @@ def _load_examples(self, klass, example_group): else: example_group.append(Example(example)) - def _examples_in(self, example_group): - return [method for name, method in self._methods_in(example_group) if self._is_example(method)] + def _examples_in(self, klass): + return [method for name, method in self._methods_in(klass) if self._is_example(method)] def _is_example(self, method): return method.__name__[10:].startswith('it') or self._is_pending_example(method) From 0afaaf37df8013ba015a01cf43808aa02d77b75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Mon, 7 Dec 2015 00:26:13 +0000 Subject: [PATCH 11/20] Loader: remove superfluous local variable The name of the method being called is more descriptive. --- mamba/loader.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index e387bbc..8b43305 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -11,9 +11,8 @@ class Loader(object): def load_examples_from(self, module): loaded = [] - top_level_classes = self._top_level_classes_in(module) - for klass in top_level_classes: + for klass in self._top_level_classes_in(module): example_group = self._create_example_group(klass) self._add_hooks_examples_and_nested_example_groups_to(klass, example_group) From 0ebd84c0dd738224ce859ca9f0a764428850ffcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Wed, 16 Dec 2015 23:31:57 +0000 Subject: [PATCH 12/20] Loader: make _create_example_group higher-level This also makes it a bit more explicit that instantiating an ExampleGroup doesn't add examples, hooks or nested examples to it. --- mamba/loader.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 8b43305..edde545 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -10,26 +10,18 @@ class Loader(object): def load_examples_from(self, module): - loaded = [] + return [ + self._create_example_group(klass) + for klass in self._top_level_classes_in(module) + ] - for klass in self._top_level_classes_in(module): - example_group = self._create_example_group(klass) - self._add_hooks_examples_and_nested_example_groups_to(klass, example_group) + def _create_example_group(self, klass): + example_group = self._create_bare_example_group(klass) + self._add_hooks_examples_and_nested_example_groups_to(klass, example_group) - loaded.append(example_group) + return example_group - return loaded - - def _top_level_classes_in(self, an_object): - return [klass for class_name, klass in self._classes_in(an_object) if self._is_name_of_example_group(class_name)] - - def _classes_in(self, an_object): - return inspect.getmembers(an_object, inspect.isclass) - - def _is_name_of_example_group(self, class_name): - return class_name.endswith('__description') - - def _create_example_group(self, klass, execution_context=None): + def _create_bare_example_group(self, klass, execution_context=None): if '__pending' in klass.__name__: return PendingExampleGroup(self._subject(klass), execution_context=execution_context) return ExampleGroup(self._subject(klass), execution_context=execution_context) @@ -87,7 +79,7 @@ def _load_nested_example_groups(self, klass, example_group): if self._is_pending_example_group(example_group): nested_example_group = PendingExampleGroup(self._subject(nested_class), execution_context=example_group.execution_context) else: - nested_example_group = self._create_example_group(nested_class, execution_context=example_group.execution_context) + nested_example_group = self._create_bare_example_group(nested_class, execution_context=example_group.execution_context) self._add_hooks_examples_and_nested_example_groups_to(nested_class, nested_example_group) example_group.append(nested_example_group) @@ -110,3 +102,12 @@ def _create_method_bound_to_object(self, method, an_object): return types.MethodType(method, an_object) else: return types.MethodType(method.im_func, an_object, an_object.__class__) + + def _top_level_classes_in(self, an_object): + return [klass for class_name, klass in self._classes_in(an_object) if self._is_name_of_example_group(class_name)] + + def _classes_in(self, an_object): + return inspect.getmembers(an_object, inspect.isclass) + + def _is_name_of_example_group(self, class_name): + return class_name.endswith('__description') From 994a9df52f8f8b329d31b81d2a760e3cb30b2ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Wed, 16 Dec 2015 23:34:25 +0000 Subject: [PATCH 13/20] Loader: rename _subject()'s parameters to clarify that it receives a class, not an example group --- mamba/loader.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index edde545..35086bf 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -26,15 +26,15 @@ def _create_bare_example_group(self, klass, execution_context=None): return PendingExampleGroup(self._subject(klass), execution_context=execution_context) return ExampleGroup(self._subject(klass), execution_context=execution_context) - def _subject(self, example_group): + def _subject(self, klass): return getattr( - example_group, + klass, '_subject_class', - self._generate_default_subject(example_group) + self._generate_default_subject(klass) ) - def _generate_default_subject(self, example_group): - return example_group.__name__.replace('__description', '').replace('__pending', '')[10:] + def _generate_default_subject(self, klass): + return klass.__name__.replace('__description', '').replace('__pending', '')[10:] def _add_hooks_examples_and_nested_example_groups_to(self, klass, example_group): self._load_hooks(klass, example_group) From 3a1dab1ba058e04f70819a9150726c92096a0340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Wed, 16 Dec 2015 23:36:09 +0000 Subject: [PATCH 14/20] Loader: _subject -> _subject_of --- mamba/loader.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 35086bf..16fd590 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -23,10 +23,10 @@ def _create_example_group(self, klass): def _create_bare_example_group(self, klass, execution_context=None): if '__pending' in klass.__name__: - return PendingExampleGroup(self._subject(klass), execution_context=execution_context) - return ExampleGroup(self._subject(klass), execution_context=execution_context) + return PendingExampleGroup(self._subject_of(klass), execution_context=execution_context) + return ExampleGroup(self._subject_of(klass), execution_context=execution_context) - def _subject(self, klass): + def _subject_of(self, klass): return getattr( klass, '_subject_class', @@ -77,7 +77,7 @@ def _is_pending_example_group(self, example_group): def _load_nested_example_groups(self, klass, example_group): for nested_class in self._top_level_classes_in(klass): if self._is_pending_example_group(example_group): - nested_example_group = PendingExampleGroup(self._subject(nested_class), execution_context=example_group.execution_context) + nested_example_group = PendingExampleGroup(self._subject_of(nested_class), execution_context=example_group.execution_context) else: nested_example_group = self._create_bare_example_group(nested_class, execution_context=example_group.execution_context) From a3938a2b43c76343e5a3d5425d3e233798eeff15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Wed, 16 Dec 2015 23:52:51 +0000 Subject: [PATCH 15/20] Loader: uniformize names of methods checking for names of objects This makes the remaining ones match the signatures of the previously refactored ones: since we're looking at the name, receive only the name, and make that clear in the name of the method. --- mamba/loader.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 16fd590..095cb26 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -57,19 +57,19 @@ def _is_name_of_hook(self, method_name): def _load_examples(self, klass, example_group): for example in self._examples_in(klass): - if self._is_pending_example(example) or self._is_pending_example_group(example_group): + if self._is_name_of_pending_example(example.__name__) or self._is_pending_example_group(example_group): example_group.append(PendingExample(example)) else: example_group.append(Example(example)) def _examples_in(self, klass): - return [method for name, method in self._methods_in(klass) if self._is_example(method)] + return [method for name, method in self._methods_in(klass) if self._is_name_of_example(name)] - def _is_example(self, method): - return method.__name__[10:].startswith('it') or self._is_pending_example(method) + def _is_name_of_example(self, name): + return name[10:].startswith('it') or self._is_name_of_pending_example(name) - def _is_pending_example(self, example): - return example.__name__[10:].startswith('_it') + def _is_name_of_pending_example(self, name): + return name[10:].startswith('_it') def _is_pending_example_group(self, example_group): return isinstance(example_group, PendingExampleGroup) @@ -89,10 +89,10 @@ def _load_helper_methods_to_execution_context(self, klass, execution_context): self._add_method_to_execution_context(helper_method, execution_context) def _helper_methods_in(self, klass): - return [method for name, method in self._methods_in(klass) if self._is_helper_method(method)] + return [method for name, method in self._methods_in(klass) if self._is_name_of_helper_method(name)] - def _is_helper_method(self, method): - return not self._is_example(method) + def _is_name_of_helper_method(self, name): + return not self._is_name_of_example(name) def _add_method_to_execution_context(self, method, execution_context): setattr(execution_context, method.__name__, self._create_method_bound_to_object(method, execution_context)) From c57aa23885a698cf234c040b5ba10ae6fbe2a2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Wed, 16 Dec 2015 23:58:24 +0000 Subject: [PATCH 16/20] Loader: _examples_in -> _methods_representing_examples_in This makes clearer that this method doesn't return `Example`s but methods, which it uses to create the `Example`s. --- mamba/loader.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 095cb26..2c40e51 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -56,13 +56,13 @@ def _is_name_of_hook(self, method_name): return method_name.startswith('before') or method_name.startswith('after') def _load_examples(self, klass, example_group): - for example in self._examples_in(klass): - if self._is_name_of_pending_example(example.__name__) or self._is_pending_example_group(example_group): - example_group.append(PendingExample(example)) + for method in self._methods_representing_examples_in(klass): + if self._is_name_of_pending_example(method.__name__) or self._is_pending_example_group(example_group): + example_group.append(PendingExample(method)) else: - example_group.append(Example(example)) + example_group.append(Example(method)) - def _examples_in(self, klass): + def _methods_representing_examples_in(self, klass): return [method for name, method in self._methods_in(klass) if self._is_name_of_example(name)] def _is_name_of_example(self, name): From 014bee92494838a3092d537252770917a18e5492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Thu, 17 Dec 2015 00:07:59 +0000 Subject: [PATCH 17/20] Loader: remove unnecessary pass-by-keyword syntax usage This is unnecessary because _create_bare_example_group only takes two parameters and it's almost always called with an explicit second parameter. --- mamba/loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 2c40e51..8eec8cc 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -77,9 +77,9 @@ def _is_pending_example_group(self, example_group): def _load_nested_example_groups(self, klass, example_group): for nested_class in self._top_level_classes_in(klass): if self._is_pending_example_group(example_group): - nested_example_group = PendingExampleGroup(self._subject_of(nested_class), execution_context=example_group.execution_context) + nested_example_group = PendingExampleGroup(self._subject_of(nested_class), example_group.execution_context) else: - nested_example_group = self._create_bare_example_group(nested_class, execution_context=example_group.execution_context) + nested_example_group = self._create_bare_example_group(nested_class, example_group.execution_context) self._add_hooks_examples_and_nested_example_groups_to(nested_class, nested_example_group) example_group.append(nested_example_group) From 3267db09697af4d3ded8183ded2159f17ea1aac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Thu, 17 Dec 2015 00:12:03 +0000 Subject: [PATCH 18/20] Loaer: reorder methods to match reading order --- mamba/loader.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 8eec8cc..dccb07b 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -84,6 +84,15 @@ def _load_nested_example_groups(self, klass, example_group): self._add_hooks_examples_and_nested_example_groups_to(nested_class, nested_example_group) example_group.append(nested_example_group) + def _top_level_classes_in(self, an_object): + return [klass for class_name, klass in self._classes_in(an_object) if self._is_name_of_example_group(class_name)] + + def _classes_in(self, an_object): + return inspect.getmembers(an_object, inspect.isclass) + + def _is_name_of_example_group(self, class_name): + return class_name.endswith('__description') + def _load_helper_methods_to_execution_context(self, klass, execution_context): for helper_method in self._helper_methods_in(klass): self._add_method_to_execution_context(helper_method, execution_context) @@ -102,12 +111,3 @@ def _create_method_bound_to_object(self, method, an_object): return types.MethodType(method, an_object) else: return types.MethodType(method.im_func, an_object, an_object.__class__) - - def _top_level_classes_in(self, an_object): - return [klass for class_name, klass in self._classes_in(an_object) if self._is_name_of_example_group(class_name)] - - def _classes_in(self, an_object): - return inspect.getmembers(an_object, inspect.isclass) - - def _is_name_of_example_group(self, class_name): - return class_name.endswith('__description') From 110c499dc49d38245806328b789d3fe952b90593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Thu, 17 Dec 2015 00:13:14 +0000 Subject: [PATCH 19/20] Loaer: class_name -> name This is the way the other methods querying names are naming their parameters. The fact that it's the name of a class is irrelvant to `_is_name_of_example_group`. --- mamba/loader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index dccb07b..1ba1e3a 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -85,13 +85,13 @@ def _load_nested_example_groups(self, klass, example_group): example_group.append(nested_example_group) def _top_level_classes_in(self, an_object): - return [klass for class_name, klass in self._classes_in(an_object) if self._is_name_of_example_group(class_name)] + return [klass for name, klass in self._classes_in(an_object) if self._is_name_of_example_group(name)] def _classes_in(self, an_object): return inspect.getmembers(an_object, inspect.isclass) - def _is_name_of_example_group(self, class_name): - return class_name.endswith('__description') + def _is_name_of_example_group(self, name): + return name.endswith('__description') def _load_helper_methods_to_execution_context(self, klass, execution_context): for helper_method in self._helper_methods_in(klass): From c7f9170db973640aa2154f4133236eaa83ab3314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Wed, 23 Dec 2015 00:20:59 +0100 Subject: [PATCH 20/20] Loader: refactor to remove 'else' clause --- mamba/loader.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mamba/loader.py b/mamba/loader.py index 1ba1e3a..a7fe38d 100644 --- a/mamba/loader.py +++ b/mamba/loader.py @@ -109,5 +109,4 @@ def _add_method_to_execution_context(self, method, execution_context): def _create_method_bound_to_object(self, method, an_object): if is_python3(): return types.MethodType(method, an_object) - else: - return types.MethodType(method.im_func, an_object, an_object.__class__) + return types.MethodType(method.im_func, an_object, an_object.__class__)