Giter VIP home page Giter VIP logo

pymox's People

pymox's Issues

IgnoreArgs

sometimes i really don't want to care about any of the args.  afaict the only 
way to do this is multiple mox.IgnoreArg() arguments, that's silly.  allow 
mox.IgnoreArgs() to just ignore all args so we're not testing things we don't 
care to test (e.g. how many args are sent to our logging function!)

Original issue reported on code.google.com by [email protected] on 28 Jun 2010 at 8:03

StubOutWithMock does work if used more than twice

What steps will reproduce the problem?
1. Use StubOutWithMock() to mock a module in 3 separate tests.

What is the expected output?
All tests to pass

What do you see instead?

Traceback (most recent call last):
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/pydevd.
py",
line 583, in trace_dispatch
    filename, base = pydevd_file_utils.GetFilenameAndBase(frame)
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/pydevd_
file_utils.py",
line 141, in GetFilenameAndBase
    filename = _NormFile(f)
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/pydevd_
file_utils.py",
line 73, in _NormFile
    rPath = os.path.abspath
  File "/local/devel/PhotoMap2/test/mox.py", line 414, in __getattr__
Traceback (most recent call last):
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/pydevd.
py",
line 852, in <module>
    debugger.run(setup['file'], None, None)
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/pydevd.
py",
line 689, in run
    execfile(file, globals, locals) #execute the script
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/runfile
s.py",
line 246, in <module>
    PydevTestRunner(dirs, test_filter, verbosity).run_tests()
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/runfile
s.py",
line 238, in run_tests
    runner.run(unittest.TestSuite(all_tests))
  File "/usr/lib64/python2.5/unittest.py", line 705, in run
    test(result)
  File "/usr/lib64/python2.5/unittest.py", line 437, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib64/python2.5/unittest.py", line 433, in run
    test(result)
  File "/usr/lib64/python2.5/unittest.py", line 437, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib64/python2.5/unittest.py", line 433, in run
    test(result)
  File "/usr/lib64/python2.5/unittest.py", line 437, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib64/python2.5/unittest.py", line 433, in run
    test(result)
  File "/usr/lib64/python2.5/unittest.py", line 281, in __call__
    return self.run(*args, **kwds)
  File "/usr/lib64/python2.5/unittest.py", line 263, in run
    result.addFailure(self, self._exc_info())
  File "/usr/lib64/python2.5/unittest.py", line 667, in addFailure
    TestResult.addFailure(self, test, err)
  File "/usr/lib64/python2.5/unittest.py", line 129, in addFailure
    self.failures.append((test, self._exc_info_to_string(err, test)))
  File "/usr/lib64/python2.5/unittest.py", line 153, in _exc_info_to_string
    return ''.join(traceback.format_exception(exctype, value, tb))
  File "/usr/lib64/python2.5/traceback.py", line 131, in format_exception
    def format_exception(etype, value, tb, limit = None):
  File
"/local/packages/eclipse-3.4/plugins/org.python.pydev.debug_1.3.18/pysrc/pydevd.
py",
line 615, in trace_dispatch
    traceback.print_exc()
  File "/usr/lib64/python2.5/traceback.py", line 227, in print_exc
    print_exception(etype, value, tb, limit, file)
  File "/usr/lib64/python2.5/traceback.py", line 125, in print_exception
    print_tb(tb, limit, file)
  File "/usr/lib64/python2.5/traceback.py", line 69, in print_tb
    line = linecache.getline(filename, lineno, f.f_globals)
  File "/usr/lib64/python2.5/linecache.py", line 14, in getline
    lines = getlines(filename, module_globals)
  File "/usr/lib64/python2.5/linecache.py", line 40, in getlines
    return updatecache(filename, module_globals)
  File "/usr/lib64/python2.5/linecache.py", line 82, in updatecache
    basename = os.path.split(filename)[1]
  File "/local/devel/PhotoMap2/src/mox.py", line 414, in __getattr__
    raise UnknownMethodCallError(name)
mox.UnknownMethodCallError: Method called is not a member of the object: split

What version of the product are you using? On what operating system?
Mox 0.5.0. On Fedora 9 x86_64

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 25 Sep 2008 at 7:26

Attachments:

inspect is not imported into stubout.py

What steps will reproduce the problem?
1. import stubout into a test module
2. invoke StubOutForTesting.SmartSet
3. run the test

