Skip to content

Commit

Permalink
grants special refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielfalcao committed Dec 27, 2023
1 parent 82395e2 commit 3b7b868
Show file tree
Hide file tree
Showing 25 changed files with 190 additions and 186 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [v3.0.0]
- Sure's featured synctactic-sugar of injecting/monkey-patching
``.should``, ``.should_not``, et cetera methods into
:py:class:`object` and its subclasses is disabled by default and needs to be enabled explicitly, programmatically via ``sure.enable_magic_syntax()`` or via command-line with the flags: ``-s`` or ``--syntax-magic``
:py:class:`object` and its subclasses is disabled by default and needs to be enabled explicitly, programmatically via ``sure.enable_special_syntax()`` or via command-line with the flags: ``-s`` or ``--special-syntax``

## [v2.0.0]
### Fixed
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ test tests: clean | $(VENV)/bin/pytest # $(VENV)/bin/nosetests # @$(VENV)/bin/no

# run main command-line tool
run: | $(MAIN_CLI_PATH)
# $(MAIN_CLI_PATH) --syntax-magic --with-coverage --cover-branches --cover-module=sure.core tests/
# $(MAIN_CLI_PATH) --syntax-magic --with-coverage --cover-branches --cover-module=sure.core --immediate
# $(MAIN_CLI_PATH) --syntax-magic --with-coverage --cover-branches --cover-module=sure.core --cover-module=sure tests/runner/
$(MAIN_CLI_PATH) --syntax-magic --with-coverage --cover-branches --cover-module=sure.runtime tests/unit/
# $(MAIN_CLI_PATH) --special-syntax --with-coverage --cover-branches --cover-module=sure.core tests/
# $(MAIN_CLI_PATH) --special-syntax --with-coverage --cover-branches --cover-module=sure.core --immediate
# $(MAIN_CLI_PATH) --special-syntax --with-coverage --cover-branches --cover-module=sure.runtime tests/unit/
$(MAIN_CLI_PATH) --special-syntax --with-coverage --cover-branches --cover-module=sure.core --cover-module=sure tests/runner/

# Pushes release of this package to pypi
push-release: dist # pushes distribution tarballs of the current version
Expand Down
8 changes: 4 additions & 4 deletions docs/source/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ Differently of `ruby <http://www.ruby-lang.org>`__ python doesn't have
`open classes
<http://blog.aizatto.com/2007/06/01/ruby-and-open-classes/>`__, but
`sure uses a technique
<https://github.com/gabrielfalcao/sure/blob/master/sure/magic.py>`_
<https://github.com/gabrielfalcao/sure/blob/master/sure/special.py>`_
involving the module :py:mod:`ctypes` to write directly in the private
``__dict__`` of in-memory objects.
For more information check out the `Forbidden Fruit <https://github.com/clarete/forbiddenfruit>`_ project.
Expand Down Expand Up @@ -879,7 +879,7 @@ Use the ``chainproperty`` decorator like the following to build your own *chain*
class Foo:
magic = 42
special = 42
@chainproperty
Expand All @@ -903,8 +903,8 @@ Use the ``chainproperty`` decorator like the following to build your own *chain*
self.obj, name)
# Build awesome assertion chains
expect(Foo).having.attribute('magic')
Foo.doesnt.implement.attribute('nomagic')
expect(Foo).having.attribute('special')
Foo.doesnt.implement.attribute('nospecial')
Use custom assertion messages with ``ensure``
---------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions docs/source/how-it-works.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ actually challenged Lincoln to do try and do so.

As Gabriel imagined, it wouldn't take long for Lincoln Clarete to
achieve that goal, he then presently wrote most if not all the code
currently present inside :py:mod:`sure.magic` and also took the idea
currently present inside :py:mod:`sure.special` and also took the idea
forward and evolvend it, ultimately resulting in the publishing of the
Python Package `forbidden fruit
<http://clarete.github.io/forbiddenfruit/>`_.

The only catch is that the functionallity inside :py:mod:`sure.magic`
The only catch is that the functionallity inside :py:mod:`sure.special`
is primarily guaranteed to work only with CPython, the original
implementation of Python in the C programming language.

