Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-

language: python

python:
- "2.6"
- "2.7"
- "3.3"

install:
- pip install --upgrade pip --use-mirrors
- pip install coveralls --use-mirrors
- pip install .

script:
- coverage run --source=fixture setup.py test

after_success:
- coveralls

notifications:
email: false
8 changes: 4 additions & 4 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ To build docs run ::

$ make -C docs html

For info on running tests, see fixture/test/__init__.py
For info on running tests, see tests/__init__.py

To run tests ::
$ python setup_test_buildout.py

$ python setup.py test
$ ./bin/buildout
$ ./bin/test-fixture
$ ./bin/test-fixture
14 changes: 11 additions & 3 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# serve to show the default value.

import sys, os
# for doctests of Django examples to work
# for doctests of Django examples to work
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'fixture', 'examples', 'django_example'))

# register some docutils directives
Expand All @@ -21,6 +21,7 @@
# for version number:
import fixture


# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
Expand Down Expand Up @@ -50,9 +51,16 @@
# other places throughout the built documents.
#
# The short X.Y version.
version = fixture.__version__

# Get the version string. Cannot be done with import!
with open(os.path.join('..', '..', 'fixture', 'version.py'), 'rt') as f:
version = re.search(
'__version__\s*=\s*"(?P<version>.*)"\n',
f.read()
).group('version')

# The full version, including alpha/beta/rc tags.
release = fixture.__version__
release = version

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/using-loadable-fixture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Fixture is designed for applications that already have a way to store data; the
>>> engine = create_engine('sqlite:////tmp/fixture_example.db')
>>> metadata = MetaData()
>>> metadata.bind = engine
>>> Session = scoped_session(sessionmaker(bind=metadata.bind, autoflush=True, transactional=True))
>>> Session = scoped_session(sessionmaker(bind=metadata.bind, autoflush=True))
>>> session = Session()

Set up the table and mapper for authors ...
Expand Down
47 changes: 8 additions & 39 deletions ez_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

This file can also be run as a script to install or upgrade setuptools.
"""

from __future__ import print_function

import sys
DEFAULT_VERSION = "0.6c8"
DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
Expand Down Expand Up @@ -88,10 +91,10 @@ def do_download():
try:
import pkg_resources
except ImportError:
return do_download()
return do_download()
try:
pkg_resources.require("setuptools>="+version); return
except pkg_resources.VersionConflict, e:
except pkg_resources.VersionConflict as e:
if was_imported:
print >>sys.stderr, (
"The required version of setuptools (>=%s) is not available, and\n"
Expand Down Expand Up @@ -154,40 +157,6 @@ def download_setuptools(
return os.path.realpath(saveto)




































def main(argv, version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
try:
Expand Down Expand Up @@ -226,8 +195,8 @@ def main(argv, version=DEFAULT_VERSION):
from setuptools.command.easy_install import main
main(argv)
else:
print "Setuptools version",version,"or greater has been installed."
print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
print("Setuptools version {0} or greater has been installed.".format(version))
print('(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)')

def update_md5(filenames):
"""Update our built-in md5 registry"""
Expand All @@ -251,7 +220,7 @@ def update_md5(filenames):

match = re.search("\nmd5_data = {\n([^}]+)}", src)
if not match:
print >>sys.stderr, "Internal error!"
print("Internal error!", file=sys.stderr)
sys.exit(2)

src = src[:match.start(1)] + repl + src[match.end(1):]
Expand Down
8 changes: 3 additions & 5 deletions fixture/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

"""fixture is a python module for loading and referencing test data

It provides several utilities for achieving a *fixed state* when testing
Python programs. Specifically, these utilities setup / teardown databases and
It provides several utilities for achieving a *fixed state* when testing
Python programs. Specifically, these utilities setup / teardown databases and
work with temporary file systems.

You may want to start by reading the `End User Documentation`_.
Expand All @@ -22,8 +22,6 @@

"""

__version__ = "1.5"

import logging
import sys

Expand All @@ -32,9 +30,9 @@
from fixture.util import *
from fixture.io import *
from fixture.style import *
from fixture.version import __version__

def setup_test_not_supported():
"""hook for setup for the test command."""
raise NotImplementedError("use: `python setup.py nosetests` instead")
setup_test_not_supported.__test__ = False

75 changes: 37 additions & 38 deletions fixture/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
The more useful bits are in :mod:`fixture.loadable`

"""
import sys, traceback
import inspect
import sys
import traceback
try:
from functools import wraps
except ImportError:
Expand All @@ -17,21 +19,18 @@ def wrap_with_f(new_f):
new_f.__module__ = f.__module__
return new_f
return wrap_with_f