What is the expected output? What do you see instead?
The test should succeed, it fails with a stack trace ending in:
File ".../lib/python2.4/site-packages/stubout.py", line 59, in SmartSet
    if (inspect.ismodule(obj) or
NameError: global name 'inspect' is not defined


What version of the product are you using? On what operating system?
0.5.0 on Linux

Please provide any additional information below.



Original issue reported on code.google.com by [email protected] on 25 Mar 2009 at 9:30

StubOutClassWithMocks does not work with abstract base classes (ABC)

What steps will reproduce the problem?
Create a file foo.py containing the following class definitions:
import abc

class Foo(object):
  __metaclass__ = abc.ABCMeta

class Bar(Foo):
  pass

Now execute the following:
import foo
import mox
mox.Mox().StubOutClassWithMocks(foo, 'Foo')

What is the expected output?
StubOutClassWithMocks() should not produce any errors.

What do you see instead?
Raises "TypeError: Given attr is not a Class.  Use StubOutWithMock."

Reason: type(foo.Foo) is <class 'abc.ABCMeta'>, which doesn't fall into any of 
the categories in _USE_MOCK_FACTORY.

Original issue reported on code.google.com by [email protected] on 12 Apr 2012 at 11:53

CreateMock should support arbitrary attribute setting

At the present time, Mox has one shortcoming: whenever you need to set
attributes on an instance, you need to create the mock object and then set
attributes on it.

This is often the case for attributes that are usually set in the object's
__init__ method and can't be easily inferred by CreateMock, e.g.

class MyClass(object):
  def __init__(self):
    self.a = 1

# you must mock it this way:

m = Mox()
mockobj = m.CreateMock(MyClass)
mockobj.a = 1

even though this is usually done in setUp(), it might get boring and make
unit tests less and less readable.

This patch lets arbitrary kw args to be supplied to createmock, e.g.

mockobj = m.CreateMock(MyClass, a=1)
self.assertEquals(1, mockobj.a)

This makes it easy to both add instance attributes and to change instance
attribute values from the default (class defined) value.

Original issue reported on code.google.com by [email protected] on 11 Dec 2009 at 1:48

Attachments:

CreateMockAnything() should not allow attribute getting for unknown attributes in replay mode

Currently the following works:

-----
m = mox.Mox()
obj = m.CreateMockAnything()
m.ReplayAll()
print obj.f

-----

This hides many bugs when doing unit testing, because attribute accesses to 
'forbidden' or nonexistent attributes is not spotted. 

As to the obvious solution of using CreateMock() instead of 
CreateMockAnything(), it's not applicable in some cases, like unit-testing a 
piece of code before the objects with which it interacts have been developed.

My suggestion is to cause such attribute access fail with 
UnexpectedAttributeAccess exception or something similar. Of course this will 
slightly modify the current behavior, according to which the exception is only 
thrown when 'f' gets called.

Original issue reported on code.google.com by [email protected] on 4 Jul 2010 at 2:15

Documentation changed before code submited?

http://code.google.com/p/pymox/source/detail?spec=svn71&r=71
This documentation change does not seem to be coherent with the newest source 
version.
See Mox.StubOutWithMock.

Original issue reported on code.google.com by lamvak on 26 Mar 2012 at 4:59

New release

It's two years from last release - last file from downloads, which is in turn 
pulled by pypi and linux distributions packaging agents - the newest version in 
Gentoo is 0.5.3.

Original issue reported on code.google.com by lamvak on 26 Mar 2012 at 4:55

Comparison page outdated

According to PyPI the most popular Python mocking libraries are mock, Mox and 
then MiniMock. Yet the comparison page includes neither mock nor MiniMock!

More up to date comparisons (based on your Mox examples) can be found here:

http://www.voidspace.org.uk/python/mock/compare.html

They include a new library called "flexmock" but unfortunately not yet MiniMock.


Original issue reported on code.google.com by fuzzyman on 27 Feb 2011 at 5:52

Mox ExpectedMethodCallsError's _str__ method prints out one character per line

See: 
http://stackoverflow.com/questions/6124180/python-nose-tests-actually-the-error-
is-from-mox-print-out-errors-one-character

My Fix:

Adding this line to the top of str method of ExpectedMethodCallsError in mox.py 
fixes the problem (or this symptom anyway):

if isinstance(self._expected_methods, str):
  self._expected_methods = self._expected_methods.split("\n")

Original issue reported on code.google.com by [email protected] on 26 May 2011 at 9:01

Optional arguments

Related to issue 12, I want to stub out a function with optional arguments. I 
can't know in advance whether the optional arguments will be provided or not.
IgnoreArg() is no help with missing arguments.

def bar(one, two=None):
  pass

The test subject may call
bar(1)
or
bar(1, two=None)
or
bar(1, None)
or
bar(1, 42)

I'd like to be able to do
bar(1, two=IgnoreArg())
and have it match all of the above.

Original issue reported on code.google.com by stefano.rivera on 16 Aug 2011 at 9:12

ExpectedMethodCallsError problems with async code (twisted)

Hello,
while i like Mox, I've encountered a small issue when testing async twisted
code running trial (the twisted builtin test tool, supporting different
reactors, output, debugging, etc).

Since twisted wraps exceptions into failures, it may happen that, in order:

- VerifyAll() is called in a test method, but a certain expected method is
not called;
- a deferred is returned by the same method;
- the deferred then triggers a callback that calls the expected method:

this is what the trial output look like:

===============================================================================
[ERROR]: test_mox_async.AsyncMoxTestCase.testAsyncMox

Traceback (most recent call last):
  File
"/home/alan/Private/Dropbox/code/mox-0.5.1.fixtraceback/test_mox_async.py",
line 24, in testAsyncMox
    m.VerifyAll()
  File "/home/alan/Private/Dropbox/code/mox-0.5.1.fixtraceback/mox.py",
line 198, in VerifyAll
    mock_obj._Verify()
  File "/home/alan/Private/Dropbox/code/mox-0.5.1.fixtraceback/mox.py",
line 353, in _Verify
    raise ExpectedMethodCallsError(self._expected_calls_queue)
mox.ExpectedMethodCallsError: Verify: Expected methods never called:


The error is raised but, since the call has happened (too late, e.g. after
VerifyAll(), but it has happened), I can't see what the problem really is.

you can see the problem by yourself by running the attached file on a
system with twisted 8.2 installed:

trial test_mox_async.py 

This seems to be caused by the fact that the exception instance saves the
call queue and concatenates the string to be shown just when __str__ is
called (and that's too late when using trial and twisted).

The attached patch saves formatted calls on init, preventing further issues.

output on a patched Mox:

===============================================================================
[ERROR]: test_mox_async.AsyncMoxTestCase.testAsyncMox

Traceback (most recent call last):
  File
"/home/alan/Private/Dropbox/code/mox-0.5.1.fixtraceback/test_mox_async.py",
line 24, in testAsyncMox
    m.VerifyAll()
  File "/home/alan/Private/Dropbox/code/mox-0.5.1.fixtraceback/mox.py",
line 198, in VerifyAll
    mock_obj._Verify()
  File "/home/alan/Private/Dropbox/code/mox-0.5.1.fixtraceback/mox.py",
line 353, in _Verify
    raise ExpectedMethodCallsError(self._expected_calls_queue)
mox.ExpectedMethodCallsError: Verify: Expected methods never called:
  0.  __call__('value') -> None
-------------------------------------------------------------------------------
Ran 1 tests in 0.007s

FAILED (errors=1)





Original issue reported on code.google.com by [email protected] on 9 Oct 2009 at 4:22

Attachments:

Mox sometimes swallows unexpected method calls

Tested againt latest trunk (rev. 38)

I've encountered one bad issue in mock: it can sometimes happen that an
error is silently "swallowed" by the mocking framework. (see the attached
file).

Basically, what happens is that MockMethod just raises an exception
immediately if the method is called unexpectedly. But if the exception is
trapped in the caller code, e.g. something like

try:
    mockobject.callUnknownMethod()
except:
    log.error.something(....)


the exception is swallowed and the test passes without error.

Of course, the try...except in the caller code might be perfectly legit
(because there might be the absolute need the func not to throw at
anytime), but it is aimed at catching exceptions which are raised by the
function call itself, not by the fact that the function should not be called.

I do not provide a patch since I think this would need a bit of "rework",
e.g. a MockMethod raising such error should trigger a change in the
"global" Mox object state which should then be re-raised when calling
VerifyAll().





Original issue reported on code.google.com by [email protected] on 21 Dec 2009 at 3:38

Attachments:

MoxTestBase silently ignores overriding test methods

What steps will reproduce the problem?
1. Create and run the following script:

#!/usr/bin/python
import unittest
import mox

class Test1(mox.MoxTestBase):
    def testOK(self):
        self.assertEquals(1, 1)

class Test2(Test1):
    def testOK(self):
        self.assertEquals(1, 2)

if __name__ == '__main__':
    unittest.main()


What is the expected output?

FAIL: testOK (__main__.Test2)
Traceback (most recent call last):
  File "./lib/apt_forktracer/tests/test_mox.py", line 28, in testOK
    self.assertEquals(1, 2)
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)


What do you see instead?

..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK


What version of the product are you using?

0.5.1-1

On what operating system?

Ubuntu

Please provide any additional information below.

If I use plain unittest.TestCase everything works as expected - Test2.testOK 
overrides 
Test1.testOK and two methods are run: Test1.testOK and Test2.testOK

However when using mox.MoxTestBase, the same Test1.testOK method is run twice! 
Once in Test1 
context, once in Test2 context.

This is using python 2.5.2

Original issue reported on code.google.com by [email protected] on 28 Mar 2010 at 2:44

And comparator should use == comparison rather than .equals

What steps will reproduce the problem?
>>> import mox
>>> comparator = mox.And(1, mox.IsA(int))
>>> comparator == 1
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/var/lib/python-support/python2.4/mox.py", line 781, in __eq__
    return self.equals(rhs)
  File "/var/lib/python-support/python2.4/mox.py", line 1067, in equals
    if not comparator.equals(rhs):
AttributeError: 'int' object has no attribute 'equals'

What is the expected output? What do you see instead?
I expect True to be returned, however the AttributeError is raised.

What version of the product are you using? On what operating system?
Unknown, however the trunk version of pymox appears to have this bug in 
trunk as of Feb 23rd 2010.

Please provide any additional information below.
By using the == operator instead of the .equals() method (with the expected 
value on the lhs), this would make literal values usable. Currently 
mox.Func(lambda rhs: literal===rhs) needs to be employed to reach the same 
effect.

Comparators define __eq__ to call self.equals, so this should preserve 
existing behaviour when comparators are passed to the And() comparator. 
Although making this change could affect existing test cases that define a 
class that defines an equals method that is not called by an __eq__ method.

Note: the same problem/non-feature affects the Or comparator.

Original issue reported on code.google.com by [email protected] on 23 Apr 2010 at 5:38

Stubs are not unset properly for classmethods

What steps will reproduce the problem?
1. Stub out a classmethod (method) of a base class (Foo) with one child (Bar)
    Note that Bar.method.im_self == Bar at this point
2. Execute stub
3. Unset stubs
4. Check Bar.method.im_self.  Note that it is now equivalent to Foo

  See attached test case for complete example

What is the expected output? What do you see instead?
  Bar.method.im_self should revert to it's original value (e.g. Bar, not Foo)

What version of the product are you using? On what operating system?
mox 0.5, OS X



Original issue reported on code.google.com by [email protected] on 5 Mar 2009 at 8:11

Attachments:

MockObject should be smarter about recording args vs kwargs

Given the object:

class Foo(object):
  def bar(one, two, three=None):
    pass

When recording or replaying a MockObject(Foo)
 m_foo = mox.MockObject(Foo)
 # should be recorded in the same for both calls.
 m_foo.bar(1, 2, 3)  
 m_foo.bar(1, 2, three=3)

And verify should work for either:
 m_foo.bar(1, 2, 3)
 m_foo.bar(1, 2, 3)

... or ...
 m_foo.bar(1, 2, three=3)
 m_foo.bar(1, 2, three=3)


... or any combination thereof ...

This would require inspecting the method signature, and properly mapping 
keyword args, where appropriate.  I'm not sure if this is possible or not, 
but I'd like to hope so.


What is the expected output? What do you see instead?

See above.



Original issue reported on code.google.com by [email protected] on 25 Sep 2009 at 8:28

__equals__ impl of MockObject is too generous; fails e.g. when passing mocks as expected arguments

What steps will reproduce the problem?
Record an expectation, where a mock is passed as argument to a method of 
another mock. This expectation will be fulfilled, even if another mock-instance 
is actually passed, as long as this is of the same type. Example code is 
attached.

What is the expected output? What do you see instead?
Expectation should fails. Testing for object identity in __equals__ would 
achieve this.

What version of the product are you using? On what operating system?
pymox 0.5.3, windows 7 64 bit, jython 2.5.2rc3

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 2 Mar 2011 at 10:41

Attachments:

different versions of 0.5.3 on googlecode and on PyPI

There is a tarball up on googlecode labeled 0.5.3. There is also one on PyPI. 
They have different contents. Fedora packages are using the one from PyPI and 
Ubuntu is using the one from googlecode. In at least one scenario, we hit 
OpenStack test cases which passed on Ubuntu (erroneously) and failed on Fedora 
(correctly) - so it seems like the PyPI version may be "more" correct?

In any case - would it be possible to just go ahead and cut an 0.5.4 based on 
where things are at now and upload it to both googlecode and PyPI? Having two 
things with the same name is ... well, I'm sure OpenStack won't be the other 
set of folks to hit confusion. :)