Expand Down
4 changes: 2 additions & 2 deletions examples/unit-tests/behavior_definition_simplify_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
# Notes:
# ~~~~~
#
# * the following methods require exactly one positional argument: ``mock_name``, otherwise: ``raise AssertionError("self.mock.simple() and self.mock.magic() require one positional argument: its name.")``
# * the following methods require exactly one positional argument: ``mock_name``, otherwise: ``raise AssertionError("self.mock.simple() and self.mock.special() require one positional argument: its name.")``
# * ``self.mock.simple()``
# * ``self.mock.magic()``
# * ``self.mock.special()``
# * self.mock.install() forwards keyword-arguments to ``mock.patch``, for example:
# * ``self.mock.install('myapp.api.http.db.engine.connect', return_value='DUMMY_CONNECTION')
# * ``self.mock.install('myapp.api.http.db.engine.connect', return_value='DUMMY_CONNECTION')
Expand Down
22 changes: 15 additions & 7 deletions sure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals

import re
import os
import sys
Expand All @@ -42,7 +40,7 @@
from sure.core import safe_repr
from sure.core import anything # noqa

from sure.magic import is_cpython, patchable_builtin
from sure.special import is_cpython, patchable_builtin
from sure.registry import context as _registry
import sure.reporters

Expand Down Expand Up @@ -483,11 +481,21 @@ def __init__(
self._name = name
self.negative = negative

self.obj = obj
self._obj = obj
self._callable_args = callable_args or []
self._callable_kw = callable_kw or {}
self._that = AssertionHelper(self.obj)

def get_obj(self):
if isinstance(self._obj, AssertionBuilder):
return self._obj.obj
return self._obj

def set_obj(self, obj):
self._obj = obj

obj = property(get_obj, set_obj)

def __call__(self, obj):
self.obj = obj

Expand Down Expand Up @@ -1143,7 +1151,7 @@ def method(self):
old_dir = dir


def enable_magic_syntax():
def enable_special_syntax():
@wraps(builtins.dir)
def _new_dir(*obj):
if not obj:
Expand Down Expand Up @@ -1175,7 +1183,7 @@ def _new_dir(*obj):
do_enable()


enable = enable_magic_syntax
enable = enable_special_syntax

if is_cpython and allows_new_syntax:
enable_magic_syntax()
enable_special_syntax()
8 changes: 4 additions & 4 deletions sure/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
@click.option("-i", "--immediate", is_flag=True)
@click.option("-l", "--log-level", type=click.Choice(['none', 'debug', 'info', 'warning', 'error']), help="default='none'")
@click.option("-F", "--log-file", help='path to a log file. Default to SURE_LOG_FILE')
@click.option("-s", "--syntax-magic", is_flag=True)
@click.option("-s", "--special-syntax", is_flag=True)
@click.option("-c", "--with-coverage", is_flag=True)
@click.option("--cover-branches", is_flag=True)
@click.option("--cover-module", multiple=True, help="specify module names to cover")
def entrypoint(paths, reporter, immediate, log_level, log_file, syntax_magic, with_coverage, cover_branches, cover_module):
def entrypoint(paths, reporter, immediate, log_level, log_file, special_syntax, with_coverage, cover_branches, cover_module):
if not paths:
paths = glob('test*/**')
else:
Expand All @@ -66,8 +66,8 @@ def entrypoint(paths, reporter, immediate, log_level, log_file, syntax_magic, wi
cov.load()
cov.start()

if syntax_magic:
sure.enable_magic_syntax()
if special_syntax:
sure.enable_special_syntax()

runner = Runner(resolve_path(os.getcwd()), reporter)
try:
Expand Down
32 changes: 1 addition & 31 deletions sure/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
from __future__ import unicode_literals

import six
from collections import OrderedDict

try:
from collections.abc import Iterable
except ImportError:
from collections import Iterable

from sure.terminal import red, green, yellow
from sure.doubles import FakeOrderedDict


if six.PY2:
Expand Down Expand Up @@ -39,36 +39,6 @@ def compat_repr(object_repr):
def compat_repr(object_repr):
return object_repr

# FIXME: move FakeOrderedDict to another module since it
# does not have anything todo with compat.
# The safe_repr function should already get a
# FakeOrderedDict instance. Maybe the _obj_with_safe_repr
# function should be part of the FakeOrderedDict
# classes __repr__ method.
class FakeOrderedDict(OrderedDict):
""" OrderedDict that has the repr of a normal dict
We must return a string whether in py2 or py3.
"""
def __unicode__(self):
if not self:
return '{}'
key_values = []
for key, value in self.items():
key, value = repr(key), repr(value)
if isinstance(value, six.binary_type) and six.PY2:
value = value.decode("utf-8")
key_values.append("{0}: {1}".format(key, value))
res = "{{{0}}}".format(", ".join(key_values))
return res

if six.PY2:
def __repr__(self):
return self.__unicode__().encode('utf-8')
else:
def __repr__(self):
return self.__unicode__()


def _obj_with_safe_repr(obj):
if isinstance(obj, dict):
Expand Down
4 changes: 3 additions & 1 deletion sure/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@
from mock.mock import _CallList

import inspect

from collections import OrderedDict
from six import (
text_type, integer_types, string_types, binary_type,
get_function_code
)

from sure.terminal import red, green, yellow
from sure.compat import safe_repr, OrderedDict
from sure.compat import safe_repr


class Anything(object):
Expand Down
22 changes: 22 additions & 0 deletions sure/doubles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Sure's own Test-Doubles"""
from collections import OrderedDict


class FakeOrderedDict(OrderedDict):
""" OrderedDict that has the repr of a normal dict
We must return a string whether in py2 or py3.
"""
def __str__(self):
if len(self) == 0:
return '{}'
key_values = []
for key, value in self.items():
key, value = repr(key), repr(value)
key_values.append("{0}: {1}".format(key, value))

res = "{{{0}}}".format(", ".join(key_values))
return res

def __repr__(self):
return self.__str__()
2 changes: 1 addition & 1 deletion sure/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def traverse_to_package(cls, path):
module_is_artificial = path.parent.joinpath('__init__.py').exists()
module_name = path.parent.name
if not module_is_artificial:
relative = str(path.relative_to(root.parent))
relative = str(path.relative_to(package.parent))
module_name = os.path.splitext(relative)[0].replace(os.sep, '.')

spec = importlib.util.spec_from_file_location(module_name, path)
Expand Down
1 change: 0 additions & 1 deletion sure/meta.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# <sure - utility belt for automated testing in python>
# Copyright (C) <2010-2023> Gabriel Falcão <gabriel@nacaolivre.org>
Expand Down
2 changes: 1 addition & 1 deletion sure/original.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""original module from sure's inception prior to the creation of :py:mod:`sure.magic`"""
"""original module from sure's inception prior to the creation of :py:mod:`sure.special`"""
import os
import re
import traceback
Expand Down
5 changes: 2 additions & 3 deletions sure/reporter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# <sure - utility belt for automated testing in python>
# Copyright (C) <2010-2023> Gabriel Falcão <gabriel@nacaolivre.org>
Expand Down Expand Up @@ -145,7 +144,7 @@ class test_done:
"""
raise NotImplementedError

def on_failure(self, scenario, error):
def on_failure(self, scenario_result, error):
"""Called when a scenario fails without crashing
.. code:: python
Expand Down Expand Up @@ -196,7 +195,7 @@ def on_internal_runtime_error(self, scenario):
"""
raise NotImplementedError

def on_error(self, scenario, error):
def on_error(self, scenario_result, error):
"""Called when a scenario fails with exception
.. code:: python
Expand Down
20 changes: 10 additions & 10 deletions sure/reporters/feature.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# <sure - utility belt for automated testing in python>
# Copyright (C) <2010-2023> Gabriel Falcão <gabriel@nacaolivre.org>
Expand Down Expand Up @@ -78,23 +77,18 @@ def on_success(self, test):
sh.green(checkmark)
sh.reset("\n")

def on_error(self, test, error):
def on_error(self, test, result):
self.errors.append(test)
self.failures.append(test)
self.indentation += 2
sh.red(ballot)
sh.reset("\n")
sh.bold_red(f"Error started at {result.location.ort}\n")
sh.bold_red(f"{result.stack.nonlocation_specific_error()}")
sh.bold_red(f"{' ' * self.indentation}{result.error}")
sh.reset(" " * self.indentation)
sh.bold_red(" ".join(error.args))
sh.reset("\n")
self.indentation -= 2

def on_internal_runtime_error(self, context, error):
sh = Shell()
sh.bold_yellow("Internal Runtime Error\n")
sh.bold_red(error.traceback)
raise SystemExit(error.code)

def on_finish(self):
failed = len(self.failures)
errors = len(self.errors)
Expand All @@ -112,3 +106,9 @@ def on_finish(self):
sh.green(f"{successful} successful")
sh.reset("\n")
sh.reset(" ")

def on_internal_runtime_error(self, context, error):
sh = Shell()
sh.bold_yellow("Internal Runtime Error\n")
sh.bold_red(error.traceback)
raise SystemExit(error.code)
1 change: 0 additions & 1 deletion sure/reporters/logs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# <sure - utility belt for automated testing in python>
# Copyright (C) <2010-2023> Gabriel Falcão <gabriel@nacaolivre.org>
Expand Down

0 comments on commit 3b7b868

Please sign in to comment.