from fixture.dataset import SuperSet
from compiler.consts import CO_GENERATOR

def is_generator(func):
try:
return func.func_code.co_flags & CO_GENERATOR != 0
except AttributeError:
return False
return inspect.isgeneratorfunction(func)


class FixtureData(object):
"""
Loads one or more DataSet objects and provides an interface into that
Loads one or more DataSet objects and provides an interface into that
data.

Typically this is attached to a concrete Fixture class and constructed by ``data = fixture.data(...)``
"""
def __init__(self, datasets, dataclass, loader):
Expand All @@ -42,15 +41,15 @@ def __init__(self, datasets, dataclass, loader):

def __enter__(self):
"""enter a with statement block.

calls self.setup()
"""
self.setup()
return self

def __exit__(self, type, value, traceback):
"""exit a with statement block.

calls self.teardown()
"""
self.teardown()
Expand All @@ -76,43 +75,43 @@ def teardown(self):

class Fixture(object):
"""An environment for loading data.

An instance of this class can safely be a module-level object.
It may be more useful to use a concrete LoadableFixture, such as
SQLAlchemyFixture

Keywords arguments:

dataclass
class to instantiate with datasets (defaults to SuperSet)
loader
class to instantiate and load data sets with.

"""
dataclass = SuperSet
loader = None
Data = FixtureData

def __init__(self, dataclass=None, loader=None):
if dataclass:
self.dataclass = dataclass
if loader:
self.loader = loader

def __iter__(self):
for k in self.__dict__:
yield k

def with_data(self, *datasets, **cfg):
"""returns a decorator to wrap data around a method.

All positional arguments are DataSet class objects.
the decorated method will receive a new first argument,

the decorated method will receive a new first argument,
the Fixture.Data instance.

Keyword arguments:

setup
optional callable to be executed before test
teardown
Expand All @@ -139,14 +138,14 @@ def passthru_teardown():
if teardown: teardown()
else:
passthru_teardown = teardown

def setup_data():
data = self.data(*datasets)
data.setup()
return data
def teardown_data(data):
data.teardown()

@wraps(routine)
def call_routine(*a,**kw):
data = setup_data()
Expand All @@ -155,21 +154,21 @@ def call_routine(*a,**kw):
except KeyboardInterrupt:
# user wants to abort everything :
raise
except Exception, exc:
except Exception as exc:
# caught exception, so try to teardown but do it safely :
etype, val, tb = sys.exc_info()
try:
teardown_data(data)
except:
t_ident = ("-----[exception in teardown %s]-----" %
t_ident = ("-----[exception in teardown %s]-----" %
hex(id(teardown_data)))
sys.stderr.write("\n\n%s\n" % t_ident)
traceback.print_exc()
sys.stderr.write("%s\n\n" % t_ident)
raise exc, None, tb
raise exc
else:
teardown_data(data)

@wraps(routine)
def iter_routine():
for stack in routine():
Expand All @@ -188,35 +187,35 @@ def atomic_routine(*genargs,**kw):
genargs = (data,) + genargs
try:
fn(*genargs, **kw)
except Exception, exc:
except Exception as exc:
etype, val, tb = sys.exc_info()
try:
teardown_data(data)
except:
t_ident = (
"-----[exception in teardown %s]-----" %
"-----[exception in teardown %s]-----" %
hex(id(teardown_data)))
sys.stderr.write("\n\n%s\n" % t_ident)
traceback.print_exc()
sys.stderr.write("%s\n\n" % t_ident)
raise exc, None, tb
raise exc
else:
teardown_data(data)

restack = (atomic_routine, setup_data) + args
yield restack

if is_generator(routine):
wrapped_routine = iter_routine
else:
wrapped_routine = call_routine
decorate = with_setup( setup=passthru_setup,

decorate = with_setup( setup=passthru_setup,
teardown=passthru_teardown )
return decorate( wrapped_routine )
return decorate_with_data

def data(self, *datasets):
"""returns a :class:`FixtureData` object for datasets."""
return self.Data(datasets, self.dataclass, self.loader)

Loading