Original issue reported on code.google.com by [email protected] on 16 Sep 2011 at 4:45

SwallowedExceptionError's _str__ method prints out one character per line when used with nose

Similar to Issue 34

This fixed the problems for me:

    def __str__(self):
        if isinstance(self._previous_exceptions, basestring):
            exceptions = self._previous_exceptions
        else:
            exceptions = "\n".join(["%3d.  %s: %s" % (i, e.__class__.__name__, e)
                                    for i, e in enumerate(self._previous_exceptions)])
        return "Previous exceptions thrown:\n%s" % (exceptions,)

Original issue reported on code.google.com by [email protected] on 28 Jul 2012 at 2:26

mox fails when it tries to substitute a user given tuple for a %s

What steps will reproduce the problem?
1. Use the In() comparator with a tuple (In((1, 2, 3)) so that you're 
matching a function call with something that contains a tuple
2. Fail the call check

What is the expected output? What do you see instead?
pymox should give a proper error how the call signature did not match but 
instead it fails with this:
mox/mox.py", line 1400, in __repr__
    return '<sequence or map containing \'%s\'>' % self._key

What version of the product are you using? On what operating system?
0.5.0 (I browsed the SVN source and seems to have the issue). Linux based 
OS.

Please provide any additional information below.

The problem is obvious, if self._key happens to be a tuple Python will try 
to perform multiple substitutions which is not the case. So the above code 
should wrap the user value like: str(self._key) and then this issue is 
gone. I haven't checked all the other comparators but it's theoretically 
possible for this to happen in any comparator where a %s substitution is 
tried for a user given input (which can be a tuple).

Original issue reported on code.google.com by [email protected] on 5 Jun 2010 at 12:20

Mox should format expected versus actual method call discrepancies elegantly.

What steps will reproduce the problem?
Mock a given method that has a long and complex signature, and have the 
actual call to the mock not match the recorded call.

mock_my_object = self.mox.CreateMock(MyObject)
mock_my_object.SomeComplexMethod(1, 2, 3, 4, 5, 6).AndReturn(True)
self.mox.ReplayAll()

self.assertTrue(mock_my_object.SomeComplexMethod(1, 2, 3, 4, 5, 6, 7))

What is the expected output? What do you see instead?
I would hope that Mox would more elegantly print where the discrepancy in 
the method calls is---e.g., "Unequal number of arguments between recorded 
and called method: 1 extra argument provided." for the case above.

Something like this would be nice:

Expected <MyObject mock>.SomeComplexMethod(1, 2, 3, 4, 5, 6)
Actual   <MyObject mock>.SomeComplexMethod(1, 2, 3, 4, 5, 6, 7)
                                            Extra parameter /|\

What version of the product are you using? On what operating system?
0.5.0 on Linux. 

Please provide any additional information below.
It can be really hard to read the discrepancy reports of the current 
version.

Original issue reported on code.google.com by [email protected] on 9 Mar 2009 at 9:11

Mox isn't playing well with nosetests on failures - OSX

I'm not sure if this is a nose problem or a mox problem; but I thought I would 
share it here.

The problem is the readability of the error.  The error is being thrown because 
the mock isn't matching, which is good.  However, the error gives no clue as to 
what 
failed.  In OSX, I have no idea what mock getting the wrong data sent to it.

What steps will reproduce the problem?
1. Create a failing test that use mox
2. Run the tests with nose

What is the expected output? What do you see instead?
I expect to see output like:

======================================================================
FAIL: test_failing_hello (mymodule_test.TestHello)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "build/bdist.linux-i686/egg/mox.py", line 1374, in new_method
    func(self, *args, **kwargs)
  File "/home/pope/Documents/code/gist-74723/mymodule_test.py", line 13, in test_failing_hello
    mymodule.hello()
  File "/home/pope/Documents/code/gist-74723/mymodule.py", line 6, in hello
    return repeater("Hello")
  File "build/bdist.linux-i686/egg/mox.py", line 562, in __call__
    expected_method = self._VerifyMethodCall()
  File "build/bdist.linux-i686/egg/mox.py", line 608, in _VerifyMethodCall
    raise UnexpectedMethodCallError(self, expected)
UnexpectedMethodCallError: Unexpected method call: __call__('Hello') -> None.  
Expecting: __call__('World') -> 'HelloWorld'

----------------------------------------------------------------------

However, I am seeing this:

======================================================================
ERROR: test_failing_hello (mymodule_test.TestHello)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/case.py", line 131, in run
    self.runTest(result)
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/case.py", line 149, in runTest
    test(result)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 300, in __call__
    return self.run(*args, **kwds)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 282, in run
    result.addFailure(self, self._exc_info())
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/proxy.py", line 131, in addFailure
    formatted = plugins.formatFailure(self.test, err)
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/plugins/manager.py", line 81, in __call__
    return self.call(*arg, **kw)
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/plugins/manager.py", line 119, in chain
    result = meth(*arg, **kw)
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/plugins/failuredetail.py", line 40, in formatFailure
    tbinfo = inspect_traceback(tb)
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/inspector.py", line 33, in inspect_traceback
    inspect_lines, mark_line = find_inspectable_lines(lines, exc_line)
  File "/Users/pope/Desktop/mox_test/nose-0.10.4-py2.6.egg/nose/inspector.py", line 122, in find_inspectable_lines
    home = lines[pos]
TypeError: 'NoneType' object is unsubscriptable

----------------------------------------------------------------------


What version of the product are you using? On what operating system?
I'm using Mox 0.5.0, Nose 0.10.4, Python 2.5 and 2.6, Mac OS X 10.5.6 Intel

Please provide any additional information below.
I set up a REALLY dumb test case at http://gist.github.com/74723

Original issue reported on code.google.com by [email protected] on 6 Mar 2009 at 3:10

UnorderedGroup __str__ obscures expected method calls

What steps will reproduce the problem?

import unittest
import mox

class Foo(object):

    def a(self, a, b):
        pass

    def b(self, a, b):
        pass


class TestFoo(unittest.TestCase):

    def setUp(self):
        self.mox = mox.Mox()

    def test_in_any_order_missing_calls(self):
        a = self.mox.CreateMock(Foo)
        a.a(a=1, b=2).InAnyOrder("foo")
        a.a(a=1, b=2).InAnyOrder("foo")
        a.b(a=1, b=2).InAnyOrder("foo")

        self.mox.ReplayAll()
        a.a(a=1, b=2)
        self.mox.VerifyAll()

    def test_in_any_order_bad_call(self):
        a = self.mox.CreateMock(Foo)
        a.a(a=1, b=2).InAnyOrder("foo")
        a.a(a=1, b=2).InAnyOrder("foo")
        a.b(a=1, b=2).InAnyOrder("foo")

        self.mox.ReplayAll()
        a.a(a=1, b=2)
        a.a(a=2, b=2)
        self.mox.VerifyAll()

What is the expected output? What do you see instead?

Output as following (running in nosetests):

======================================================================
FAIL: test_in_any_order_bad_call (foo.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../foo.py", line 46, in test_in_any_order_bad_call
    a.a(a=2, b=2)
  File ".../mox.py", line 983, in __call__
    expected_method = self._VerifyMethodCall()
  File ".../mox.py", line 1035, in _VerifyMethodCall
    expected, method = expected.MethodCalled(self)
  File ".../mox.py", line 1752, in MethodCalled
    raise UnexpectedMethodCallError(mock_method, self)
UnexpectedMethodCallError: Unexpected method call.  unexpected:-  
expected:+
- Foo.a(a=2, b=2) -> None
+ <UnorderedGroup "foo">

======================================================================
FAIL: test_in_any_order_missing_calls (foo.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../foo.py", line 36, in test_in_any_order_missing_calls
    self.mox.VerifyAll()
  File ".../mox.py", line 284, in VerifyAll
    mock_obj._Verify()
  File ".../mox.py", line 504, in _Verify
    raise ExpectedMethodCallsError(self._expected_calls_queue)
ExpectedMethodCallsError: Verify: Expected methods never called:
  0.  <UnorderedGroup "foo">

----------------------------------------------------------------------

The Problem with the above is that in the first case the unexpected method
call's expected method call is obscured by the UnorderedGroup 
representation.
The problem in the second case is that it's not obvious which calls are
missing.

The following is from a patched version of pymox:

======================================================================
FAIL: test_in_any_order_bad_call (foo.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../foo.py", line 46, in test_in_any_order_bad_call
    a.a(a=2, b=2)
  File ".../mox.py", line 983, in __call__
    expected_method = self._VerifyMethodCall()
  File ".../mox.py", line 1035, in _VerifyMethodCall
    expected, method = expected.MethodCalled(self)
  File ".../mox.py", line 1756, in MethodCalled
    raise UnexpectedMethodCallError(mock_method, self)
UnexpectedMethodCallError: Unexpected method call.  unexpected:-  
expected:+
+ UnorderedGroup "foo" pending calls:
- Foo.a(a=2, b=2) -> None
?         ^
+ Foo.a(a=1, b=2) -> None
?         ^              +
+ Foo.b(a=1, b=2) -> None

======================================================================
FAIL: test_in_any_order_missing_calls (foo.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../foo.py", line 36, in test_in_any_order_missing_calls
    self.mox.VerifyAll()
  File ".../mox.py", line 284, in VerifyAll
    mock_obj._Verify()
  File ".../mox.py", line 504, in _Verify
    raise ExpectedMethodCallsError(self._expected_calls_queue)
ExpectedMethodCallsError: Verify: Expected methods never called:
  0.  UnorderedGroup "foo" pending calls:
Foo.a(a=1, b=2) -> None
Foo.b(a=1, b=2) -> None

----------------------------------------------------------------------


What version of the product are you using? On what operating system?

SVN trunk r47 (0.5.3 being the latest release prior)

Please provide any additional information below.

I've patched pymox to:

a) Remove spurious newlines in the difflib output from unexpected method 
calls.
b) Display the pending method calls in an UnorderedGroup object via 
__repr__.

Both changes are included in the attached patch.

Original issue reported on code.google.com by [email protected] on 11 May 2010 at 6:29

Attachments:

ContainsAttributeValue missing __repr__ (issues useless errors)

What steps will reproduce the problem?
1. Use mox.ContainsAttributeValue comparator for a check that would fail
2. Run the test and get error printed

What is the expected output? What do you see instead?
Just like with the other Comparator classes, it should say something that tells 
what's wrong. Should contain at least what is checking. Instead it displays a 
useless generic Python description of the class instance:
+ function.__call__(<IgnoreArg>, <IgnoreArg>, <mox.ContainsAttributeValue 
instance at 0x8bb4b6c>) -> 0

From that message I cannot tell what attribute/value was expected and is 
missing.

What version of the product are you using? On what operating system?
Latest SVN has the same problem. Linux.


Original issue reported on code.google.com by [email protected] on 1 Aug 2011 at 9:30

Support for properties

I would like to mock classes with properties, but cannot find any example
for this.

When I try set expectations for a property the framework does not
understand the propery attribute. I then tried to set expectations for the
__get* and __set* method for that property, but still when using the
property from the mock-ed class in another class (the class to be tested)
the type of that property is a 'property' and the getter is never executed.

Do I have to manually bind the ID property of the mock class to the getter
and setter? What is the suggested best practice here?

Thanks!

Original issue reported on code.google.com by [email protected] on 3 Aug 2009 at 8:25

SameElementsAs dies with attributeerror when printed to string

What steps will reproduce the problem?
import mox

print mox.SameElementsAs([1,2,3])


What is the expected output? What do you see instead?
<sequence with same elements as '1,2,3'>

AttributeError


What version of the product are you using? On what operating system?
in trunk



Please provide any additional information below.

__repr__ should use self._expected_list not self._expected_seq

Original issue reported on code.google.com by [email protected] on 20 Sep 2010 at 9:23

UnexpectedMethodCallError in an other moudle call moxed time.localtime()

What steps will reproduce the problem?
1. mox the time.localtime()
2. call time.localtime() in an other moudle

code:
0 .... 
1 t = time.gmtime(time.mktime((2012, 10, 1, 15, 26,0,0,0,0))) 
2 self.mox.StubOutWithMock?(time, 'localtime') 
3 time.localtime().AndReturn?(t) 
4 self.mox.ReplayAll()
5 print "mox localtime:", time.localtime()    # correct
6 othermoudle.func() # call time.localtime() in func()  # error
7 ...

What is the expected output? What do you see instead?
on the line 5,I got a correct mox time: 
(Pdb) time.localtime() 
time.struct_time(tm_year=2012, tm_mon=10, tm_mday=1, tm_hour=7, tm_min=26, 
tm_sec=0, tm_wday=0, tm_yday=275, tm_isdst=0)

and then call time.localtime in an other moudle, I got an error: 
(Pdb) time.time() 
1333178201.334844 
(Pdb) time.localtime() 
UnexpectedMethodCallError: Unexpected method call Stub for <built-in function 
localtime>.call() -> None 
(Pdb)


What version of the product are you using? On what operating system?
mox-0.5.3-py2.7.egg
python 2.7
Ubuntu 11.10 desktop

Please provide any additional information below.
my error msg is:
Unit test of worker.

mox localtime: time.struct_time(tm_year=2012, tm_mon=10, tm_mday=1, tm_hour=7, 
tm_min=26, tm_sec=0, tm_wday=0, tm_yday=275, tm_isdst=0)

F
======================================================================
FAIL: testIsTimeToWorkFirst (__main__.WorkerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_worker.py", line 64, in testIsTimeToWorkFirst
    ret = w.is_timeto_work()
  File "/home/pyw/work/demux/worker/worker.py", line 119, in is_timeto_work
    self.update_time()
  File "/home/pyw/work/demux/worker/worker.py", line 92, in update_time
    localtime = time.localtime()
  File "/usr/local/lib/python2.7/dist-packages/mox-0.5.3-py2.7.egg/mox.py", line 1002, in __call__
    expected_method = self._VerifyMethodCall()
  File "/usr/local/lib/python2.7/dist-packages/mox-0.5.3-py2.7.egg/mox.py", line 1049, in _VerifyMethodCall
    expected = self._PopNextMethod()
  File "/usr/local/lib/python2.7/dist-packages/mox-0.5.3-py2.7.egg/mox.py", line 1035, in _PopNextMethod
    raise UnexpectedMethodCallError(self, None)
UnexpectedMethodCallError: Unexpected method call Stub for <built-in function 
localtime>.__call__() -> None

Original issue reported on code.google.com by [email protected] on 31 Mar 2012 at 7:47

Mox should check that expected calls match with objects API

If I have a class

class Foo(object):
  def bar(a):
    pass

Then the following should fail
 m_foo = mox.MockObject(Foo)
 m_foo.bar(1, 2)

because the number of arguments doesn't match the acutal implementations 
restrictions.

This will allow tests to fail if the API that they are testing changes from 
beneath them.  

Original issue reported on code.google.com by [email protected] on 12 Oct 2011 at 6:16

pymox is not easy_install'able

I would really like to have this library as a dependency of my application,
but at the moment it is impossible, because pymox is not on PyPI.

Original issue reported on code.google.com by [email protected] on 20 Nov 2008 at 3:57

Signature matching of unbound methods doesn't work for subclasses

What steps will reproduce the problem?

Given module foo:
class Bar:
  def Qux(self):
    pass

# test
StubOut(foo.Bar, "Qux")
foo.Bar.Qux(IsA(BarSubclass))

# error, since when doing signature inspection, Bar is not an instance of 
BarSubclass.

Using an instance of Bar works just fine, as does IgnoreArg()

The signature matching code needs to be smarter, more specifically when IsA 
comparator is used.

What is the expected output? What do you see instead?


What version of the product are you using? On what operating system?


Head.

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 18 Aug 2010 at 9:13

pymox should support a context handler for verification

[this is a feature request]

I recently wrote a small helper class to allow a context handlers to provide 
verification.  e.g.

  def testFoo(self):
    # set expectations
    with Verification(self.mox):
      # call code, assert results.

The implementation is simple:

class Verification(object):
  def __init__(self, m):
    self.m = m

  def __enter__(self):
    self.m.ReplayAll()

  def __exit__(self, exc_type, exc_value, traceback):
    if exc_type is None and exc_value is None and traceback is None:
      self.m.VerifyAll()

I think that this should probably be a core part of mox, allowing one to say:

  def testFoo(self):
    with self.mox.Verification():
      # …

To my eye, this nicely delineates the code under test from the setup code.

I've attached a sample implementation for discussion.  Some points from that:

- I'm not sure what the minimum Python version of pymox is.  Context handlers 
are a 2.6ism.
- I placed a function on the Mox class, which uses another class, Verification. 
 This seemed more flexible than just saying "with self.mox" as it allows for 
other context handlers if necessary.

Original issue reported on code.google.com by [email protected] on 30 Jul 2012 at 8:46

Attachments:

Mox should offer a stubout call which is safe to call repeatedly and won't try to mock out the mock object

I've been using code like this to do it.  I'm happy to contribute a patch
if you agree this is useful and isn't dangerous for some reason that I'm
not seeing:

def StubOutIfNeeded(mox_obj, parent_object, attribute):
  """Stubs out the call only if it's not already a mock."""
  if not isinstance(getattr(parent_object, attribute),
                    (mox.MockAnything, mox.MockObject)):
    mox_obj.StubOutWithMock(parent_object, attribute)

Then if I want to set multiple expectations on the thing that I'm stubbing
out, I can safely call StubOutIfNeeded(self.mox, module, 'FunctionName')
each time before setting an expectation, and not worry about whether it's
already been stubbed out or not.

Combined with using mox.MoxTestBase which will unset all stubs in self.mox,
this seems pretty safe, because things will succeed whether I create and
use the stub or don't.

Original issue reported on code.google.com by [email protected] on 29 May 2009 at 5:30

Deprecation warnings when __new__ is stubbed using python 2.6

What steps will reproduce the problem?
1. Stub out __new__ on a class without an explicit __new__ definition when
using Python 2.6
2. Unset stubs
3. Try to instantiate the class again

What is the expected output? What do you see instead?

Everything works as expected except that there is a deprecation warning:
  DeprecationWarning: object.__new__() takes no parameters 

What version of the product are you using? On what operating system?
  Mox 0.50, OS X, but most importantly Python 2.6.2 (or any other 2.6.x)  

Please provide any additional information below.
  This seems to be another edge case of python weirdness that isn't
explicitly covered by mox.  Classes that don't explicitly define __new__
use a special, built-in version defined by python.  It doesn't seem to be
possible to recover this version, or at least properly rebind it, when
stubs are unset (or something like that, I don't quite understand the
magic).  The result seems to be that __new__ is called for object with all
args intact.  As of 2.6 object.__new__ only accepts the cls parameter and
barfs a DeprecationWarning if it gets extra args.  While it doesn't
actually break anything the warnings are pretty annoying and presumably it
will become a breaking problem when extra args are truly deprecated.

  I've attached a patch that fixes the problem as well as a test script
that demonstrates the issue using both mox and just the generic issue in
python.  All the patch does is watch for attempts to stub out __new__ when
the existing implementation is a built-in method.  If that's the case it
stubs out __new__ it will unstub with a lambda that calls __new__ on the
parent class without any extra args.

Original issue reported on code.google.com by [email protected] on 26 May 2009 at 6:18

Attachments:

Add Is() comparator to mox

Would be nice when testing objects that have __eq__/__cmp__ logic that might 
create false positives or true negatives.

Suggested patch included:
-----------8< ------- 8< ---------

diff --git a/mox.py b/mox.py
index ba73bd3..dd66f3b 100755
--- a/mox.py
+++ b/mox.py
@@ -1220,6 +1220,13 @@ class Comparator:
   def __ne__(self, rhs):
     return not self.equals(rhs)

+class Is(Comparator):
+  def __init__(self, obj):
+    self._obj = obj
+  def equals(self, rhs):
+    return rhs is self._obj
+  def __repr__(self):
+    return "<is %r (%s)>" % (self._obj, id(self._obj))

 class IsA(Comparator):
   """This class wraps a basic Python type or class.  It is used to verify

diff --git a/mox_test.py b/mox_test.py
index 2e429e6..f1c4b56 100755
--- a/mox_test.py
+++ b/mox_test.py
@@ -259,6 +259,51 @@ class RegexTest(unittest.TestCase):
                  "<regular expression 'a\s+b', flags=4>")


+class IsTest(unittest.TestCase):
+  """Verify Is correctly checks equality based upon identity, not value"""
+
+  class AlwaysComparesTrue(object):
+    def __eq__(self, other):
+      return True
+    def __cmp__(self, other):
+      return 0
+    def __ne__(self, other):
+      return False
+
+  def testEqualityValid(self):
+    o1 = self.AlwaysComparesTrue()
+    self.assertTrue(mox.Is(o1), o1)
+
+  def testEqualityInvalid(self):
+    o1 = self.AlwaysComparesTrue()
+    o2 = self.AlwaysComparesTrue()
+    self.assertTrue(o1 == o2)
+    # but...
+    self.assertFalse(mox.Is(o1) == o2)
+
+  def testInequalityValid(self):
+    o1 = self.AlwaysComparesTrue()
+    o2 = self.AlwaysComparesTrue()
+    self.assertTrue(mox.Is(o1) != o2)
+

+  def testInequalityInvalid(self):
+    o1 = self.AlwaysComparesTrue()
+    self.assertFalse(mox.Is(o1) != o1)
+
+  def testEqualityInListValid(self):
+    o1 = self.AlwaysComparesTrue()
+    o2 = self.AlwaysComparesTrue()
+    isa_list = [mox.Is(o1), mox.Is(o2)]
+    str_list = [o1, o2]
+    self.assertTrue(isa_list == str_list)
+
+  def testEquailtyInListInvalid(self):
+    o1 = self.AlwaysComparesTrue()
+    o2 = self.AlwaysComparesTrue()
+    isa_list = [mox.Is(o1), mox.Is(o2)]
+    mixed_list = [o2, o1]
+    self.assertFalse(isa_list == mixed_list)
+
 class IsATest(unittest.TestCase):
   """Verify IsA correctly checks equality based upon class type, not value."""

Original issue reported on code.google.com by [email protected] on 23 Jun 2010 at 11:50

MockObject should provide a way to test methods like __str__

What steps will reproduce the problem?

class Foo:
    def __str__(self):
        print "Foo!"

class TestSuite(unittest.TestCase):
    def setUp(self):
        self.m = mox.Mox()
    def tearDown(self):
        self.m.UnsetStubs()

    def test_Foo_str(self):
        f = self.m.CreateMock(Foo)
        self.m.ReplayAll()
        res = str(f)  # res receives '<MockAnything instance at xx>'
        self.m.VerifyAll()


What is the expected output? What do you see instead?

In most situations, MockObject.__str__ is useful but in some, it prevents from 
testing a class's __str__ method. Instead of receiving '<MockAnything...>' in 
the example above, there should be a way to make it receive "Foo!"

What version of the product are you using? On what operating system?

0.5.3

Debian GNU/Linux

Please provide any additional information below.

A short discussion was held about this subject on the mailing list[1] and it 
was suggested that some mechanism could disable MockObject's additional methods.

[1]:http://groups.google.com/group/mox-discuss/browse_thread/thread/72c214e943a3
ec16

Original issue reported on code.google.com by [email protected] on 27 Sep 2010 at 6:34

Method call failures involving MockAnything are unprintable

When trying to use MockAnything in a recorded method call, failures will be
unprintable because MockAnything will record the __repr__ call and raise an
exception.

Using this test code:

mock = mox.Mox ()
mock_qs = mock.CreateMockAnything ()
mock_qs.all ().AndReturn (mock_qs)
mock.ReplayAll ()
mock.VerifyAll ()

Causes this (rather unhelpful) failure:

Traceback (most recent call last):
  File "tests/test_gallery.py", line 47, in test_already_contains
    mock.VerifyAll ()
  File "/usr/lib/python2.5/site-packages/mox-0.5.0-py2.5.egg/mox.py", line
197, in VerifyAll
    mock_obj._Verify()
  File "/usr/lib/python2.5/site-packages/mox-0.5.0-py2.5.egg/mox.py", line
344, in _Verify
    raise ExpectedMethodCallsError(self._expected_calls_queue)
ExpectedMethodCallsError: <unprintable ExpectedMethodCallsError object>

Original issue reported on code.google.com by [email protected] on 4 Oct 2008 at 5:06

python 3 compatibility

It would be great to have a python 3 compatible version of pymox.

Original issue reported on code.google.com by lamvak on 28 Mar 2012 at 6:45

mox fails with python 2.7.2rc1

While updating to python 2.7.2rc1 we got the following traceback:

  File "/usr/lib/pymodules/python2.7/mox.py", line 256, in CreateMock
    new_mock = MockObject(class_to_mock, attrs=attrs)
  File "/usr/lib/pymodules/python2.7/mox.py", line 553, in __init__
    for method in dir(class_to_mock):
TypeError: __dir__() must return a list, not MockMethod


Original issue reported on code.google.com by [email protected] on 2 Jun 2011 at 7:35

Mox should handle class attributes raising an AttributeError

Hello,
while using some classes from some external libraries, i realized that if the 
parent class uses 
zope.interface classProvides and the child does not, I get an AttributeError 
while trying to use it 
with CreateMock()

this happens because a "rogue" class attribute persists in the class dir() 
output (as it is inherited 
by the parent class), but it raises AttributeError whenever it is called on the 
child class.

A small example which employs a metaclass is attached, so you don't need 
installing 
zope.interface  if you don't want to.

This happens because Mox uses dir() and then something like 
getattr(class_to_mock, method), 
which breaks in the event an AttributeError is raised. But raising 
AttributeError is *the* right way 
to do this in python, if you just want customize your object behaviour. 

IMHO just using the failsafe getattr(class_to_mock, method, NO_ATTR) signature 
is the best 
choice; it will break if other errors are raised, just trapping AttributeError. 
Of course, in such a 
case, the mocked object should NOT expose such attribute.

a patch, with tests, is attached.


Original issue reported on code.google.com by [email protected] on 10 Oct 2009 at 3:04

Attachments:

UnsetStubs doesn't work if stub is unused

What steps will reproduce the problem?
1. Create a test with e.g.

self.mox = mox.Mox()
self.mox.StubOutWithMock(module_under_test.logging, 'info')
...
# other code that doesn't use module.logging
...
self.mox.UnsetStubs()

2. Run the test

What is the expected output? What do you see instead?

I would expect the UnsetStubs call (probably in a tearDown method or
similar) to return module_under_test.logging to its original state.
Instead, all my other tests start failing.

Inserting the line:
module_under_test.logging.info(mox.IsA(str)
just after StubOutWithMock causes the issue to disappear.

What version of the product are you using? On what operating system?


Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 22 Sep 2008 at 3:55

__contains__ is not prpoperly handled is class hiararchies

What steps will reproduce the problem?
1. create a class A that defines __contains__
2. create a class B that inherits from A but does not override __contains__
3. try to write a test and stub out __contains__ for the instance of B

You will get a TypeError raised because of current implementation __contains__ 
lookup:

...
    contains = self._class_to_mock.__dict__.get('__contains__', None)
    if contains is None:
      raise TypeError('unsubscriptable object')
...

What is the expected output? What do you see instead?

The __contains__ should be properly stubbed out in class B object instance

What version of the product are you using? On what operating system?
Python 2.7.2
Windows



Original issue reported on code.google.com by [email protected] on 3 Sep 2011 at 1:01

Separate error message from arguments

What steps will reproduce the problem?

mock.AMethod().AndRaise(StopIteration)

What is the expected output? What do you see instead?

The following error message is printed:

AttributeError: No values given for arguments cell groups

It's not obvious that "cell groups" are the argument names used in the 
tested code, and the actual message from mox ends at "arguments". One could 
imagine an even more confusing combination.

Using some punctuation would help considerably:

AttributeError: No values given for arguments: cell, groups

This is just one place I've encountered this. There might be more similar 
cases in need of improvement.

Original issue reported on code.google.com by [email protected] on 24 May 2010 at 12:21

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.